[//000000001]: # (punkshell\_module\_punk::ansi \- punk Ansi library)
[//000000002]: # (Generated from file '\_module\_ansi\-0\.1\.0\.tm\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright © 2023)
[//000000004]: # (punkshell\_module\_punk::ansi\(0\) 0\.1\.0 doc "punk Ansi library")
[ Main Table Of Contents | Table Of Contents | Keyword Index ]
# NAME
punkshell\_module\_punk::ansi \- Ansi string functions
# Table Of Contents
- [Table Of Contents](#toc)
- [Synopsis](#synopsis)
- [Description](#section1)
- [Overview](#section2)
- [Concepts](#subsection1)
- [dependencies](#subsection2)
- [API](#section3)
- [Namespace punk::ansi](#subsection3)
- [Namespace punk::ansi::ta](#subsection4)
- [Namespace punk::ansi::ansistring](#subsection5)
- [Keywords](#keywords)
- [Copyright](#copyright)
# SYNOPSIS
package require punk::ansi
[__stripansi__ *text*](#1)
[__a?__ ?ansicode\.\.\.?](#2)
[__a\+__ ?ansicode\.\.\.?](#3)
[__a__ ?ansicode\.\.\.?](#4)
[__get\_code\_name__ *code*](#5)
[__reset__](#6)
[__reset\_soft__](#7)
[__reset\_colour__](#8)
[__clear__](#9)
[__clear\_above__](#10)
[__clear\_below__](#11)
[__cursor\_on__](#12)
[__cursor\_off__](#13)
[__move__ *row* *col*](#14)
[__move\_emit__ *row* *col* *data* ?row col data\.\.\.?](#15)
[__move\_forward__ *n*](#16)
[__move\_back__ *n*](#17)
[__move\_up__ *n*](#18)
[__move\_down__ *n*](#19)
[__erase\_line__](#20)
[__erase\_sol__](#21)
[__erase\_eol__](#22)
[__cursor\_pos__](#23)
[__titleset__ *windowtitles*](#24)
[__detect__ *text*](#25)
[__detect\_csi__ *text*](#26)
[__detect\_sgr__ *text*](#27)
[__strip__ *text*](#28)
[__length__ *text*](#29)
[__index__ *string* *index*](#30)
# DESCRIPTION
Ansi based terminal control string functions
See __punk::ansi::console__ for related functions for controlling a console
# Overview
overview of punk::ansi
punk::ansi functions return their values \- no implicit emission to
console/stdout
## Concepts
Ansi codes can be used to control most terminals on most platforms in an
'almost' standard manner
There are many differences in terminal implementations \- but most should support
a core set of features
punk::ansi does not contain any code for direct terminal manipulation via the
local system APIs\.
Sticking to ansi codes where possible may be better for cross\-platform and
remote operation where such APIs are unlikely to be useable\.
## dependencies
packages used by punk::ansi
- __Tcl 8\.6__
# API
## Namespace punk::ansi
Core API functions for punk::ansi
- __stripansi__ *text*
Return a string with ansi codes stripped out
- __a?__ ?ansicode\.\.\.?
Return an ansi string representing a table of codes and a panel showing the
colours
- __a\+__ ?ansicode\.\.\.?
Returns the ansi code to apply those from the supplied list \- without any
reset being performed first
e\.g to set foreground red and bold
punk::ansi::a red bold
to set background red
punk::ansi::a Red
see __punk::ansi::a?__ to display a list of codes
- __a__ ?ansicode\.\.\.?
Returns the ansi code to reset any current settings and apply those from the
supplied list
by calling punk::ansi::a with no arguments \- the result is a reset to plain
text
e\.g to set foreground red and bold
punk::ansi::a red bold
to set background red
punk::ansi::a Red
see __punk::ansi::a?__ to display a list of codes
- __get\_code\_name__ *code*
for example
get\_code\_name red will return 31
get\_code\_name 31 will return red
- __reset__
reset console
- __reset\_soft__
- __reset\_colour__
reset colour only
- __clear__
- __clear\_above__
- __clear\_below__
- __cursor\_on__
- __cursor\_off__
- __move__ *row* *col*
Return an ansi sequence to move to row,col
aka cursor home
- __move\_emit__ *row* *col* *data* ?row col data\.\.\.?
Return an ansi string representing a move to row col with data appended
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
Compare to punk::console::move\_emit which calls this function \- but writes
it to stdout
punk::console::move\_emit\_return will also return the cursor to the original
position
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\.
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\.
punk::console::move\_emit\_return does it by emitting that code and starting a
loop to read stdin
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\.
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:
punk::ansi::move_emit 10 10 blah {*}[punk::console::get_cursor_pos_list] DONE
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\.
- __move\_forward__ *n*
- __move\_back__ *n*
- __move\_up__ *n*
- __move\_down__ *n*
- __erase\_line__
- __erase\_sol__
Erase to start of line, leaving cursor position alone\.
- __erase\_eol__
- __cursor\_pos__
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
The output on screen will look something like ^\[\[47;3R
Use punk::console::get\_cursor\_pos or punk::console::get\_cursor\_pos\_list
instead\.
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\.
The punk::ansi::cursor\_pos function is used by punk::console::get\_cursor\_pos
and punk::console::get\_cursor\_pos\_list
- __titleset__ *windowtitles*
Returns the code to set the title of the terminal window to windowtitle
This may not work on terminals which have multiple panes/windows
## Namespace punk::ansi::ta
text ansi functions
based on but not identical to the Perl Text Ansi module:
https://github\.com/perlancar/perl\-Text\-ANSI\-Util/blob/master/lib/Text/ANSI/BaseUtil\.pm
- __detect__ *text*
Return a boolean indicating whether Ansi codes were detected in text
- __detect\_csi__ *text*
Return a boolean indicating whether an Ansi Control Sequence Introducer
\(CSI\) was detected in text
The csi is often represented in code as \\x1b or \\033 followed by a left
bracket \[
The initial byte or escape is commonly referenced as ESC in Ansi
documentation
There is also a multi\-byte escape sequence \\u009b
This is less commonly used but is also detected here
\(This function is not in perl ta\)
- __detect\_sgr__ *text*
Return a boolean indicating whether an ansi Select Graphics Rendition code
was detected\.
This is the set of CSI sequences ending in 'm'
This is most commonly an Ansi colour code \- but also things such as
underline and italics
An SGR with empty or a single zero argument is a reset of the SGR features \-
this is also detected\.
\(This function is not in perl ta\)
- __strip__ *text*
Return text stripped of Ansi codes
This is a tailcall to punk::ansi::stripansi
- __length__ *text*
Return the character length after stripping ansi codes \- not the printing
length
## Namespace punk::ansi::ansistring
punk::ansi::string ensemble
- __index__ *string* *index*
Takes a string that possibly contains ansi codes such as colour,underline
etc \(SGR codes\)
Returns the character \(with applied ansi effect\) at position index
The string could contain non SGR ansi codes \- and these will \(mostly\) be
ignored, so shouldn't affect the output\.
Some terminals don't hide 'privacy message' and other strings within an ESC
X ESC ^ or ESC \_ sequence \(terminated by ST\)
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\.
If the caller wants just the character \- they should use a normal string
index after calling stripansi, or call stripansi afterwards\.
As any operation using end\-\+ will need to strip ansi to precalculate
the length anyway; the caller should probably just use stripansi and
standard string index if the ansi coded output isn't required and they are
using and end\-based index\.
In fact, any operation where the ansi info isn't required in the output
would probably be slightly more efficiently obtained by using stripansi and
normal string operations on that\.
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
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\.
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\.
This shouldn't make any difference to the visual output \- but a possible
future enhancement is something to produce the shortest ansi sequence
possible
Notes:
This function has to split the whole string into plaintext & ansi codes even
for a very low index
Some sort of generator that parses more of the string as required might be
more efficient for large chunks\.
For end\-x operations we have to pre\-calculate the content\-length by
stripping the ansi \- which is also potentially sub\-optimal
# KEYWORDS
[ansi](\.\./\.\./\.\./index\.md\#ansi), [console](\.\./\.\./\.\./index\.md\#console),
[module](\.\./\.\./\.\./index\.md\#module), [string](\.\./\.\./\.\./index\.md\#string),
[terminal](\.\./\.\./\.\./index\.md\#terminal)
# COPYRIGHT
Copyright © 2023