Advertisement
Guest User

CSI

a guest
Nov 6th, 2022
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 39.97 KB | None | 0 0
  1. using System.Collections.Immutable;
  2. using System.Runtime.Versioning;
  3.  
  4. namespace ControlSequences;
  5.  
  6. using static System.Console;
  7. /// <summary>
  8. ///     Collection of CSI console commands.
  9. /// </summary>
  10. /// <remarks>
  11. ///     <seealso href="https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#text-formatting" />
  12. /// </remarks>
  13. public static class ControlSequenceIntroducer
  14. {
  15.     public const string ESC = "\x1b";
  16.     public const string CSI = "\x1b[";
  17.     public const string OSC = "\x1b]";
  18.     public const string ST = "\x1b\x5c";
  19.     public const string DEC_LINE_MODE = "\x1b(0";
  20.     public const string ASCII_MODE = "\x1b(B";
  21.  
  22.     public const string RESETCOLOR = "\x1b[0m";
  23.     public const string RESETFOREGROUND = "\x1b[39m";
  24.     public const string RESETBACKGROUND = "\x1b[49m";
  25.     public const string RGB_FOREGROUND_FORMAT = "38;2;{0};{1};{2}";
  26.     public const string RGB_BACKGROUND_FORMAT = "48;2;{0};{1};{2}";
  27.     public const string PALETTE_FOREGROUND_FORMAT = "38;5;{0}";
  28.     public const string PALETTE_BACKGROUND_FORMAT = "48;5;{0}";
  29.     /// <summary>
  30.     /// Writes the control sequence to the console.
  31.     /// </summary>
  32.     /// <param name="value">The control sequence.</param>
  33.     internal static void SendCommand(string value) => Write(value);
  34.     /// <inheritdoc cref="SendCommand(string)"/>
  35.     internal static void SendCommand(string format, params object[] values) => Write(format, values);
  36.     /// <inheritdoc cref="SendCommand(string)"/>
  37.     internal static void SendCommand(char value) => Write(value);
  38.     /// <summary>
  39.     /// Get the Console WindowWidth and WindowHeight property values.
  40.     /// </summary>
  41.     /// <returns>(int Width, int Height) tuple.</returns>
  42.     public static (int Width, int Height) GetWindowSize() => (WindowWidth, WindowHeight);
  43.     /// <summary>Replaces text on the screen with space characters.</summary>
  44.     public static void ClearDisplay() => EraseDisplay(2);
  45.     public static void EnterVirtualBuffer() => SendCommand($"{CSI}?1049h");
  46.     public static void EnterMainBuffer() => SendCommand($"{CSI}?1049l");
  47.     public static void EnterLineMode() => SendCommand(DEC_LINE_MODE);
  48.     public static void ExitLineMode() => SendCommand(ASCII_MODE);
  49.     #region TEXT
  50.     /*
  51.     ESC [ <n> @ ICH Insert Character    Insert <n> spaces at the current cursor position, shifting all existing text to the right. Text exiting the screen to the right is removed.
  52.     ESC [ <n> P DCH Delete Character    Delete <n> characters at the current cursor position, shifting in space characters from the right edge of the screen.
  53.     ESC [ <n> X ECH Erase Character Erase <n> characters from the current cursor position by overwriting them with a space character.
  54.     ESC [ <n> L IL  Insert Line Inserts <n> lines into the buffer at the cursor position. The line the cursor is on, and lines below it, will be shifted downwards.
  55.     ESC [ <n> M DL  Delete Line Deletes <n> lines from the buffer, starting with the row the cursor is on.
  56.     */
  57.     /// <summary>
  58.     /// Insert <paramref name="n"/> spaces at the current cursor position, shifting all existing text to the right. Text exiting the screen to the right is removed.
  59.     /// </summary>
  60.     /// <param name="n"></param>
  61.     public static void InsertCharacter(int n = 1) => SendCommand($"{CSI}{n}@");
  62.     /// <summary>
  63.     /// Delete <paramref name="n"/> characters at the current cursor position, shifting in space characters from the right edge of the screen.
  64.     /// </summary>
  65.     /// <param name="n">Number of characters to delete.</param>
  66.     public static void DeleteCharacter(int n = 1) => SendCommand($"{CSI}{n}P");
  67.     /// <summary>
  68.     /// Erase <paramref name="n"/> characters from the current cursor position by overwriting them with a space character.
  69.     /// </summary>
  70.     /// <param name="n">Number of characters to replace with space.</param>
  71.     public static void EraseCharacter(int n = 1) => SendCommand($"{CSI}{n}X");
  72.     /// <summary>
  73.     /// Inserts <paramref name="n"/> lines into the buffer at the cursor position. The line the cursor is on, and lines below it, will be shifted downwards.
  74.     /// </summary>
  75.     /// <param name="n">Number of lines to insert after current cursor position.</param>
  76.     public static void InsertLine(int n = 1) => SendCommand($"{CSI}{n}L");
  77.     /// <summary>
  78.     /// Deletes <paramref name="n"/> lines from the buffer, starting with the row the cursor is on.
  79.     /// </summary>
  80.     /// <param name="n">Number of lines to delete.</param>
  81.     public static void DeleteLine(int n = 1) => SendCommand($"{CSI}{n}M");
  82.     /*
  83.     For the following commands, the parameter <n> has 3 valid values:
  84.     0 erases from the current cursor position (inclusive) to the end of the line/display
  85.     1 erases from the beginning of the line/display up to and including the current cursor position
  86.     2 erases the entire line/display
  87.     ESC [ <n> J ED  Erase in Display    Replace all text in the current viewport/screen specified by <n> with space characters
  88.     ESC [ <n> K EL  Erase in Line   Replace all text on the line with the cursor specified by <n> with space characters
  89.     */
  90.     /// <summary>
  91.     /// Replaces text on the screen with space characters.
  92.     /// </summary>
  93.     /// <param name="n">
  94.     /// <list type="table">
  95.     ///     <item>
  96.     ///         <term>0</term>
  97.     ///         <description>Erase from current position to end of the display.</description>
  98.     ///     </item>
  99.     ///     <item>
  100.     ///         <term>1</term>
  101.     ///         <description>Erase from beginning of the display to current position.</description>
  102.     ///     </item>
  103.     ///     <item>
  104.     ///         <term>2</term>
  105.     ///         <description>Erase the entire the display.</description>
  106.     ///     </item>
  107.     /// </list>
  108.     /// </param>
  109.     public static void EraseDisplay(int n = 0) => SendCommand($"{CSI}{n}J");
  110.     /// <summary>
  111.     /// Replaces text on the current line with space characters.
  112.     /// </summary>
  113.     /// <param name="n">
  114.     /// <list type="table">
  115.     ///     <item>
  116.     ///         <term>0</term>
  117.     ///         <description>Erase from current position to end of the line.</description>
  118.     ///     </item>
  119.     ///     <item>
  120.     ///         <term>1</term>
  121.     ///         <description>Erase from beginning of the line to current position.</description>
  122.     ///     </item>
  123.     ///     <item>
  124.     ///         <term>2</term>
  125.     ///         <description>Erase the entire line.</description>
  126.     ///     </item>
  127.     /// </list>
  128.     /// </param>
  129.     public static void EraseLine(int n = 0) => SendCommand($"{CSI}{n}K");
  130.     #endregion TEXT
  131.  
  132.     #region CURSOR
  133.     /*
  134.     ESC M   RI  Reverse Index – Performs the reverse operation of \n, moves cursor up one line, maintains horizontal position, scrolls buffer if necessary*
  135.     ESC 7   DECSC   Save Cursor Position in Memory**
  136.     ESC 8   DECSR   Restore Cursor Position from Memory**
  137.     */
  138.     /// <summary>
  139.     /// Performs the reverse operation of \n, moves cursor up one line, maintains horizontal position, scrolls buffer if necessary
  140.     /// </summary>
  141.     /// <remarks>If there are scroll margins set, reversing inside the margins will scroll only the contents of the margins, and leave the viewport unchanged.
  142.     /// See <seealso cref="SetScrollRegion"/>
  143.     /// </remarks>
  144.     public static void ReverseCursor() => SendCommand($"{ESC}M");
  145.     /// <summary>
  146.     /// Save Cursor Position in Memory.
  147.     /// </summary>
  148.     /// <remarks>
  149.     /// The only way to access the saved value is with the restore command <see cref="RestoreCursorPosition"/>.
  150.     /// </remarks>
  151.     public static void SaveCursorPosition() => SendCommand($"{ESC}7");
  152.     /// <summary>
  153.     /// Restore Cursor Position from Memory.
  154.     /// </summary>
  155.     /// <remarks>
  156.     /// There will be no value saved in memory until the first use of the save command <see cref="SaveCursorPosition"/>.
  157.     /// </remarks>
  158.     public static void RestoreCursorPosition() => SendCommand($"{ESC}8");
  159.     /*
  160.     ESC [ <n> A CUU Cursor Up                                   Cursor up by <n>
  161.     ESC [ <n> B CUD Cursor Down                                 Cursor down by <n>
  162.     ESC [ <n> C CUF Cursor Forward                              Cursor forward (Right) by <n>
  163.     ESC [ <n> D CUB Cursor Backward                             Cursor backward (Left) by <n>
  164.     ESC [ <n> E CNL Cursor Next Line                            Cursor down <n> lines from current position
  165.     ESC [ <n> F CPL Cursor Previous Line                        Cursor up <n> lines from current position
  166.     ESC [ <n> G CHA Cursor Horizontal Absolute                  Cursor moves to <n>th position horizontally in the current line
  167.     ESC [ <n> d VPA Vertical Line Position Absolute             Cursor moves to the <n>th position vertically in the current column
  168.     ESC [ <y> ; <x> H   CUP Cursor Position *                   Cursor moves to <x>; <y> coordinate within the viewport, where <x> is the column of the <y> line
  169.     ESC [ <y> ; <x> f   HVP Horizontal Vertical Position    *   Cursor moves to <x>; <y> coordinate within the viewport, where <x> is the column of the <y> line
  170.     ESC [ s ANSISYSSC   Save Cursor – Ansi.sys emulation  **With no parameters, performs a save cursor operation like DECSC
  171.     ESC [ u ANSISYSSC   Restore Cursor – Ansi.sys emulation   **With no parameters, performs a restore cursor operation like DECRC
  172.     */
  173.     /// <summary>
  174.     /// Cursor up by <paramref name="n"/>
  175.     /// </summary>
  176.     public static void CursorUp(int n = 1) => SendCommand($"{CSI}{n}A");
  177.     /// <summary>
  178.     /// Cursor down by <paramref name="n"/>
  179.     /// </summary>
  180.     /// <param name="n"></param>
  181.     public static void CursorDown(int n = 1) => SendCommand($"{CSI}{n}B");
  182.     /// <summary>
  183.     /// Cursor forward (Right) by <paramref name="n"/>
  184.     /// </summary>
  185.     /// <param name="n"></param>
  186.     public static void CursorForward(int n = 1) => SendCommand($"{CSI}{n}C");
  187.     /// <summary>
  188.     /// Cursor backward (Left) by <paramref name="n"/>
  189.     /// </summary>
  190.     /// <param name="n"></param>
  191.     public static void CursorBackward(int n = 1) => SendCommand($"{CSI}{n}D");
  192.     /// <summary>
  193.     /// Cursor down <paramref name="n"/> lines from current position
  194.     /// </summary>
  195.     /// <param name="n"></param>
  196.     public static void CursorNextLine(int n = 1) => SendCommand($"{CSI}{n}E");
  197.     /// <summary>
  198.     /// Cursor up <paramref name="n"/> lines from current position
  199.     /// </summary>
  200.     /// <param name="n"></param>
  201.     public static void CursorPreviousLine(int n = 1) => SendCommand($"{CSI}{n}F");
  202.     /// <summary>
  203.     /// Cursor moves to <paramref name="n"/>th position horizontally in the current line
  204.     /// </summary>
  205.     /// <param name="n"></param>
  206.     public static void CursorHorizontal(int n = 1) => SendCommand($"{CSI}{n}G");
  207.     /// <summary>
  208.     /// Cursor moves to the <paramref name="n"/>th position vertically in the current column
  209.     /// </summary>
  210.     /// <param name="n"></param>
  211.     public static void CursorVertical(int n = 1) => SendCommand($"{CSI}{n}d");
  212.     /// <summary>
  213.     /// Cursor moves to <paramref name="x"/>, <paramref name="y"/> coordinate within the viewport, where <paramref name="x"/> is the column of the <paramref name="y"/> line
  214.     /// </summary>
  215.     public static void CursorHorizontalVertical(int x = 1, int y = 1) => SendCommand($"{CSI}{y};{x}f");
  216.  
  217.     /// <summary>
  218.     /// Set the cursor position using x, y one-based indexes.
  219.     /// </summary>
  220.     public static void SetCursorPosition(int x = 1, int y = 1) => SendCommand(ToCursorPosition(x, y));
  221.     /// <inheritdoc cref="Console.GetCursorPosition"/>
  222.     public static (int X, int Y) GetCursorPosition() => (CursorLeft + 1, CursorTop + 1);
  223.  
  224.     /// <summary>
  225.     /// Get the CSI command for the x, y one-based index cursor position.
  226.     /// </summary>
  227.     internal static string ToCursorPosition(int x, int y) => $"{CSI}{y};{x}H";
  228.     /*
  229.     ESC [ ? 12 h    ATT160  Text Cursor Enable Blinking Start the cursor blinking
  230.     ESC [ ? 12 l    ATT160  Text Cursor Disable Blinking    Stop blinking the cursor
  231.     ESC [ ? 25 h    DECTCEM Text Cursor Enable Mode Show    Show the cursor
  232.     ESC [ ? 25 l    DECTCEM Text Cursor Enable Mode Hide    Hide the cursor
  233.     */
  234.     public static void EnableCursorBlink() => SendCommand($"{CSI}?12h");
  235.     public static void DisableCursorBlink() => SendCommand($"{CSI}?12l");
  236.     public static void ShowCursor() => SendCommand($"{CSI}?25h");
  237.     public static void HideCursor() => SendCommand($"{CSI}?25l");
  238.  
  239.     #endregion CURSOR
  240.  
  241.     #region VIEWPORT
  242.     /*
  243.     ESC [ <n> S SU  Scroll Up   Scroll text up by <n>. Also known as pan down, new lines fill in from the bottom of the screen
  244.     ESC [ <n> T SD  Scroll Down Scroll down by <n>. Also known as pan up, new lines fill in from the top of the screen
  245.     */
  246.     /// <summary>
  247.     /// Scroll text up by <paramref name="n"/>. Also known as pan down, new lines fill in from the bottom of the screen
  248.     /// </summary>
  249.     /// <remarks>Scroll refers to which direction the text moves during the operation.</remarks>
  250.     public static void ScrollUp(int n = 1) => SendCommand($"{CSI}{n}S");
  251.     /// <summary>
  252.     /// Scroll down by <paramref name="n"/>. Also known as pan up, new lines fill in from the top of the screen
  253.     /// </summary>
  254.     /// <remarks>Scroll refers to which direction the text moves during the operation.</remarks>
  255.     public static void ScrollDown(int n = 1) => SendCommand($"{CSI}{n}T");
  256.     /*
  257.     ESC [ <t> ; <b> r   DECSTBM Set Scrolling Region    Sets the VT scrolling margins of the viewport.
  258.     */
  259.     /// <summary>
  260.     /// Sets the scrolling margins of the viewport. If the parameters are omitted, <paramref name="top"/> defaults to 1 and <paramref name="bottom"/> defaults to the current viewport height.
  261.     /// </summary>
  262.     /// <remarks>Useful for having a portion of the screen that doesn’t scroll when the rest of the screen is filled, such as having a title bar at the top or a status bar at the bottom of your application.</remarks>
  263.     /// <param name="top">Top margin.</param>
  264.     /// <param name="bottom">Bottom margin.</param>
  265.     public static void SetScrollRegion(int top, int bottom) => SendCommand($"{CSI}{top};{bottom}r");
  266.     /// <inheritdoc cref="SetScrollRegion(int, int)"/>
  267.     public static void SetScrollRegion(int top) => SendCommand($"{CSI}{top}r");
  268.     /// <inheritdoc cref="SetScrollRegion(int, int)"/>
  269.     public static void SetScrollRegion() => SendCommand($"{CSI}r");
  270.     #endregion VIEWPORT
  271.  
  272.     #region TABS
  273.     /*
  274.     ESC H   HTS Horizontal Tab Set  Sets a tab stop in the current column the cursor is in.
  275.     ESC [ <n> I CHT Cursor Horizontal (Forward) Tab Advance the cursor to the next column (in the same row) with a tab stop. If there are no more tab stops, move to the last column in the row. If the cursor is in the last column, move to the first column of the next row.
  276.     ESC [ <n> Z CBT Cursor Backwards Tab    Move the cursor to the previous column (in the same row) with a tab stop. If there are no more tab stops, moves the cursor to the first column. If the cursor is in the first column, doesn’t move the cursor.
  277.     ESC [ 0 g   TBC Tab Clear (current column)  Clears the tab stop in the current column, if there is one. Otherwise does nothing.
  278.     ESC [ 3 g   TBC Tab Clear (all columns) Clears all currently set tab stops.
  279.      */
  280.     /// <summary>
  281.     /// Move to the next tabstop.
  282.     /// </summary>
  283.     public static void NextTabstop(int n = 1) => SendCommand($"{CSI}{n}I");
  284.     //public static void NextTabstop() => SendCommand('\t');
  285.     /// <summary>
  286.     /// Sets a tab stop in the current column the cursor is in.
  287.     /// </summary>
  288.     public static void SetTabstop() => SendCommand($"{ESC}H");
  289.     /// <summary>
  290.     /// Sets a tab stop in the column specified by <paramref name="x"/>.
  291.     /// </summary>
  292.     /// <param name="x">The column to move to, one-based index.</param>
  293.     /// <param name="restoreCursorPosition">True to move back to the original cursor position after setting the tabstop, otherwise stay at the new position. Default is true.</param>
  294.     public static void SetTabstop(int x, bool restoreCursorPosition = true)
  295.     {
  296.         CommandReturnPosition(SetTabstop, x, 1, restoreCursorPosition);
  297.     }
  298.     /// <summary>
  299.     /// Clears the tab stop in the current column, if there is one. Otherwise does nothing.
  300.     /// </summary>
  301.     public static void ClearTabstop() => SendCommand($"{CSI}0g");
  302.     /// <summary>
  303.     /// Clears the tab stop in the column specified by <paramref name="x"/>.
  304.     /// </summary>
  305.     /// <param name="x">The column to move to, one-based index.</param>
  306.     /// <param name="restoreCursorPosition">True to move back to the original cursor position after setting the tabstop, otherwise stay at the new position. Default is true.</param>
  307.     public static void ClearTabstop(int x, bool restoreCursorPosition = true)
  308.     {
  309.         CommandReturnPosition(ClearTabstop, x, 1, restoreCursorPosition);
  310.     }
  311.     /// <summary>
  312.     /// Clears all currently set tab stops.
  313.     /// </summary>
  314.     public static void ClearTabstops() => SendCommand($"{CSI}3g");
  315.  
  316.     internal static void CommandReturnPosition(Action command, int x, int y, bool restoreCursorPosition)
  317.     {
  318.         if (command == null)
  319.             throw new ArgumentNullException(nameof(command));
  320.         if (restoreCursorPosition)
  321.             SaveCursorPosition();
  322.         SetCursorPosition(x, y);
  323.         command();
  324.         if (restoreCursorPosition)
  325.             RestoreCursorPosition();
  326.     }
  327.     #endregion TABS
  328.  
  329.     #region COLORS
  330.     /// <summary>
  331.     /// Get the CSI command to set console colors.
  332.     /// </summary>
  333.     /// <remarks>
  334.     /// <list type="table">
  335.     /// <listheader>
  336.     ///     <description>Syntax</description>
  337.     ///     <description>Type</description>
  338.     ///     <description>Description</description>
  339.     /// </listheader>
  340.     /// <item>
  341.     ///     <term>38;2;r;g;b</term>
  342.     ///     <term>RGB</term>
  343.     ///     <description>Sequence of numbers to set the foreground color.</description>
  344.     /// </item>
  345.     /// <item>
  346.     ///     <term>48;2;r;g;b</term>
  347.     ///     <term>RGB</term>
  348.     ///     <description>Sequence of numbers to set the background color.</description>
  349.     /// </item>
  350.     /// <item>
  351.     ///     <term>38;5;color</term>
  352.     ///     <term>Palette</term>
  353.     ///     <description>Sequence of numbers to set the foreground color from the 88_255 palette.</description>
  354.     /// </item>
  355.     /// <item>
  356.     ///     <term>48;5;color</term>
  357.     ///     <term>Palette</term>
  358.     ///     <description>Sequence of numbers to set the background color from the 88_255 palette.</description>
  359.     /// </item>
  360.     /// <item>For SGR sequences, see <see cref="SGR"/></item>
  361.     /// <item>
  362.     ///     <term>0</term>
  363.     ///     <description>Restore colors.</description>
  364.     /// </item>
  365.     /// <item>
  366.     ///     <term>1</term>
  367.     ///     <description>Bright foreground.</description>
  368.     /// </item>
  369.     /// <item>
  370.     ///     <term>4</term>
  371.     ///     <description>Underline</description>
  372.     /// </item>
  373.     /// <item>
  374.     ///     <term>7</term>
  375.     ///     <description>Swap to negative.</description>
  376.     /// </item>
  377.     /// </list>
  378.     /// For more: <seealso href="https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#text-formatting" />
  379.     /// </remarks>
  380.     /// <param name="colors"></param>
  381.     /// <returns></returns>
  382.     /// <seealso cref="SGR"/>
  383.     public static string ColorFormat(params int[] colors) => colors switch
  384.     {
  385.         null => RESETCOLOR,
  386.         { Length: 0 } => RESETCOLOR,
  387.         { Length: 1 } when colors[0] is 0 => RESETCOLOR,
  388.         // todo: with list-patterns in preview:
  389.         // [] => RESETCOLOR, // empty or null
  390.         // [0] => RESETCOLOR, // only one item as it is 0
  391.         _ => $"{CSI}{string.Join(';', colors)}m"
  392.     };
  393.     /// <summary> Uses a CSI command to set console colors.</summary>
  394.     /// <inheritdoc cref="ColorFormat(int[])"/>
  395.     public static void SetColor(params int[] colors) => SendCommand(ColorFormat(colors));
  396.     public static void SetSgr(SgrColors color) => SetSgr((int)color);
  397.     public static void SetSgr(int color) => SendCommand(ColorFormat(color));
  398.     public static void SetForegroundPalette(int color) => SetColor(38, 5, color);
  399.     public static void SetBackgroundPalette(int color) => SetColor(48, 5, color);
  400.     public static void SetForeground(int r, int g, int b) => SetColor(38, 2, r, g, b);
  401.     public static void SetBackground(int r, int g, int b) => SetColor(48, 2, r, g, b);
  402.     public static void ResetColor() => SendCommand(RESETCOLOR);
  403.     #endregion COLORS
  404.  
  405.     public static readonly ImmutableDictionary<char, (char Value, string Description)> DecLinemodeMap = ImmutableDictionary.CreateRange(new Dictionary<char, (char, string)>
  406.     {
  407.        {'j', ( '┘', "CornerBottomRight"        ) },
  408.        {'k', ( '┐', "CornerTopRight"           ) },
  409.        {'l', ( '┌', "CornerTopLeft"            ) },
  410.        {'m', ( '└', "CornerBottomLeft"         ) },
  411.        {'n', ( '┼', "IntersectionMiddle"       ) },
  412.        {'q', ( '─', "Horizontal"               ) },
  413.        {'t', ( '├', "IntersectionLeft"         ) },
  414.        {'u', ( '┤', "IntersectionRight"        ) },
  415.        {'v', ( '┴', "IntersectionBottom"       ) },
  416.        {'w', ( '┬', "IntersectionTop"          ) },
  417.        {'x', ( '│', "Vertical"                 ) },
  418.  
  419.     });
  420.     public static class DecLineMode
  421.     {
  422.         /*
  423.             ┘   0x6a    'j'
  424.             ┐   0x6b    'k'
  425.             ┌   0x6c    'l'
  426.             └   0x6d    'm'
  427.             ┼   0x6e    'n'
  428.             ─   0x71    'q'
  429.             ├   0x74    't'
  430.             ┤   0x75    'u'
  431.             ┴   0x76    'v'
  432.             ┬   0x77    'w'
  433.             │   0x78    'x'
  434.         */
  435.         public static readonly char CornerBottomRight = 'j';
  436.         public static readonly char CornerTopRight = 'k';
  437.         public static readonly char CornerTopLeft = 'l';
  438.         public static readonly char CornerBottomLeft = 'm';
  439.         public static readonly char IntersectionMiddle = 'n';
  440.         public static readonly char Horizontal = 'q';
  441.         public static readonly char IntersectionLeft = 't';
  442.         public static readonly char IntersectionRight = 'u';
  443.         public static readonly char IntersectionBottom = 'v';
  444.         public static readonly char IntersectionTop = 'w';
  445.         public static readonly char Vertical = 'x';
  446.     }
  447.  
  448.     [SupportedOSPlatform("windows")]
  449.     public static void Palette()
  450.     {
  451.         EnterMainBuffer();
  452.         int tabStops = 36;
  453.         int tabSize = 6;
  454.         var size = tabStops * tabSize;
  455.         try
  456.         {
  457.             WindowWidth = size;
  458.         }
  459.         catch (IOException ex)
  460.         {
  461.             WriteLine(ex);
  462.             throw;
  463.         }
  464.         // Tab stops
  465.         SendCommand($"{CSI}3g");
  466.         for (int t = 1; t < tabStops; t++)
  467.         {
  468.             SendCommand($"{CSI}1;{t * tabSize}H{ESC}H");
  469.         }
  470.         //Write($"{CSI}3;{size.Y - 2}");
  471.         SendCommand($"{CSI}1;1H");
  472.         // Write data
  473.         int lines = 256;
  474.         for (int i = 16; i < lines;)
  475.         {
  476.             for (int j = 0; j < tabStops; j++)
  477.             {
  478.                 SendCommand($"{CSI}38;5;{i}m{i},");
  479.                 SendCommand($"\t");
  480.                 i++;
  481.             }
  482.             SendCommand($"\t");
  483.         }
  484.         SendCommand(CSI + "m");
  485.     }
  486.     public static void OtherFormats()
  487.     {
  488.         SendCommand("\x1b[31mThis text has a red foreground using SGR.31.\r\n");
  489.         SendCommand("\x1b[1mThis text has a bright (bold) red foreground using SGR.1 to affect the previous color setting.\r\n");
  490.         SendCommand("\x1b[mThis text has returned to default colors using SGR.0 implicitly.\r\n");
  491.         SendCommand("\x1b[34;46mThis text shows the foreground and background change at the same time.\r\n");
  492.         SendCommand("\x1b[0mThis text has returned to default colors using SGR.0 explicitly.\r\n");
  493.         SendCommand("\x1b[31;32;33;34;35;36;101;102;103;104;105;106;107mThis text attempts to apply many colors in the same command. Note the colors are applied from left to right so only the right-most option of foreground cyan (SGR.36) and background bright white (SGR.107) is effective.\r\n");
  494.         SendCommand("\x1b[39mThis text has restored the foreground color only.\r\n");
  495.         SendCommand("\x1b[49mThis text has restored the background color only.\r\n");
  496.     }
  497.     public static void Win10AnniversaryFeatures()
  498.     {
  499.  
  500.         void PrintVerticalBorder()
  501.         {
  502.             SendCommand(ESC + "(0"); // Enter Line drawing mode
  503.             SendCommand(CSI + "104;93m"); // bright yellow on bright blue
  504.             SendCommand("x"); // in line drawing mode, \x78 -> \u2502 "Vertical Bar"
  505.             SendCommand(CSI + "0m"); // restore color
  506.             SendCommand(ESC + "(B"); // exit line drawing mode
  507.         }
  508.  
  509.         void PrintHorizontalBorder((int X, int Y) size, bool isTop)
  510.         {
  511.             SendCommand(ESC + "(0"); // Enter Line drawing mode
  512.             SendCommand(CSI + "104;93m"); // Make the border bright yellow on bright blue
  513.             SendCommand(isTop ? "l" : "m"); // print left corner
  514.  
  515.             for (int i = 1; i < size.X - 1; i++)
  516.                 SendCommand("q"); // in line drawing mode, \x71 -> \u2500 "HORIZONTAL SCAN LINE-5"
  517.  
  518.             SendCommand(isTop ? "k" : "j"); // print right corner
  519.             SendCommand(CSI + "0m");
  520.             SendCommand(ESC + "(B"); // exit line drawing mode
  521.         }
  522.  
  523.         void PrintStatusLine(string message, (int X, int Y) size)
  524.         {
  525.             SendCommand(CSI + "{0};1H", size.Y);
  526.             SendCommand(CSI + "K"); // clear the line
  527.             SendCommand(message);
  528.         }
  529.  
  530.         var size = (X: WindowWidth, Y: WindowHeight);
  531.  
  532.         // Enter the alternate buffer
  533.         SendCommand(CSI + "?1049h");
  534.  
  535.         // Clear screen, tab stops, set, stop at columns 16, 32
  536.         SendCommand(CSI + "1;1H");
  537.         SendCommand(CSI + "2J"); // Clear screen
  538.  
  539.         int iNumTabStops = 4; // (0, 20, 40, width)
  540.         SendCommand(CSI + "3g"); // clear all tab stops
  541.         SendCommand(CSI + "1;20H"); // Move to column 20
  542.         SendCommand(ESC + "H"); // set a tab stop
  543.  
  544.         SendCommand(CSI + "1;40H"); // Move to column 40
  545.         SendCommand(ESC + "H"); // set a tab stop
  546.  
  547.         // Set scrolling margins to 3, h-2
  548.         SendCommand(CSI + "3;{0}r", size.Y - 2);
  549.         int numLines = size.Y - 4;
  550.  
  551.         SendCommand(CSI + "1;1H");
  552.         SendCommand(CSI + "102;30m");
  553.         SendCommand("Windows 10 Anniversary Update - VT Example");
  554.         SendCommand(CSI + "0m");
  555.  
  556.         // Print a top border - Yellow
  557.         SendCommand(CSI + "2;1H");
  558.         PrintHorizontalBorder(size, true);
  559.  
  560.         // // Print a bottom border
  561.         SendCommand(CSI + "{0};1H", size.Y - 1);
  562.         PrintHorizontalBorder(size, false);
  563.  
  564.         // draw columns
  565.         SendCommand(CSI + "3;1H");
  566.         int line;
  567.         for (line = 0; line < numLines * iNumTabStops; line++)
  568.         {
  569.             PrintVerticalBorder();
  570.             if (line + 1 != numLines * iNumTabStops) // don't advance to next line if this is the last line
  571.                 SendCommand("\t"); // advance to next tab stop
  572.  
  573.         }
  574.  
  575.         PrintStatusLine("Press any key to see text printed between tab stops.", size);
  576.         ReadKey(true);
  577.  
  578.         // Fill columns with output
  579.         SendCommand(CSI + "3;1H");
  580.         for (line = 0; line < numLines; line++)
  581.         {
  582.             for (var tab = 0; tab < iNumTabStops - 1; tab++)
  583.             {
  584.                 PrintVerticalBorder();
  585.                 SendCommand("line={0}", line);
  586.                 SendCommand("\t"); // advance to next tab stop
  587.             }
  588.             PrintVerticalBorder();// print border at right side
  589.             if (line + 1 != numLines)
  590.                 SendCommand("\t"); // advance to next tab stop, (on the next line)
  591.         }
  592.  
  593.         PrintStatusLine("Press any key to demonstrate scroll margins", size);
  594.         ReadKey(true);
  595.  
  596.         SendCommand(CSI + "3;1H");
  597.         for (line = 0; line < numLines * 2; line++)
  598.         {
  599.             SendCommand(CSI + "K"); // clear the line
  600.             for (var tab = 0; tab < iNumTabStops - 1; tab++)
  601.             {
  602.                 PrintVerticalBorder();
  603.                 SendCommand("line={0}", line);
  604.                 SendCommand("\t"); // advance to next tab stop
  605.             }
  606.             PrintVerticalBorder(); // print border at right side
  607.             if (line + 1 != numLines * 2)
  608.             {
  609.                 SendCommand("\n"); //Advance to next line. If we're at the bottom of the margins, the text will scroll.
  610.                 SendCommand("\r"); //return to first col in buffer
  611.             }
  612.         }
  613.  
  614.         PrintStatusLine("Press any key to exit", size);
  615.         ReadKey(true);
  616.  
  617.         // Exit the alternate buffer
  618.         SendCommand(CSI + "?1049l");
  619.     }
  620. }
  621.  
  622. /// <summary>
  623. /// Set Graphics Rendition
  624. /// </summary>
  625. public static class SGR
  626. {
  627.     /// <summary>Returns all attributes to the default state prior to modification.</summary>
  628.     public static readonly int Default = (int)SgrColors.Default;
  629.     /// <summary>Applies brightness/intensity flag to foreground color.</summary>
  630.     public static readonly int BoldBright = (int)SgrColors.BoldBright;
  631.     /// <summary>Removes brightness/intensity flag from foreground color.</summary>
  632.     public static readonly int NoBoldBright = (int)SgrColors.NoBoldBright;
  633.     /// <summary>Adds underline.</summary>
  634.     public static readonly int Underline = (int)SgrColors.Underline;
  635.     /// <summary>Removes underline.</summary>
  636.     public static readonly int NoUnderline = (int)SgrColors.NoUnderline;
  637.     /// <summary>Swaps foreground and background colors.</summary>
  638.     public static readonly int Negative = (int)SgrColors.Negative;
  639.     /// <summary>Returns foreground/background to normal.</summary>
  640.     public static readonly int PositiveNoNegative = (int)SgrColors.PositiveNoNegative;
  641.     /// <summary>Applies non-bold/bright black to foreground.</summary>
  642.     public static readonly int ForegroundBlack = (int)SgrColors.ForegroundBlack;
  643.     /// <summary>Applies non-bold/bright red to foreground.</summary>
  644.     public static readonly int ForegroundRed = (int)SgrColors.ForegroundRed;
  645.     /// <summary>Applies non-bold/bright green to foreground.</summary>
  646.     public static readonly int ForegroundGreen = (int)SgrColors.ForegroundGreen;
  647.     /// <summary>Applies non-bold/bright yellow to foreground.</summary>
  648.     public static readonly int ForegroundYellow = (int)SgrColors.ForegroundYellow;
  649.     /// <summary>Applies non-bold/bright blue to foreground.</summary>
  650.     public static readonly int ForegroundBlue = (int)SgrColors.ForegroundBlue;
  651.     /// <summary>Applies non-bold/bright magenta to foreground.</summary>
  652.     public static readonly int ForegroundMagenta = (int)SgrColors.ForegroundMagenta;
  653.     /// <summary>Applies non-bold/bright cyan to foreground.</summary>
  654.     public static readonly int ForegroundCyan = (int)SgrColors.ForegroundCyan;
  655.     /// <summary>Applies non-bold/bright white to foreground.</summary>
  656.     public static readonly int ForegroundWhite = (int)SgrColors.ForegroundWhite;
  657.     /// <summary>Applies extended color value to the foreground in the palette or rgb format.</summary>
  658.     public static readonly int ForegroundExtended = (int)SgrColors.ForegroundExtended;
  659.     /// <summary>Applies only the foreground portion of the defaults (see 0)</summary>
  660.     public static readonly int ForegroundDefault = (int)SgrColors.ForegroundDefault;
  661.     /// <summary>Applies non-bold/bright black to background</summary>
  662.     public static readonly int BackgroundBlack = (int)SgrColors.BackgroundBlack;
  663.     /// <summary>Applies non-bold/bright red to background.</summary>
  664.     public static readonly int BackgroundRed = (int)SgrColors.BackgroundRed;
  665.     /// <summary>Applies non-bold/bright green to background.</summary>
  666.     public static readonly int BackgroundGreen = (int)SgrColors.BackgroundGreen;
  667.     /// <summary>Applies non-bold/bright yellow to background.</summary>
  668.     public static readonly int BackgroundYellow = (int)SgrColors.BackgroundYellow;
  669.     /// <summary>Applies non-bold/bright blue to background.</summary>
  670.     public static readonly int BackgroundBlue = (int)SgrColors.BackgroundBlue;
  671.     /// <summary>Applies non-bold/bright magenta to background.</summary>
  672.     public static readonly int BackgroundMagenta = (int)SgrColors.BackgroundMagenta;
  673.     /// <summary>Applies non-bold/bright cyan to background.</summary>
  674.     public static readonly int BackgroundCyan = (int)SgrColors.BackgroundCyan;
  675.     /// <summary>Applies non-bold/bright white to background.</summary>
  676.     public static readonly int BackgroundWhite = (int)SgrColors.BackgroundWhite;
  677.     /// <summary>Applies extended color value to the background in the palette or rgb format.</summary>
  678.     public static readonly int BackgroundExtended = (int)SgrColors.BackgroundExtended;
  679.     /// <summary>Applies only the background portion of the defaults (see 0)</summary>
  680.     public static readonly int BackgroundDefault = (int)SgrColors.BackgroundDefault;
  681.     /// <summary>Applies bold/bright black to foreground.</summary>
  682.     public static readonly int BrightForegroundBlack = (int)SgrColors.BrightForegroundBlack;
  683.     /// <summary>Applies bold/bright red to foreground.</summary>
  684.     public static readonly int BrightForegroundRed = (int)SgrColors.BrightForegroundRed;
  685.     /// <summary>Applies bold/bright green to foreground.</summary>
  686.     public static readonly int BrightForegroundGreen = (int)SgrColors.BrightForegroundGreen;
  687.     /// <summary>Applies bold/bright yellow to foreground.</summary>
  688.     public static readonly int BrightForegroundYellow = (int)SgrColors.BrightForegroundYellow;
  689.     /// <summary>Applies bold/bright blue to foreground.</summary>
  690.     public static readonly int BrightForegroundBlue = (int)SgrColors.BrightForegroundBlue;
  691.     /// <summary>Applies bold/bright magenta to foreground.</summary>
  692.     public static readonly int BrightForegroundMagenta = (int)SgrColors.BrightForegroundMagenta;
  693.     /// <summary>Applies bold/bright cyan to foreground.</summary>
  694.     public static readonly int BrightForegroundCyan = (int)SgrColors.BrightForegroundCyan;
  695.     /// <summary>Applies bold/bright white to foreground.</summary>
  696.     public static readonly int BrightForegroundWhite = (int)SgrColors.BrightForegroundWhite;
  697.     /// <summary>Applies bold/bright black to background.</summary>
  698.     public static readonly int BrightBackgroundBlack = (int)SgrColors.BrightBackgroundBlack;
  699.     /// <summary>Applies bold/bright red to background.</summary>
  700.     public static readonly int BrightBackgroundRed = (int)SgrColors.BrightBackgroundRed;
  701.     /// <summary>Applies bold/bright green to background.</summary>
  702.     public static readonly int BrightBackgroundGreen = (int)SgrColors.BrightBackgroundGreen;
  703.     /// <summary>Applies bold/bright yellow to background.</summary>
  704.     public static readonly int BrightBackgroundYellow = (int)SgrColors.BrightBackgroundYellow;
  705.     /// <summary>Applies bold/bright blue to background.</summary>
  706.     public static readonly int BrightBackgroundBlue = (int)SgrColors.BrightBackgroundBlue;
  707.     /// <summary>Applies bold/bright magenta to background.</summary>
  708.     public static readonly int BrightBackgroundMagenta = (int)SgrColors.BrightBackgroundMagenta;
  709.     /// <summary>Applies bold/bright cyan to background.</summary>
  710.     public static readonly int BrightBackgroundCyan = (int)SgrColors.BrightBackgroundCyan;
  711.     /// <summary>Applies bold/bright white to background.</summary>
  712.     public static readonly int BrightBackgroundWhite = (int)SgrColors.BrightBackgroundWhite;
  713. }
  714.  
  715. /// <summary>
  716. /// Set Graphics Rendition
  717. /// </summary>
  718. public enum SgrColors
  719. {
  720.     /// <summary>Returns all attributes to the default state prior to modification.</summary>
  721.     Default = 0,
  722.     /// <summary>Applies brightness/intensity flag to foreground color.</summary>
  723.     BoldBright = 1,
  724.     /// <summary>Removes brightness/intensity flag from foreground color.</summary>
  725.     NoBoldBright = 22,
  726.     /// <summary>Adds underline.</summary>
  727.     Underline = 4,
  728.     /// <summary>Removes underline.</summary>
  729.     NoUnderline = 24,
  730.     /// <summary>Swaps foreground and background colors.</summary>
  731.     Negative = 7,
  732.     /// <summary>Returns foreground/background to normal.</summary>
  733.     PositiveNoNegative = 27,
  734.     /// <summary>Applies non-bold/bright black to foreground.</summary>
  735.     ForegroundBlack = 30,
  736.     /// <summary>Applies non-bold/bright red to foreground.</summary>
  737.     ForegroundRed = 31,
  738.     /// <summary>Applies non-bold/bright green to foreground.</summary>
  739.     ForegroundGreen = 32,
  740.     /// <summary>Applies non-bold/bright yellow to foreground.</summary>
  741.     ForegroundYellow = 33,
  742.     /// <summary>Applies non-bold/bright blue to foreground.</summary>
  743.     ForegroundBlue = 34,
  744.     /// <summary>Applies non-bold/bright magenta to foreground.</summary>
  745.     ForegroundMagenta = 35,
  746.     /// <summary>Applies non-bold/bright cyan to foreground.</summary>
  747.     ForegroundCyan = 36,
  748.     /// <summary>Applies non-bold/bright white to foreground.</summary>
  749.     ForegroundWhite = 37,
  750.     /// <summary>Applies extended color value to the foreground in the palette or rgb format.</summary>
  751.     ForegroundExtended = 38,
  752.     /// <summary>Applies only the foreground portion of the defaults (see 0)</summary>
  753.     ForegroundDefault = 39,
  754.     /// <summary>Applies non-bold/bright black to background</summary>
  755.     BackgroundBlack = 40,
  756.     /// <summary>Applies non-bold/bright red to background.</summary>
  757.     BackgroundRed = 41,
  758.     /// <summary>Applies non-bold/bright green to background.</summary>
  759.     BackgroundGreen = 42,
  760.     /// <summary>Applies non-bold/bright yellow to background.</summary>
  761.     BackgroundYellow = 43,
  762.     /// <summary>Applies non-bold/bright blue to background.</summary>
  763.     BackgroundBlue = 44,
  764.     /// <summary>Applies non-bold/bright magenta to background.</summary>
  765.     BackgroundMagenta = 45,
  766.     /// <summary>Applies non-bold/bright cyan to background.</summary>
  767.     BackgroundCyan = 46,
  768.     /// <summary>Applies non-bold/bright white to background.</summary>
  769.     BackgroundWhite = 47,
  770.     /// <summary>Applies extended color value to the background in the palette or rgb format.</summary>
  771.     BackgroundExtended = 48,
  772.     /// <summary>Applies only the background portion of the defaults (see 0)</summary>
  773.     BackgroundDefault = 49,
  774.     /// <summary>Applies bold/bright black to foreground.</summary>
  775.     BrightForegroundBlack = 90,
  776.     /// <summary>Applies bold/bright red to foreground.</summary>
  777.     BrightForegroundRed = 91,
  778.     /// <summary>Applies bold/bright green to foreground.</summary>
  779.     BrightForegroundGreen = 92,
  780.     /// <summary>Applies bold/bright yellow to foreground.</summary>
  781.     BrightForegroundYellow = 93,
  782.     /// <summary>Applies bold/bright blue to foreground.</summary>
  783.     BrightForegroundBlue = 94,
  784.     /// <summary>Applies bold/bright magenta to foreground.</summary>
  785.     BrightForegroundMagenta = 95,
  786.     /// <summary>Applies bold/bright cyan to foreground.</summary>
  787.     BrightForegroundCyan = 96,
  788.     /// <summary>Applies bold/bright white to foreground.</summary>
  789.     BrightForegroundWhite = 97,
  790.     /// <summary>Applies bold/bright black to background.</summary>
  791.     BrightBackgroundBlack = 100,
  792.     /// <summary>Applies bold/bright red to background.</summary>
  793.     BrightBackgroundRed = 101,
  794.     /// <summary>Applies bold/bright green to background.</summary>
  795.     BrightBackgroundGreen = 102,
  796.     /// <summary>Applies bold/bright yellow to background.</summary>
  797.     BrightBackgroundYellow = 103,
  798.     /// <summary>Applies bold/bright blue to background.</summary>
  799.     BrightBackgroundBlue = 104,
  800.     /// <summary>Applies bold/bright magenta to background.</summary>
  801.     BrightBackgroundMagenta = 105,
  802.     /// <summary>Applies bold/bright cyan to background.</summary>
  803.     BrightBackgroundCyan = 106,
  804.     /// <summary>Applies bold/bright white to background.</summary>
  805.     BrightBackgroundWhite = 107,
  806. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement