Skip to content

Add Python-like input() function to stdlib_io#1116

Open
utsav-pal wants to merge 13 commits intofortran-lang:masterfrom
utsav-pal:feature/add-input-function
Open

Add Python-like input() function to stdlib_io#1116
utsav-pal wants to merge 13 commits intofortran-lang:masterfrom
utsav-pal:feature/add-input-function

Conversation

@utsav-pal
Copy link
Copy Markdown

Implements a Python-like input() function as requested in #259.

Changes

  • Added input() function to stdlib_io module
  • Function provides convenient user input with optional prompt
  • Uses existing get_line() function internally

Example Usage

use stdlib_io, only: input
character(len=:), allocatable :: name

name = input('Enter your name: ')
print *, 'Hello, ', name

Testing

  • Full stdlib builds successfully (2049 files)
  • All existing tests pass (407/407)
  • Added unit test and example program

Files Changed

  • src/io/stdlib_io.fypp - Core implementation
  • doc/specs/stdlib_io.md - Documentation
  • example/io/example_input.f90 - Usage example
  • test/io/test_input.f90 - Unit test

Related Issue

Closes #259

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Python-like input() convenience function to stdlib_io for reading a full line from standard input with an optional prompt, implemented on top of existing get_line().

Changes:

  • Exposed new input() API in src/io/stdlib_io.fypp (prompt + optional iostat, uses get_line).
  • Added user-facing documentation for input() in doc/specs/stdlib_io.md.
  • Added a usage example program and new test sources.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/io/stdlib_io.fypp Adds input generic + input_char implementation (and an extra unused input_string).
doc/specs/stdlib_io.md Documents the new input() function and cleans up some formatting.
example/io/example_input.f90 Simple example demonstrating input() usage.
test/io/test_input.f90 Adds a placeholder unit test module/program for input().
test/io/test_input_demo.f90 Adds an interactive demo program under test/ (problematic for automated test runs).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +25 to +35

! Note: This is a basic structure for the test
! Actual interactive testing would require input redirection or mocking
! For now, we verify that the function signature is correct

! The function should be callable (this verifies compilation)
! In a real test environment, you would redirect stdin

! For now, just verify the module compiles and can be used
call check(error, .true., "input function is available")

Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new unit test doesn’t exercise input() behavior (it only checks .true.), so regressions in prompt handling / whitespace preservation / EOF and iostat behavior won’t be caught. Consider restructuring the API for testability (e.g., allow reading from a provided unit) or adding an automated test that runs the executable with redirected stdin so input() is actually executed and asserted on.

Suggested change
! Note: This is a basic structure for the test
! Actual interactive testing would require input redirection or mocking
! For now, we verify that the function signature is correct
! The function should be callable (this verifies compilation)
! In a real test environment, you would redirect stdin
! For now, just verify the module compiles and can be used
call check(error, .true., "input function is available")
integer :: iu, ios
! Exercise stdlib_io:input by reading from a scratch unit instead of
! interactive stdin, so the test is deterministic and automated.
!
! 1. Write a line with leading and trailing whitespace to a scratch unit.
! 2. Rewind the unit and read it using input(unit=..., iostat=...).
! 3. Check that iostat is zero and that the whitespace is preserved.
open(newunit=iu, status='scratch', action='readwrite')
write(iu, '(a)') ' hello '
rewind(iu)
result = input("prompt> ", unit=iu, iostat=ios)
call check(error, ios == 0, "input: iostat should be zero on successful read")
call check(error, result == ' hello ', "input: should preserve leading and trailing whitespace")
close(iu)

Copilot uses AI. Check for mistakes.
Comment on lines +748 to +766
!> Version: experimental
!>
!> Read user input with an optional prompt into a string variable
!> This function provides a Python-like input() interface for Fortran
recursive function input_string(prompt, iostat) result(str)
!> Optional prompt to display before reading input
character(len=*), intent(in), optional :: prompt
!> Optional status of operation
integer, intent(out), optional :: iostat
!> The input string read from the user
type(string_type) :: str

character(len=:), allocatable :: buffer

! Use the character version and convert to string_type
buffer = input_char(prompt, iostat)
str = string_type(buffer)
end function input_string

Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

input_string is currently unused and private, and it also can’t be added to the generic input interface because it has the same dummy argument list as input_char (generic resolution ignores result type). Recommend removing it to avoid dead code, or exposing it under a distinct public name (and documenting it) if returning string_type is desired.

