You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
15 KiB
224 lines
15 KiB
[comment {--- punk::docgen generated from inline doctools comments ---}] |
|
[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}] |
|
[comment {--- punk::docgen overwrites this file ---}] |
|
[manpage_begin punkshell_module_punk::ansi 0 0.1.1] |
|
[copyright "2023"] |
|
[titledesc {Ansi string functions}] [comment {-- Name section and table of contents description --}] |
|
[moddesc {punk Ansi library}] [comment {-- Description at end of page heading --}] |
|
[require punk::ansi] |
|
[keywords module ansi terminal console string] |
|
[description] |
|
[para]Ansi based terminal control string functions |
|
[para]See [package punk::ansi::console] for related functions for controlling a console |
|
[section Overview] |
|
[para] overview of punk::ansi |
|
[para]punk::ansi functions return their values - no implicit emission to console/stdout |
|
[subsection Concepts] |
|
[para]Ansi codes can be used to control most terminals on most platforms in an 'almost' standard manner |
|
[para]There are many differences in terminal implementations - but most should support a core set of features |
|
[para]punk::ansi does not contain any code for direct terminal manipulation via the local system APIs. |
|
[para]Sticking to ansi codes where possible may be better for cross-platform and remote operation where such APIs are unlikely to be useable. |
|
[subsection dependencies] |
|
[para] packages used by punk::ansi |
|
[list_begin itemized] |
|
[item] [package {Tcl 8.6-}] |
|
[item] [package {punk::char}] |
|
[list_end] |
|
[section API] |
|
[subsection {Namespace punk::ansi}] |
|
[para] Core API functions for punk::ansi |
|
[list_begin definitions] |
|
[call [fun a?] [opt {ansicode...}]] |
|
[para]Return an ansi string representing a table of codes and a panel showing the colours |
|
[call [fun a+] [opt {ansicode...}]] |
|
[para]Returns the ansi code to apply those from the supplied list - without any reset being performed first |
|
[para] e.g to set foreground red and bold |
|
[para]punk::ansi::a red bold |
|
[para]to set background red |
|
[para]punk::ansi::a Red |
|
[para]see [cmd punk::ansi::a?] to display a list of codes |
|
[call [fun a] [opt {ansicode...}]] |
|
[para]Returns the ansi code to reset any current settings and apply those from the supplied list |
|
[para] by calling punk::ansi::a with no arguments - the result is a reset to plain text |
|
[para] e.g to set foreground red and bold |
|
[para]punk::ansi::a red bold |
|
[para]to set background red |
|
[para]punk::ansi::a Red |
|
[para]see [cmd punk::ansi::a?] to display a list of codes |
|
[call [fun get_code_name] [arg code]] |
|
[para]for example |
|
[para] get_code_name red will return 31 |
|
[para] get_code_name 31 will return red |
|
[call [fun reset]] |
|
[para]reset console |
|
[call [fun reset_soft]] |
|
[call [fun reset_colour]] |
|
[para]reset colour only |
|
[call [fun clear]] |
|
[call [fun clear_above]] |
|
[call [fun clear_below]] |
|
[call [fun cursor_on]] |
|
[call [fun cursor_off]] |
|
[call [fun move] [arg row] [arg col]] |
|
[para]Return an ansi sequence to move to row,col |
|
[para]aka cursor home |
|
[call [fun move_emit] [arg row] [arg col] [arg data] [opt {row col data...}]] |
|
[para]Return an ansi string representing a move to row col with data appended |
|
[para]row col data can be repeated any number of times to return a string representing the output of the data elements at all those points |
|
[para]Compare to punk::console::move_emit which calls this function - but writes it to stdout |
|
[para]punk::console::move_emit_return will also return the cursor to the original position |
|
[para]There is no punk::ansi::move_emit_return because in a standard console there is no ansi string which can represent a jump back to starting position. |
|
[para]There is an ansi code to write the current cursor position to stdin (which will generally display on the console) - this is not quite the same thing. |
|
[para]punk::console::move_emit_return does it by emitting that code and starting a loop to read stdin |
|
[para]punk::ansi could implement a move_emit_return using the punk::console mechanism - but the resulting string would capture the cursor position at the time the string is built - which is not necessarily when the string is used. |
|
[para]The following example shows how to do this manually, emitting the string blah at screen position 10,10 and emitting DONE back at the line we started: |
|
[para][example {punk::ansi::move_emit 10 10 blah {*}[punk::console::get_cursor_pos_list] DONE}] |
|
[para]A string created by any move_emit_return for punk::ansi would not behave in an intuitive manner compared to other punk::ansi move functions - so is deliberately omitted. |
|
[call [fun move_emitblock] [arg row] [arg col] [arg textblock]] |
|
[call [fun move_emitblock] [arg row] [arg col] [arg textblock]] |
|
[call [fun move_forward] [arg n]] |
|
[call [fun move_back] [arg n]] |
|
[call [fun move_up] [arg n]] |
|
[call [fun move_down] [arg n]] |
|
[call [fun move_column] [arg col]] |
|
[call [fun move_row] [arg row]] |
|
[para]VPA - Vertical Line Position Absolute |
|
[call [fun cursor_save]] |
|
[para] equivalent term::ansi::code::ctrl::sc |
|
[para] This is the ANSI/SCO cursor save as opposed to the DECSC version |
|
[para] On many terminals either will work - but cursor_save_dec is shorter and perhaps more widely supported |
|
[call [fun cursor_restore]] |
|
[para] equivalent term::ansi::code::ctrl::rc |
|
[para] ANSI/SCO - see also cursor_restore_dec for the DECRC version |
|
[call [fun cursor_save_dec]] |
|
[para] equivalent term::ansi::code::ctrl::sca |
|
[para] DECSC |
|
[call [fun cursor_restore_attributes]] |
|
[para] equivalent term::ansi::code::ctrl::rca |
|
[para] DECRC |
|
[call [fun enable_line_wrap]] |
|
[para] enable automatic line wrapping when characters entered beyond rightmost column |
|
[para] This will also allow forward movements to move to subsequent lines |
|
[para] This is DECAWM - and is the same sequence output by 'tput smam' |
|
[call [fun disable_line_wrap]] |
|
[para] disable automatic line wrapping |
|
[para] reset DECAWM - same sequence output by 'tput rmam' |
|
tput rmam |
|
[call [fun query_mode_line_wrap]] |
|
[para] DECRQM to query line-wrap state |
|
[para] The punk::ansi::query_mode_ functions just emit the ansi query sequence. |
|
[call [fun erase_line]] |
|
[call [fun erase_sol]] |
|
[para]Erase to start of line, leaving cursor position alone. |
|
[call [fun erase_eol]] |
|
[call [fun scroll_up] [arg n]] |
|
[call [fun scroll_down] [arg n]] |
|
[call [fun insert_spaces] [arg count]] |
|
[call [fun delete_characters] [arg count]] |
|
[call [fun erase_characters] [arg count]] |
|
[call [fun insert_lines] [arg count]] |
|
[call [fun delete_lines] [arg count]] |
|
[call [fun cursor_pos]] |
|
[para]cursor_pos unlikely to be useful on it's own like this as when written to the terminal, this sequence causes the terminal to emit the row;col sequence to stdin |
|
[para]The output on screen will look something like ^[lb][lb]47;3R |
|
[para]Use punk::console::get_cursor_pos or punk::console::get_cursor_pos_list instead. |
|
[para]These functions will emit the code - but read it in from stdin so that it doesn't display, and then return the row and column as a colon-delimited string or list respectively. |
|
[para]The punk::ansi::cursor_pos function is used by punk::console::get_cursor_pos and punk::console::get_cursor_pos_list |
|
[call [fun request_cursor_information]] |
|
[para]DECRQPSR (DEC Request Presentation State Report) for DECCCIR Cursor Information report |
|
[para]When written to the terminal, this sequence causes the terminal to emit cursor information to stdin |
|
[para]A stdin readloop will need to be in place to read this information |
|
[call [fun request_tabstops]] |
|
[para]DECRQPSR (DEC Request Presentation State Report) for DECTABSR Tab stop report |
|
[para]When written to the terminal, this sequence causes the terminal to emit tabstop information to stdin |
|
[call [fun titleset] [arg windowtitles]] |
|
[para]Returns the code to set the title of the terminal window to windowtitle |
|
[para]This may not work on terminals which have multiple panes/windows |
|
[call [fun ansistrip] [arg text] ] |
|
[para]Return a string with ansi codes stripped out |
|
[para]Alternate graphics chars are replaced with modern unicode equivalents (e.g boxdrawing glyphs) |
|
[call [fun ansistrip2] [arg text] ] |
|
[para]Return a string with ansi codes stripped out |
|
[para]Alternate graphics chars are replaced with modern unicode equivalents (e.g boxdrawing glyphs) |
|
[call [fun ansistripraw] [arg text] ] |
|
[para]Return a string with ansi codes stripped out |
|
[para]Alternate graphics modes will be stripped rather than converted to unicode - exposing the raw ascii characters as they appear without graphics mode. |
|
[para]ie instead of a horizontal line you may see: qqqqqq |
|
[list_end] [comment {--- end definitions namespace punk::ansi ---}] |
|
[subsection {Namespace punk::ansi::codetype}] |
|
[para] API functions for punk::ansi::codetype |
|
[para] Utility functions for processing ansi code sequences |
|
[list_begin definitions] |
|
[call [fun is_sgr_reset] [arg code]] |
|
[para]Return a boolean indicating whether this string has a trailing pure SGR reset |
|
[para]Note that if the reset is not the very last item in the string - it will not be detected. |
|
[para]This is primarily intended for testing a single ansi code sequence, but code can be any string where the trailing SGR code is to be tested. |
|
[call [fun has_sgr_leadingreset] [arg code]] |
|
[para]The reset must be the very first item in code to be detected. Trailing strings/codes ignored. |
|
[list_end] [comment {--- end definitions namespace punk::ansi::codetype ---}] |
|
[subsection {Namespace punk::ansi::ta}] |
|
[para] text ansi functions |
|
[para] based on but not identical to the Perl Text Ansi module: |
|
[para] https://github.com/perlancar/perl-Text-ANSI-Util/blob/master/lib/Text/ANSI/BaseUtil.pm |
|
[list_begin definitions] |
|
[call [fun detect] [arg text]] |
|
[para]Return a boolean indicating whether Ansi codes were detected in text |
|
[para]Important caveat: |
|
[para] When text is a tcl list made from splitting (or lappending) some ansi string - individual elements may be braced or have certain chars escaped. (one example is if a list element contains an unbalanced brace) |
|
[para] This can cause square brackets that form part of the ansi being backslash escaped - and the regexp can fail to match |
|
[call [fun detect_csi] [arg text]] |
|
[para]Return a boolean indicating whether an Ansi Control Sequence Introducer (CSI) was detected in text |
|
[para]The csi is often represented in code as \x1b or \033 followed by a left bracket [lb] |
|
[para]The initial byte or escape is commonly referenced as ESC in Ansi documentation |
|
[para]There is also a multi-byte escape sequence \u009b |
|
[para]This is less commonly used but is also detected here |
|
[para](This function is not in perl ta) |
|
[call [fun detect_sgr] [arg text]] |
|
[para]Return a boolean indicating whether an ansi Select Graphics Rendition code was detected. |
|
[para]This is the set of CSI sequences ending in 'm' |
|
[para]This is most commonly an Ansi colour code - but also things such as underline and italics |
|
[para]An SGR with empty or a single zero argument is a reset of the SGR features - this is also detected. |
|
[para](This function is not in perl ta) |
|
[call [fun strip] [arg text]] |
|
[para]Return text stripped of Ansi codes |
|
[para]This is a tailcall to punk::ansi::ansistrip |
|
[call [fun length] [arg text]] |
|
[para]Return the character length after stripping ansi codes - not the printing length |
|
[list_end] [comment {--- end definitions namespace punk::ansi::ta ---}] |
|
[subsection {Namespace punk::ansi::ansistring}] |
|
[para]punk::ansi::ansistring ensemble - ansi-aware string operations |
|
[para]Working with strings containing ansi in a way that preserves/understands the codes is always going to be significantly slower than working with plain strings |
|
[para]Just as working with other forms of markup such as HTML - you simply need to be aware of the tradeoffs and design accordingly. |
|
[list_begin definitions] |
|
[call [fun VIEW] [arg string]] |
|
[para]Return a string with specific ANSI control characters substituted with visual equivalents frome the appropriate unicode C0 and C1 visualisation sets |
|
[para]For debugging purposes, certain other standard control characters are converted to visual representation, for example backspace (mapped to \\U2408 '\U2408') |
|
[para]Horizontal tab is mapped to \\U2409 '\U2409'. For many of the punk terminal text operations, tabs have already been mapped to the appropriate number of spaces using textutil::tabify functions |
|
[para]As punkshell uses linefeed where possible in preference to crlf even on windows, cr is mapped to \\U240D '\U240D' - but lf is left as is. |
|
[call [fun COUNT] [arg string]] |
|
[para]Returns the count of visible graphemes and non-ansi control characters |
|
[para]Incomplete! grapheme clustering support not yet implemented - only diacritics are currently clustered to count as one grapheme. |
|
[para]This will not count strings hidden inside a 'privacy message' or other ansi codes which may have content between their opening escape and their termination sequence. |
|
[para]This is not quite equivalent to calling string length on the result of ansistrip $string due to diacritics and/or grapheme combinations |
|
[para]Note that this returns the number of characters in the payload (after applying combiners) |
|
It is not always the same as the width of the string as rendered on a terminal due to 2wide Unicode characters and the usual invisible control characters such as \r and \n |
|
[para]To get the width, use punk::ansi::printing_length instead, which is also ansi aware. |
|
[call [fun index] [arg string] [arg index]] |
|
[para]Takes a string that possibly contains ansi codes such as colour,underline etc (SGR codes) |
|
[para]Returns the character (with applied ansi effect) at position index |
|
[para]The string could contain non SGR ansi codes - and these will (mostly) be ignored, so shouldn't affect the output. |
|
[para]Some terminals don't hide 'privacy message' and other strings within an ESC X ESC ^ or ESC _ sequence (terminated by ST) |
|
[para]It's arguable some of these are application specific - but this function takes the view that they are probably non-displaying - so index won't see them. |
|
[para]If the caller wants just the character - they should use a normal string index after calling ansistrap, or call ansistrip afterwards. |
|
[para]As any operation using end-+<int> will need to strip ansi to precalculate the length anyway; the caller should probably just use ansistrip and standard string index if the ansi coded output isn't required and they are using and end-based index. |
|
[para]In fact, any operation where the ansi info isn't required in the output would probably be slightly more efficiently obtained by using ansistrip and normal string operations on that. |
|
[para]The returned character will (possibly) have a leading ansi escape sequence but no trailing escape sequence - even if the string was taken from a position immediately before a reset or other SGR ansi code |
|
[para]The ansi-code prefix in the returned string is built up by concatenating previous SGR ansi codes seen - but it is optimised to re-start the process if any full SGR reset is encountered. |
|
[para]The code sequence doesn't detect individual properties being turned on and then off again, only full resets; so in some cases the ansi-prefix may not be as short as it could be. |
|
[para]This shouldn't make any difference to the visual output - but a possible future enhancement is something to produce the shortest ansi sequence possible |
|
[para]Notes: |
|
[para]This function has to split the whole string into plaintext & ansi codes even for a very low index |
|
[para]Some sort of generator that parses more of the string as required might be more efficient for large chunks. |
|
[para]For end-x operations we have to pre-calculate the content-length by stripping the ansi - which is also potentially sub-optimal |
|
[list_end] [comment {--- end definitions namespace punk::ansi::ta ---}] |
|
[manpage_end]
|
|
|