Skip to content

Commit 8b2e55f

Browse files
committed
stdlib_system: add get_console_width function
1 parent 6aa5177 commit 8b2e55f

File tree

7 files changed

+109
-5
lines changed

7 files changed

+109
-5
lines changed

doc/specs/stdlib_system.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,3 +532,40 @@ The file is removed from the filesystem if the operation is successful. If the o
532532
```fortran
533533
{!example/system/example_delete_file.f90!}
534534
```
535+
536+
## `get_console_width` - Get the width of the console
537+
538+
### Status
539+
540+
Experimental
541+
542+
### Description
543+
544+
This function returns the width of the console window in characters.
545+
It is designed to work across multiple platforms. On Windows, the width is determined by the console window's size.
546+
On UNIX-like systems (Linux, macOS), the width is determined by the terminal's size.
547+
548+
Note: This routine performs a detailed runtime inspection, so it has non-negligible overhead.
549+
550+
### Syntax
551+
552+
`width = [[stdlib_system(module):get_console_width(function)]]()`
553+
554+
### Class
555+
556+
Function
557+
558+
### Arguments
559+
560+
None.
561+
562+
### Return Value
563+
564+
- **Type:** `integer`
565+
- Returns the width of the console window in characters.
566+
567+
### Example
568+
569+
```fortran
570+
{!./example/system/example_get_console_width.f90}!
571+
```

example/system/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
ADD_EXAMPLE(get_runtime_os)
2+
ADD_EXAMPLE(get_console_width)
23
ADD_EXAMPLE(delete_file)
34
ADD_EXAMPLE(is_directory)
45
ADD_EXAMPLE(null_device)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
program example_get_console_width
2+
3+
use stdlib_system, only: get_console_width
4+
implicit none
5+
6+
integer :: width
7+
8+
!> Get console width
9+
width = get_console_width()
10+
11+
print "(a,i0)", "Console width is ", width
12+
print "(a)", repeat("*", width)
13+
14+
end program example_get_console_width

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ set(SRC
112112
stdlib_hashmap_open.f90
113113
stdlib_logger.f90
114114
stdlib_sorting_radix_sort.f90
115+
stdlib_system_get_console_width.c
115116
stdlib_system_subprocess.c
116117
stdlib_system_subprocess.F90
117118
stdlib_system.F90

src/stdlib_system.F90

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ module stdlib_system
8383
public :: kill
8484
public :: elapsed
8585
public :: is_windows
86-
86+
87+
public :: get_console_width
88+
8789
!! version: experimental
8890
!!
8991
!! Tests if a given path matches an existing directory.
@@ -547,8 +549,17 @@ module function process_get_ID(process) result(ID)
547549
!> Return a process ID
548550
integer(process_ID) :: ID
549551
end function process_get_ID
550-
551-
end interface
552+
553+
!! Returns the width of the console window.
554+
!!
555+
!! ### Returns:
556+
!! - **integer**: The width of the console window.
557+
!!
558+
!! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead.
559+
integer function get_console_width() bind(C)
560+
end function get_console_width
561+
562+
end interface
552563

553564
contains
554565

src/stdlib_system_get_console_width.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <stdlib.h>
2+
3+
#ifdef _WIN32
4+
#include <windows.h>
5+
#else
6+
#include <sys/ioctl.h>
7+
#include <unistd.h>
8+
#endif
9+
10+
int get_console_width()
11+
{
12+
int width = 80; // default value
13+
#ifdef _WIN32
14+
CONSOLE_SCREEN_BUFFER_INFO csbi;
15+
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
16+
if (GetConsoleScreenBufferInfo(hConsole, &csbi))
17+
{
18+
width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
19+
}
20+
#else
21+
struct winsize w;
22+
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0)
23+
{
24+
width = w.ws_col;
25+
}
26+
#endif
27+
return width;
28+
}

test/system/test_os.f90

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module test_os
22
use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test
3-
use stdlib_system, only: get_runtime_os, OS_WINDOWS, OS_UNKNOWN, OS_TYPE, is_windows, null_device
4-
3+
use stdlib_system, only: get_runtime_os, OS_WINDOWS, OS_UNKNOWN, OS_TYPE, is_windows, null_device, &
4+
get_console_width
55
implicit none
66

77
contains
@@ -12,12 +12,24 @@ subroutine collect_suite(testsuite)
1212
type(unittest_type), allocatable, intent(out) :: testsuite(:)
1313

1414
testsuite = [ &
15+
new_unittest('test_get_console_width', test_get_console_width), &
1516
new_unittest('test_get_runtime_os', test_get_runtime_os), &
1617
new_unittest('test_is_windows', test_is_windows), &
1718
new_unittest('test_null_device', test_null_device) &
1819
]
1920
end subroutine collect_suite
2021

22+
subroutine test_get_console_width(error)
23+
type(error_type), allocatable, intent(out) :: error
24+
integer :: width
25+
26+
!> Get console width
27+
width = get_console_width()
28+
29+
call check(error, width > 0, "Console width is not positive")
30+
31+
end subroutine test_get_console_width
32+
2133
subroutine test_get_runtime_os(error)
2234
type(error_type), allocatable, intent(out) :: error
2335
integer :: os

0 commit comments

Comments
 (0)