-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Update csproj set LangVersion 12, remove ImplicitUsings, add GolobalUsings.cs * Moved ExportCommand classes to new subfolder * Add `package` and `browse` commands * Update README.md
- Loading branch information
1 parent
b875465
commit 0d21af5
Showing
35 changed files
with
1,063 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
# editorconfig.org | ||
|
||
# top-most EditorConfig file | ||
root = true | ||
|
||
# Default settings: | ||
# A newline ending every file | ||
# Use 4 spaces as indentation | ||
[*] | ||
insert_final_newline = true | ||
indent_style = space | ||
indent_size = 4 | ||
trim_trailing_whitespace = true | ||
|
||
# Generated code | ||
[*{_AssemblyInfo.cs,.notsupported.cs,AsmOffsets.cs}] | ||
generated_code = true | ||
|
||
# C# files | ||
[*.cs] | ||
# New line preferences | ||
csharp_new_line_before_open_brace = all | ||
csharp_new_line_before_else = true | ||
csharp_new_line_before_catch = true | ||
csharp_new_line_before_finally = true | ||
csharp_new_line_before_members_in_object_initializers = true | ||
csharp_new_line_before_members_in_anonymous_types = true | ||
csharp_new_line_between_query_expression_clauses = true | ||
|
||
# Indentation preferences | ||
csharp_indent_block_contents = true | ||
csharp_indent_braces = false | ||
csharp_indent_case_contents = true | ||
csharp_indent_case_contents_when_block = true | ||
csharp_indent_switch_labels = true | ||
csharp_indent_labels = one_less_than_current | ||
|
||
# Modifier preferences | ||
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion | ||
|
||
# avoid this. unless absolutely necessary | ||
dotnet_style_qualification_for_field = false:suggestion | ||
dotnet_style_qualification_for_property = false:suggestion | ||
dotnet_style_qualification_for_method = false:suggestion | ||
dotnet_style_qualification_for_event = false:suggestion | ||
|
||
# Types: use keywords instead of BCL types, and always suggest var | ||
csharp_style_var_for_built_in_types = true:suggestion | ||
csharp_style_var_when_type_is_apparent = true:suggestion | ||
csharp_style_var_elsewhere = true:suggestion | ||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion | ||
dotnet_style_predefined_type_for_member_access = true:suggestion | ||
|
||
# name all constant fields using PascalCase | ||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion | ||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields | ||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style | ||
dotnet_naming_symbols.constant_fields.applicable_kinds = field | ||
dotnet_naming_symbols.constant_fields.required_modifiers = const | ||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case | ||
|
||
# static fields should have s_ prefix | ||
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion | ||
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields | ||
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style | ||
dotnet_naming_symbols.static_fields.applicable_kinds = field | ||
dotnet_naming_symbols.static_fields.required_modifiers = static | ||
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected | ||
dotnet_naming_style.static_prefix_style.required_prefix = s_ | ||
dotnet_naming_style.static_prefix_style.capitalization = camel_case | ||
|
||
# internal and private fields should be _camelCase | ||
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion | ||
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields | ||
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style | ||
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field | ||
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal | ||
dotnet_naming_style.camel_case_underscore_style.required_prefix = _ | ||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case | ||
|
||
# Code style defaults | ||
csharp_using_directive_placement = outside_namespace:suggestion | ||
dotnet_sort_system_directives_first = true | ||
csharp_prefer_braces = true:silent | ||
csharp_preserve_single_line_blocks = true:none | ||
csharp_preserve_single_line_statements = false:none | ||
csharp_prefer_static_local_function = true:suggestion | ||
csharp_prefer_simple_using_statement = false:none | ||
csharp_style_prefer_primary_constructors = false:none | ||
csharp_style_prefer_switch_expression = true:suggestion | ||
dotnet_style_readonly_field = true:suggestion | ||
|
||
# Expression-level preferences | ||
dotnet_style_object_initializer = true:suggestion | ||
dotnet_style_collection_initializer = true:suggestion | ||
dotnet_style_explicit_tuple_names = true:suggestion | ||
dotnet_style_coalesce_expression = true:suggestion | ||
dotnet_style_null_propagation = true:suggestion | ||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion | ||
dotnet_style_prefer_inferred_tuple_names = true:suggestion | ||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion | ||
dotnet_style_prefer_auto_properties = true:suggestion | ||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent | ||
dotnet_style_prefer_conditional_expression_over_return = true:silent | ||
csharp_prefer_simple_default_expression = true:suggestion | ||
|
||
# Expression-bodied members | ||
csharp_style_expression_bodied_methods = true:silent | ||
csharp_style_expression_bodied_constructors = true:silent | ||
csharp_style_expression_bodied_operators = true:silent | ||
csharp_style_expression_bodied_properties = true:silent | ||
csharp_style_expression_bodied_indexers = true:silent | ||
csharp_style_expression_bodied_accessors = true:silent | ||
csharp_style_expression_bodied_lambdas = true:silent | ||
csharp_style_expression_bodied_local_functions = true:silent | ||
|
||
# Pattern matching | ||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion | ||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion | ||
csharp_style_inlined_variable_declaration = true:suggestion | ||
|
||
# Null checking preferences | ||
csharp_style_throw_expression = true:suggestion | ||
csharp_style_conditional_delegate_call = true:suggestion | ||
|
||
# Other features | ||
csharp_style_prefer_index_operator = false:none | ||
csharp_style_prefer_range_operator = false:none | ||
csharp_style_pattern_local_over_anonymous_function = false:none | ||
|
||
# Space preferences | ||
csharp_space_after_cast = false | ||
csharp_space_after_colon_in_inheritance_clause = true | ||
csharp_space_after_comma = true | ||
csharp_space_after_dot = false | ||
csharp_space_after_keywords_in_control_flow_statements = true | ||
csharp_space_after_semicolon_in_for_statement = true | ||
csharp_space_around_binary_operators = before_and_after | ||
csharp_space_around_declaration_statements = do_not_ignore | ||
csharp_space_before_colon_in_inheritance_clause = true | ||
csharp_space_before_comma = false | ||
csharp_space_before_dot = false | ||
csharp_space_before_open_square_brackets = false | ||
csharp_space_before_semicolon_in_for_statement = false | ||
csharp_space_between_empty_square_brackets = false | ||
csharp_space_between_method_call_empty_parameter_list_parentheses = false | ||
csharp_space_between_method_call_name_and_opening_parenthesis = false | ||
csharp_space_between_method_call_parameter_list_parentheses = false | ||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false | ||
csharp_space_between_method_declaration_name_and_open_parenthesis = false | ||
csharp_space_between_method_declaration_parameter_list_parentheses = false | ||
csharp_space_between_parentheses = false | ||
csharp_space_between_square_brackets = false | ||
|
||
# License header | ||
# file_header_template = | ||
|
||
# C++ Files | ||
[*.{cpp,h,in}] | ||
curly_bracket_next_line = true | ||
indent_brace_style = Allman | ||
|
||
# Xml project files | ||
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] | ||
indent_size = 2 | ||
|
||
[*.{csproj,vbproj,proj,nativeproj,locproj}] | ||
charset = utf-8 | ||
|
||
# Xml build files | ||
[*.builds] | ||
indent_size = 2 | ||
|
||
# Xml files | ||
[*.{xml,stylecop,resx,ruleset}] | ||
indent_size = 2 | ||
|
||
# Xml config files | ||
[*.{props,targets,config,nuspec}] | ||
indent_size = 2 | ||
|
||
# YAML config files | ||
[*.{yml,yaml}] | ||
indent_size = 2 | ||
|
||
# Shell scripts | ||
[*.sh] | ||
end_of_line = lf | ||
[*.{cmd,bat}] | ||
end_of_line = crlf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using Dax.Vpax.CLI.Commands.Package; | ||
|
||
namespace Dax.Vpax.CLI.Commands.Browse; | ||
|
||
internal sealed class BrowseColumnCommand : Command | ||
{ | ||
public static BrowseColumnCommand Instance { get; } = new BrowseColumnCommand(); | ||
|
||
private BrowseColumnCommand() | ||
: base(name: "column", description: "Display columns information") | ||
{ | ||
AddAlias("c"); | ||
Handler = new BrowseColumnCommandHandler(); | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
src/Dax.Vpax.CLI/Commands/Browse/BrowseColumnCommandHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
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); | ||
|
||
AnsiConsole.Write(GetColumns(context, model)); | ||
return Task.FromResult(context.ExitCode); | ||
} | ||
|
||
private IRenderable GetColumns(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 table = 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())) | ||
.AddColumn(new TableColumn(new Markup("[yellow]Size %[/]").Centered())) | ||
.AddColumn(new TableColumn(new Markup("[yellow]Data Size[/]").Centered())) | ||
.AddColumn(new TableColumn(new Markup("[yellow]Dictionary Size[/]").Centered())) | ||
.AddColumn(new TableColumn(new Markup("[yellow]Hierarchies Size[/]").Centered())) | ||
.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 | ||
{ | ||
"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); | ||
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 style = c.IsHidden ? new Style(foreground: Color.Grey) : Style.Plain; | ||
var sizePercentage = (double)c.TotalSize / modelSize; | ||
|
||
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() | ||
); | ||
} | ||
|
||
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(); | ||
|
||
return table; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
namespace Dax.Vpax.CLI.Commands.Browse; | ||
|
||
internal sealed class BrowseCommand : Command | ||
{ | ||
public static BrowseCommand Instance { get; } = new BrowseCommand(); | ||
|
||
private BrowseCommand() | ||
: base(name: "browse", description: "(Experimental) Browse metadata of a tabular model in a VPAX package file") | ||
{ | ||
AddCommand(BrowseModelCommand.Instance); | ||
AddCommand(BrowseTableCommand.Instance); | ||
AddCommand(BrowseColumnCommand.Instance); | ||
AddCommand(BrowseRelationshipCommand.Instance); | ||
|
||
AddGlobalOption(Commands.CommonOptions.PathOption); | ||
AddGlobalOption(CommonOptions.ExcludeHiddenOption); | ||
AddGlobalOption(CommonOptions.OrderByOption); | ||
AddGlobalOption(CommonOptions.TopOption); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace Dax.Vpax.CLI.Commands.Browse; | ||
|
||
internal sealed class BrowseModelCommand : Command | ||
{ | ||
public static BrowseModelCommand Instance { get; } = new BrowseModelCommand(); | ||
|
||
private BrowseModelCommand() | ||
: base(name: "model", description: "Display tabular model information") | ||
{ | ||
AddAlias("m"); | ||
Handler = new BrowseModelCommandHandler(); | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
src/Dax.Vpax.CLI/Commands/Browse/BrowseModelCommandHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using Spectre.Console; | ||
|
||
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 grid = new Grid() | ||
.AddColumns(1) | ||
.AddRow(GetProperties(model)) | ||
.AddEmptyRow() | ||
.AddRow(GetSizeChart(model)); | ||
|
||
AnsiConsole.Write(new Panel(grid)); | ||
return Task.FromResult(context.ExitCode); | ||
} | ||
|
||
private IRenderable GetProperties(Metadata.Model model) | ||
{ | ||
var table = new Spectre.Console.Table().HideHeaders().Expand().BorderColor(Color.Yellow) | ||
.AddColumn("Name") | ||
.AddColumn("Value") | ||
.AddRow("[yellow]Model[/]", model.ModelName.Name) | ||
.AddRow("[yellow]Compatibility Level[/]", model.CompatibilityLevel.ToString()) | ||
.AddRow("[yellow]Compatibility Mode[/]", model.CompatibilityMode.ToEmptyIfNull()) | ||
.AddRow("[yellow]Version[/]", model.Version.ToString()) | ||
.AddRow("[yellow]Culture[/]", model.Culture.ToEmptyIfNull()) | ||
.AddRow("[yellow]Last Refresh[/]", model.LastDataRefresh.ToString("o", CultureInfo.InvariantCulture)) | ||
.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]Size (in memory)[/]", model.Tables.Sum((t) => t.TableSize).ToSizeString()); | ||
|
||
return table; | ||
} | ||
|
||
private IRenderable GetSizeChart(Metadata.Model model) | ||
{ | ||
var dataSize = model.Tables.Sum((t) => t.ColumnsDataSize); | ||
var dictionariesSize = model.Tables.Sum((t) => t.ColumnsDictionarySize); | ||
var hierarchiesSize = model.Tables.Sum((t) => t.ColumnsHierarchiesSize); | ||
var totalSize = dataSize + dictionariesSize + hierarchiesSize; | ||
|
||
var dataPercentage = Math.Floor((double)dataSize / totalSize * 100); | ||
var dictionariePercentage = Math.Floor((double)dictionariesSize / totalSize * 100); | ||
var hierarchiesPercentage = 100 - dataPercentage - dictionariePercentage; | ||
|
||
var chart = new BreakdownChart().ShowPercentage().FullSize() | ||
.AddItem("Data", dataPercentage, Color.Red) | ||
.AddItem("Dictionary", dictionariePercentage, Color.Green) | ||
.AddItem("Hierarchy", hierarchiesPercentage, Color.Blue); | ||
|
||
return chart; | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/Dax.Vpax.CLI/Commands/Browse/BrowseRelationshipCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using Dax.Vpax.CLI.Commands.Package; | ||
|
||
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") | ||
{ | ||
AddAlias("r"); | ||
Handler = new BrowseRelationshipCommandHandler(); | ||
} | ||
} |
Oops, something went wrong.