Skip to content

Commit

Permalink
Refactor browse and package command args for CLI tool (#194)
Browse files Browse the repository at this point in the history
* Update command descriptions to use singular form

Updated the description text in `BrowseColumnCommand.cs` and `BrowseRelationshipCommand.cs` to use the singular form of "column" and "relationship" for improved clarity and accuracy.
  • Loading branch information
albertospelta authored Jan 26, 2025
1 parent 0d21af5 commit 308b25c
Show file tree
Hide file tree
Showing 25 changed files with 377 additions and 348 deletions.
21 changes: 19 additions & 2 deletions src/Dax.Vpax.CLI/Commands/Browse/BrowseColumnCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Dax.Vpax.CLI.Commands.Package;
using static Dax.Vpax.CLI.Commands.Browse.BrowseColumnCommandOptions;

namespace Dax.Vpax.CLI.Commands.Browse;

Expand All @@ -7,9 +7,26 @@ internal sealed class BrowseColumnCommand : Command
public static BrowseColumnCommand Instance { get; } = new BrowseColumnCommand();

private BrowseColumnCommand()
: base(name: "column", description: "Display columns information")
: base(name: "column", description: "Display column information")
{
AddAlias("c");
AddOption(CommonOptions.VpaxOption);
AddOption(TableOption);
AddOption(CommonOptions.ExcludeHiddenOption);
AddOption(CommonOptions.OrderByOption);
AddOption(CommonOptions.TopOption);

Handler = new BrowseColumnCommandHandler();
}
}

internal static class BrowseColumnCommandOptions
{
public static readonly Option<string> TableOption = new(
name: "--table",
description: "Specify the table name"
)
{
ArgumentHelpName = "name"
};
}
113 changes: 72 additions & 41 deletions src/Dax.Vpax.CLI/Commands/Browse/BrowseColumnCommandHandler.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
namespace Dax.Vpax.CLI.Commands.Browse;
using static Dax.Vpax.CLI.Commands.Browse.BrowseColumnCommandOptions;

namespace Dax.Vpax.CLI.Commands.Browse;

