1
!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.

2
  • 1
    Welcome, I suggest taking the tour and reading How to Ask. Which operating system and what kind of virtual terminal are you using? The interpretation of the sequences is up to your terminal. Normal terminals in MS Windows won't interpret them. Commented Nov 15, 2024 at 8:50
  • I am using a Linux terminal, and I have identified the cause of the issue. It seems I was using the format incorrectly. I was using the format like 'a2' to add a blank, but it cut off the string like '[3'. After checking formats from 'A3' to 'A6', I realized that caused my misunderstanding. Thank you very much for your advice, I truly appreciate it. Commented Nov 18, 2024 at 9:04

1 Answer 1

2

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$
Sign up to request clarification or add additional context in comments.

4 Comments

"having them allocatable when you don't need to them just needlessly introduces extra classes of bugs" - having them variable when you don't need... character(*), parameter :: red=... means no need to be allocatable or to count.
@francescalus Indeed, I thought strongly about including that but I don't know the OPs final use case
I think this is a good answer considering OP's apparent level of expertise and current problem.
I’ve solved the issue, thanks a lot for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.