From 02e9e56eef63fa4e4a2fde4e734f8c5ba9631e6e Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Fri, 26 Dec 2025 04:04:08 -0800 Subject: [PATCH] Move more handlers into testWindow.ts --- demo/client.ts | 500 -------------------------- demo/components/window/testWindow.ts | 506 ++++++++++++++++++++++++++- 2 files changed, 496 insertions(+), 510 deletions(-) diff --git a/demo/client.ts b/demo/client.ts index 1c2508e8..4fd85611 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -301,23 +301,13 @@ if (document.location.pathname === '/test') { document.getElementById('create-new-window').addEventListener('click', createNewWindowButtonHandler); document.getElementById('serialize').addEventListener('click', serializeButtonHandler); document.getElementById('htmlserialize').addEventListener('click', htmlSerializeButtonHandler); - document.getElementById('custom-glyph-alignment').addEventListener('click', customGlyphAlignmentHandler); - document.getElementById('custom-glyph-ranges').addEventListener('click', customGlyphRangesHandler); document.getElementById('load-test').addEventListener('click', loadTest); document.getElementById('load-test-long-lines').addEventListener('click', loadTestLongLines); - document.getElementById('print-cjk-sgr').addEventListener('click', addCjkRandomSgr); - document.getElementById('powerline-symbol-test').addEventListener('click', powerlineSymbolTest); - document.getElementById('underline-test').addEventListener('click', underlineTest); - document.getElementById('ansi-colors').addEventListener('click', ansiColorsTest); - document.getElementById('osc-hyperlinks').addEventListener('click', addAnsiHyperlink); - document.getElementById('sgr-test').addEventListener('click', sgrTest); - document.getElementById('add-grapheme-clusters').addEventListener('click', addGraphemeClusters); document.getElementById('add-decoration').addEventListener('click', addDecoration); document.getElementById('add-overview-ruler').addEventListener('click', addOverviewRuler); document.getElementById('decoration-stress-test').addEventListener('click', decorationStressTest); document.getElementById('ligatures-test').addEventListener('click', ligaturesTest); document.getElementById('weblinks-test').addEventListener('click', testWeblinks); - document.getElementById('bce').addEventListener('click', coloredErase); initImageAddonExposed(); testEvents(); progressButtons(); @@ -662,190 +652,6 @@ function htmlSerializeButtonHandler(): void { document.getElementById('htmlserialize-output-result').innerText = 'Copied to clipboard'; } - - -function customGlyphAlignmentHandler(): void { - term.write('\n\r'); - term.write('\n\r'); - term.write('Box styles: ┎┰┒┍┯┑╓╥╖╒╤╕ ┏┳┓┌┲┓┌┬┐┏┱┐\n\r'); - term.write('┌─┬─┐ ┏━┳━┓ ╔═╦═╗ ┠╂┨┝┿┥╟╫╢╞╪╡ ┡╇┩├╊┫┢╈┪┣╉┤\n\r'); - term.write('│ │ │ ┃ ┃ ┃ ║ ║ ║ ┖┸┚┕┷┙╙╨╜╘╧╛ └┴┘└┺┛┗┻┛┗┹┘\n\r'); - term.write('├─┼─┤ ┣━╋━┫ ╠═╬═╣ ┏┱┐┌┲┓┌┬┐┌┬┐ ┏┳┓┌┮┓┌┬┐┏┭┐\n\r'); - term.write('│ │ │ ┃ ┃ ┃ ║ ║ ║ ┡╃┤├╄┩├╆┪┢╅┤ ┞╀┦├┾┫┟╁┧┣┽┤\n\r'); - term.write('└─┴─┘ ┗━┻━┛ ╚═╩═╝ └┴┘└┴┘└┺┛┗┹┘ └┴┘└┶┛┗┻┛┗┵┘\n\r'); - term.write('\n\r'); - - term.write('Other:\n\r'); - term.write('╭─╮ ╲ ╱ ╷╻╎╏┆┇┊┋ ╺╾╴ ╌╌╌ ┄┄┄ ┈┈┈\n\r'); - term.write('│ │ ╳ ╽╿╎╏┆┇┊┋ ╶╼╸ ╍╍╍ ┅┅┅ ┉┉┉\n\r'); - term.write('╰─╯ ╱ ╲ ╹╵╎╏┆┇┊┋\n\r'); - term.write('\n\r'); - - term.write('Box drawing alignment tests:\x1b[31m █\n\r'); - term.write(' ▉\n\r'); - term.write(' ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳\n\r'); - term.write(' ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳\n\r'); - term.write(' ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳\n\r'); - term.write(' ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳\n\r'); - term.write(' ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎\n\r'); - term.write(' ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏\n\r'); - term.write(' ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█\n\r'); - term.write('\x1b[0mBox drawing alignment tests:\x1b[32m █\n\r'); - term.write(' ▉\n\r'); - term.write(' ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳\n\r'); - term.write(' ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳\n\r'); - term.write(' ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳\n\r'); - term.write(' ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳\n\r'); - term.write(' ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎\n\r'); - term.write(' ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏\n\r'); - term.write(' ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█\n\r'); - - term.write('\x1b[0mSmooth mosaic terminal graphic characters alignment tests:\x1b[33m\n\r'); - term.write(' 🭇🬼 🭈🬽 🭉🬾 🭊🬿 🭋🭀 🭁🭌 🭂🭍 🭃🭎 🭄🭏 🭅🭐 🭆🭑 🭨🭪 🭩 🭯 🭮🭬\n\r'); - term.write(' 🭢🭗 🭣🭘 🭤🭙 🭥🭚 🭦🭛 🭒🭝 🭓🭞 🭔🭟 🭕🭠 🭖🭡 🭧🭜 🭫 🭭\n\r'); - term.write(' 🭇🬼 🭉🬾 🭋🭀\n\r'); - term.write(' 🭊🭁🭌🬿 🭈🭆🭂🭍🭑🬽 🭇🭄🭏🬼 🭃🭎 🭅🭐 🭨🭪\n\r'); - term.write(' 🭥🭒🭝🭚 🭣🭧🭓🭞🭜🭘 🭢🭕🭠🭗 🭔🭟 🭖🭡 🭪🭨\n\r'); - term.write(' 🭢🭗 🭤🭙 🭦🭛\n\r'); - - term.write('\x1b[0mCharacter cell diagonals (1FBA0-1FBAE) alignment tests:\x1b[34m\n\r'); - term.write(' \u{1FBA3}\u{1FBA7}\u{1FBA2} \u{1FBA3}\u{1FBA8}\u{1FBA0} \u{1FBAD}\u{1FBA2} \u{1FBA3}\u{1FBAC} \u{1FBAE}\n\r'); - term.write(' \u{1FBA3}\u{1FBA0} \u{1FBA1}\u{1FBA2} \u{1FBA1}\u{1FBA9}\u{1FBA2} \u{1FBA1}\u{1FBAA} \u{1FBAB}\u{1FBA0}\n\r'); - term.write(' \u{1FBA4} \u{1FBA5}\n\r'); - term.write(' \u{1FBA1}\u{1FBA2} \u{1FBA3}\u{1FBA0}\n\r'); - term.write(' \u{1FBA1}\u{1FBA6}\u{1FBA0}\n\r'); - - term.write('\x1b[0mCharacter cell diagonals (1FBD0-1FBDF) alignment tests:\x1b[34m\n\r'); - term.write(' \u{1FBD6}\u{1FBD4} \u{1FBD0}\u{1FBD1}\u{1FBD2}\u{1FBD3} \u{1FBDA} \u{1FBD9}\u{1FBDB} \u{1FBDE} \u{1FBDD}\u{1FBDF}\n\r'); - term.write(' \u{1FBD7}\u{1FBD5} \u{1FBD2}\u{1FBD3}\u{1FBD0}\u{1FBD1} \u{1FBD8} \u{1FBDC}\n\r'); - term.write(' \u{1FBD4}\u{1FBD6}\n\r'); - term.write(' \u{1FBD5}\u{1FBD7}\n\r'); - term.write(''); - - term.write('\x1b[0mComposite terminal graphics characters:\x1b[35m\n\r'); - term.write('\u{1FBB2}\u{1FBB3} \u{1FBB9}\u{1FBBA} \u{1FBC1}\u{1FBC2}\u{1FBC3}\n\r'); - - term.write('\x1b[0mFill tests:\x1b[36m\n\r'); - const fillChars = ['\u{2591}', '\u{2592}', '\u{2593}', '\u{1FB8C}', '\u{1FB8D}', '\u{1FB8E}', '\u{1FB8F}', '\u{1FB90}', '\u{1FB91}', '\u{1FB92}', '\u{1FB94}', '\u{1FB95}', '\u{1FB96}', '\u{1FB97}', '\u{1FB98}', '\u{1FB99}']; - while (fillChars.length > 0) { - const batch = fillChars.splice(0, 10); - for (const fillChar of batch) { - term.write(`${fillChar.codePointAt(0).toString(16).toUpperCase().padEnd(5, ' ')} `); - } - term.write('\n\r'); - for (let i = 0; i < 3; i++) { - for (const fillChar of batch) { - term.write(fillChar.repeat(5)); - term.write(' '); - } - term.write('\n\r'); - } - } - - term.write('\x1b[0mPowerline alignment tests:\n\r'); - const powerlineLeftChars = ['\u{E0B2}', '\u{E0B3}', '\u{E0B6}', '\u{E0B7}', '\u{E0BA}', '\u{E0BB}', '\u{E0BE}', '\u{E0BF}', '\u{E0C2}', '\u{E0C3}', '\u{E0C5}', '\u{E0C7}', '\u{E0CA}', '\u{E0D4}']; - const powerlineRightChars = ['\u{E0B0}', '\u{E0B1}', '\u{E0B4}', '\u{E0B5}', '\u{E0B8}', '\u{E0B9}', '\u{E0BC}', '\u{E0BD}', '\u{E0C0}', '\u{E0C1}', '\u{E0C4}', '\u{E0C6}', '\u{E0C8}', '\u{E0D2}', '\u{E0CC}', '\u{E0CD}', '\u{E0CE}', '\u{E0CF}', '\u{E0D0}', '\u{E0D1}']; - for (const char of powerlineLeftChars) { - term.write(`\x1b[31m${char}\x1b[0;41m \x1b[0m `); - } - term.write('\n\r'); - for (const char of powerlineRightChars) { - term.write(`\x1b[41m \x1b[0;31m${char}\x1b[0m `); - } - term.write('\n\r'); - - term.write('\x1b[0mGit Branch Symbols alignment tests:\x1b[32m\n\r'); - term.write(' \u{F5F7}\u{F5F7} \u{F5EE}\u{F5EF} \u{F5F6}\u{F5F7} \u{F5D6}\u{F5D0}\u{F5D7} \u{F5FC}\u{F5FC}\u{F5FE} \u{F5FD}\u{F609}\u{F5FF}\n\r'); - term.write(' \u{F5DA}\u{F5DD} \u{F5F0}\u{F5F4}\u{F5F2} \u{F5FA}\u{F5FB} \u{F5D1} \u{F5D1} \u{F604}\u{F60C}\u{F606} \u{F605}\u{F60D}\u{F607}\n\r'); - term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D8}\u{F5D0}\u{F5D9} \u{F600}\u{F60A}\u{F602} \u{F601}\u{F60B}\u{F603}\n\r'); - term.write(' \u{F5DC}\u{F5DF} \u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\n\r'); - term.write('\u{F5F1}\u{F5E6}\u{F5E7}\u{F5F3} \u{F5D3}\u{F5D0}\u{F5E0}\u{F5E1}\u{F5E2}\u{F5E3}\u{F5E4}\u{F5E5}\u{F5E8}\u{F5E9}\u{F5EC}\u{F5ED}\u{F5D2}\n\r'); - term.write('\u{F5F1}\u{F5EA}\u{F5EB}\u{F5F3} \u{F5F9}\u{F5F9}\u{F5F9} \u{F5F9}\u{F5F9}\u{F5F9}\u{F5F9}\n\r'); - term.write(' \u{F5F9}\u{F5F9} \n\r'); - term.write('\x1b[0m'); - term.write('\n\r'); - window.scrollTo(0, 0); -} - -function customGlyphRangesHandler(): void { - // Box Drawing - // 2500-257F - // https://www.unicode.org/charts/PDF/U2500.pdf - writeUnicodeTable(term, 'Box Drawing', 0x2500, 0x257F, [ - ['Light and heavy solid lines', 0x2500, 0x2503], - ['Light and heavy dashed lines', 0x2504, 0x250B], - ['Light and heavy line box components', 0x250C, 0x254B], - ['Light and heavy dashed lines', 0x254C, 0x254F], - ['Double lines', 0x2550, 0x2551], - ['Light and double line box components', 0x2552, 0x256C], - ['Character cell arcs', 0x256D, 0x2570], - ['Character cell diagonals', 0x2571, 0x2573], - ['Light and heavy half lines', 0x2574, 0x257B], - ['Mixed light and heavy lines', 0x257C, 0x257F], - ]); - // Box Elements - // 2580-259F - // https://www.unicode.org/charts/PDF/U2580.pdf - writeUnicodeTable(term, 'Box Elements', 0x2580, 0x259F, [ - ['Block elements', 0x2580, 0x2590], - ['Shade characters', 0x2591, 0x2593], - ['Block elements', 0x2594, 0x2595], - ['Terminal graphic characters', 0x2596, 0x259F], - ]); - // Braille Patterns - // 2800-28FF - // https://www.unicode.org/charts/PDF/U2800.pdf - writeUnicodeTable(term, 'Braille patterns', 0x2800, 0x28FF, [ - ['Braille patterns', 0x2800, 0x28FF], - ]); - // Powerline Symbols - // Range: E0A0–E0D4 - // https://github.com/ryanoasis/nerd-fonts - writeUnicodeTable(term, 'Powerline Symbols', 0xE0A0, 0xE0D4, [ - ['Powerline symbols', 0xE0A0, 0xE0B3, [0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, 0xE0A8, 0xE0A9, 0xE0AA, 0xE0AB, 0xE0AC, 0xE0AD, 0xE0AE, 0xE0AF]], - ['Powerline extra symbols', 0xE0B4, 0xE0D4, [0xE0C9, 0xE0CB, 0xE0D3]], - ]); - // Git Branch Symbols - // F5D0-F60D - // https://github.com/xtermjs/xterm.js/issues/5477 - writeUnicodeTable(term, 'Git Branch Symbols', 0xF5D0, 0xF5FB, [ - ['Straight lines', 0xF5D0, 0xF5D5], - ['Curved lines', 0xF5D6, 0xF5D9], - ['Branching lines', 0xF5DA, 0xF5ED], - ['Nodes', 0xF5EE, 0xF5FB], - ['Extended nodes', 0xF5FC, 0xF60D], - ]); - // Symbols for Legacy Computing - // Range: 1FB00–1FBFF - // https://www.unicode.org/charts/PDF/U1FB00.pdf - writeUnicodeTable(term, 'Symbols for Legacy Computing', 0x1FB00, 0x1FBFF, [ - ['Block mosaic terminal graphic characters (Sextants)', 0x1FB00, 0x1FB3B], - ['Smooth mosaic terminal graphic characters', 0x1FB3C, 0x1FB6F], - ['Block elements', 0x1FB70, 0x1FB80], - ['Window title bar', 0x1FB81, 0x1FB81], - ['Block elements', 0x1FB82, 0x1FB8B], - ['Rectangular shade characters', 0x1FB8C, 0x1FB94, [0x1FB93]], - ['Fill characters', 0x1FB95, 0x1FB97], - ['Diagonal fill characters', 0x1FB98, 0x1FB99], - ['Smooth mosaic terminal graphic characters', 0x1FB9A, 0x1FB9B], - ['Triangular shade characters', 0x1FB9C, 0x1FB9F], - ['Character cell diagonals', 0x1FBA0, 0x1FBAE], - ['Light solid line with stroke', 0x1FBAF, 0x1FBAF], - ['Terminal graphic characters', 0x1FBB0, 0x1FBB3], - ['Arrows', 0x1FBB4, 0x1FBB8], - ['Terminal graphic characters', 0x1FBB9, 0x1FBBC], - ['Negative terminal graphic characters', 0x1FBBD, 0x1FBBF], - ['Terminal graphic characters', 0x1FBC0, 0x1FBCA], - ['Terminal graphic characters', 0x1FBCB, 0x1FBCD], - ['Block elements', 0x1FBCE, 0x1FBCF], - ['Character cell diagonals', 0x1FBD0, 0x1FBDF], - ['Geometrics shapes', 0x1FBE0, 0x1FBEF], - ['Segmented digits', 0x1FBF0, 0x1FBF9], - ['Terminal graphic character', 0x1FBFA, 0x1FBFA], - ]); -} - - function loadTest(): void { const rendererName = addons.webgl.instance ? 'webgl' : 'dom'; const testData = []; @@ -912,295 +718,6 @@ function loadTestLongLines(): void { }); } -function powerlineSymbolTest(): void { - function s(char: string): string { - return `${char} \x1b[7m${char}\x1b[0m `; - } - term.write('\n\n\r'); - term.writeln('Standard powerline symbols:'); - term.writeln(' 0 1 2 3 4 5 6 7 8 9 A B C D E F'); - term.writeln(`0xA_ ${s('\ue0a0')}${s('\ue0a1')}${s('\ue0a2')}`); - term.writeln(`0xB_ ${s('\ue0b0')}${s('\ue0b1')}${s('\ue0b2')}${s('\ue0b3')}`); - term.writeln(''); - term.writeln( - `\x1b[7m` + - ` inverse \ue0b1 \x1b[0;40m\ue0b0` + - ` 0 \ue0b1 \x1b[30;41m\ue0b0\x1b[39m` + - ` 1 \ue0b1 \x1b[31;42m\ue0b0\x1b[39m` + - ` 2 \ue0b1 \x1b[32;43m\ue0b0\x1b[39m` + - ` 3 \ue0b1 \x1b[33;44m\ue0b0\x1b[39m` + - ` 4 \ue0b1 \x1b[34;45m\ue0b0\x1b[39m` + - ` 5 \ue0b1 \x1b[35;46m\ue0b0\x1b[39m` + - ` 6 \ue0b1 \x1b[36;47m\ue0b0\x1b[30m` + - ` 7 \ue0b1 \x1b[37;49m\ue0b0\x1b[0m` - ); - term.writeln(''); - term.writeln( - `\x1b[7m` + - ` inverse \ue0b3 \x1b[0;7;40m\ue0b2\x1b[27m` + - ` 0 \ue0b3 \x1b[7;30;41m\ue0b2\x1b[27;39m` + - ` 1 \ue0b3 \x1b[7;31;42m\ue0b2\x1b[27;39m` + - ` 2 \ue0b3 \x1b[7;32;43m\ue0b2\x1b[27;39m` + - ` 3 \ue0b3 \x1b[7;33;44m\ue0b2\x1b[27;39m` + - ` 4 \ue0b3 \x1b[7;34;45m\ue0b2\x1b[27;39m` + - ` 5 \ue0b3 \x1b[7;35;46m\ue0b2\x1b[27;39m` + - ` 6 \ue0b3 \x1b[7;36;47m\ue0b2\x1b[27;30m` + - ` 7 \ue0b3 \x1b[7;37;49m\ue0b2\x1b[0m` - ); - term.writeln(''); - term.writeln( - `\x1b[7m` + - ` inverse \ue0b5 \x1b[0;40m\ue0b4` + - ` 0 \ue0b5 \x1b[30;41m\ue0b4\x1b[39m` + - ` 1 \ue0b5 \x1b[31;42m\ue0b4\x1b[39m` + - ` 2 \ue0b5 \x1b[32;43m\ue0b4\x1b[39m` + - ` 3 \ue0b5 \x1b[33;44m\ue0b4\x1b[39m` + - ` 4 \ue0b5 \x1b[34;45m\ue0b4\x1b[39m` + - ` 5 \ue0b5 \x1b[35;46m\ue0b4\x1b[39m` + - ` 6 \ue0b5 \x1b[36;47m\ue0b4\x1b[30m` + - ` 7 \ue0b5 \x1b[37;49m\ue0b4\x1b[0m` - ); - term.writeln(''); - term.writeln( - `\x1b[7m` + - ` inverse \ue0b7 \x1b[0;7;40m\ue0b6\x1b[27m` + - ` 0 \ue0b7 \x1b[7;30;41m\ue0b6\x1b[27;39m` + - ` 1 \ue0b7 \x1b[7;31;42m\ue0b6\x1b[27;39m` + - ` 2 \ue0b7 \x1b[7;32;43m\ue0b6\x1b[27;39m` + - ` 3 \ue0b7 \x1b[7;33;44m\ue0b6\x1b[27;39m` + - ` 4 \ue0b7 \x1b[7;34;45m\ue0b6\x1b[27;39m` + - ` 5 \ue0b7 \x1b[7;35;46m\ue0b6\x1b[27;39m` + - ` 6 \ue0b7 \x1b[7;36;47m\ue0b6\x1b[27;30m` + - ` 7 \ue0b7 \x1b[7;37;49m\ue0b6\x1b[0m` - ); - term.writeln(''); - term.writeln('Powerline extra symbols:'); - term.writeln(' 0 1 2 3 4 5 6 7 8 9 A B C D E F'); - term.writeln(`0xA_ ${s('\ue0a3')}`); - term.writeln(`0xB_ ${s('\ue0b4')}${s('\ue0b5')}${s('\ue0b6')}${s('\ue0b7')}${s('\ue0b8')}${s('\ue0b9')}${s('\ue0ba')}${s('\ue0bb')}${s('\ue0bc')}${s('\ue0bd')}${s('\ue0be')}${s('\ue0bf')}`); - term.writeln(`0xC_ ${s('\ue0c0')}${s('\ue0c1')}${s('\ue0c2')}${s('\ue0c3')}${s('\ue0c4')}${s('\ue0c5')}${s('\ue0c6')}${s('\ue0c7')}${s('\ue0c8')}${s('\ue0c9')}${s('\ue0ca')}${s('\ue0cb')}${s('\ue0cc')}${s('\ue0cd')}${s('\ue0be')}${s('\ue0bf')}`); - term.writeln(`0xD_ ${s('\ue0d0')}${s('\ue0d1')}${s('\ue0d2')} ${s('\ue0d4')}`); - term.writeln(''); - term.writeln('Sample of nerd fonts icons:'); - term.writeln(' nf-linux-apple (\\uF302) \uf302'); - term.writeln('nf-mdi-github_face (\\uFbd9) \ufbd9'); -} - -function underlineTest(): void { - function u(style: number): string { - return `\x1b[4:${style}m`; - } - function c(color: string): string { - return `\x1b[58:${color}m`; - } - term.write('\n\n\r'); - term.writeln('Underline styles:'); - term.writeln(''); - function showSequence(id: number, name: string): string { - let alphabet = ''; - for (let i = 97; i < 123; i++) { - alphabet += String.fromCharCode(i); - } - let numbers = ''; - for (let i = 0; i < 10; i++) { - numbers += i.toString(); - } - return `${u(id)}4:${id}m - ${name}\x1b[4:0m`.padEnd(33, ' ') + `${u(id)}${alphabet} ${numbers} 汉语 한국어 👽\x1b[4:0m`; - } - term.writeln(showSequence(0, 'No underline')); - term.writeln(showSequence(1, 'Straight')); - term.writeln(showSequence(2, 'Double')); - term.writeln(showSequence(3, 'Curly')); - term.writeln(showSequence(4, 'Dotted')); - term.writeln(showSequence(5, 'Dashed')); - term.writeln(''); - term.writeln(`Underline colors (256 color mode):`); - term.writeln(''); - for (let i = 0; i < 256; i++) { - term.write((i !== 0 ? '\x1b[0m, ' : '') + u(1 + i % 5) + c('5:' + i) + i); - } - term.writeln(`\x1b[0m\n\n\rUnderline colors (true color mode):`); - term.writeln(''); - for (let i = 0; i < 80; i++) { - const v = Math.round(i / 79 * 255); - term.write(u(1) + c(`2:0:${v}:${v}:${v}`) + (i < 4 ? 'grey'[i] : ' ')); - } - term.write('\n\r'); - for (let i = 0; i < 80; i++) { - const v = Math.round(i / 79 * 255); - term.write(u(1) + c(`2:0:${v}:${0}:${0}`) + (i < 3 ? 'red'[i] : ' ')); - } - term.write('\n\r'); - for (let i = 0; i < 80; i++) { - const v = Math.round(i / 79 * 255); - term.write(u(1) + c(`2:0:${0}:${v}:${0}`) + (i < 5 ? 'green'[i] : ' ')); - } - term.write('\n\r'); - for (let i = 0; i < 80; i++) { - const v = Math.round(i / 79 * 255); - term.write(u(1) + c(`2:0:${0}:${0}:${v}`) + (i < 4 ? 'blue'[i] : ' ')); - } - term.write('\x1b[0m\n\r'); -} - -function ansiColorsTest(): void { - term.writeln(`\x1b[0m\n\n\rStandard colors: Bright colors:`); - for (let i = 0; i < 16; i++) { - term.write(`\x1b[48;5;${i}m ${i.toString().padEnd(2, ' ').padStart(3, ' ')} \x1b[0m`); - } - - term.writeln(`\x1b[0m\n\n\rColors 17-231 from 256 palette:`); - for (let i = 0; i < 6; i++) { - const startId = 16 + i * 36; - const endId = 16 + (i + 1) * 36 - 1; - term.write(`${startId.toString().padStart(3, ' ')}-${endId.toString().padStart(3, ' ')} `); - for (let j = 0; j < 36; j++) { - const id = 16 + i * 36 + j; - term.write(`\x1b[48;5;${id}m${(id % 10).toString().padStart(2, ' ')}\x1b[0m`); - } - term.write(`\r\n`); - } - - term.writeln(`\x1b[0m\n\rGreyscale from 256 palette:`); - term.write('232-255 '); - for (let i = 232; i < 256; i++) { - term.write(`\x1b[48;5;${i}m ${(i % 10)} \x1b[0m`); - } -} - -function writeTestString(): string { - let alphabet = ''; - for (let i = 97; i < 123; i++) { - alphabet += String.fromCharCode(i); - } - let numbers = ''; - for (let i = 0; i < 10; i++) { - numbers += i.toString(); - } - return `${alphabet} ${numbers} 汉语 한국어 👽`; -} -const testString = writeTestString(); - -function sgrTest(): void { - term.write('\n\n\r'); - term.writeln(`Character Attributes (SGR, Select Graphic Rendition)`); - const entries: { ps: number, name: string }[] = [ - { ps: 0, name: 'Normal' }, - { ps: 1, name: 'Bold' }, - { ps: 2, name: 'Faint/dim' }, - { ps: 3, name: 'Italicized' }, - { ps: 4, name: 'Underlined' }, - { ps: 5, name: 'Blink' }, - { ps: 7, name: 'Inverse' }, - { ps: 8, name: 'Invisible' }, - { ps: 9, name: 'Crossed-out characters' }, - { ps: 21, name: 'Doubly-underlined' }, - { ps: 22, name: 'Normal' }, - { ps: 23, name: 'Not italicized' }, - { ps: 24, name: 'Not underlined' }, - { ps: 25, name: 'Steady (not blink)' }, - { ps: 27, name: 'Positive (not inverse)' }, - { ps: 28, name: 'Visible (not hidden)' }, - { ps: 29, name: 'Not crossed-out' }, - { ps: 30, name: 'Foreground Black' }, - { ps: 31, name: 'Foreground Red' }, - { ps: 32, name: 'Foreground Green' }, - { ps: 33, name: 'Foreground Yellow' }, - { ps: 34, name: 'Foreground Blue' }, - { ps: 35, name: 'Foreground Magenta' }, - { ps: 36, name: 'Foreground Cyan' }, - { ps: 37, name: 'Foreground White' }, - { ps: 39, name: 'Foreground default' }, - { ps: 40, name: 'Background Black' }, - { ps: 41, name: 'Background Red' }, - { ps: 42, name: 'Background Green' }, - { ps: 43, name: 'Background Yellow' }, - { ps: 44, name: 'Background Blue' }, - { ps: 45, name: 'Background Magenta' }, - { ps: 46, name: 'Background Cyan' }, - { ps: 47, name: 'Background White' }, - { ps: 49, name: 'Background default' }, - { ps: 53, name: 'Overlined' }, - { ps: 55, name: 'Not overlined' } - ]; - const maxNameLength = entries.reduce((p, c) => Math.max(c.name.length, p), 0); - for (const e of entries) { - term.writeln(`\x1b[0m\x1b[${e.ps}m ${e.ps.toString().padEnd(2, ' ')} ${e.name.padEnd(maxNameLength, ' ')} - ${testString}\x1b[0m`); - } - const entriesByPs: Map = new Map(); - for (const e of entries) { - entriesByPs.set(e.ps, e.name); - } - const comboEntries: { ps: number[] }[] = [ - { ps: [1, 2, 3, 4, 5, 6, 7, 9] }, - { ps: [2, 41] }, - { ps: [4, 53] } - ]; - term.write('\n\n\r'); - term.writeln(`Combinations`); - for (const e of comboEntries) { - const name = e.ps.map(e => entriesByPs.get(e)).join(', '); - term.writeln(`\x1b[0m\x1b[${e.ps.join(';')}m ${name}\n\r${testString}\x1b[0m`); - } -} - -function addAnsiHyperlink(): void { - term.write('\n\n\r'); - term.writeln(`Regular link with no id:`); - term.writeln('\x1b]8;;https://github.com\x07GitHub\x1b]8;;\x07'); - term.writeln('\x1b]8;;https://xtermjs.org\x07https://xtermjs.org\x1b]8;;\x07\x1b[C<- null cell'); - term.writeln(`\nAdjacent links:`); - term.writeln('\x1b]8;;https://github.com\x07GitHub\x1b]8;;https://xtermjs.org\x07\x1b[32mxterm.js\x1b[0m\x1b]8;;\x07'); - term.writeln(`\nShared ID link (underline should be shared):`); - term.writeln('╔════╗'); - term.writeln('║\x1b]8;id=testid;https://github.com\x07GitH\x1b]8;;\x07║'); - term.writeln('║\x1b]8;id=testid;https://github.com\x07ub\x1b]8;;\x07 ║'); - term.writeln('╚════╝'); - term.writeln(`\nWrapped link with no ID (not necessarily meant to share underline):`); - term.writeln('╔════╗'); - term.writeln('║ ║'); - term.writeln('║ ║'); - term.writeln('╚════╝'); - term.write('\x1b[3A\x1b[1C\x1b]8;;https://xtermjs.org\x07xter\x1b[B\x1b[4Dm.js\x1b]8;;\x07\x1b[2B\x1b[5D'); -} - -/** - * Prints the 20977 characters from the CJK Unified Ideographs unicode block with randomized styles. - */ -function addCjkRandomSgr(): void { - term.write('\n\n\r'); - for (let i = 0x4E00; i < 0x9FCC; i++) { - term.write(`\x1b[${getRandomSgr()}m${String.fromCharCode(i)}\x1b[0m`); - } -} -const randomSgrAttributes = [ - '1', '2', '3', '4', '5', '6', '7', '9', - '21', '22', '23', '24', '25', '26', '27', '28', '29', - '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', - '40', '41', '42', '43', '44', '45', '46', '47', '48', '49' -]; -function getRandomSgr(): string { - return randomSgrAttributes[Math.floor(Math.random() * randomSgrAttributes.length)]; -} - -function addGraphemeClusters(): void { - term.write('\n\n\r'); - term.writeln('🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣 [Simple emoji v6: 10 cells, v15: 20 cells]'); - term.writeln('\u{1F476}\u{1F3FF}\u{1F476} [baby with emoji modifier fitzpatrick type-6; baby]'); - term.writeln('\u{1F469}\u200d\u{1f469}\u200d\u{1f466} [woman+zwj+woman+zwj+boy]'); - term.writeln('\u{1F64B}\u{1F64B}\u{200D}\u{2642}\u{FE0F} [person/man raising hand]'); - term.writeln('\u{1F3CB}\u{FE0F}=\u{1F3CB}\u{1F3FE}\u{200D}\u{2640}\u{FE0F} [person lifting weights emoji; woman lighting weights, medium dark]'); - term.writeln('\u{1F469}\u{1F469}\u{200D}\u{1F393}\u{1F468}\u{1F3FF}\u{200D}\u{1F393} [woman; woman student; man student dark]'); - term.writeln('\u{1f1f3}\u{1f1f4}_ [REGIONAL INDICATOR SYMBOL LETTER N and RI O]'); - term.writeln('\u{1f1f3}_\u{1f1f4} {RI N; underscore; RI O]'); - term.writeln('\u0061\u0301 [letter a with acute accent]'); - term.writeln('\u1100\u1161\u11A8=\u1100\u1161= [Korean Jamo]'); - term.writeln('\uAC00=\uD685= [Hangul syllables (pre-composed)]'); - term.writeln('(\u26b0\ufe0e) [coffin with text_presentation]'); - term.writeln('(\u26b0\ufe0f) [coffin with Emoji_presentation]'); - term.writeln(' [Égalité (using separate acute) emoij_presentation]'); -} - function addDecoration(): void { term.options['overviewRuler'] = { width: 14 }; const marker = term.registerMarker(1); @@ -1322,23 +839,6 @@ stop at final '?': Maybe this one http://example.com/with?arguments=false? term.write(linkExamples.split('\n').join('\r\n')); } - -function coloredErase(): void { - const sp5 = ' '; - const data = ` -Test BG-colored Erase (BCE): - The color block in the following lines should look identical. - For newly created rows at the bottom the last color should be applied - for all cells to the right. - - def 41 42 43 44 45 46 47\x1b[47m -\x1b[m${sp5}\x1b[41m${sp5}\x1b[42m${sp5}\x1b[43m${sp5}\x1b[44m${sp5}\x1b[45m${sp5}\x1b[46m${sp5}\x1b[47m${sp5} -\x1b[m\x1b[5X\x1b[41m\x1b[5C\x1b[5X\x1b[42m\x1b[5C\x1b[5X\x1b[43m\x1b[5C\x1b[5X\x1b[44m\x1b[5C\x1b[5X\x1b[45m\x1b[5C\x1b[5X\x1b[46m\x1b[5C\x1b[5X\x1b[47m\x1b[5C\x1b[5X\x1b[m -`; - term.write(data.split('\n').join('\r\n')); -} - - function initImageAddonExposed(): void { const DEFAULT_OPTIONS: IImageAddonOptions = (addons.image.instance as any)._defaultOpts; const limitStorageElement = document.querySelector('#image-storagelimit'); diff --git a/demo/components/window/testWindow.ts b/demo/components/window/testWindow.ts index 5456aa6a..3ae50948 100644 --- a/demo/components/window/testWindow.ts +++ b/demo/components/window/testWindow.ts @@ -5,6 +5,7 @@ /// +import { writeUnicodeTable } from 'unicodeTable'; import type { IControlWindow } from '../controlBar'; import type { Terminal } from '@xterm/xterm'; @@ -39,19 +40,19 @@ export class TestWindow implements IControlWindow { this._addDdWithButton(dl, 'load-test', 'Load test', 'Write several MB of data to simulate a lot of data coming from the process'); this._addDdWithButton(dl, 'load-test-long-lines', 'Load test (long lines)', 'Write several MB of data with long lines to simulate a lot of data coming from the process'); this._addDdWithButton(dl, 'print-cjk', 'CJK Unified Ideographs', 'Prints the 20977 characters from the CJK Unified Ideographs unicode block', () => addCjk(this._terminal)); - this._addDdWithButton(dl, 'print-cjk-sgr', 'CJK Unified Ideographs (random SGR)', 'Prints the 20977 characters from the CJK Unified Ideographs unicode block with randomized SGR attributes'); + this._addDdWithButton(dl, 'print-cjk-sgr', 'CJK Unified Ideographs (random SGR)', 'Prints the 20977 characters from the CJK Unified Ideographs unicode block with randomized SGR attributes', () => addCjkRandomSgr(this._terminal)); // Styles section this._addDt(dl, 'Styles'); - this._addDdWithButton(dl, 'custom-glyph-alignment', 'Custom glyph alignment test', 'Write custom glyph alignment tests to the terminal'); - this._addDdWithButton(dl, 'custom-glyph-ranges', 'Custom glyph ranges', 'Write custom glyph unicode range to the terminal'); - this._addDdWithButton(dl, 'powerline-symbol-test', 'Powerline symbol test', 'Write powerline symbol characters to the terminal (\\ue0a0+)'); - this._addDdWithButton(dl, 'underline-test', 'Underline test', 'Write text with Kitty\'s extended underline sequences'); - this._addDdWithButton(dl, 'sgr-test', 'SGR test', 'Write text with SGR attribute'); - this._addDdWithButton(dl, 'ansi-colors', 'Ansi colors test', 'Write a wide range of ansi colors'); - this._addDdWithButton(dl, 'osc-hyperlinks', 'Ansi hyperlinks test', 'Write some OSC 8 hyperlinks'); - this._addDdWithButton(dl, 'bce', 'Colored Erase (BCE)', 'Test colored erase'); - this._addDdWithButton(dl, 'add-grapheme-clusters', 'Grapheme clusters', 'Write grapheme cluster test strings'); + this._addDdWithButton(dl, 'custom-glyph-alignment', 'Custom glyph alignment test', 'Write custom glyph alignment tests to the terminal', () => customGlyphAlignmentHandler(this._terminal)); + this._addDdWithButton(dl, 'custom-glyph-ranges', 'Custom glyph ranges', 'Write custom glyph unicode range to the terminal', () => customGlyphRangesHandler(this._terminal)); + this._addDdWithButton(dl, 'powerline-symbol-test', 'Powerline symbol test', 'Write powerline symbol characters to the terminal (\\ue0a0+)', () => powerlineSymbolTest(this._terminal)); + this._addDdWithButton(dl, 'underline-test', 'Underline test', 'Write text with Kitty\'s extended underline sequences', () => underlineTest(this._terminal)); + this._addDdWithButton(dl, 'sgr-test', 'SGR test', 'Write text with SGR attribute', () => sgrTest(this._terminal)); + this._addDdWithButton(dl, 'ansi-colors', 'Ansi colors test', 'Write a wide range of ansi colors', () => ansiColorsTest(this._terminal)); + this._addDdWithButton(dl, 'osc-hyperlinks', 'Ansi hyperlinks test', 'Write some OSC 8 hyperlinks', () => addAnsiHyperlink(this._terminal)); + this._addDdWithButton(dl, 'bce', 'Colored Erase (BCE)', 'Test colored erase', () => coloredErase(this._terminal)); + this._addDdWithButton(dl, 'add-grapheme-clusters', 'Grapheme clusters', 'Write grapheme cluster test strings', () => addGraphemeClusters(this._terminal)); // Decorations section this._addDt(dl, 'Decorations'); @@ -194,3 +195,488 @@ export function addCjk(term: Terminal): void { term.write(String.fromCharCode(i)); } } + +/** + * Prints the 20977 characters from the CJK Unified Ideographs unicode block with randomized styles. + */ +function addCjkRandomSgr(term: Terminal): void { + term.write('\n\n\r'); + for (let i = 0x4E00; i < 0x9FCC; i++) { + term.write(`\x1b[${getRandomSgr()}m${String.fromCharCode(i)}\x1b[0m`); + } +} +const randomSgrAttributes = [ + '1', '2', '3', '4', '5', '6', '7', '9', + '21', '22', '23', '24', '25', '26', '27', '28', '29', + '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', + '40', '41', '42', '43', '44', '45', '46', '47', '48', '49' +]; +function getRandomSgr(): string { + return randomSgrAttributes[Math.floor(Math.random() * randomSgrAttributes.length)]; +} + +function powerlineSymbolTest(term: Terminal): void { + function s(char: string): string { + return `${char} \x1b[7m${char}\x1b[0m `; + } + term.write('\n\n\r'); + term.writeln('Standard powerline symbols:'); + term.writeln(' 0 1 2 3 4 5 6 7 8 9 A B C D E F'); + term.writeln(`0xA_ ${s('\ue0a0')}${s('\ue0a1')}${s('\ue0a2')}`); + term.writeln(`0xB_ ${s('\ue0b0')}${s('\ue0b1')}${s('\ue0b2')}${s('\ue0b3')}`); + term.writeln(''); + term.writeln( + `\x1b[7m` + + ` inverse \ue0b1 \x1b[0;40m\ue0b0` + + ` 0 \ue0b1 \x1b[30;41m\ue0b0\x1b[39m` + + ` 1 \ue0b1 \x1b[31;42m\ue0b0\x1b[39m` + + ` 2 \ue0b1 \x1b[32;43m\ue0b0\x1b[39m` + + ` 3 \ue0b1 \x1b[33;44m\ue0b0\x1b[39m` + + ` 4 \ue0b1 \x1b[34;45m\ue0b0\x1b[39m` + + ` 5 \ue0b1 \x1b[35;46m\ue0b0\x1b[39m` + + ` 6 \ue0b1 \x1b[36;47m\ue0b0\x1b[30m` + + ` 7 \ue0b1 \x1b[37;49m\ue0b0\x1b[0m` + ); + term.writeln(''); + term.writeln( + `\x1b[7m` + + ` inverse \ue0b3 \x1b[0;7;40m\ue0b2\x1b[27m` + + ` 0 \ue0b3 \x1b[7;30;41m\ue0b2\x1b[27;39m` + + ` 1 \ue0b3 \x1b[7;31;42m\ue0b2\x1b[27;39m` + + ` 2 \ue0b3 \x1b[7;32;43m\ue0b2\x1b[27;39m` + + ` 3 \ue0b3 \x1b[7;33;44m\ue0b2\x1b[27;39m` + + ` 4 \ue0b3 \x1b[7;34;45m\ue0b2\x1b[27;39m` + + ` 5 \ue0b3 \x1b[7;35;46m\ue0b2\x1b[27;39m` + + ` 6 \ue0b3 \x1b[7;36;47m\ue0b2\x1b[27;30m` + + ` 7 \ue0b3 \x1b[7;37;49m\ue0b2\x1b[0m` + ); + term.writeln(''); + term.writeln( + `\x1b[7m` + + ` inverse \ue0b5 \x1b[0;40m\ue0b4` + + ` 0 \ue0b5 \x1b[30;41m\ue0b4\x1b[39m` + + ` 1 \ue0b5 \x1b[31;42m\ue0b4\x1b[39m` + + ` 2 \ue0b5 \x1b[32;43m\ue0b4\x1b[39m` + + ` 3 \ue0b5 \x1b[33;44m\ue0b4\x1b[39m` + + ` 4 \ue0b5 \x1b[34;45m\ue0b4\x1b[39m` + + ` 5 \ue0b5 \x1b[35;46m\ue0b4\x1b[39m` + + ` 6 \ue0b5 \x1b[36;47m\ue0b4\x1b[30m` + + ` 7 \ue0b5 \x1b[37;49m\ue0b4\x1b[0m` + ); + term.writeln(''); + term.writeln( + `\x1b[7m` + + ` inverse \ue0b7 \x1b[0;7;40m\ue0b6\x1b[27m` + + ` 0 \ue0b7 \x1b[7;30;41m\ue0b6\x1b[27;39m` + + ` 1 \ue0b7 \x1b[7;31;42m\ue0b6\x1b[27;39m` + + ` 2 \ue0b7 \x1b[7;32;43m\ue0b6\x1b[27;39m` + + ` 3 \ue0b7 \x1b[7;33;44m\ue0b6\x1b[27;39m` + + ` 4 \ue0b7 \x1b[7;34;45m\ue0b6\x1b[27;39m` + + ` 5 \ue0b7 \x1b[7;35;46m\ue0b6\x1b[27;39m` + + ` 6 \ue0b7 \x1b[7;36;47m\ue0b6\x1b[27;30m` + + ` 7 \ue0b7 \x1b[7;37;49m\ue0b6\x1b[0m` + ); + term.writeln(''); + term.writeln('Powerline extra symbols:'); + term.writeln(' 0 1 2 3 4 5 6 7 8 9 A B C D E F'); + term.writeln(`0xA_ ${s('\ue0a3')}`); + term.writeln(`0xB_ ${s('\ue0b4')}${s('\ue0b5')}${s('\ue0b6')}${s('\ue0b7')}${s('\ue0b8')}${s('\ue0b9')}${s('\ue0ba')}${s('\ue0bb')}${s('\ue0bc')}${s('\ue0bd')}${s('\ue0be')}${s('\ue0bf')}`); + term.writeln(`0xC_ ${s('\ue0c0')}${s('\ue0c1')}${s('\ue0c2')}${s('\ue0c3')}${s('\ue0c4')}${s('\ue0c5')}${s('\ue0c6')}${s('\ue0c7')}${s('\ue0c8')}${s('\ue0c9')}${s('\ue0ca')}${s('\ue0cb')}${s('\ue0cc')}${s('\ue0cd')}${s('\ue0be')}${s('\ue0bf')}`); + term.writeln(`0xD_ ${s('\ue0d0')}${s('\ue0d1')}${s('\ue0d2')} ${s('\ue0d4')}`); + term.writeln(''); + term.writeln('Sample of nerd fonts icons:'); + term.writeln(' nf-linux-apple (\\uF302) \uf302'); + term.writeln('nf-mdi-github_face (\\uFbd9) \ufbd9'); +} + +function underlineTest(term: Terminal): void { + function u(style: number): string { + return `\x1b[4:${style}m`; + } + function c(color: string): string { + return `\x1b[58:${color}m`; + } + term.write('\n\n\r'); + term.writeln('Underline styles:'); + term.writeln(''); + function showSequence(id: number, name: string): string { + let alphabet = ''; + for (let i = 97; i < 123; i++) { + alphabet += String.fromCharCode(i); + } + let numbers = ''; + for (let i = 0; i < 10; i++) { + numbers += i.toString(); + } + return `${u(id)}4:${id}m - ${name}\x1b[4:0m`.padEnd(33, ' ') + `${u(id)}${alphabet} ${numbers} 汉语 한국어 👽\x1b[4:0m`; + } + term.writeln(showSequence(0, 'No underline')); + term.writeln(showSequence(1, 'Straight')); + term.writeln(showSequence(2, 'Double')); + term.writeln(showSequence(3, 'Curly')); + term.writeln(showSequence(4, 'Dotted')); + term.writeln(showSequence(5, 'Dashed')); + term.writeln(''); + term.writeln(`Underline colors (256 color mode):`); + term.writeln(''); + for (let i = 0; i < 256; i++) { + term.write((i !== 0 ? '\x1b[0m, ' : '') + u(1 + i % 5) + c('5:' + i) + i); + } + term.writeln(`\x1b[0m\n\n\rUnderline colors (true color mode):`); + term.writeln(''); + for (let i = 0; i < 80; i++) { + const v = Math.round(i / 79 * 255); + term.write(u(1) + c(`2:0:${v}:${v}:${v}`) + (i < 4 ? 'grey'[i] : ' ')); + } + term.write('\n\r'); + for (let i = 0; i < 80; i++) { + const v = Math.round(i / 79 * 255); + term.write(u(1) + c(`2:0:${v}:${0}:${0}`) + (i < 3 ? 'red'[i] : ' ')); + } + term.write('\n\r'); + for (let i = 0; i < 80; i++) { + const v = Math.round(i / 79 * 255); + term.write(u(1) + c(`2:0:${0}:${v}:${0}`) + (i < 5 ? 'green'[i] : ' ')); + } + term.write('\n\r'); + for (let i = 0; i < 80; i++) { + const v = Math.round(i / 79 * 255); + term.write(u(1) + c(`2:0:${0}:${0}:${v}`) + (i < 4 ? 'blue'[i] : ' ')); + } + term.write('\x1b[0m\n\r'); +} + +function customGlyphAlignmentHandler(term: Terminal): void { + term.write('\n\r'); + term.write('\n\r'); + term.write('Box styles: ┎┰┒┍┯┑╓╥╖╒╤╕ ┏┳┓┌┲┓┌┬┐┏┱┐\n\r'); + term.write('┌─┬─┐ ┏━┳━┓ ╔═╦═╗ ┠╂┨┝┿┥╟╫╢╞╪╡ ┡╇┩├╊┫┢╈┪┣╉┤\n\r'); + term.write('│ │ │ ┃ ┃ ┃ ║ ║ ║ ┖┸┚┕┷┙╙╨╜╘╧╛ └┴┘└┺┛┗┻┛┗┹┘\n\r'); + term.write('├─┼─┤ ┣━╋━┫ ╠═╬═╣ ┏┱┐┌┲┓┌┬┐┌┬┐ ┏┳┓┌┮┓┌┬┐┏┭┐\n\r'); + term.write('│ │ │ ┃ ┃ ┃ ║ ║ ║ ┡╃┤├╄┩├╆┪┢╅┤ ┞╀┦├┾┫┟╁┧┣┽┤\n\r'); + term.write('└─┴─┘ ┗━┻━┛ ╚═╩═╝ └┴┘└┴┘└┺┛┗┹┘ └┴┘└┶┛┗┻┛┗┵┘\n\r'); + term.write('\n\r'); + + term.write('Other:\n\r'); + term.write('╭─╮ ╲ ╱ ╷╻╎╏┆┇┊┋ ╺╾╴ ╌╌╌ ┄┄┄ ┈┈┈\n\r'); + term.write('│ │ ╳ ╽╿╎╏┆┇┊┋ ╶╼╸ ╍╍╍ ┅┅┅ ┉┉┉\n\r'); + term.write('╰─╯ ╱ ╲ ╹╵╎╏┆┇┊┋\n\r'); + term.write('\n\r'); + + term.write('Box drawing alignment tests:\x1b[31m █\n\r'); + term.write(' ▉\n\r'); + term.write(' ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳\n\r'); + term.write(' ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳\n\r'); + term.write(' ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳\n\r'); + term.write(' ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳\n\r'); + term.write(' ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎\n\r'); + term.write(' ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏\n\r'); + term.write(' ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█\n\r'); + term.write('\x1b[0mBox drawing alignment tests:\x1b[32m █\n\r'); + term.write(' ▉\n\r'); + term.write(' ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳\n\r'); + term.write(' ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳\n\r'); + term.write(' ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳\n\r'); + term.write(' ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳\n\r'); + term.write(' ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎\n\r'); + term.write(' ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏\n\r'); + term.write(' ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█\n\r'); + + term.write('\x1b[0mSmooth mosaic terminal graphic characters alignment tests:\x1b[33m\n\r'); + term.write(' 🭇🬼 🭈🬽 🭉🬾 🭊🬿 🭋🭀 🭁🭌 🭂🭍 🭃🭎 🭄🭏 🭅🭐 🭆🭑 🭨🭪 🭩 🭯 🭮🭬\n\r'); + term.write(' 🭢🭗 🭣🭘 🭤🭙 🭥🭚 🭦🭛 🭒🭝 🭓🭞 🭔🭟 🭕🭠 🭖🭡 🭧🭜 🭫 🭭\n\r'); + term.write(' 🭇🬼 🭉🬾 🭋🭀\n\r'); + term.write(' 🭊🭁🭌🬿 🭈🭆🭂🭍🭑🬽 🭇🭄🭏🬼 🭃🭎 🭅🭐 🭨🭪\n\r'); + term.write(' 🭥🭒🭝🭚 🭣🭧🭓🭞🭜🭘 🭢🭕🭠🭗 🭔🭟 🭖🭡 🭪🭨\n\r'); + term.write(' 🭢🭗 🭤🭙 🭦🭛\n\r'); + + term.write('\x1b[0mCharacter cell diagonals (1FBA0-1FBAE) alignment tests:\x1b[34m\n\r'); + term.write(' \u{1FBA3}\u{1FBA7}\u{1FBA2} \u{1FBA3}\u{1FBA8}\u{1FBA0} \u{1FBAD}\u{1FBA2} \u{1FBA3}\u{1FBAC} \u{1FBAE}\n\r'); + term.write(' \u{1FBA3}\u{1FBA0} \u{1FBA1}\u{1FBA2} \u{1FBA1}\u{1FBA9}\u{1FBA2} \u{1FBA1}\u{1FBAA} \u{1FBAB}\u{1FBA0}\n\r'); + term.write(' \u{1FBA4} \u{1FBA5}\n\r'); + term.write(' \u{1FBA1}\u{1FBA2} \u{1FBA3}\u{1FBA0}\n\r'); + term.write(' \u{1FBA1}\u{1FBA6}\u{1FBA0}\n\r'); + + term.write('\x1b[0mCharacter cell diagonals (1FBD0-1FBDF) alignment tests:\x1b[34m\n\r'); + term.write(' \u{1FBD6}\u{1FBD4} \u{1FBD0}\u{1FBD1}\u{1FBD2}\u{1FBD3} \u{1FBDA} \u{1FBD9}\u{1FBDB} \u{1FBDE} \u{1FBDD}\u{1FBDF}\n\r'); + term.write(' \u{1FBD7}\u{1FBD5} \u{1FBD2}\u{1FBD3}\u{1FBD0}\u{1FBD1} \u{1FBD8} \u{1FBDC}\n\r'); + term.write(' \u{1FBD4}\u{1FBD6}\n\r'); + term.write(' \u{1FBD5}\u{1FBD7}\n\r'); + term.write(''); + + term.write('\x1b[0mComposite terminal graphics characters:\x1b[35m\n\r'); + term.write('\u{1FBB2}\u{1FBB3} \u{1FBB9}\u{1FBBA} \u{1FBC1}\u{1FBC2}\u{1FBC3}\n\r'); + + term.write('\x1b[0mFill tests:\x1b[36m\n\r'); + const fillChars = ['\u{2591}', '\u{2592}', '\u{2593}', '\u{1FB8C}', '\u{1FB8D}', '\u{1FB8E}', '\u{1FB8F}', '\u{1FB90}', '\u{1FB91}', '\u{1FB92}', '\u{1FB94}', '\u{1FB95}', '\u{1FB96}', '\u{1FB97}', '\u{1FB98}', '\u{1FB99}']; + while (fillChars.length > 0) { + const batch = fillChars.splice(0, 10); + for (const fillChar of batch) { + term.write(`${fillChar.codePointAt(0).toString(16).toUpperCase().padEnd(5, ' ')} `); + } + term.write('\n\r'); + for (let i = 0; i < 3; i++) { + for (const fillChar of batch) { + term.write(fillChar.repeat(5)); + term.write(' '); + } + term.write('\n\r'); + } + } + + term.write('\x1b[0mPowerline alignment tests:\n\r'); + const powerlineLeftChars = ['\u{E0B2}', '\u{E0B3}', '\u{E0B6}', '\u{E0B7}', '\u{E0BA}', '\u{E0BB}', '\u{E0BE}', '\u{E0BF}', '\u{E0C2}', '\u{E0C3}', '\u{E0C5}', '\u{E0C7}', '\u{E0CA}', '\u{E0D4}']; + const powerlineRightChars = ['\u{E0B0}', '\u{E0B1}', '\u{E0B4}', '\u{E0B5}', '\u{E0B8}', '\u{E0B9}', '\u{E0BC}', '\u{E0BD}', '\u{E0C0}', '\u{E0C1}', '\u{E0C4}', '\u{E0C6}', '\u{E0C8}', '\u{E0D2}', '\u{E0CC}', '\u{E0CD}', '\u{E0CE}', '\u{E0CF}', '\u{E0D0}', '\u{E0D1}']; + for (const char of powerlineLeftChars) { + term.write(`\x1b[31m${char}\x1b[0;41m \x1b[0m `); + } + term.write('\n\r'); + for (const char of powerlineRightChars) { + term.write(`\x1b[41m \x1b[0;31m${char}\x1b[0m `); + } + term.write('\n\r'); + + term.write('\x1b[0mGit Branch Symbols alignment tests:\x1b[32m\n\r'); + term.write(' \u{F5F7}\u{F5F7} \u{F5EE}\u{F5EF} \u{F5F6}\u{F5F7} \u{F5D6}\u{F5D0}\u{F5D7} \u{F5FC}\u{F5FC}\u{F5FE} \u{F5FD}\u{F609}\u{F5FF}\n\r'); + term.write(' \u{F5DA}\u{F5DD} \u{F5F0}\u{F5F4}\u{F5F2} \u{F5FA}\u{F5FB} \u{F5D1} \u{F5D1} \u{F604}\u{F60C}\u{F606} \u{F605}\u{F60D}\u{F607}\n\r'); + term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D8}\u{F5D0}\u{F5D9} \u{F600}\u{F60A}\u{F602} \u{F601}\u{F60B}\u{F603}\n\r'); + term.write(' \u{F5DC}\u{F5DF} \u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\n\r'); + term.write('\u{F5F1}\u{F5E6}\u{F5E7}\u{F5F3} \u{F5D3}\u{F5D0}\u{F5E0}\u{F5E1}\u{F5E2}\u{F5E3}\u{F5E4}\u{F5E5}\u{F5E8}\u{F5E9}\u{F5EC}\u{F5ED}\u{F5D2}\n\r'); + term.write('\u{F5F1}\u{F5EA}\u{F5EB}\u{F5F3} \u{F5F9}\u{F5F9}\u{F5F9} \u{F5F9}\u{F5F9}\u{F5F9}\u{F5F9}\n\r'); + term.write(' \u{F5F9}\u{F5F9} \n\r'); + term.write('\x1b[0m'); + term.write('\n\r'); + window.scrollTo(0, 0); +} + +function customGlyphRangesHandler(term: Terminal): void { + // Box Drawing + // 2500-257F + // https://www.unicode.org/charts/PDF/U2500.pdf + writeUnicodeTable(term, 'Box Drawing', 0x2500, 0x257F, [ + ['Light and heavy solid lines', 0x2500, 0x2503], + ['Light and heavy dashed lines', 0x2504, 0x250B], + ['Light and heavy line box components', 0x250C, 0x254B], + ['Light and heavy dashed lines', 0x254C, 0x254F], + ['Double lines', 0x2550, 0x2551], + ['Light and double line box components', 0x2552, 0x256C], + ['Character cell arcs', 0x256D, 0x2570], + ['Character cell diagonals', 0x2571, 0x2573], + ['Light and heavy half lines', 0x2574, 0x257B], + ['Mixed light and heavy lines', 0x257C, 0x257F], + ]); + // Box Elements + // 2580-259F + // https://www.unicode.org/charts/PDF/U2580.pdf + writeUnicodeTable(term, 'Box Elements', 0x2580, 0x259F, [ + ['Block elements', 0x2580, 0x2590], + ['Shade characters', 0x2591, 0x2593], + ['Block elements', 0x2594, 0x2595], + ['Terminal graphic characters', 0x2596, 0x259F], + ]); + // Braille Patterns + // 2800-28FF + // https://www.unicode.org/charts/PDF/U2800.pdf + writeUnicodeTable(term, 'Braille patterns', 0x2800, 0x28FF, [ + ['Braille patterns', 0x2800, 0x28FF], + ]); + // Powerline Symbols + // Range: E0A0–E0D4 + // https://github.com/ryanoasis/nerd-fonts + writeUnicodeTable(term, 'Powerline Symbols', 0xE0A0, 0xE0D4, [ + ['Powerline symbols', 0xE0A0, 0xE0B3, [0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, 0xE0A8, 0xE0A9, 0xE0AA, 0xE0AB, 0xE0AC, 0xE0AD, 0xE0AE, 0xE0AF]], + ['Powerline extra symbols', 0xE0B4, 0xE0D4, [0xE0C9, 0xE0CB, 0xE0D3]], + ]); + // Git Branch Symbols + // F5D0-F60D + // https://github.com/xtermjs/xterm.js/issues/5477 + writeUnicodeTable(term, 'Git Branch Symbols', 0xF5D0, 0xF5FB, [ + ['Straight lines', 0xF5D0, 0xF5D5], + ['Curved lines', 0xF5D6, 0xF5D9], + ['Branching lines', 0xF5DA, 0xF5ED], + ['Nodes', 0xF5EE, 0xF5FB], + ['Extended nodes', 0xF5FC, 0xF60D], + ]); + // Symbols for Legacy Computing + // Range: 1FB00–1FBFF + // https://www.unicode.org/charts/PDF/U1FB00.pdf + writeUnicodeTable(term, 'Symbols for Legacy Computing', 0x1FB00, 0x1FBFF, [ + ['Block mosaic terminal graphic characters (Sextants)', 0x1FB00, 0x1FB3B], + ['Smooth mosaic terminal graphic characters', 0x1FB3C, 0x1FB6F], + ['Block elements', 0x1FB70, 0x1FB80], + ['Window title bar', 0x1FB81, 0x1FB81], + ['Block elements', 0x1FB82, 0x1FB8B], + ['Rectangular shade characters', 0x1FB8C, 0x1FB94, [0x1FB93]], + ['Fill characters', 0x1FB95, 0x1FB97], + ['Diagonal fill characters', 0x1FB98, 0x1FB99], + ['Smooth mosaic terminal graphic characters', 0x1FB9A, 0x1FB9B], + ['Triangular shade characters', 0x1FB9C, 0x1FB9F], + ['Character cell diagonals', 0x1FBA0, 0x1FBAE], + ['Light solid line with stroke', 0x1FBAF, 0x1FBAF], + ['Terminal graphic characters', 0x1FBB0, 0x1FBB3], + ['Arrows', 0x1FBB4, 0x1FBB8], + ['Terminal graphic characters', 0x1FBB9, 0x1FBBC], + ['Negative terminal graphic characters', 0x1FBBD, 0x1FBBF], + ['Terminal graphic characters', 0x1FBC0, 0x1FBCA], + ['Terminal graphic characters', 0x1FBCB, 0x1FBCD], + ['Block elements', 0x1FBCE, 0x1FBCF], + ['Character cell diagonals', 0x1FBD0, 0x1FBDF], + ['Geometrics shapes', 0x1FBE0, 0x1FBEF], + ['Segmented digits', 0x1FBF0, 0x1FBF9], + ['Terminal graphic character', 0x1FBFA, 0x1FBFA], + ]); +} + +function ansiColorsTest(term: Terminal): void { + term.writeln(`\x1b[0m\n\n\rStandard colors: Bright colors:`); + for (let i = 0; i < 16; i++) { + term.write(`\x1b[48;5;${i}m ${i.toString().padEnd(2, ' ').padStart(3, ' ')} \x1b[0m`); + } + + term.writeln(`\x1b[0m\n\n\rColors 17-231 from 256 palette:`); + for (let i = 0; i < 6; i++) { + const startId = 16 + i * 36; + const endId = 16 + (i + 1) * 36 - 1; + term.write(`${startId.toString().padStart(3, ' ')}-${endId.toString().padStart(3, ' ')} `); + for (let j = 0; j < 36; j++) { + const id = 16 + i * 36 + j; + term.write(`\x1b[48;5;${id}m${(id % 10).toString().padStart(2, ' ')}\x1b[0m`); + } + term.write(`\r\n`); + } + + term.writeln(`\x1b[0m\n\rGreyscale from 256 palette:`); + term.write('232-255 '); + for (let i = 232; i < 256; i++) { + term.write(`\x1b[48;5;${i}m ${(i % 10)} \x1b[0m`); + } +} + +function writeTestString(): string { + let alphabet = ''; + for (let i = 97; i < 123; i++) { + alphabet += String.fromCharCode(i); + } + let numbers = ''; + for (let i = 0; i < 10; i++) { + numbers += i.toString(); + } + return `${alphabet} ${numbers} 汉语 한국어 👽`; +} +const testString = writeTestString(); + +function sgrTest(term: Terminal): void { + term.write('\n\n\r'); + term.writeln(`Character Attributes (SGR, Select Graphic Rendition)`); + const entries: { ps: number, name: string }[] = [ + { ps: 0, name: 'Normal' }, + { ps: 1, name: 'Bold' }, + { ps: 2, name: 'Faint/dim' }, + { ps: 3, name: 'Italicized' }, + { ps: 4, name: 'Underlined' }, + { ps: 5, name: 'Blink' }, + { ps: 7, name: 'Inverse' }, + { ps: 8, name: 'Invisible' }, + { ps: 9, name: 'Crossed-out characters' }, + { ps: 21, name: 'Doubly-underlined' }, + { ps: 22, name: 'Normal' }, + { ps: 23, name: 'Not italicized' }, + { ps: 24, name: 'Not underlined' }, + { ps: 25, name: 'Steady (not blink)' }, + { ps: 27, name: 'Positive (not inverse)' }, + { ps: 28, name: 'Visible (not hidden)' }, + { ps: 29, name: 'Not crossed-out' }, + { ps: 30, name: 'Foreground Black' }, + { ps: 31, name: 'Foreground Red' }, + { ps: 32, name: 'Foreground Green' }, + { ps: 33, name: 'Foreground Yellow' }, + { ps: 34, name: 'Foreground Blue' }, + { ps: 35, name: 'Foreground Magenta' }, + { ps: 36, name: 'Foreground Cyan' }, + { ps: 37, name: 'Foreground White' }, + { ps: 39, name: 'Foreground default' }, + { ps: 40, name: 'Background Black' }, + { ps: 41, name: 'Background Red' }, + { ps: 42, name: 'Background Green' }, + { ps: 43, name: 'Background Yellow' }, + { ps: 44, name: 'Background Blue' }, + { ps: 45, name: 'Background Magenta' }, + { ps: 46, name: 'Background Cyan' }, + { ps: 47, name: 'Background White' }, + { ps: 49, name: 'Background default' }, + { ps: 53, name: 'Overlined' }, + { ps: 55, name: 'Not overlined' } + ]; + const maxNameLength = entries.reduce((p, c) => Math.max(c.name.length, p), 0); + for (const e of entries) { + term.writeln(`\x1b[0m\x1b[${e.ps}m ${e.ps.toString().padEnd(2, ' ')} ${e.name.padEnd(maxNameLength, ' ')} - ${testString}\x1b[0m`); + } + const entriesByPs: Map = new Map(); + for (const e of entries) { + entriesByPs.set(e.ps, e.name); + } + const comboEntries: { ps: number[] }[] = [ + { ps: [1, 2, 3, 4, 5, 6, 7, 9] }, + { ps: [2, 41] }, + { ps: [4, 53] } + ]; + term.write('\n\n\r'); + term.writeln(`Combinations`); + for (const e of comboEntries) { + const name = e.ps.map(e => entriesByPs.get(e)).join(', '); + term.writeln(`\x1b[0m\x1b[${e.ps.join(';')}m ${name}\n\r${testString}\x1b[0m`); + } +} + +function addAnsiHyperlink(term: Terminal): void { + term.write('\n\n\r'); + term.writeln(`Regular link with no id:`); + term.writeln('\x1b]8;;https://github.com\x07GitHub\x1b]8;;\x07'); + term.writeln('\x1b]8;;https://xtermjs.org\x07https://xtermjs.org\x1b]8;;\x07\x1b[C<- null cell'); + term.writeln(`\nAdjacent links:`); + term.writeln('\x1b]8;;https://github.com\x07GitHub\x1b]8;;https://xtermjs.org\x07\x1b[32mxterm.js\x1b[0m\x1b]8;;\x07'); + term.writeln(`\nShared ID link (underline should be shared):`); + term.writeln('╔════╗'); + term.writeln('║\x1b]8;id=testid;https://github.com\x07GitH\x1b]8;;\x07║'); + term.writeln('║\x1b]8;id=testid;https://github.com\x07ub\x1b]8;;\x07 ║'); + term.writeln('╚════╝'); + term.writeln(`\nWrapped link with no ID (not necessarily meant to share underline):`); + term.writeln('╔════╗'); + term.writeln('║ ║'); + term.writeln('║ ║'); + term.writeln('╚════╝'); + term.write('\x1b[3A\x1b[1C\x1b]8;;https://xtermjs.org\x07xter\x1b[B\x1b[4Dm.js\x1b]8;;\x07\x1b[2B\x1b[5D'); +} + +function addGraphemeClusters(term: Terminal): void { + term.write('\n\n\r'); + term.writeln('🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣 [Simple emoji v6: 10 cells, v15: 20 cells]'); + term.writeln('\u{1F476}\u{1F3FF}\u{1F476} [baby with emoji modifier fitzpatrick type-6; baby]'); + term.writeln('\u{1F469}\u200d\u{1f469}\u200d\u{1f466} [woman+zwj+woman+zwj+boy]'); + term.writeln('\u{1F64B}\u{1F64B}\u{200D}\u{2642}\u{FE0F} [person/man raising hand]'); + term.writeln('\u{1F3CB}\u{FE0F}=\u{1F3CB}\u{1F3FE}\u{200D}\u{2640}\u{FE0F} [person lifting weights emoji; woman lighting weights, medium dark]'); + term.writeln('\u{1F469}\u{1F469}\u{200D}\u{1F393}\u{1F468}\u{1F3FF}\u{200D}\u{1F393} [woman; woman student; man student dark]'); + term.writeln('\u{1f1f3}\u{1f1f4}_ [REGIONAL INDICATOR SYMBOL LETTER N and RI O]'); + term.writeln('\u{1f1f3}_\u{1f1f4} {RI N; underscore; RI O]'); + term.writeln('\u0061\u0301 [letter a with acute accent]'); + term.writeln('\u1100\u1161\u11A8=\u1100\u1161= [Korean Jamo]'); + term.writeln('\uAC00=\uD685= [Hangul syllables (pre-composed)]'); + term.writeln('(\u26b0\ufe0e) [coffin with text_presentation]'); + term.writeln('(\u26b0\ufe0f) [coffin with Emoji_presentation]'); + term.writeln(' [Égalité (using separate acute) emoij_presentation]'); +} + +function coloredErase(term: Terminal): void { + const sp5 = ' '; + const data = ` +Test BG-colored Erase (BCE): + The color block in the following lines should look identical. + For newly created rows at the bottom the last color should be applied + for all cells to the right. + + def 41 42 43 44 45 46 47\x1b[47m +\x1b[m${sp5}\x1b[41m${sp5}\x1b[42m${sp5}\x1b[43m${sp5}\x1b[44m${sp5}\x1b[45m${sp5}\x1b[46m${sp5}\x1b[47m${sp5} +\x1b[m\x1b[5X\x1b[41m\x1b[5C\x1b[5X\x1b[42m\x1b[5C\x1b[5X\x1b[43m\x1b[5C\x1b[5X\x1b[44m\x1b[5C\x1b[5X\x1b[45m\x1b[5C\x1b[5X\x1b[46m\x1b[5C\x1b[5X\x1b[47m\x1b[5C\x1b[5X\x1b[m +`; + term.write(data.split('\n').join('\r\n')); +} \ No newline at end of file