77using System . Collections . Generic ;
88using System . Linq ;
99using NuGet . Shared ;
10+ using Spectre . Console ;
11+ using Spectre . Console . Rendering ;
1012
1113namespace NuGet . CommandLine . XPlat . Commands . Why
1214{
1315 internal static class DependencyGraphPrinter
1416 {
15- private const ConsoleColor TargetPackageColor = ConsoleColor . Cyan ;
16-
17- // Dependency graph console output symbols
18- private const string ChildNodeSymbol = "├─ " ;
19- private const string LastChildNodeSymbol = "└─ " ;
20-
21- private const string ChildPrefixSymbol = "│ " ;
22- private const string LastChildPrefixSymbol = " " ;
17+ private static readonly Color TargetPackageColor = Color . Cyan ;
2318
2419 /// <summary>
2520 /// Prints the dependency graphs for all target frameworks.
2621 /// </summary>
2722 /// <param name="dependencyGraphPerFramework">A dictionary mapping target frameworks to their dependency graphs.</param>
2823 /// <param name="targetPackage">The package we want the dependency paths for.</param>
2924 /// <param name="logger"></param>
30- public static void PrintAllDependencyGraphs ( Dictionary < string , List < DependencyNode > ? > dependencyGraphPerFramework , string targetPackage , ILoggerWithColor logger )
25+ public static void PrintAllDependencyGraphs ( Dictionary < string , List < DependencyNode > ? > dependencyGraphPerFramework , string targetPackage , IAnsiConsole logger )
3126 {
3227 // print empty line
33- logger . LogMinimal ( "" ) ;
28+ logger . WriteLine ( ) ;
3429
3530 // deduplicate the dependency graphs
3631 List < List < string > > deduplicatedFrameworks = GetDeduplicatedFrameworks ( dependencyGraphPerFramework ) ;
@@ -51,71 +46,67 @@ public static void PrintAllDependencyGraphs(Dictionary<string, List<DependencyNo
5146 /// <param name="topLevelNodes">The top-level package nodes of the dependency graph.</param>
5247 /// <param name="targetPackage">The package we want the dependency paths for.</param>
5348 /// <param name="logger"></param>
54- private static void PrintDependencyGraphPerFramework ( List < string > frameworks , List < DependencyNode > ? topLevelNodes , string targetPackage , ILoggerWithColor logger )
49+ private static void PrintDependencyGraphPerFramework ( List < string > frameworks , List < DependencyNode > ? topLevelNodes , string targetPackage , IAnsiConsole logger )
5550 {
56- // print framework header
57- foreach ( var framework in frameworks )
58- {
59- logger . LogMinimal ( $ " [{ framework } ]") ;
60- }
61-
62- logger . LogMinimal ( $ " { ChildPrefixSymbol } ") ;
51+ var tree = new Tree ( string . Join ( "\n " , frameworks . Select ( f => $ "[[{ f } ]]") ) ) ;
6352
6453 if ( topLevelNodes == null || topLevelNodes . Count == 0 )
6554 {
66- logger . LogMinimal ( $ " { LastChildNodeSymbol } { Strings . WhyCommand_Message_NoDependencyGraphsFoundForFramework } \n \n ") ;
55+ tree . AddNode ( Strings . WhyCommand_Message_NoDependencyGraphsFoundForFramework ) ;
56+ logger . Write ( PadTree ( tree ) ) ;
6757 return ;
6858 }
6959
7060 var stack = new Stack < StackOutputData > ( ) ;
7161
7262 // initialize the stack with all top-level nodes
73- int counter = 0 ;
7463 foreach ( var node in topLevelNodes . OrderByDescending ( c => c . Id , StringComparer . OrdinalIgnoreCase ) )
7564 {
76- stack . Push ( new StackOutputData ( node , prefix : " " , isLastChild : counter ++ == 0 ) ) ;
65+ stack . Push ( new StackOutputData
66+ {
67+ Node = node ,
68+ ParentNode = tree
69+ } ) ;
7770 }
7871
7972 // print the dependency graph
8073 while ( stack . Count > 0 )
8174 {
8275 var current = stack . Pop ( ) ;
8376
84- string currentPrefix , childPrefix ;
85- if ( current . IsLastChild )
86- {
87- currentPrefix = current . Prefix + LastChildNodeSymbol ;
88- childPrefix = current . Prefix + LastChildPrefixSymbol ;
89- }
90- else
91- {
92- currentPrefix = current . Prefix + ChildNodeSymbol ;
93- childPrefix = current . Prefix + ChildPrefixSymbol ;
94- }
95-
96- // print current node
97- if ( current . Node . Id . Equals ( targetPackage , StringComparison . OrdinalIgnoreCase ) )
98- {
99- logger . LogMinimal ( $ "{ currentPrefix } ", Console . ForegroundColor ) ;
100- logger . LogMinimal ( $ "{ current . Node . Id } (v{ current . Node . Version } )\n ", TargetPackageColor ) ;
101- }
102- else
103- {
104- logger . LogMinimal ( $ "{ currentPrefix } { current . Node . Id } (v{ current . Node . Version } )") ;
105- }
77+ var treeNodeText = GetNodeText ( current . Node , targetPackage ) ;
78+ var treeNode = current . ParentNode . AddNode ( treeNodeText ) ;
10679
10780 if ( current . Node . Children ? . Count > 0 )
10881 {
109- // push all the node's children onto the stack
110- counter = 0 ;
11182 foreach ( var child in current . Node . Children . OrderByDescending ( c => c . Id , StringComparer . OrdinalIgnoreCase ) )
11283 {
113- stack . Push ( new StackOutputData ( child , childPrefix , isLastChild : counter ++ == 0 ) ) ;
84+ stack . Push ( new StackOutputData
85+ {
86+ Node = child ,
87+ ParentNode = treeNode
88+ } ) ;
11489 }
11590 }
11691 }
11792
118- logger . LogMinimal ( "" ) ;
93+ logger . Write ( PadTree ( tree ) ) ;
94+ logger . WriteLine ( ) ;
95+ }
96+
97+ private static IRenderable GetNodeText ( DependencyNode node , string targetPackage )
98+ {
99+ string text = $ "{ node . Id } (v{ node . Version } )";
100+ Style ? style = node . Id . Equals ( targetPackage , StringComparison . OrdinalIgnoreCase )
101+ ? new Style ( foreground : TargetPackageColor )
102+ : null ;
103+
104+ return new Text ( text , style ) ;
105+ }
106+
107+ private static IRenderable PadTree ( Tree tree )
108+ {
109+ return new Padder ( tree , new Padding ( left : 2 , 0 , 0 , 0 ) ) ;
119110 }
120111
121112 /// <summary>
@@ -173,16 +164,9 @@ private static int GetDependencyGraphHashCode(List<DependencyNode>? graph)
173164
174165 private class StackOutputData
175166 {
176- public DependencyNode Node { get ; set ; }
177- public string Prefix { get ; set ; }
178- public bool IsLastChild { get ; set ; }
167+ public required DependencyNode Node { get ; init ; }
179168
180- public StackOutputData ( DependencyNode node , string prefix , bool isLastChild )
181- {
182- Node = node ;
183- Prefix = prefix ;
184- IsLastChild = isLastChild ;
185- }
169+ public required IHasTreeNodes ParentNode { get ; init ; }
186170 }
187171 }
188172}
0 commit comments