display_width Function

public pure function display_width(text) result(width)

Number of columns text occupies.

Counts UTF-8 code points and skips ANSI escape sequences, which take no space on screen. Continuation bytes, those with the top two bits 10, do not start a character and so do not count. A byte that is not valid UTF-8 counts as one, so invalid input degrades to the byte count rather than to something arbitrary.

One column per code point: an East Asian wide character occupies two and is counted once here. Getting that right needs a width table, and is out of scope.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: text

Text to measure.

Return Value integer(kind=default_int)


Calls

proc~~display_width~~CallsGraph proc~display_width display_width proc~escape_length escape_length proc~display_width->proc~escape_length

Variables

Type Visibility Attributes Name Initial
integer(kind=default_int), private :: byte
integer(kind=default_int), private :: i
integer(kind=default_int), private :: skip

Source Code

   pure function display_width(text) result(width)
      !! Number of columns `text` occupies.
      !!
      !! Counts UTF-8 code points and skips ANSI escape sequences, which take
      !! no space on screen. Continuation bytes, those with the top two bits
      !! `10`, do not start a character and so do not count. A byte that is
      !! not valid UTF-8 counts as one, so invalid input degrades to the byte
      !! count rather than to something arbitrary.
      !!
      !! One column per code point: an East Asian wide character occupies two
      !! and is counted once here. Getting that right needs a width table, and
      !! is out of scope.
      character(len=*), intent(in) :: text
         !! Text to measure.
      integer(default_int) :: width

      integer(default_int) :: i, byte, skip

      width = 0_default_int
      i = 1_default_int
      do while (i <= len(text, kind=default_int))
         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
            width = width + 1_default_int
         end if
         i = i + 1_default_int
      end do
   end function display_width