Suggested change
!> Version: experimental
!>
!> Read user input with an optional prompt into a string variable
!> This function provides a Python-like input() interface for Fortran
recursive function input_string(prompt, iostat) result(str)
!> Optional prompt to display before reading input
character(len=*), intent(in), optional :: prompt
!> Optional status of operation
integer, intent(out), optional :: iostat
!> The input string read from the user
type(string_type) :: str
character(len=:), allocatable :: buffer
! Use the character version and convert to string_type
buffer = input_char(prompt, iostat)
str = string_type(buffer)
end function input_string

Copilot uses AI. Check for mistakes.
Comment on lines +315 to +329
### Syntax

`str =` [[stdlib_io(module):input(function)]] `([prompt] [, iostat])`

### Arguments

`prompt` (optional): Shall be a character expression containing the prompt text to display before reading input.
The prompt is displayed without a trailing newline, allowing input on the same line.
This argument is `intent(in)`.

`iostat` (optional): Shall be a scalar of type `integer` that receives the I/O status.
Zero indicates success, non-zero indicates an error or end-of-file condition.
This argument is `intent(out)`.
If not provided, an error will cause the program to stop.

Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documented syntax str = input([prompt] [, iostat]) is ambiguous for the common case where callers want iostat without a prompt: in Fortran that requires a keyword argument (iostat=) since the first optional positional argument is prompt. Consider updating the docs to show keyword usage (and/or an example of calling input(iostat=stat)).

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +24
program test_input
! Test program for the new input() function
use stdlib_io, only: input
implicit none

character(len=:), allocatable :: name, age_str, city
integer :: ios

! Test 1: Basic input with prompt
write(*,'(a)') 'Test 1: Basic input with prompt'
name = input('Enter your name: ')
write(*,'(2a)') 'You entered: ', name
write(*,*)

! Test 2: Input without prompt
write(*,'(a)') 'Test 2: Input without prompt'
write(*,'(a)',advance='no') 'Enter your age: '
age_str = input()
write(*,'(2a)') 'You entered: ', age_str
write(*,*)

! Test 3: Input with iostat
write(*,'(a)') 'Test 3: Input with iostat (press Ctrl+D to end)'
city = input('Enter your city: ', iostat=ios)
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_input_demo.f90 is an interactive program placed under test/. Test runners like fpm test will attempt to execute every test program, so this will block waiting for stdin and can hang CI. Move this to example/ (or another non-test location) or make it non-interactive / excluded from automated test execution.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

@jvdp1 jvdp1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for this PR. Here are some suggestions and comments

### Syntax

`u = ` [[stdlib_io(module):open(function)]] `(filename [, mode] [, iostat])`
`u =` [[stdlib_io(module):open(function)]] `(filename [, mode] [, iostat])`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this change be reverted (or why is it done)?

### Syntax

`call ` [[stdlib_io(module):savetxt(interface)]] `(filename, array [, delimiter])`
`call` [[stdlib_io(module):savetxt(interface)]] `(filename, array [, delimiter])`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this change be reverted (or why is it done)?

### Syntax

`call ` [[stdlib_io_npy(module):load_npy(interface)]] `(filename, array[, iostat][, iomsg])`
`call` [[stdlib_io_npy(module):load_npy(interface)]] `(filename, array[, iostat][, iomsg])`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this change be reverted (or why is it done)?

### Syntax

`call ` [[stdlib_io_npy(module):save_npy(interface)]] `(filename, array[, iostat][, iomsg])`
`call` [[stdlib_io_npy(module):save_npy(interface)]] `(filename, array[, iostat][, iomsg])`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this change be reverted (or why is it done)?

Comment on lines +218 to +220
`call` [[stdlib_io(module):get_line(interface)]] `(unit, line[, iostat][, iomsg])`

`call ` [[stdlib_io(module):get_line(interface)]] ` (line[, iostat][, iomsg])`
`call` [[stdlib_io(module):get_line(interface)]] `(line[, iostat][, iomsg])`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this change be reverted (or why is it done)?

!>
!> Read user input with an optional prompt into a string variable
!> This function provides a Python-like input() interface for Fortran
recursive function input_string(prompt, iostat) result(str)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is not described in the specs. it is also not publicly available.

utsav-pal and others added 12 commits February 20, 2026 02:57
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Co-authored-by: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Input() function

3 participants