Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,12 @@ public SwitchParameter AutoSize
}
private Nullable<bool> _autosize = null;

/// <summary>
/// Gets or sets if header is repeated per screen.
/// </summary>
[Parameter]
public SwitchParameter RepeatHeader { get; set; }
Comment thread
SteveL-MSFT marked this conversation as resolved.

/// <summary>
/// optional, non positional parameter
/// </summary>
Expand Down Expand Up @@ -809,6 +815,11 @@ internal override FormattingCommandLineParameters GetCommandLineParameters()
if (_autosize.HasValue)
parameters.autosize = _autosize.Value;

if (RepeatHeader)
{
parameters.repeatHeader = true;
}

parameters.groupByParameter = this.ProcessGroupByParameter();

TableSpecificParameters tableParameters = new TableSpecificParameters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ internal sealed class FormattingCommandLineParameters
/// </summary>
internal Nullable<bool> autosize = null;

/// <summary>
/// If true, the header for a table is repeated after each screen full
/// of content.
/// </summary>
internal bool repeatHeader = false;

/// <summary>
/// errors are shown as out of band messages
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ private enum FormattingState
private enum PreprocessingState { raw, processed, error }

private const int DefaultConsoleWidth = 120;
private const int DefaultConsoleHeight = int.MaxValue;
internal const int StackAllocThreshold = 120;

/// <summary>
Expand Down Expand Up @@ -743,20 +744,14 @@ private void ProcessCachedGroupOnWide(WideViewHeaderInfo wvhi, List<PacketInfoDa
_formattingHint = hint;
}

/// <summary>
/// In cases like implicit remoting, there is no console so reading the console width results in an exception.
/// Instead of handling exception every time we cache this value to increase performance.
/// </summary>
static private bool _noConsole = false;

/// <summary>
/// Tables and Wides need to use spaces for padding to maintain table look even if console window is resized.
/// For all other output, we use int.MaxValue if the user didn't explicitly specify a width.
/// If we detect that int.MaxValue is used, first we try to get the current console window width.
/// However, if we can't read that (for example, implicit remoting has no console window), we default
/// to something reasonable: 120 columns.
/// </summary>
static private int GetConsoleWindowWidth(int columnNumber)
private static int GetConsoleWindowWidth(int columnNumber)
{
if (InternalTestHooks.SetConsoleWidthToZero)
{
Expand All @@ -765,10 +760,6 @@ static private int GetConsoleWindowWidth(int columnNumber)

if (columnNumber == int.MaxValue)
{
if (_noConsole)
{
return DefaultConsoleWidth;
}
try
{
// if Console width is set to 0, the default width is returned so that the output string is not null.
Expand All @@ -777,13 +768,40 @@ static private int GetConsoleWindowWidth(int columnNumber)
}
catch
{
_noConsole = true;
return DefaultConsoleWidth;
}
}

return columnNumber;
}

/// <summary>
/// Return the console height.null If not available (like when remoting), treat as Int.MaxValue.
/// </summary>
private static int GetConsoleWindowHeight(int rowNumber)
{
if (InternalTestHooks.SetConsoleHeightToZero)
{
return DefaultConsoleHeight;
}

if (rowNumber <= 0)
{
try
{
// if Console height is set to 0, the default height is returned.
// This can happen in environments where TERM is not set.
return (Console.WindowHeight > 0) ? Console.WindowHeight : DefaultConsoleHeight;
}
catch
{
return DefaultConsoleHeight;
}
}

return rowNumber;
}

/// <summary>
/// base class for all the formatting hints
/// </summary>
Expand Down Expand Up @@ -925,6 +943,12 @@ internal TableOutputContextBase(OutCommandInner cmd,

private sealed class TableOutputContext : TableOutputContextBase
{
private int _rowCount = 0;
private int _consoleHeight = -1;
private int _consoleWidth = -1;
private const int WhitespaceAndPagerLineCount = 2;
private bool _repeatHeader = false;

/// <summary>
/// construct a context to push on the stack
/// </summary>
Expand All @@ -936,6 +960,13 @@ internal TableOutputContext(OutCommandInner cmd,
GroupStartData formatData)
: base(cmd, parentContext, formatData)
{
if (parentContext is FormatOutputContext foc)
{
if (foc.Data.shapeInfo is TableHeaderInfo thi)
{
_repeatHeader = thi.repeatHeader;
}
}
}

/// <summary>
Expand All @@ -952,7 +983,8 @@ internal override void Initialize()
columnWidthsHint = tableHint.columnWidths;
}

int columnsOnTheScreen = GetConsoleWindowWidth(this.InnerCommand._lo.ColumnNumber);
_consoleHeight = GetConsoleWindowHeight(this.InnerCommand._lo.RowNumber);
_consoleWidth = GetConsoleWindowWidth(this.InnerCommand._lo.ColumnNumber);

int columns = this.CurrentTableHeaderInfo.tableColumnInfoList.Count;
if (columns == 0)
Expand All @@ -971,7 +1003,7 @@ internal override void Initialize()
alignment[k] = tci.alignment;
k++;
}
this.Writer.Initialize(0, columnsOnTheScreen, columnWidths, alignment, this.CurrentTableHeaderInfo.hideHeader);
this.Writer.Initialize(0, _consoleWidth, columnWidths, alignment, this.CurrentTableHeaderInfo.hideHeader);
}

/// <summary>
Expand All @@ -992,7 +1024,7 @@ internal override void GroupStart()
{
properties[k++] = tci.label ?? tci.propertyName;
}
this.Writer.GenerateHeader(properties, this.InnerCommand._lo);
_rowCount += this.Writer.GenerateHeader(properties, this.InnerCommand._lo);
}

/// <summary>
Expand All @@ -1008,6 +1040,12 @@ internal override void ProcessPayload(FormatEntryData fed)
return;
}

if (_repeatHeader && _rowCount >= _consoleHeight - WhitespaceAndPagerLineCount)
{
this.InnerCommand._lo.WriteLine(string.Empty);
_rowCount = this.Writer.GenerateHeader(null, this.InnerCommand._lo);
}

TableRowEntry tre = fed.formatEntryInfo as TableRowEntry;

// need to make sure we have matching counts: the header count will have to prevail
Expand All @@ -1029,7 +1067,8 @@ internal override void ProcessPayload(FormatEntryData fed)
alignment[k] = TextAlignment.Left; // hard coded default
}
}
this.Writer.GenerateRow(values, this.InnerCommand._lo, tre.multiLine, alignment, InnerCommand._lo.DisplayCells);
this.Writer.GenerateRow(values, this.InnerCommand._lo, tre.multiLine, alignment, InnerCommand._lo.DisplayCells, generatedRows: null);
_rowCount++;
}

private TableHeaderInfo CurrentTableHeaderInfo
Expand Down Expand Up @@ -1182,7 +1221,7 @@ internal override void Initialize()
alignment[k] = TextAlignment.Left;
}

this.Writer.Initialize(0, columnsOnTheScreen, columnWidths, alignment, false);
this.Writer.Initialize(0, columnsOnTheScreen, columnWidths, alignment, false, GetConsoleWindowHeight(this.InnerCommand._lo.RowNumber));
}

/// <summary>
Expand Down Expand Up @@ -1239,7 +1278,7 @@ private void WriteStringBuffer()
else
values[k] = string.Empty;
}
this.Writer.GenerateRow(values, this.InnerCommand._lo, false, null, InnerCommand._lo.DisplayCells);
this.Writer.GenerateRow(values, this.InnerCommand._lo, false, null, InnerCommand._lo.DisplayCells, generatedRows: null);
_buffer.Reset();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,11 @@ internal abstract class ControlBody : ControlBase
/// RULE: valid only for table and wide only
/// </summary>
internal bool? autosize = null;

/// <summary>
/// RULE: only valid for table
/// </summary>
internal bool repeatHeader = false;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ private void InitializeHelper()
InitializeFormatErrorManager();
InitializeGroupBy();
InitializeAutoSize();
InitializeRepeatHeader();
}

private void InitializeFormatErrorManager()
Expand Down Expand Up @@ -147,6 +148,14 @@ private void InitializeAutoSize()
}
}

private void InitializeRepeatHeader()
{
if (parameters != null)
{
_repeatHeader = parameters.repeatHeader;
}
}

internal virtual FormatStartData GenerateStartData(PSObject so)
{
FormatStartData startFormat = new FormatStartData();
Expand Down Expand Up @@ -312,6 +321,12 @@ protected bool AutoSize
}
private bool _autosize = false;

protected bool RepeatHeader
{
get { return _repeatHeader; }
}
private bool _repeatHeader = false;

protected class DataBaseInfo
{
internal TypeInfoDataBase db = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ private TableHeaderInfo GenerateTableHeaderInfoFromDataBaseInfo(PSObject so)
bool dummy;
List<TableRowItemDefinition> activeRowItemDefinitionList = GetActiveTableRowDefinition(_tableBody, so, out dummy);
thi.hideHeader = this.HideHeaders;
thi.repeatHeader = this.RepeatHeader;

int col = 0;
foreach (TableRowItemDefinition rowItem in activeRowItemDefinitionList)
Expand Down Expand Up @@ -293,6 +294,19 @@ private bool HideHeaders
}
}

private bool RepeatHeaders
{
get
{
if (this.parameters != null)
{
return this.parameters.repeatHeader;
}

return false;
}
}

private static int ComputeDefaultAlignment(PSObject so, PSPropertyExpression ex)
{
List<PSPropertyExpressionResult> rList = ex.GetValues(so);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ public TableHeaderInfo()
public override string ClassId2e4f51ef21dd47e99d3c952918aff9cd { get { return CLSID; } }

public bool hideHeader;
public bool repeatHeader;
public List<TableColumnInfo> tableColumnInfoList;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ internal override void Deserialize(PSObject so, FormatObjectDeserializer deseria
{
base.Deserialize(so, deserializer);
this.hideHeader = deserializer.DeserializeBoolMemberVariable(so, "hideHeader");
this.hideHeader = deserializer.DeserializeBoolMemberVariable(so, "repeatHeader");
FormatInfoDataListDeserializer<TableColumnInfo>.ReadList(so, "tableColumnInfoList", this.tableColumnInfoList, deserializer);
}
}
Expand Down
Loading