From 8b2e55f1cda8228f864955842d74a7ae10b1c2f0 Mon Sep 17 00:00:00 2001 From: ZUO Zhihua Date: Sun, 20 Apr 2025 16:28:50 +0800 Subject: [PATCH 1/6] stdlib_system: add get_console_width function --- doc/specs/stdlib_system.md | 37 ++++++++++++++++++++ example/system/CMakeLists.txt | 1 + example/system/example_get_console_width.f90 | 14 ++++++++ src/CMakeLists.txt | 1 + src/stdlib_system.F90 | 17 +++++++-- src/stdlib_system_get_console_width.c | 28 +++++++++++++++ test/system/test_os.f90 | 16 +++++++-- 7 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 example/system/example_get_console_width.f90 create mode 100644 src/stdlib_system_get_console_width.c diff --git a/doc/specs/stdlib_system.md b/doc/specs/stdlib_system.md index 96eebb2e8..3a6908d9e 100644 --- a/doc/specs/stdlib_system.md +++ b/doc/specs/stdlib_system.md @@ -532,3 +532,40 @@ The file is removed from the filesystem if the operation is successful. If the o ```fortran {!example/system/example_delete_file.f90!} ``` + +## `get_console_width` - Get the width of the console + +### Status + +Experimental + +### Description + +This function returns the width of the console window in characters. +It is designed to work across multiple platforms. On Windows, the width is determined by the console window's size. +On UNIX-like systems (Linux, macOS), the width is determined by the terminal's size. + +Note: This routine performs a detailed runtime inspection, so it has non-negligible overhead. + +### Syntax + +`width = [[stdlib_system(module):get_console_width(function)]]()` + +### Class + +Function + +### Arguments + +None. + +### Return Value + +- **Type:** `integer` +- Returns the width of the console window in characters. + +### Example + +```fortran +{!./example/system/example_get_console_width.f90}! +``` diff --git a/example/system/CMakeLists.txt b/example/system/CMakeLists.txt index a2a7525c9..8ce555251 100644 --- a/example/system/CMakeLists.txt +++ b/example/system/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_EXAMPLE(get_runtime_os) +ADD_EXAMPLE(get_console_width) ADD_EXAMPLE(delete_file) ADD_EXAMPLE(is_directory) ADD_EXAMPLE(null_device) diff --git a/example/system/example_get_console_width.f90 b/example/system/example_get_console_width.f90 new file mode 100644 index 000000000..c639c83f9 --- /dev/null +++ b/example/system/example_get_console_width.f90 @@ -0,0 +1,14 @@ +program example_get_console_width + + use stdlib_system, only: get_console_width + implicit none + + integer :: width + + !> Get console width + width = get_console_width() + + print "(a,i0)", "Console width is ", width + print "(a)", repeat("*", width) + +end program example_get_console_width diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d82aae118..e261636c8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -112,6 +112,7 @@ set(SRC stdlib_hashmap_open.f90 stdlib_logger.f90 stdlib_sorting_radix_sort.f90 + stdlib_system_get_console_width.c stdlib_system_subprocess.c stdlib_system_subprocess.F90 stdlib_system.F90 diff --git a/src/stdlib_system.F90 b/src/stdlib_system.F90 index a9c3e4d55..d8f12ee1f 100644 --- a/src/stdlib_system.F90 +++ b/src/stdlib_system.F90 @@ -83,7 +83,9 @@ module stdlib_system public :: kill public :: elapsed public :: is_windows - + +public :: get_console_width + !! version: experimental !! !! Tests if a given path matches an existing directory. @@ -547,8 +549,17 @@ module function process_get_ID(process) result(ID) !> Return a process ID integer(process_ID) :: ID end function process_get_ID - -end interface + + !! Returns the width of the console window. + !! + !! ### Returns: + !! - **integer**: The width of the console window. + !! + !! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead. + integer function get_console_width() bind(C) + end function get_console_width + +end interface contains diff --git a/src/stdlib_system_get_console_width.c b/src/stdlib_system_get_console_width.c new file mode 100644 index 000000000..010da8777 --- /dev/null +++ b/src/stdlib_system_get_console_width.c @@ -0,0 +1,28 @@ +#include + +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +int get_console_width() +{ + int width = 80; // default value +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (GetConsoleScreenBufferInfo(hConsole, &csbi)) + { + width = csbi.srWindow.Right - csbi.srWindow.Left + 1; + } +#else + struct winsize w; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) + { + width = w.ws_col; + } +#endif + return width; +} diff --git a/test/system/test_os.f90 b/test/system/test_os.f90 index 1607b7ec1..e08b3fbd4 100644 --- a/test/system/test_os.f90 +++ b/test/system/test_os.f90 @@ -1,7 +1,7 @@ module test_os use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test - use stdlib_system, only: get_runtime_os, OS_WINDOWS, OS_UNKNOWN, OS_TYPE, is_windows, null_device - + use stdlib_system, only: get_runtime_os, OS_WINDOWS, OS_UNKNOWN, OS_TYPE, is_windows, null_device, & + get_console_width implicit none contains @@ -12,12 +12,24 @@ subroutine collect_suite(testsuite) type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & + new_unittest('test_get_console_width', test_get_console_width), & new_unittest('test_get_runtime_os', test_get_runtime_os), & new_unittest('test_is_windows', test_is_windows), & new_unittest('test_null_device', test_null_device) & ] end subroutine collect_suite + subroutine test_get_console_width(error) + type(error_type), allocatable, intent(out) :: error + integer :: width + + !> Get console width + width = get_console_width() + + call check(error, width > 0, "Console width is not positive") + + end subroutine test_get_console_width + subroutine test_get_runtime_os(error) type(error_type), allocatable, intent(out) :: error integer :: os From 8d6fcad96ea97ba3a9630650c71e39ff5d1996d7 Mon Sep 17 00:00:00 2001 From: ZUO Zhihua Date: Sun, 20 Apr 2025 21:20:04 +0800 Subject: [PATCH 2/6] feat(stdlib_system): rename get_console_width to get_terminal_size and update its functionality --- doc/specs/stdlib_system.md | 19 ++++++++----------- example/system/CMakeLists.txt | 2 +- example/system/example_get_console_width.f90 | 14 -------------- example/system/example_get_terminal_size.f90 | 14 ++++++++++++++ src/CMakeLists.txt | 2 +- src/stdlib_system.F90 | 12 +++++++----- ...th.c => stdlib_system_get_terminal_size.c} | 17 ++++++++++------- test/system/test_os.f90 | 19 +++++++++++-------- 8 files changed, 52 insertions(+), 47 deletions(-) delete mode 100644 example/system/example_get_console_width.f90 create mode 100644 example/system/example_get_terminal_size.f90 rename src/{stdlib_system_get_console_width.c => stdlib_system_get_terminal_size.c} (58%) diff --git a/doc/specs/stdlib_system.md b/doc/specs/stdlib_system.md index 3a6908d9e..dc787c302 100644 --- a/doc/specs/stdlib_system.md +++ b/doc/specs/stdlib_system.md @@ -533,7 +533,7 @@ The file is removed from the filesystem if the operation is successful. If the o {!example/system/example_delete_file.f90!} ``` -## `get_console_width` - Get the width of the console +## `get_terminal_size` - Get the size of the terminal window ### Status @@ -541,31 +541,28 @@ Experimental ### Description -This function returns the width of the console window in characters. -It is designed to work across multiple platforms. On Windows, the width is determined by the console window's size. -On UNIX-like systems (Linux, macOS), the width is determined by the terminal's size. +This subroutine returns the size of the terminal window in characters. Note: This routine performs a detailed runtime inspection, so it has non-negligible overhead. ### Syntax -`width = [[stdlib_system(module):get_console_width(function)]]()` +`call [[stdlib_system(module):get_terminal_size(subroutine)]](columns, lines)` ### Class -Function +Subroutine ### Arguments -None. +`columns`: Shall be an `intent(out)` argument of type `integer` that will contain the number of columns in the terminal window. -### Return Value +`lines`: Shall be an `intent(out)` argument of type `integer` that will contain the number of lines in the terminal window. -- **Type:** `integer` -- Returns the width of the console window in characters. +Note: If the query fails, the values of `columns` and `lines` will be set to `-1`. ### Example ```fortran -{!./example/system/example_get_console_width.f90}! +{!./example/system/example_get_terminal_size.f90}! ``` diff --git a/example/system/CMakeLists.txt b/example/system/CMakeLists.txt index 8ce555251..2cb6a7da5 100644 --- a/example/system/CMakeLists.txt +++ b/example/system/CMakeLists.txt @@ -1,5 +1,5 @@ ADD_EXAMPLE(get_runtime_os) -ADD_EXAMPLE(get_console_width) +ADD_EXAMPLE(get_terminal_size) ADD_EXAMPLE(delete_file) ADD_EXAMPLE(is_directory) ADD_EXAMPLE(null_device) diff --git a/example/system/example_get_console_width.f90 b/example/system/example_get_console_width.f90 deleted file mode 100644 index c639c83f9..000000000 --- a/example/system/example_get_console_width.f90 +++ /dev/null @@ -1,14 +0,0 @@ -program example_get_console_width - - use stdlib_system, only: get_console_width - implicit none - - integer :: width - - !> Get console width - width = get_console_width() - - print "(a,i0)", "Console width is ", width - print "(a)", repeat("*", width) - -end program example_get_console_width diff --git a/example/system/example_get_terminal_size.f90 b/example/system/example_get_terminal_size.f90 new file mode 100644 index 000000000..8b6e61d97 --- /dev/null +++ b/example/system/example_get_terminal_size.f90 @@ -0,0 +1,14 @@ +program example_get_terminal_size + + use stdlib_system, only: get_terminal_size + implicit none + + integer :: columns, lines + + !> Get terminal size + call get_terminal_size(columns, lines) + + print "(2(a,i0))", "Terminal size is ", columns, 'x', lines + print "(a)", repeat("*", columns) + +end program example_get_terminal_size diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e261636c8..37bb195c5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -112,7 +112,7 @@ set(SRC stdlib_hashmap_open.f90 stdlib_logger.f90 stdlib_sorting_radix_sort.f90 - stdlib_system_get_console_width.c + stdlib_system_get_terminal_size.c stdlib_system_subprocess.c stdlib_system_subprocess.F90 stdlib_system.F90 diff --git a/src/stdlib_system.F90 b/src/stdlib_system.F90 index d8f12ee1f..f8d0e94ec 100644 --- a/src/stdlib_system.F90 +++ b/src/stdlib_system.F90 @@ -84,7 +84,7 @@ module stdlib_system public :: elapsed public :: is_windows -public :: get_console_width +public :: get_terminal_size !! version: experimental !! @@ -550,14 +550,16 @@ module function process_get_ID(process) result(ID) integer(process_ID) :: ID end function process_get_ID - !! Returns the width of the console window. + !! Returns the size of the terminal window. !! !! ### Returns: - !! - **integer**: The width of the console window. + !! - **columns**: The number of columns in the terminal window. + !! - **lines**: The number of lines in the terminal window. !! !! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead. - integer function get_console_width() bind(C) - end function get_console_width + subroutine get_terminal_size(columns, lines) bind(C) + integer, intent(out) :: columns, lines + end subroutine get_terminal_size end interface diff --git a/src/stdlib_system_get_console_width.c b/src/stdlib_system_get_terminal_size.c similarity index 58% rename from src/stdlib_system_get_console_width.c rename to src/stdlib_system_get_terminal_size.c index 010da8777..d7aa7ad2f 100644 --- a/src/stdlib_system_get_console_width.c +++ b/src/stdlib_system_get_terminal_size.c @@ -7,22 +7,25 @@ #include #endif -int get_console_width() +void get_terminal_size(int *columns, int *lines) { - int width = 80; // default value + *columns = -1; + *lines = -1; + #ifdef _WIN32 - CONSOLE_SCREEN_BUFFER_INFO csbi; HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(hConsole, &csbi)) { - width = csbi.srWindow.Right - csbi.srWindow.Left + 1; + *columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; + *lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } #else struct winsize w; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) { - width = w.ws_col; + *columns = w.ws_col; + *lines = w.ws_row; } #endif - return width; -} +} \ No newline at end of file diff --git a/test/system/test_os.f90 b/test/system/test_os.f90 index e08b3fbd4..47682dd6a 100644 --- a/test/system/test_os.f90 +++ b/test/system/test_os.f90 @@ -1,7 +1,7 @@ module test_os use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_system, only: get_runtime_os, OS_WINDOWS, OS_UNKNOWN, OS_TYPE, is_windows, null_device, & - get_console_width + get_terminal_size implicit none contains @@ -12,23 +12,26 @@ subroutine collect_suite(testsuite) type(unittest_type), allocatable, intent(out) :: testsuite(:) testsuite = [ & - new_unittest('test_get_console_width', test_get_console_width), & + new_unittest('test_get_terminal_size', test_get_terminal_size), & new_unittest('test_get_runtime_os', test_get_runtime_os), & new_unittest('test_is_windows', test_is_windows), & new_unittest('test_null_device', test_null_device) & ] end subroutine collect_suite - subroutine test_get_console_width(error) + subroutine test_get_terminal_size(error) type(error_type), allocatable, intent(out) :: error - integer :: width + integer :: columns, lines - !> Get console width - width = get_console_width() + !> Get terminal size + call get_terminal_size(columns, lines) - call check(error, width > 0, "Console width is not positive") + call check(error, columns > 0, "Terminal width is not positive") + if (allocated(error)) return + + call check(error, lines > 0, "Terminal height is not positive") - end subroutine test_get_console_width + end subroutine test_get_terminal_size subroutine test_get_runtime_os(error) type(error_type), allocatable, intent(out) :: error From 35ada19f684be74c2c0a15f78b051db35c0373d8 Mon Sep 17 00:00:00 2001 From: ZUO Zhihua Date: Sun, 20 Apr 2025 21:55:51 +0800 Subject: [PATCH 3/6] feat(stdlib_system): add optional error argument to get_terminal_size --- doc/specs/stdlib_system.md | 4 +- example/system/example_get_terminal_size.f90 | 4 +- src/stdlib_system.F90 | 39 ++++++++++++++------ src/stdlib_system_get_terminal_size.c | 34 +++++++++++++---- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/doc/specs/stdlib_system.md b/doc/specs/stdlib_system.md index dc787c302..6cb35c73e 100644 --- a/doc/specs/stdlib_system.md +++ b/doc/specs/stdlib_system.md @@ -547,7 +547,7 @@ Note: This routine performs a detailed runtime inspection, so it has non-negligi ### Syntax -`call [[stdlib_system(module):get_terminal_size(subroutine)]](columns, lines)` +`call [[stdlib_system(module):get_terminal_size(subroutine)]](columns, lines[, err])` ### Class @@ -559,6 +559,8 @@ Subroutine `lines`: Shall be an `intent(out)` argument of type `integer` that will contain the number of lines in the terminal window. +`err`: Shall be an `intent(out)` and `optional` argument of type `type(state_type)` that will contain the error state. If not provided, the program stops execution on error. + Note: If the query fails, the values of `columns` and `lines` will be set to `-1`. ### Example diff --git a/example/system/example_get_terminal_size.f90 b/example/system/example_get_terminal_size.f90 index 8b6e61d97..ed0a0fbc6 100644 --- a/example/system/example_get_terminal_size.f90 +++ b/example/system/example_get_terminal_size.f90 @@ -1,12 +1,14 @@ program example_get_terminal_size use stdlib_system, only: get_terminal_size + use stdlib_error, only: state_type implicit none integer :: columns, lines + type(state_type) :: err !> Get terminal size - call get_terminal_size(columns, lines) + call get_terminal_size(columns, lines, err) print "(2(a,i0))", "Terminal size is ", columns, 'x', lines print "(a)", repeat("*", columns) diff --git a/src/stdlib_system.F90 b/src/stdlib_system.F90 index f8d0e94ec..c20cf652c 100644 --- a/src/stdlib_system.F90 +++ b/src/stdlib_system.F90 @@ -550,21 +550,38 @@ module function process_get_ID(process) result(ID) integer(process_ID) :: ID end function process_get_ID - !! Returns the size of the terminal window. - !! - !! ### Returns: - !! - **columns**: The number of columns in the terminal window. - !! - **lines**: The number of lines in the terminal window. - !! - !! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead. - subroutine get_terminal_size(columns, lines) bind(C) - integer, intent(out) :: columns, lines - end subroutine get_terminal_size - end interface contains +!! Returns the size of the terminal window. +!! +!! ### Returns: +!! - **columns**: The number of columns in the terminal window. +!! - **lines**: The number of lines in the terminal window. +!! - **err**: An optional error object. +!! +!! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead. +subroutine get_terminal_size(columns, lines, err) + integer, intent(out) :: columns, lines + type(state_type), intent(out), optional :: err + type(state_type) :: err0 + integer :: stat + interface + subroutine c_get_terminal_size(columns, lines, stat) bind(C, name="get_terminal_size") + integer, intent(out) :: columns, lines, stat + end subroutine c_get_terminal_size + end interface + + call c_get_terminal_size(columns, lines, stat) + if (stat /= 0) then + err0 = state_type('get_terminal_size',STDLIB_FS_ERROR,'Failed to get terminal size') + call err0%handle(err) + end if + +end subroutine get_terminal_size + + integer function get_runtime_os() result(os) !! The function identifies the OS by inspecting environment variables and filesystem attributes. !! diff --git a/src/stdlib_system_get_terminal_size.c b/src/stdlib_system_get_terminal_size.c index d7aa7ad2f..263cd97bc 100644 --- a/src/stdlib_system_get_terminal_size.c +++ b/src/stdlib_system_get_terminal_size.c @@ -5,27 +5,47 @@ #else #include #include +#include #endif -void get_terminal_size(int *columns, int *lines) +void get_terminal_size(int *columns, int *lines, int *stat) { + /* Initialize outputs to error state */ *columns = -1; *lines = -1; + *stat = 0; #ifdef _WIN32 + /* Windows implementation using Console API */ HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == INVALID_HANDLE_VALUE) + { + *stat = (int)GetLastError(); // Return Windows system error code + return; + } + CONSOLE_SCREEN_BUFFER_INFO csbi; - if (GetConsoleScreenBufferInfo(hConsole, &csbi)) + if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) { - *columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; - *lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + *stat = (int)GetLastError(); // Failed to get console info + return; } + + /* Calculate visible window dimensions */ + *columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; + *lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + #else + /* Unix implementation using termios ioctl */ struct winsize w; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == -1) { - *columns = w.ws_col; - *lines = w.ws_row; + *stat = errno; // Return POSIX system error code + return; } + + /* Directly use reported terminal dimensions */ + *columns = w.ws_col; + *lines = w.ws_row; #endif } \ No newline at end of file From c1d7a164699056d625d6f3863ec1c083742b920a Mon Sep 17 00:00:00 2001 From: ZUO Zhihua Date: Sun, 20 Apr 2025 23:16:57 +0800 Subject: [PATCH 4/6] fix(stdlib_system): add check for non-terminal stdout in get_terminal_size --- src/stdlib_system_get_terminal_size.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/stdlib_system_get_terminal_size.c b/src/stdlib_system_get_terminal_size.c index 263cd97bc..4cd077061 100644 --- a/src/stdlib_system_get_terminal_size.c +++ b/src/stdlib_system_get_terminal_size.c @@ -8,6 +8,12 @@ #include #endif + +// Get terminal size +// @param[out] columns Pointer to store terminal width +// @param[out] lines Pointer to store terminal height +// @param[out] stat Pointer to store error code +// (0: Success, otherwise: Error, Windows: GetLastError(), Unix: ENOTTY/errno) void get_terminal_size(int *columns, int *lines, int *stat) { /* Initialize outputs to error state */ @@ -37,6 +43,12 @@ void get_terminal_size(int *columns, int *lines, int *stat) #else /* Unix implementation using termios ioctl */ + if (!isatty(STDOUT_FILENO)) + { + *stat = ENOTTY; + return; + } + struct winsize w; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == -1) { From b61538c71e1f77526243e79d7c08e16a2fed470a Mon Sep 17 00:00:00 2001 From: ZUO Zhihua Date: Mon, 21 Apr 2025 08:33:59 +0800 Subject: [PATCH 5/6] docs: improve description and error handling of get_terminal_size --- doc/specs/stdlib_system.md | 29 +++++++++++++++----- example/system/example_get_terminal_size.f90 | 2 +- src/stdlib_system.F90 | 4 +-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/doc/specs/stdlib_system.md b/doc/specs/stdlib_system.md index 6cb35c73e..04a98397d 100644 --- a/doc/specs/stdlib_system.md +++ b/doc/specs/stdlib_system.md @@ -533,7 +533,7 @@ The file is removed from the filesystem if the operation is successful. If the o {!example/system/example_delete_file.f90!} ``` -## `get_terminal_size` - Get the size of the terminal window +## `get_terminal_size` - Get terminal window size in characters ### Status @@ -541,9 +541,13 @@ Experimental ### Description -This subroutine returns the size of the terminal window in characters. +Queries the terminal window size in characters (columns × lines). -Note: This routine performs a detailed runtime inspection, so it has non-negligible overhead. +This routine performs the following checks: +1. Verifies stdout is connected to a terminal (not redirected); +2. Queries terminal dimensions via platform-specific APIs. + +Typical execution time: <100μs on modern systems. ### Syntax @@ -555,13 +559,24 @@ Subroutine ### Arguments -`columns`: Shall be an `intent(out)` argument of type `integer` that will contain the number of columns in the terminal window. +`columns`: `integer, intent(out)`. + Number of columns in the terminal window. Set to `-1` on error. + +`lines`: `integer, intent(out)`. + Number of lines in the terminal window. Set to `-1` on error. -`lines`: Shall be an `intent(out)` argument of type `integer` that will contain the number of lines in the terminal window. +`err`: `type(state_type), intent(out), optional`. + Error state object. If absent, errors terminate execution. -`err`: Shall be an `intent(out)` and `optional` argument of type `type(state_type)` that will contain the error state. If not provided, the program stops execution on error. +### Error Handling -Note: If the query fails, the values of `columns` and `lines` will be set to `-1`. +- **Success**: `columns` and `lines` contain valid dimensions. +- **Failure**: + - Both arguments set to `-1`. + - If `err` present, `stat` contains error code: + - Unix: Contains `errno` (typically `ENOTTY` when redirected); + - Windows: Contains `GetLastError()` code. + - If `err` absent: Program stops with error message. ### Example diff --git a/example/system/example_get_terminal_size.f90 b/example/system/example_get_terminal_size.f90 index ed0a0fbc6..3e331ab4f 100644 --- a/example/system/example_get_terminal_size.f90 +++ b/example/system/example_get_terminal_size.f90 @@ -11,6 +11,6 @@ program example_get_terminal_size call get_terminal_size(columns, lines, err) print "(2(a,i0))", "Terminal size is ", columns, 'x', lines - print "(a)", repeat("*", columns) + if (err%ok()) print "(a)", repeat("*", columns) end program example_get_terminal_size diff --git a/src/stdlib_system.F90 b/src/stdlib_system.F90 index c20cf652c..48ab925fc 100644 --- a/src/stdlib_system.F90 +++ b/src/stdlib_system.F90 @@ -554,7 +554,7 @@ end function process_get_ID contains -!! Returns the size of the terminal window. +!! Returns terminal window size in characters. !! !! ### Returns: !! - **columns**: The number of columns in the terminal window. @@ -575,7 +575,7 @@ end subroutine c_get_terminal_size call c_get_terminal_size(columns, lines, stat) if (stat /= 0) then - err0 = state_type('get_terminal_size',STDLIB_FS_ERROR,'Failed to get terminal size') + err0 = state_type('get_terminal_size',STDLIB_FS_ERROR,'Failed to get terminal size,','stat =',stat) call err0%handle(err) end if From 0bc1fda28eb2ef2eb9c6a2071fb1dc9e62ca8465 Mon Sep 17 00:00:00 2001 From: ZUO Zhihua Date: Mon, 21 Apr 2025 08:58:19 +0800 Subject: [PATCH 6/6] fix(test_os): handle get_terminal_size error --- test/system/test_os.f90 | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/test/system/test_os.f90 b/test/system/test_os.f90 index 47682dd6a..8d9513774 100644 --- a/test/system/test_os.f90 +++ b/test/system/test_os.f90 @@ -2,6 +2,7 @@ module test_os use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test use stdlib_system, only: get_runtime_os, OS_WINDOWS, OS_UNKNOWN, OS_TYPE, is_windows, null_device, & get_terminal_size + use stdlib_error, only: state_type implicit none contains @@ -22,14 +23,25 @@ end subroutine collect_suite subroutine test_get_terminal_size(error) type(error_type), allocatable, intent(out) :: error integer :: columns, lines + type(state_type) :: err !> Get terminal size - call get_terminal_size(columns, lines) + call get_terminal_size(columns, lines, err) - call check(error, columns > 0, "Terminal width is not positive") - if (allocated(error)) return + if (err%ok()) then + call check(error, columns > 0, "Terminal width is not positive") + if (allocated(error)) return + + call check(error, lines > 0, "Terminal height is not positive") + + !> In Github Actions, the terminal size is not available, standard output is redirected to a file + else + call check(error, columns, -1) + if (allocated(error)) return + + call check(error, lines, -1) - call check(error, lines > 0, "Terminal height is not positive") + end if end subroutine test_get_terminal_size