internal sealed class BrowseColumnCommandHandler : CommandHandler
{
public override Task<int> InvokeAsync(InvocationContext context)
{
var model = GetCurrentModel(context);
if (model is null)
return Task.FromResult(context.ExitCode);
var vpax = context.ParseResult.GetValueForOption(CommonOptions.VpaxOption)!;

var model = GetModel(context, vpax);
if (model is not null)
{
AnsiConsole.Write(GetView(context, model));
}

AnsiConsole.Write(GetColumns(context, model));
return Task.FromResult(context.ExitCode);
}

private IRenderable GetColumns(InvocationContext context, Metadata.Model model)
private IRenderable GetView(InvocationContext context, Metadata.Model model)
{
var top = context.ParseResult.GetValueForOption(CommonOptions.TopOption);
var excludeHidden = context.ParseResult.GetValueForOption(CommonOptions.ExcludeHiddenOption);
var orderBy = context.ParseResult.GetValueForOption(CommonOptions.OrderByOption);
var top = context.ParseResult.GetValueForOption(CommonOptions.TopOption);
var table = context.ParseResult.GetValueForOption(TableOption);

var table = new Spectre.Console.Table().BorderColor(Color.Yellow)
var view = new Spectre.Console.Table().BorderColor(Color.Yellow)
.AddColumn(new TableColumn(new Markup("[yellow]Name[/]").Centered()).NoWrap())
.AddColumn(new TableColumn(new Markup("[yellow]Cardinality[/]").Centered()))
.AddColumn(new TableColumn(new Markup("[yellow]Size[/]").Centered()))
Expand All @@ -29,47 +35,72 @@ private IRenderable GetColumns(InvocationContext context, Metadata.Model model)
.AddColumn(new TableColumn(new Markup("[yellow]Encoding[/]").Centered()))
.AddColumn(new TableColumn(new Markup("[yellow]Data Type[/]").Centered()));

var query = model.Tables.SelectMany((t) => t.Columns).Where(c => !c.IsRowNumber);

query = orderBy switch
var totalSize = model.Tables.Sum((t) => t.TableSize);
var query = model.Tables.Where((t) => table is null || table.Equals(t.TableName.Name, StringComparison.OrdinalIgnoreCase)).SelectMany((t) => t.Columns).Where((c) => !c.IsRowNumber).Select((t) => new Row(t, totalSize));
if (orderBy.HasValue)
{
"name" or "n" => query.OrderBy((c) => c.ToDisplayName()),
"cardinality" or "c" => query.OrderByDescending((c) => c.ColumnCardinality),
"size" or "s" => query.OrderByDescending((c) => c.TotalSize),
_ => query
};

if (excludeHidden) query = query.Where((c) => !c.IsHidden);
query = orderBy switch
{
-1 => query.OrderByDescending(_ => _.Name),
+1 => query.OrderBy(_ => _.Name),
2 => query.OrderByDescending(_ => _.Cardinality),
3 => query.OrderByDescending(_ => _.Size),
4 => query.OrderByDescending(_ => _.SizePercentage),
5 => query.OrderByDescending(_ => _.DataSize),
6 => query.OrderByDescending(_ => _.DictionarySize),
7 => query.OrderByDescending(_ => _.HierarchiesSize),
-8 => query.OrderByDescending(_ => _.Encoding),
+8 => query.OrderBy(_ => _.Encoding),
-9 => query.OrderByDescending(_ => _.DataType),
+9 => query.OrderBy(_ => _.DataType),
_ => query.OrderByDescending(_ => 0), // ignore invalid order by
};
}
if (excludeHidden) query = query.Where((r) => !r.IsHidden);
if (top.HasValue) query = query.Take(top.Value);

var modelSize = model.Tables.Sum((t) => t.TableSize);
var columns = query.ToArray();

foreach (var c in columns)
var rows = query.ToArray();
foreach (var r in rows)
{
var style = c.IsHidden ? new Style(foreground: Color.Grey) : Style.Plain;
var sizePercentage = (double)c.TotalSize / modelSize;
var style = r.IsHidden ? new Style(foreground: Color.Grey) : Style.Plain;

table.AddRow(
new Text(c.ToDisplayName(), style).LeftJustified(),
new Text(c.ColumnCardinality.ToString("N0"), style).RightJustified(),
new Text(c.TotalSize.ToString("N0"), style).RightJustified(),
new Text(sizePercentage.ToString("P2"), style).RightJustified(),
new Text(c.DataSize.ToString("N0"), style).RightJustified(),
new Text(c.DictionarySize.ToString("N0"), style).RightJustified(),
new Text(c.HierarchiesSize.ToString("N0"), style).RightJustified(),
new Text(c.Encoding, style).RightJustified(),
new Text(c.DataType, style).RightJustified()
view.AddRow(
new Text(r.Name, style).LeftJustified(),
new Text(r.Cardinality.ToString("N0"), style).RightJustified(),
new Text(r.Size.ToString("N0"), style).RightJustified(),
new Text(r.SizePercentage.ToString("P2"), style).RightJustified(),
new Text(r.DataSize.ToString("N0"), style).RightJustified(),
new Text(r.DictionarySize.ToString("N0"), style).RightJustified(),
new Text(r.HierarchiesSize.ToString("N0"), style).RightJustified(),
new Text(r.Encoding, style).RightJustified(),
new Text(r.DataType, style).RightJustified()
);
}

table.Columns[0].Footer = new Markup($"[grey]{columns.Length:N0} items[/]").LeftJustified();
table.Columns[1].Footer = new Markup($"[grey]{columns.Sum(_ => _.ColumnCardinality):N0}[/]").RightJustified();
table.Columns[2].Footer = new Markup($"[grey]{columns.Sum(_ => _.TotalSize).ToSizeString():N0}[/]").RightJustified();
table.Columns[4].Footer = new Markup($"[grey]{columns.Sum(_ => _.DataSize).ToSizeString():N0}[/]").RightJustified();
table.Columns[5].Footer = new Markup($"[grey]{columns.Sum(_ => _.DictionarySize).ToSizeString():N0}[/]").RightJustified();
table.Columns[6].Footer = new Markup($"[grey]{columns.Sum(_ => _.HierarchiesSize).ToSizeString():N0}[/]").RightJustified();
view.Columns[0].Footer = new Markup($"[grey]{rows.Length:N0} items[/]").LeftJustified();
view.Columns[1].Footer = new Markup($"[grey]{rows.Sum(_ => _.Cardinality):N0}[/]").RightJustified();
view.Columns[2].Footer = new Markup($"[grey]{rows.Sum(_ => _.Size).ToSizeString():N0}[/]").RightJustified();
// table.Columns[3].Footer = // SizePercentage
view.Columns[4].Footer = new Markup($"[grey]{rows.Sum(_ => _.DataSize).ToSizeString():N0}[/]").RightJustified();
view.Columns[5].Footer = new Markup($"[grey]{rows.Sum(_ => _.DictionarySize).ToSizeString():N0}[/]").RightJustified();
view.Columns[6].Footer = new Markup($"[grey]{rows.Sum(_ => _.HierarchiesSize).ToSizeString():N0}[/]").RightJustified();
// table.Columns[7].Footer = // Encoding
// table.Columns[8].Footer = // DataType

return table;
return view;
}

private sealed record Row(Metadata.Column column, long totalSize)
{
public bool IsHidden => column.IsHidden;
public string Name => column.ToDisplayName();
public long Cardinality => column.ColumnCardinality;
public long Size => column.TotalSize;
public double SizePercentage => (double)column.TotalSize / totalSize;
public long DataSize => column.DataSize;
public long DictionarySize => column.DictionarySize;
public long HierarchiesSize => column.HierarchiesSize;
public string Encoding => column.Encoding;
public string DataType => column.DataType;
}
}
5 changes: 0 additions & 5 deletions src/Dax.Vpax.CLI/Commands/Browse/BrowseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,5 @@ private BrowseCommand()
AddCommand(BrowseTableCommand.Instance);
AddCommand(BrowseColumnCommand.Instance);
AddCommand(BrowseRelationshipCommand.Instance);

