mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-04 10:35:27 +08:00 
			
		
		
		
	Make VT-100 sequences easier to understand
This commit is contained in:
		
				
					committed by
					
						
						Phil Scott
					
				
			
			
				
	
			
			
			
						parent
						
							20650f1e7e
						
					
				
				
					commit
					1ed7e65fcb
				
			@@ -1,5 +1,6 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using static Spectre.Console.AnsiSequences;
 | 
			
		||||
 | 
			
		||||
namespace Spectre.Console
 | 
			
		||||
{
 | 
			
		||||
@@ -49,9 +50,8 @@ namespace Spectre.Console
 | 
			
		||||
                return text;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var ansiCodes = string.Join(";", result);
 | 
			
		||||
            var ansi = result.Length > 0
 | 
			
		||||
                ? $"\u001b[{ansiCodes}m{text}\u001b[0m"
 | 
			
		||||
                ? $"{SGR(result)}{text}{SGR(0)}"
 | 
			
		||||
                : text;
 | 
			
		||||
 | 
			
		||||
            if (style.Link != null && !_profile.Capabilities.Legacy)
 | 
			
		||||
@@ -65,7 +65,7 @@ namespace Spectre.Console
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var linkId = _linkHasher.GenerateId(link, text);
 | 
			
		||||
                ansi = $"\u001b]8;id={linkId};{link}\u001b\\{ansi}\u001b]8;;\u001b\\";
 | 
			
		||||
                ansi = $"{CSI}]8;id={linkId};{link}{CSI}\\{ansi}{CSI}]8;;{CSI}\\";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ansi;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using Spectre.Console.Rendering;
 | 
			
		||||
using static Spectre.Console.AnsiSequences;
 | 
			
		||||
 | 
			
		||||
namespace Spectre.Console
 | 
			
		||||
{
 | 
			
		||||
@@ -21,11 +22,11 @@ namespace Spectre.Console
 | 
			
		||||
 | 
			
		||||
        public void Clear(bool home)
 | 
			
		||||
        {
 | 
			
		||||
            Write(new ControlSequence("\u001b[2J"));
 | 
			
		||||
            Write(new ControlSequence(ED(2)));
 | 
			
		||||
 | 
			
		||||
            if (home)
 | 
			
		||||
            {
 | 
			
		||||
                Cursor.SetPosition(0, 0);
 | 
			
		||||
                Write(new ControlSequence(CUP(0, 0)));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using System;
 | 
			
		||||
using static Spectre.Console.AnsiSequences;
 | 
			
		||||
 | 
			
		||||
namespace Spectre.Console
 | 
			
		||||
{
 | 
			
		||||
@@ -15,11 +16,11 @@ namespace Spectre.Console
 | 
			
		||||
        {
 | 
			
		||||
            if (show)
 | 
			
		||||
            {
 | 
			
		||||
                _backend.Write(new ControlSequence("\u001b[?25h"));
 | 
			
		||||
                _backend.Write(new ControlSequence(SM(DECTCEM)));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                _backend.Write(new ControlSequence("\u001b[?25l"));
 | 
			
		||||
                _backend.Write(new ControlSequence(RM(DECTCEM)));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -33,23 +34,23 @@ namespace Spectre.Console
 | 
			
		||||
            switch (direction)
 | 
			
		||||
            {
 | 
			
		||||
                case CursorDirection.Up:
 | 
			
		||||
                    _backend.Write(new ControlSequence($"\u001b[{steps}A"));
 | 
			
		||||
                    _backend.Write(new ControlSequence(CUU(steps)));
 | 
			
		||||
                    break;
 | 
			
		||||
                case CursorDirection.Down:
 | 
			
		||||
                    _backend.Write(new ControlSequence($"\u001b[{steps}B"));
 | 
			
		||||
                    _backend.Write(new ControlSequence(CUD(steps)));
 | 
			
		||||
                    break;
 | 
			
		||||
                case CursorDirection.Right:
 | 
			
		||||
                    _backend.Write(new ControlSequence($"\u001b[{steps}C"));
 | 
			
		||||
                    _backend.Write(new ControlSequence(CUF(steps)));
 | 
			
		||||
                    break;
 | 
			
		||||
                case CursorDirection.Left:
 | 
			
		||||
                    _backend.Write(new ControlSequence($"\u001b[{steps}D"));
 | 
			
		||||
                    _backend.Write(new ControlSequence(CUB(steps)));
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SetPosition(int column, int line)
 | 
			
		||||
        {
 | 
			
		||||
            _backend.Write(new ControlSequence($"\u001b[{line};{column}H"));
 | 
			
		||||
            _backend.Write(new ControlSequence(CUP(line, column)));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										169
									
								
								src/Spectre.Console/Internal/Backends/Ansi/AnsiSequences.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/Spectre.Console/Internal/Backends/Ansi/AnsiSequences.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace Spectre.Console
 | 
			
		||||
{
 | 
			
		||||
    internal static class AnsiSequences
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Introduces a control sequence that uses 8-bit characters.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public const string CSI = "\u001b";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Text cursor enable.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/DECRQM.html#T5-8"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public const int DECTCEM = 25;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This control function selects one or more character attributes at the same time.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/SGR.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string SGR(params int[] codes)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + "[" + string.Join(";", codes.Select(c => c.ToString())) + "m";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This control function selects one or more character attributes at the same time.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/SGR.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string SGR(params byte[] codes)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + "[" + string.Join(";", codes.Select(c => c.ToString())) + "m";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This control function erases characters from part or all of the display.
 | 
			
		||||
        /// When you erase complete lines, they become single-height, single-width lines,
 | 
			
		||||
        /// with all visual character attributes cleared.
 | 
			
		||||
        /// ED works inside or outside the scrolling margins.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/ED.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string ED(int code)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[{code}J";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Moves the cursor up a specified number of lines in the same column.
 | 
			
		||||
        /// The cursor stops at the top margin.
 | 
			
		||||
        /// If the cursor is already above the top margin, then the cursor stops at the top line.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/CUU.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <param name="steps">The number of steps to move up.</param>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string CUU(int steps)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[{steps}A";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This control function moves the cursor down a specified number of lines in the same column.
 | 
			
		||||
        /// The cursor stops at the bottom margin.
 | 
			
		||||
        /// If the cursor is already below the bottom margin, then the cursor stops at the bottom line.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/CUD.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <param name="steps">The number of steps to move down.</param>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string CUD(int steps)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[{steps}B";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This control function moves the cursor to the right by a specified number of columns.
 | 
			
		||||
        /// The cursor stops at the right border of the page.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/CUF.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <param name="steps">The number of steps to move forward.</param>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string CUF(int steps)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[{steps}C";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This control function moves the cursor to the left by a specified number of columns.
 | 
			
		||||
        /// The cursor stops at the left border of the page.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/CUB.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <param name="steps">The number of steps to move backward.</param>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string CUB(int steps)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[{steps}D";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Moves the cursor to the specified position.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="line">The line to move to.</param>
 | 
			
		||||
        /// <param name="column">The column to move to.</param>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/CUP.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string CUP(int line, int column)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[{line};{column}H";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Hides the cursor.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/RM.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string RM(int code)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[?{code}l";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Shows the cursor.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/SM.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string SM(int code)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[?{code}h";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This control function erases characters on the line that has the cursor.
 | 
			
		||||
        /// EL clears all character attributes from erased character positions.
 | 
			
		||||
        /// EL works inside or outside the scrolling margins.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// See <see href="https://vt100.net/docs/vt510-rm/EL.html"/>.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <returns>The ANSI escape code.</returns>
 | 
			
		||||
        public static string EL(int code)
 | 
			
		||||
        {
 | 
			
		||||
            return CSI + $"[{code}K";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user