Skip to content

Commit 35ada19

Browse files
committed
feat(stdlib_system): add optional error argument to get_terminal_size
1 parent 8d6fcad commit 35ada19

File tree

4 files changed

+61
-20
lines changed

4 files changed

+61
-20
lines changed

doc/specs/stdlib_system.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ Note: This routine performs a detailed runtime inspection, so it has non-negligi
547547

548548
### Syntax
549549

550-
`call [[stdlib_system(module):get_terminal_size(subroutine)]](columns, lines)`
550+
`call [[stdlib_system(module):get_terminal_size(subroutine)]](columns, lines[, err])`
551551

552552
### Class
553553

@@ -559,6 +559,8 @@ Subroutine
559559

560560
`lines`: Shall be an `intent(out)` argument of type `integer` that will contain the number of lines in the terminal window.
561561

562+
`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.
563+
562564
Note: If the query fails, the values of `columns` and `lines` will be set to `-1`.
563565

564566
### Example

example/system/example_get_terminal_size.f90

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
program example_get_terminal_size
22

33
use stdlib_system, only: get_terminal_size
4+
use stdlib_error, only: state_type
45
implicit none
56

67
integer :: columns, lines
8+
type(state_type) :: err
79

810
!> Get terminal size
9-
call get_terminal_size(columns, lines)
11+
call get_terminal_size(columns, lines, err)
1012

1113
print "(2(a,i0))", "Terminal size is ", columns, 'x', lines
1214
print "(a)", repeat("*", columns)

src/stdlib_system.F90

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -550,21 +550,38 @@ module function process_get_ID(process) result(ID)
550550
integer(process_ID) :: ID
551551
end function process_get_ID
552552

553-
!! Returns the size of the terminal window.
554-
!!
555-
!! ### Returns:
556-
!! - **columns**: The number of columns in the terminal window.
557-
!! - **lines**: The number of lines in the terminal window.
558-
!!
559-
!! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead.
560-
subroutine get_terminal_size(columns, lines) bind(C)
561-
integer, intent(out) :: columns, lines
562-
end subroutine get_terminal_size
563-
564553
end interface
565554

566555
contains
567556

557+
!! Returns the size of the terminal window.
558+
!!
559+
!! ### Returns:
560+
!! - **columns**: The number of columns in the terminal window.
561+
!! - **lines**: The number of lines in the terminal window.
562+
!! - **err**: An optional error object.
563+
!!
564+
!! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead.
565+
subroutine get_terminal_size(columns, lines, err)
566+
integer, intent(out) :: columns, lines
567+
type(state_type), intent(out), optional :: err
568+
type(state_type) :: err0
569+
integer :: stat
570+
interface
571+
subroutine c_get_terminal_size(columns, lines, stat) bind(C, name="get_terminal_size")
572+
integer, intent(out) :: columns, lines, stat
573+
end subroutine c_get_terminal_size
574+
end interface
575+
576+
call c_get_terminal_size(columns, lines, stat)
577+
if (stat /= 0) then
578+
err0 = state_type('get_terminal_size',STDLIB_FS_ERROR,'Failed to get terminal size')
579+
call err0%handle(err)
580+
end if
581+
582+
end subroutine get_terminal_size
583+
584+
568585
integer function get_runtime_os() result(os)
569586
!! The function identifies the OS by inspecting environment variables and filesystem attributes.
570587
!!

src/stdlib_system_get_terminal_size.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,47 @@
55
#else
66
#include <sys/ioctl.h>
77
#include <unistd.h>
8+
#include <errno.h>
89
#endif
910

10-
void get_terminal_size(int *columns, int *lines)
11+
void get_terminal_size(int *columns, int *lines, int *stat)
1112
{
13+
/* Initialize outputs to error state */
1214
*columns = -1;
1315
*lines = -1;
16+
*stat = 0;
1417

1518
#ifdef _WIN32
19+
/* Windows implementation using Console API */
1620
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
21+
if (hConsole == INVALID_HANDLE_VALUE)
22+
{
23+
*stat = (int)GetLastError(); // Return Windows system error code
24+
return;
25+
}
26+
1727
CONSOLE_SCREEN_BUFFER_INFO csbi;
18-
if (GetConsoleScreenBufferInfo(hConsole, &csbi))
28+
if (!GetConsoleScreenBufferInfo(hConsole, &csbi))
1929
{
20-
*columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
21-
*lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
30+
*stat = (int)GetLastError(); // Failed to get console info
31+
return;
2232
}
33+
34+
/* Calculate visible window dimensions */
35+
*columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
36+
*lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
37+
2338
#else
39+
/* Unix implementation using termios ioctl */
2440
struct winsize w;
25-
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0)
41+
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == -1)
2642
{
27-
*columns = w.ws_col;
28-
*lines = w.ws_row;
43+
*stat = errno; // Return POSIX system error code
44+
return;
2945
}
46+
47+
/* Directly use reported terminal dimensions */
48+
*columns = w.ws_col;
49+
*lines = w.ws_row;
3050
#endif
3151
}

0 commit comments

Comments
 (0)