From bfd9b06249814ad7c4bc47c0f065d6337f87076c Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Mon, 22 Nov 2021 16:13:01 +0000 Subject: Add: backend_output to manage pretty printing of build progress --- src/fpm_backend_console.f90 | 82 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/fpm_backend_console.f90 (limited to 'src/fpm_backend_console.f90') diff --git a/src/fpm_backend_console.f90 b/src/fpm_backend_console.f90 new file mode 100644 index 0000000..4db0cdc --- /dev/null +++ b/src/fpm_backend_console.f90 @@ -0,0 +1,82 @@ +module fpm_backend_console +use iso_fortran_env, only: stdout=>output_unit +implicit none + +private +public :: console_t + +character(len=*), parameter :: ESC = char(27) + +type console_t + integer :: n_line = 1 + logical :: plain_mode = .false. + character(:), allocatable :: LINE_RESET + character(:), allocatable :: LINE_UP + character(:), allocatable :: LINE_DOWN +contains + procedure :: init => console_init + procedure :: write_line => console_write_line + procedure :: update_line => console_update_line +end type console_t + +contains + +subroutine console_init(console,plain_mode) + class(console_t), intent(out), target :: console + logical, intent(in), optional :: plain_mode + + if (present(plain_mode)) then + console%plain_mode = plain_mode + end if + + if (console%plain_mode) then + console%LINE_RESET = "" + console%LINE_UP = "" + console%LINE_DOWN = "" + else + console%LINE_RESET = ESC//"[2K"//ESC//"[1G" + console%LINE_UP = ESC//"[1A" + console%LINE_DOWN = ESC//"[1B" + end if + +end subroutine console_init + +function console_write_line(console,str) result(line) + class(console_t), intent(inout), target :: console + character(*), intent(in) :: str + integer :: line + + !$omp critical + line = console%n_line + + write(stdout,*) console%LINE_RESET//str + + console%n_line = console%n_line + 1 + !$omp end critical + +end function console_write_line + +subroutine console_update_line(console,line_no,str) + class(console_t), intent(in) :: console + integer, intent(in) :: line_no + character(*), intent(in) :: str + + integer :: n + + !$omp critical + + n = console%n_line - line_no !+ 1 !+ 1 + + ! Step back to line + write(stdout,'(A)',advance="no") repeat(console%LINE_UP,n)//console%LINE_RESET + + write(stdout,*) str + + ! Step forward to end + write(stdout,'(A)',advance="no") repeat(console%LINE_DOWN,n)//console%LINE_RESET + + !$omp end critical + +end subroutine console_update_line + +end module fpm_backend_console \ No newline at end of file -- cgit v1.2.3 From 37ba9d7cf61d6b9ddbfe59a4456311fda62ef101 Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Fri, 26 Nov 2021 17:32:07 +0000 Subject: Simplify implementation and cleanup plain mode output --- src/fpm_backend_console.f90 | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src/fpm_backend_console.f90') diff --git a/src/fpm_backend_console.f90 b/src/fpm_backend_console.f90 index 4db0cdc..7daff14 100644 --- a/src/fpm_backend_console.f90 +++ b/src/fpm_backend_console.f90 @@ -41,20 +41,36 @@ subroutine console_init(console,plain_mode) end subroutine console_init -function console_write_line(console,str) result(line) +subroutine console_write_line(console,str,line,advance) class(console_t), intent(inout), target :: console character(*), intent(in) :: str - integer :: line + integer, intent(out), optional :: line + logical, intent(in), optional :: advance + + character(3) :: adv + + adv = "yes" + if (present(advance)) then + if (.not.advance) then + adv = "no" + end if + end if !$omp critical - line = console%n_line - write(stdout,*) console%LINE_RESET//str + if (present(line)) then + line = console%n_line + end if + + write(stdout,'(A)',advance=trim(adv)) console%LINE_RESET//str + + if (adv=="yes") then + console%n_line = console%n_line + 1 + end if - console%n_line = console%n_line + 1 !$omp end critical -end function console_write_line +end subroutine console_write_line subroutine console_update_line(console,line_no,str) class(console_t), intent(in) :: console -- cgit v1.2.3 From 93b629e504900432ea712cc3ed65dd937483e1c1 Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Sat, 27 Nov 2021 17:35:12 +0000 Subject: Add: developer documentation to new files --- src/fpm_backend_console.f90 | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/fpm_backend_console.f90') diff --git a/src/fpm_backend_console.f90 b/src/fpm_backend_console.f90 index 7daff14..4422037 100644 --- a/src/fpm_backend_console.f90 +++ b/src/fpm_backend_console.f90 @@ -1,3 +1,13 @@ +!># Build Backend Console +!> This module provides a lightweight implementation for printing to the console +!> and updating previously-printed console lines. It used by `[[fpm_backend_output]]` +!> for pretty-printing build status and progress. +!> +!> @note The implementation for updating previous lines relies on no other output +!> going to `stdout`/`stderr` except through the `console_t` object provided. +!> +!> @note All write statements to `stdout` are enclosed within OpenMP `critical` regions +!> module fpm_backend_console use iso_fortran_env, only: stdout=>output_unit implicit none @@ -7,22 +17,34 @@ public :: console_t character(len=*), parameter :: ESC = char(27) +!> Console object type console_t + !> Number of lines printed integer :: n_line = 1 + !> 'Plain' output (no escape codes) logical :: plain_mode = .false. + !> Escape code for erasing current line character(:), allocatable :: LINE_RESET + !> Escape code for moving up one line character(:), allocatable :: LINE_UP + !> Escape code for moving down one line character(:), allocatable :: LINE_DOWN contains + !> Initialise the console object procedure :: init => console_init + !> Write a single line to the console procedure :: write_line => console_write_line + !> Update a previously-written console line procedure :: update_line => console_update_line end type console_t contains +!> Initialise the console object subroutine console_init(console,plain_mode) + !> Console object to initialise class(console_t), intent(out), target :: console + !> 'Plain' output (no escape codes) logical, intent(in), optional :: plain_mode if (present(plain_mode)) then @@ -41,10 +63,15 @@ subroutine console_init(console,plain_mode) end subroutine console_init +!> Write a single line to the standard output subroutine console_write_line(console,str,line,advance) + !> Console object class(console_t), intent(inout), target :: console + !> String to write character(*), intent(in) :: str + !> Integer needed to later update console line integer, intent(out), optional :: line + !> Advancing output (print newline?) logical, intent(in), optional :: advance character(3) :: adv @@ -72,9 +99,13 @@ subroutine console_write_line(console,str,line,advance) end subroutine console_write_line +!> Overwrite a previously-written line in standard output subroutine console_update_line(console,line_no,str) + !> Console object class(console_t), intent(in) :: console + !> Integer output from `[[console_write_line]]` integer, intent(in) :: line_no + !> New string to overwrite line character(*), intent(in) :: str integer :: n -- cgit v1.2.3 From 6aba40db1385007e0bf4e9c2b9b4afe8bb105593 Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Sun, 28 Nov 2021 11:24:41 +0000 Subject: Apply suggestion: don't use TBP for new constructors --- src/fpm_backend_console.f90 | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/fpm_backend_console.f90') diff --git a/src/fpm_backend_console.f90 b/src/fpm_backend_console.f90 index 4422037..73bcd5d 100644 --- a/src/fpm_backend_console.f90 +++ b/src/fpm_backend_console.f90 @@ -30,22 +30,25 @@ type console_t !> Escape code for moving down one line character(:), allocatable :: LINE_DOWN contains - !> Initialise the console object - procedure :: init => console_init !> Write a single line to the console procedure :: write_line => console_write_line !> Update a previously-written console line procedure :: update_line => console_update_line end type console_t +!> Constructor for console_t +interface console_t + procedure :: new_console +end interface console_t + contains -!> Initialise the console object -subroutine console_init(console,plain_mode) - !> Console object to initialise - class(console_t), intent(out), target :: console +!> Initialise a new console object +function new_console(plain_mode) result(console) !> 'Plain' output (no escape codes) logical, intent(in), optional :: plain_mode + !> Console object to initialise + type(console_t) :: console if (present(plain_mode)) then console%plain_mode = plain_mode @@ -61,12 +64,12 @@ subroutine console_init(console,plain_mode) console%LINE_DOWN = ESC//"[1B" end if -end subroutine console_init +end function new_console !> Write a single line to the standard output subroutine console_write_line(console,str,line,advance) !> Console object - class(console_t), intent(inout), target :: console + class(console_t), intent(inout) :: console !> String to write character(*), intent(in) :: str !> Integer needed to later update console line -- cgit v1.2.3 From b0115d1a000ee15d3ca773c3da3300595d805454 Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Sun, 28 Nov 2021 11:43:49 +0000 Subject: Apply suggestion: don't use M_attr, simplify implementation --- src/fpm_backend_console.f90 | 59 +++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 39 deletions(-) (limited to 'src/fpm_backend_console.f90') diff --git a/src/fpm_backend_console.f90 b/src/fpm_backend_console.f90 index 73bcd5d..014e800 100644 --- a/src/fpm_backend_console.f90 +++ b/src/fpm_backend_console.f90 @@ -14,21 +14,30 @@ implicit none private public :: console_t +public :: LINE_RESET +public :: COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_RESET character(len=*), parameter :: ESC = char(27) +!> Escape code for erasing current line +character(len=*), parameter :: LINE_RESET = ESC//"[2K"//ESC//"[1G" +!> Escape code for moving up one line +character(len=*), parameter :: LINE_UP = ESC//"[1A" +!> Escape code for moving down one line +character(len=*), parameter :: LINE_DOWN = ESC//"[1B" +!> Escape code for red foreground color +character(len=*), parameter :: COLOR_RED = ESC//"[31m" +!> Escape code for green foreground color +character(len=*), parameter :: COLOR_GREEN = ESC//"[32m" +!> Escape code for yellow foreground color +character(len=*), parameter :: COLOR_YELLOW = ESC//"[93m" +!> Escape code to reset foreground color +character(len=*), parameter :: COLOR_RESET = ESC//"[0m" !> Console object type console_t !> Number of lines printed integer :: n_line = 1 - !> 'Plain' output (no escape codes) - logical :: plain_mode = .false. - !> Escape code for erasing current line - character(:), allocatable :: LINE_RESET - !> Escape code for moving up one line - character(:), allocatable :: LINE_UP - !> Escape code for moving down one line - character(:), allocatable :: LINE_DOWN + contains !> Write a single line to the console procedure :: write_line => console_write_line @@ -36,36 +45,8 @@ contains procedure :: update_line => console_update_line end type console_t -!> Constructor for console_t -interface console_t - procedure :: new_console -end interface console_t - contains -!> Initialise a new console object -function new_console(plain_mode) result(console) - !> 'Plain' output (no escape codes) - logical, intent(in), optional :: plain_mode - !> Console object to initialise - type(console_t) :: console - - if (present(plain_mode)) then - console%plain_mode = plain_mode - end if - - if (console%plain_mode) then - console%LINE_RESET = "" - console%LINE_UP = "" - console%LINE_DOWN = "" - else - console%LINE_RESET = ESC//"[2K"//ESC//"[1G" - console%LINE_UP = ESC//"[1A" - console%LINE_DOWN = ESC//"[1B" - end if - -end function new_console - !> Write a single line to the standard output subroutine console_write_line(console,str,line,advance) !> Console object @@ -92,7 +73,7 @@ subroutine console_write_line(console,str,line,advance) line = console%n_line end if - write(stdout,'(A)',advance=trim(adv)) console%LINE_RESET//str + write(stdout,'(A)',advance=trim(adv)) LINE_RESET//str if (adv=="yes") then console%n_line = console%n_line + 1 @@ -118,12 +99,12 @@ subroutine console_update_line(console,line_no,str) n = console%n_line - line_no !+ 1 !+ 1 ! Step back to line - write(stdout,'(A)',advance="no") repeat(console%LINE_UP,n)//console%LINE_RESET + write(stdout,'(A)',advance="no") repeat(LINE_UP,n)//LINE_RESET write(stdout,*) str ! Step forward to end - write(stdout,'(A)',advance="no") repeat(console%LINE_DOWN,n)//console%LINE_RESET + write(stdout,'(A)',advance="no") repeat(LINE_DOWN,n)//LINE_RESET !$omp end critical -- cgit v1.2.3 From 6cd53f7dfce8628b54a232c551b5f20171932dbb Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Sat, 12 Feb 2022 11:28:20 +0000 Subject: Fix: for consistent alignment of backend console output. --- src/fpm_backend_console.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/fpm_backend_console.f90') diff --git a/src/fpm_backend_console.f90 b/src/fpm_backend_console.f90 index 014e800..59d8f0e 100644 --- a/src/fpm_backend_console.f90 +++ b/src/fpm_backend_console.f90 @@ -96,12 +96,12 @@ subroutine console_update_line(console,line_no,str) !$omp critical - n = console%n_line - line_no !+ 1 !+ 1 + n = console%n_line - line_no ! Step back to line write(stdout,'(A)',advance="no") repeat(LINE_UP,n)//LINE_RESET - write(stdout,*) str + write(stdout,'(A)') str ! Step forward to end write(stdout,'(A)',advance="no") repeat(LINE_DOWN,n)//LINE_RESET -- cgit v1.2.3