diff --git a/ConsoleGuiTools.Common.props b/ConsoleGuiTools.Common.props index 390d688..92fc67c 100644 --- a/ConsoleGuiTools.Common.props +++ b/ConsoleGuiTools.Common.props @@ -1,6 +1,6 @@ - 0.7.7 + 0.8.0 Microsoft © Microsoft Corporation. diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs index e4385e1..99aead4 100644 --- a/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs @@ -6,14 +6,14 @@ using System.Diagnostics; using System.Linq; using System.Reflection; -using System.Text; -using OutGridView.Models; +using Microsoft.PowerShell.ConsoleGuiTools.Models; using Terminal.Gui; -namespace OutGridView.Cmdlet +namespace Microsoft.PowerShell.ConsoleGuiTools { + internal sealed class ConsoleGui : IDisposable { private const string FILTER_LABEL = "Filter"; @@ -32,41 +32,39 @@ internal sealed class ConsoleGui : IDisposable private GridViewDataSource _inputSource; // _listViewSource is a filtered copy of _inputSource that ListView.Source is set to. - // Changes to IsMarked are propogated back to _inputSource. + // Changes to IsMarked are propagated back to _inputSource. private GridViewDataSource _listViewSource; private ApplicationData _applicationData; - private GridViewDetails _gridViewDetails; - public HashSet Start(ApplicationData applicationData) + public IEnumerable Start(ApplicationData applicationData) { _applicationData = applicationData; // Note, in Terminal.Gui v2, this property is renamed to Application.UseNetDriver, hence // using that terminology here. Application.UseSystemConsole = _applicationData.UseNetDriver; Application.Init(); - _gridViewDetails = new GridViewDetails - { + + var (gridViewHeader, gridViewDataSource) = GridViewHelpers.CreateGridViewInputs( // If OutputMode is Single or Multiple, then we make items selectable. If we make them selectable, // 2 columns are required for the check/selection indicator and space. - ListViewOffset = _applicationData.OutputMode != OutputModeOption.None ? MARGIN_LEFT + CHECK_WIDTH : MARGIN_LEFT - }; + listViewOffset: _applicationData.OutputMode != OutputModeOption.None ? MARGIN_LEFT + CHECK_WIDTH : MARGIN_LEFT, + applicationData: _applicationData, + properties: _applicationData.Properties, + leftMargin: MARGIN_LEFT + ); Window win = CreateTopLevelWindow(); - // Create the headers and calculate column widths based on the DataTable - List gridHeaders = _applicationData.DataTable.DataColumns.Select((c) => c.Label).ToList(); - CalculateColumnWidths(gridHeaders); - // Copy the input DataTable into our master ListView source list; upon exit any items // that are IsMarked are returned (if Outputmode is set) - _inputSource = LoadData(); + _inputSource = gridViewDataSource; if (!_applicationData.MinUI) { // Add Filter UI AddFilter(win); // Add Header UI - AddHeaders(win, gridHeaders); + AddHeaders(win, gridViewHeader); } // Add ListView @@ -76,8 +74,8 @@ public HashSet Start(ApplicationData applicationData) AddStatusBar(!_applicationData.MinUI); // We *always* apply a filter, even if the -Filter parameter is not set or Filtering is not - // available. The ListView always shows a fitlered version of _inputSource even if there is no - // actual fitler. + // available. The ListView always shows a filtered version of _inputSource even if there is no + // actual filter. ApplyFilter(); _listView.SetFocus(); @@ -86,52 +84,16 @@ public HashSet Start(ApplicationData applicationData) Application.Run(); Application.Shutdown(); - // Return results of selection if required. - HashSet selectedIndexes = new HashSet(); + // Return results of selection if required. if (_cancelled) { - return selectedIndexes; + return Enumerable.Empty(); } // Return any items that were selected. - foreach (GridViewRow gvr in _inputSource.GridViewRowList) - { - if (gvr.IsMarked) - { - selectedIndexes.Add(gvr.OriginalIndex); - } - } - - return selectedIndexes; - } - - private GridViewDataSource LoadData() - { - var items = new List(); - int newIndex = 0; - for (int i = 0; i < _applicationData.DataTable.Data.Count; i++) - { - var dataTableRow = _applicationData.DataTable.Data[i]; - var valueList = new List(); - foreach (var dataTableColumn in _applicationData.DataTable.DataColumns) - { - string dataValue = dataTableRow.Values[dataTableColumn.ToString()].DisplayValue; - valueList.Add(dataValue); - } - - string displayString = GridViewHelpers.GetPaddedString(valueList, 0, _gridViewDetails.ListViewColumnWidths); - - items.Add(new GridViewRow - { - DisplayString = displayString, - // We use this to keep _inputSource up to date when a filter is applied - OriginalIndex = i - }); - - newIndex++; - } - - return new GridViewDataSource(items); + return _inputSource.GridViewRowList + .Where(gvr => gvr.IsMarked) + .Select(gvr => gvr.OriginalIndex); } private void ApplyFilter() @@ -249,57 +211,12 @@ private void AddStatusBar(bool visible) $"{Application.Driver} v{FileVersionInfo.GetVersionInfo(Assembly.GetAssembly(typeof(Application)).Location).ProductVersion}", null)); } - var statusBar = new StatusBar(statusItems.ToArray()); - statusBar.Visible = visible; - Application.Top.Add(statusBar); - } - - private void CalculateColumnWidths(List gridHeaders) - { - _gridViewDetails.ListViewColumnWidths = new int[gridHeaders.Count]; - var listViewColumnWidths = _gridViewDetails.ListViewColumnWidths; - - for (int i = 0; i < gridHeaders.Count; i++) - { - listViewColumnWidths[i] = gridHeaders[i].Length; - } - - // calculate the width of each column based on longest string in each column for each row - foreach (var row in _applicationData.DataTable.Data) - { - int index = 0; - - // use half of the visible buffer height for the number of objects to inspect to calculate widths - foreach (var col in row.Values.Take(Application.Top.Frame.Height / 2)) - { - var len = col.Value.DisplayValue.Length; - if (len > listViewColumnWidths[index]) - { - listViewColumnWidths[index] = len; - } - index++; - } - } - - // if the total width is wider than the usable width, remove 1 from widest column until it fits - _gridViewDetails.UsableWidth = Application.Top.Frame.Width - MARGIN_LEFT - listViewColumnWidths.Length - _gridViewDetails.ListViewOffset; - int columnWidthsSum = listViewColumnWidths.Sum(); - while (columnWidthsSum >= _gridViewDetails.UsableWidth) + var statusBar = new StatusBar(statusItems.ToArray()) { - int maxWidth = 0; - int maxIndex = 0; - for (int i = 0; i < listViewColumnWidths.Length; i++) - { - if (listViewColumnWidths[i] > maxWidth) - { - maxWidth = listViewColumnWidths[i]; - maxIndex = i; - } - } + Visible = visible + }; - listViewColumnWidths[maxIndex]--; - columnWidthsSum--; - } + Application.Top.Add(statusBar); } private void AddFilter(Window win) @@ -360,47 +277,28 @@ private void AddFilter(Window win) _filterField.CursorPosition = _filterField.Text.Length; } - private void AddHeaders(Window win, List gridHeaders) + private void AddHeaders(Window win, GridViewHeader gridViewHeader) { - var header = new Label(GridViewHelpers.GetPaddedString( - gridHeaders, - _gridViewDetails.ListViewOffset, - _gridViewDetails.ListViewColumnWidths)); - header.X = 0; - if (_applicationData.MinUI) + var header = new Label(gridViewHeader.HeaderText) { - header.Y = 0; - } - else - { - header.Y = 2; - } + X = 0, + Y = _applicationData.MinUI ? 0 : 2 + }; + win.Add(header); - // This renders dashes under the header to make it more clear what is header and what is data - var headerLineText = new StringBuilder(); - foreach (char c in header.Text) + if (_applicationData.MinUI) { - if (c.Equals(' ')) - { - headerLineText.Append(' '); - } - else - { - // When gui.cs supports text decorations, should replace this with just underlining the header - headerLineText.Append('-'); - } + return; } - if (!_applicationData.MinUI) + var headerLine = new Label(gridViewHeader.HeaderUnderLine) { - var headerLine = new Label(headerLineText.ToString()) - { - X = 0, - Y = Pos.Bottom(header) - }; - win.Add(headerLine); - } + X = 0, + Y = Pos.Bottom(header) + }; + + win.Add(headerLine); } private void AddListView(Window win) diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/FormatHelper.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/FormatHelper.cs new file mode 100644 index 0000000..706e254 --- /dev/null +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/FormatHelper.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.PowerShell.ConsoleGuiTools; + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Data; +using System.Linq; +using System.Management.Automation; +using Microsoft.PowerShell.ConsoleGuiTools.Models; + +/// +/// Helper class for formatting objects passed pipeline object into text. +/// +internal static class FormatHelper +{ + /// + /// Formats the output of a command as a table with the selected properties of the object in each column. + /// The object type determines the default layout and properties that are displayed in each column. + /// You can use the Property parameter to select the properties that you want to display. + /// + /// Collection of + /// Specifies the object properties that appear in the display and the order in which they appear. + /// Type one or more property names, separated by commas, or use a hash table to display a calculated property. + /// Wildcards are permitted. + /// data transfer object that contains header and rows in string. + /// + /// Format-Table Powershell command is used to format the inputs objects as a table. + /// + internal static Table FormatTable(IReadOnlyList inputs, bool force, object[] properties = null) + { + if (inputs.Count == 0) + { + return Table.Empty; + } + + using var ps = PowerShell.Create(RunspaceMode.CurrentRunspace); + ps.AddCommand("Format-Table"); + ps.AddParameter("AutoSize"); + + if (properties != null) + { + ps.AddParameter("Property", properties); + } + + if (force == true) + { + ps.AddParameter("Force"); + } + + ps.AddParameter("InputObject", inputs); + + // Format-Table's output objects are internal to Powershell, + // we cannot use them here, so we need to convert it to a string as workaround. + ps.AddCommand("Out-String"); + + var results = ps.Invoke(); + var text = results.FirstOrDefault()?.BaseObject.ToString(); + + var lines = text.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries) + .Where(line => string.IsNullOrEmpty(line) == false).ToList(); + + /* + * Format-Table sometimes outputs a label on the top based on input's data type. + * We need to detect and skip the label and extract only header and rows. + * Strategy is to detect the index of the line under the header with dashes and spaces ('---- -- --- '). + */ + + static bool isHeaderLine(string text) => text.Contains('-') && text.All(c => c == '-' || c == ' '); + + var headerLineIndex = lines.FindIndex(isHeaderLine); + + if (headerLineIndex == -1) + { + // unexpected result, return the whole text + headerLineIndex = 1; + } + + return new Table + { + Header = lines.Skip(headerLineIndex - 1).FirstOrDefault(), + HeaderLine = lines.Skip(headerLineIndex).FirstOrDefault(), + Rows = lines.Skip(headerLineIndex + 1) + }; + } +} diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDataSource.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDataSource.cs index 4d6724a..7a43a05 100644 --- a/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDataSource.cs +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDataSource.cs @@ -4,30 +4,33 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; + +using Microsoft.PowerShell.ConsoleGuiTools.Models; using NStack; using Terminal.Gui; -namespace OutGridView.Cmdlet +namespace Microsoft.PowerShell.ConsoleGuiTools { internal sealed class GridViewDataSource : IListDataSource { - public List GridViewRowList { get; set; } + internal List GridViewRowList { get; init; } public int Count => GridViewRowList.Count; - public GridViewDataSource(List itemList) + public int Length { get; } + + public GridViewDataSource(IEnumerable gridViewRowList) { - GridViewRowList = itemList; + this.GridViewRowList = gridViewRowList.ToList(); } - public int Length { get; } - public void Render(ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start) { container.Move(col, line); - RenderUstr(driver, GridViewRowList[item].DisplayString, col, line, width); + RenderUstr(driver, GridViewRowList[item].DisplayString, width); } public bool IsMarked(int item) => GridViewRowList[item].IsMarked; @@ -59,7 +62,7 @@ public IList ToList() } // A slightly adapted method from gui.cs: https://github.com/migueldeicaza/gui.cs/blob/fc1faba7452ccbdf49028ac49f0c9f0f42bbae91/Terminal.Gui/Views/ListView.cs#L433-L461 - private static void RenderUstr(ConsoleDriver driver, ustring ustr, int col, int line, int width) + private static void RenderUstr(ConsoleDriver driver, ustring ustr, int width) { int used = 0; int index = 0; diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDetails.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDetails.cs deleted file mode 100644 index 7c660f9..0000000 --- a/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDetails.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace OutGridView.Cmdlet -{ - internal sealed class GridViewDetails - { - // Contains the width of each column in the grid view. - public int[] ListViewColumnWidths { get; set; } - - // Dictates where the header should actually start considering - // some offset is needed to factor in the checkboxes - public int ListViewOffset { get; set; } - - // The width that is actually useable on the screen after - // subtracting space needed for a clean UI (spaces between columns, etc). - public int UsableWidth { get; set; } - } -} diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewHelpers.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewHelpers.cs index 482fe1d..6eb8ac4 100644 --- a/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewHelpers.cs +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewHelpers.cs @@ -2,17 +2,20 @@ // Licensed under the MIT License. using System.Collections.Generic; +using System.Data; using System.Linq; -using System.Text; using System.Text.RegularExpressions; -namespace OutGridView.Cmdlet +using Microsoft.PowerShell.ConsoleGuiTools.Models; + +namespace Microsoft.PowerShell.ConsoleGuiTools { - internal sealed class GridViewHelpers + + internal static class GridViewHelpers { // Add all items already selected plus any that match the filter // The selected items should be at the top of the list, in their original order - public static List FilterData(List listToFilter, string filter) + internal static List FilterData(List listToFilter, string filter) { var filteredList = new List(); if (string.IsNullOrEmpty(filter)) @@ -26,41 +29,34 @@ public static List FilterData(List listToFilter, strin return filteredList; } - public static string GetPaddedString(List strings, int offset, int[] listViewColumnWidths) + /// + /// Creates the header and data source for the GridView. + /// + /// Dictates where the header should actually start considering + /// some offset is needed to factor in the checkboxes + /// + /// + /// Dictates where the header should actually start considering some offset is needed to factor in the checkboxes + /// and from commandlet inputs. + internal static (GridViewHeader Header, GridViewDataSource DataSource) CreateGridViewInputs(int listViewOffset, int leftMargin, ApplicationData applicationData, object[] properties) { - var builder = new StringBuilder(); - if (offset > 0) - { - builder.Append(string.Empty.PadRight(offset)); - } + var table = FormatHelper.FormatTable(applicationData.Input, applicationData.Force, properties); - for (int i = 0; i < strings.Count; i++) + var gridViewHeader = new GridViewHeader { - if (i > 0) - { - // Add a space between columns - builder.Append(' '); - } + HeaderText = string.Concat(new string(' ', listViewOffset), table.Header), + HeaderUnderLine = string.Concat(new string(' ', listViewOffset), table.HeaderLine) + }; - // Replace any newlines with encoded newline/linefeed (`n or `r) - // Note we can't use Environment.Newline because we don't know that the - // Command honors that. - strings[i] = strings[i].Replace("\r", "`r"); - strings[i] = strings[i].Replace("\n", "`n"); - - // If the string won't fit in the column, append an ellipsis. - if (strings[i].Length > listViewColumnWidths[i]) - { - builder.Append(strings[i], 0, listViewColumnWidths[i] - 3); - builder.Append("..."); - } - else - { - builder.Append(strings[i].PadRight(listViewColumnWidths[i])); - } - } + var gridViewDataSource = new GridViewDataSource(table.Rows.Select((line, index) => new GridViewRow + { + DisplayString = line, + OriginalIndex = index + })); - return builder.ToString(); + return ( + gridViewHeader, + gridViewDataSource); } } } diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewRow.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewRow.cs deleted file mode 100644 index 2ecc80e..0000000 --- a/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewRow.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace OutGridView.Cmdlet -{ - public class GridViewRow - { - public string DisplayString { get; set; } - public bool IsMarked { get; set; } - public int OriginalIndex { get; set; } - public override string ToString() => DisplayString; - } -} diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.csproj b/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.csproj index da77cf2..50ccabc 100644 --- a/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.csproj +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -11,6 +11,7 @@ - Add ';https://api.nuget.org/v3/index.json' to the end of the RestoreSources property group below - Uncomment the RestoreSources property group below --> + diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.psd1 b/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.psd1 index 80c0fe8..b6602c3 100644 --- a/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.psd1 +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.psd1 @@ -9,7 +9,7 @@ RootModule = 'Microsoft.PowerShell.ConsoleGuiTools.dll' # Version number of this module. -ModuleVersion = '0.7.7' +ModuleVersion = '0.8.0' # Supported PSEditions CompatiblePSEditions = @( 'Core' ) diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/Models/ApplicationData.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/ApplicationData.cs new file mode 100644 index 0000000..73647ae --- /dev/null +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/ApplicationData.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.PowerShell.ConsoleGuiTools.Models +{ + + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Management.Automation; + + internal class ApplicationData + { + public string Title { get; set; } + public OutputModeOption OutputMode { get; set; } + public bool PassThru { get; set; } + public string Filter { get; set; } + public bool MinUI { get; set; } + + public bool UseNetDriver { get; set; } + public bool Verbose { get; set; } + public bool Debug { get; set; } + + public string ModuleVersion { get; set; } + + /// + /// Get's the objects from the pipeline. + /// + public IReadOnlyList Input { get; init; } + + /// + /// Gets the Properties parameter. + /// + public object[] Properties { get; init; } + + /// + /// Gets the Force parameter. + /// + public bool Force { get; init; } + } +} \ No newline at end of file diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/Models/GridViewHeader.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/GridViewHeader.cs new file mode 100644 index 0000000..da9c4de --- /dev/null +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/GridViewHeader.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.PowerShell.ConsoleGuiTools.Models; + +internal sealed class GridViewHeader +{ + internal string HeaderText { get; init; } + + internal string HeaderUnderLine { get; init; } +} diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/Models/GridViewRow.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/GridViewRow.cs new file mode 100644 index 0000000..f7e0dcc --- /dev/null +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/GridViewRow.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.PowerShell.ConsoleGuiTools.Models; + +public class GridViewRow +{ + public string DisplayString { get; set; } + public bool IsMarked { get; set; } + public int OriginalIndex { get; set; } + public override string ToString() => DisplayString; +} diff --git a/src/Microsoft.PowerShell.OutGridView.Models/OutputModeOptions.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/OutputModeOptions.cs similarity index 92% rename from src/Microsoft.PowerShell.OutGridView.Models/OutputModeOptions.cs rename to src/Microsoft.PowerShell.ConsoleGuiTools/Models/OutputModeOptions.cs index 3170c98..201683e 100644 --- a/src/Microsoft.PowerShell.OutGridView.Models/OutputModeOptions.cs +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/OutputModeOptions.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -namespace OutGridView.Models +namespace Microsoft.PowerShell.ConsoleGuiTools.Models { public enum OutputModeOption { diff --git a/src/Microsoft.PowerShell.OutGridView.Models/Serializers.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/Serializers.cs similarity index 92% rename from src/Microsoft.PowerShell.OutGridView.Models/Serializers.cs rename to src/Microsoft.PowerShell.ConsoleGuiTools/Models/Serializers.cs index 6165c23..fb2623e 100644 --- a/src/Microsoft.PowerShell.OutGridView.Models/Serializers.cs +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/Serializers.cs @@ -4,17 +4,18 @@ using Newtonsoft.Json; using System; using System.Text; -using System.Collections.Generic; -//TODO: swich to JSON.NET +//TODO: switch to JSON.NET -namespace OutGridView.Models +namespace Microsoft.PowerShell.ConsoleGuiTools.Models { + public class Serializers { private readonly static JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + public static string ObjectToJson(T obj) { var jsonString = JsonConvert.SerializeObject(obj, jsonSerializerSettings); @@ -29,7 +30,6 @@ public static T ObjectFromJson(string base64Json) return JsonConvert.DeserializeObject(jsonString, jsonSerializerSettings); } - private static string FromBase64String(string base64string) { return Encoding.UTF8.GetString(Convert.FromBase64String(base64string)); diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/Models/Table.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/Table.cs new file mode 100644 index 0000000..4a73813 --- /dev/null +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/Models/Table.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.PowerShell.ConsoleGuiTools.Models; + +using System.Collections.Generic; +using System.Linq; + +/// +/// Data transfer object containing the formatted table data. +/// +internal class Table +{ + /// + /// Represents an empty table. + /// + internal static Table Empty { get; } = new Table + { + Header = string.Empty, + HeaderLine = string.Empty, + Rows = Enumerable.Empty() + }; + + /// + /// Gets the header of the table with labels for each column in a line. + /// + internal string Header { get; init; } + + /// + /// Gets the line under the header with dashes and spaces ('---- -- --- '). + /// + internal string HeaderLine { get; init; } + + /// + /// Gets the rows of the table. + /// + internal IEnumerable Rows { get; init; } +} diff --git a/src/Microsoft.PowerShell.ConsoleGuiTools/OutConsoleGridviewCmdletCommand.cs b/src/Microsoft.PowerShell.ConsoleGuiTools/OutConsoleGridviewCmdletCommand.cs index 94bb7e1..4d7439d 100644 --- a/src/Microsoft.PowerShell.ConsoleGuiTools/OutConsoleGridviewCmdletCommand.cs +++ b/src/Microsoft.PowerShell.ConsoleGuiTools/OutConsoleGridviewCmdletCommand.cs @@ -6,11 +6,12 @@ using System.Collections.Generic; using System.Management.Automation; using System.Management.Automation.Internal; +using System.Reflection.Metadata; +using Microsoft.PowerShell.ConsoleGuiTools.Models; -using OutGridView.Models; - -namespace OutGridView.Cmdlet +namespace Microsoft.PowerShell.ConsoleGuiTools { + [Cmdlet(VerbsData.Out, "ConsoleGridView")] [Alias("ocgv")] public class OutConsoleGridViewCmdletCommand : PSCmdlet, IDisposable @@ -27,6 +28,50 @@ public class OutConsoleGridViewCmdletCommand : PSCmdlet, IDisposable #region Input Parameters + /// + /// Positional parameter for properties, property sets and table sets + /// specified on the command line. + /// The parameter is optional, since the defaults + /// will be determined using property sets, etc. + /// + /// + /// This parameter will be passed to Format-Table command. + /// Help message is copied from Format-Table documentation. + /// + [Parameter(Position = 0, + HelpMessage = @"Specifies the object properties that appear in the display and the order in which they appear. Type one or more property names, separated by commas, or use a hash table to display a calculated property. Wildcards are permitted. + +If you omit this parameter, the properties that appear in the display depend on the first object's properties. For example, if the first object has PropertyA and PropertyB but subsequent objects have PropertyA, PropertyB, and PropertyC, then only the PropertyA and PropertyB headers are displayed. + +The value of the Property parameter can be a new calculated property. The calculated property can be a script block or a hash table.Valid key-value pairs are: + + - Name (or Label) - + - Expression - or