!example
program main
implicit none
character(len=8) :: red, reset
character(len=16) :: redO
red = char(27) // '[31m'
reset = char(27) // '[0m'
redO = trim(adjustl(red // "O" // reset))
write (*,"(A)") redO
end program main
Above code for an example.
I am trying to print the letter 'O' in red using ANSI escape sequences, but the issue is that the escape sequences themselves are being counted as part of the string's length, causing unexpected spaces in the output.
So the result looks like:
" O "
I want the output to appear as:
"O"
How can I avoid the escape sequences affecting the length of the output string?
I expected the output to be just the letter "O" printed in red, without any extra spaces or length caused by the escape sequences.
Firstly I assume you understand this isn't portable. Fortran doesn't say anything about ANSI escape sequences and how they will be handled will depend upon your environment. There is no guarantee of redness. That said the problem appears to be not related to the control sequences, but to how you are declaring your character variables.
"I expected the output to be just the letter "O" printed in red, without any extra spaces or length caused by the escape sequences". You have declared red
as 8 characters long. This means in Fortran it is always 8 characters long, yet you have filled only a subset of the characters - the rest will be filled with spaces, and these are the spaces you are seeing, nothing to do with any "control characters"; it can't be, your program doesn't contain anything outside standard 7 bit ASCII. And similarly for the other character variables.
Probably the simplest way to avoid lots of careful counting is the following
program main
implicit none
character(len=:), Allocatable :: red, reset
character(len=:), Allocatable :: redO
red = char(27) // '[31m'
reset = char(27) // '[0m'
redO = trim(adjustl(red // "O" // reset))
write (*,"(A,a)") redO, "next"
end program main
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ gfortran i.f90
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ./a.out
Onext
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ifx i.f90
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ./a.out
Onext
ijb@LAPTOP-GUG8KQ9I:~/work/stack$
( the "O" is read in both cases on my terminal) though personally in a "real" program I would prefer to count the length and declare the variables as such, having them allocatable when you don't need to them just needlessly introduces extra classes of bugs. Something like
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ cat i2.f90
program main
implicit none
character(len=5) :: red
character(len=4) :: reset
character(len=10) :: redO
red = char(27) // '[31m'
reset = char(27) // '[0m'
redO = trim(adjustl(red // "O" // reset))
write (*,"(A,a)") redO, "next"
end program main
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ gfortran i2.f90
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ./a.out
Onext
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ifx i.f90
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ./a.out
Onext
ijb@LAPTOP-GUG8KQ9I:~/work/stack$