Cut text to at most width columns, never mid-character and never
inside an escape sequence.
Escape sequences are kept and cost nothing, so a styled row keeps its
colours and is cut by what it shows rather than by how it is spelled.
Note that a cut can leave an attribute set with its reset dropped;
ansi_reset() after writing a truncated row settles that.
A width of zero still keeps nothing at all, escape sequences
included: a caller asking for no columns wants no bytes.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | text |
Text to truncate. |
||
| integer(kind=default_int), | intent(in) | :: | width |
Maximum width in columns. |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer(kind=default_int), | private | :: | byte | ||||
| integer(kind=default_int), | private | :: | i | ||||
| integer(kind=default_int), | private | :: | last | ||||
| integer(kind=default_int), | private | :: | seen | ||||
| integer(kind=default_int), | private | :: | skip |
pure function truncate_to_width(text, width) result(cut) !! Cut `text` to at most `width` columns, never mid-character and never !! inside an escape sequence. !! !! Escape sequences are kept and cost nothing, so a styled row keeps its !! colours and is cut by what it shows rather than by how it is spelled. !! Note that a cut can leave an attribute set with its reset dropped; !! `ansi_reset()` after writing a truncated row settles that. !! !! A `width` of zero still keeps nothing at all, escape sequences !! included: a caller asking for no columns wants no bytes. character(len=*), intent(in) :: text !! Text to truncate. integer(default_int), intent(in) :: width !! Maximum width in columns. character(len=:), allocatable :: cut integer(default_int) :: i, byte, seen, skip, last if (width <= 0_default_int) then cut = "" return end if seen = 0_default_int last = len(text, kind=default_int) i = 1_default_int do while (i <= last) skip = escape_length(text, i) if (skip > 0_default_int) then i = i + skip cycle end if byte = iachar(text(i:i), default_int) if (byte < 128_default_int .or. byte >= 192_default_int) then if (seen == width) then cut = text(1:i - 1_default_int) return end if seen = seen + 1_default_int end if i = i + 1_default_int end do cut = text end function truncate_to_width