AddGlobalOption(Commands.CommonOptions.PathOption);
AddGlobalOption(CommonOptions.ExcludeHiddenOption);
AddGlobalOption(CommonOptions.OrderByOption);
AddGlobalOption(CommonOptions.TopOption);
}
}
2 changes: 2 additions & 0 deletions src/Dax.Vpax.CLI/Commands/Browse/BrowseModelCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ private BrowseModelCommand()
: base(name: "model", description: "Display tabular model information")
{
AddAlias("m");
AddOption(CommonOptions.VpaxOption);

Handler = new BrowseModelCommandHandler();
}
}
41 changes: 21 additions & 20 deletions src/Dax.Vpax.CLI/Commands/Browse/BrowseModelCommandHandler.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
using Spectre.Console;

namespace Dax.Vpax.CLI.Commands.Browse;
namespace Dax.Vpax.CLI.Commands.Browse;

internal sealed class BrowseModelCommandHandler : CommandHandler
{
public override Task<int> InvokeAsync(InvocationContext context)
{
var model = GetCurrentModel(context);
if (model is null)
return Task.FromResult(context.ExitCode);
var vpax = context.ParseResult.GetValueForOption(CommonOptions.VpaxOption)!;

var model = GetModel(context, vpax);
if (model is not null)
{
var grid = new Grid()
.AddColumns(1)
.AddRow(GetTableView(model))
.AddEmptyRow()
.AddRow(GetChartView(model));

var grid = new Grid()
.AddColumns(1)
.AddRow(GetProperties(model))
.AddEmptyRow()
.AddRow(GetSizeChart(model));
AnsiConsole.Write(new Panel(grid));
}

AnsiConsole.Write(new Panel(grid));
return Task.FromResult(context.ExitCode);
}

private IRenderable GetProperties(Metadata.Model model)
private IRenderable GetTableView(Metadata.Model model)
{
var table = new Spectre.Console.Table().HideHeaders().Expand().BorderColor(Color.Yellow)
.AddColumn("Name")
Expand All @@ -34,26 +35,26 @@ private IRenderable GetProperties(Metadata.Model model)
.AddRow("[yellow]Last Process[/]", model.LastProcessed.ToString("o", CultureInfo.InvariantCulture))
.AddRow("[yellow]Last Update[/]", model.LastUpdate.ToString("o", CultureInfo.InvariantCulture))
.AddRow("[yellow]Tables[/]", model.Tables.Count.ToString())
.AddRow("[yellow]Columns[/]", model.Tables.SelectMany((t) => t.Columns).Where(c => !c.IsRowNumber).Count().ToString())
.AddRow("[yellow]Columns[/]", model.Tables.SelectMany((t) => t.Columns).Count(c => !c.IsRowNumber).ToString())
.AddRow("[yellow]Size (in memory)[/]", model.Tables.Sum((t) => t.TableSize).ToSizeString());

return table;
}

private IRenderable GetSizeChart(Metadata.Model model)
private IRenderable GetChartView(Metadata.Model model)
{
var dataSize = model.Tables.Sum((t) => t.ColumnsDataSize);
var dictionariesSize = model.Tables.Sum((t) => t.ColumnsDictionarySize);
var dictionarySize = model.Tables.Sum((t) => t.ColumnsDictionarySize);
var hierarchiesSize = model.Tables.Sum((t) => t.ColumnsHierarchiesSize);
var totalSize = dataSize + dictionariesSize + hierarchiesSize;
var totalSize = dataSize + dictionarySize + hierarchiesSize;

var dataPercentage = Math.Floor((double)dataSize / totalSize * 100);
var dictionariePercentage = Math.Floor((double)dictionariesSize / totalSize * 100);
var hierarchiesPercentage = 100 - dataPercentage - dictionariePercentage;
var dictionaryPercentage = Math.Floor((double)dictionarySize / totalSize * 100);
var hierarchiesPercentage = 100 - dataPercentage - dictionaryPercentage;

var chart = new BreakdownChart().ShowPercentage().FullSize()
.AddItem("Data", dataPercentage, Color.Red)
.AddItem("Dictionary", dictionariePercentage, Color.Green)
.AddItem("Dictionary", dictionaryPercentage, Color.Green)
.AddItem("Hierarchy", hierarchiesPercentage, Color.Blue);

return chart;
Expand Down
11 changes: 7 additions & 4 deletions src/Dax.Vpax.CLI/Commands/Browse/BrowseRelationshipCommand.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using Dax.Vpax.CLI.Commands.Package;

namespace Dax.Vpax.CLI.Commands.Browse;
namespace Dax.Vpax.CLI.Commands.Browse;

internal sealed class BrowseRelationshipCommand : Command
{
public static BrowseRelationshipCommand Instance { get; } = new BrowseRelationshipCommand();

private BrowseRelationshipCommand()
: base(name: "relationship", description: "Display relationships information")
: base(name: "relationship", description: "Display relationship information")
{
AddAlias("r");
AddOption(CommonOptions.VpaxOption);
AddOption(CommonOptions.ExcludeHiddenOption);
AddOption(CommonOptions.OrderByOption);
AddOption(CommonOptions.TopOption);

Handler = new BrowseRelationshipCommandHandler();
}
}
Loading

0 comments on commit 308b25c

Please sign in to comment.