Skip to content

Commit f915e0c

Browse files
Merge pull request #22 from TimeWarpEngineering/Cramer/2025-12-22/dev
feat: Complete Console API surface coverage for IConsole/ITerminal
2 parents 5ca181c + 28cd1c8 commit f915e0c

28 files changed

Lines changed: 5691 additions & 150 deletions

Directory.Build.props

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@
5454

5555
<!-- Suppress specific warnings -->
5656
<!-- CA1014: CLS compliance not required for this library -->
57+
<!-- CA1716: Reserved keywords (matching System.Console API: In, Error) -->
5758
<!-- CA1724: Type name conflicts (acceptable in this context) -->
5859
<!-- CA1812: False positives for DI-instantiated classes -->
5960
<!-- IL2026, IL2067, IL2070, IL2075, IL3050, IL2104, IL3053: AOT warnings (not yet implemented) -->
60-
<NoWarn>$(NoWarn);CA1014;CA1724;CA1812;IL2026;IL2067;IL2070;IL2075;IL3050;IL2104;IL3053</NoWarn>
61+
<NoWarn>$(NoWarn);CA1014;CA1716;CA1724;CA1812;IL2026;IL2067;IL2070;IL2075;IL3050;IL2104;IL3053</NoWarn>
6162
</PropertyGroup>
6263

6364
<!-- Code analyzers applied to all projects -->
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Add stream access APIs to IConsole
2+
3+
## Description
4+
5+
Add raw stream access methods to `IConsole` to match `System.Console` capabilities. This enables scenarios where code needs direct `Stream` access to stdin/stdout/stderr, or needs to redirect I/O via `TextReader`/`TextWriter`.
6+
7+
Parent: #020
8+
9+
## Checklist
10+
11+
### Implementation
12+
- [x] Add `OpenStandardInput()``Stream` to `IConsole`
13+
- [x] Add `OpenStandardOutput()``Stream` to `IConsole`
14+
- [x] Add `OpenStandardError()``Stream` to `IConsole`
15+
- [x] Add `In``TextReader` property to `IConsole`
16+
- [x] Add `Out``TextWriter` property to `IConsole`
17+
- [x] Add `Error``TextWriter` property to `IConsole`
18+
- [x] Add `SetIn(TextReader)` method to `IConsole`
19+
- [x] Add `SetOut(TextWriter)` method to `IConsole`
20+
- [x] Add `SetError(TextWriter)` method to `IConsole`
21+
- [x] Implement in `TimeWarpConsole`
22+
- [x] Implement in `TimeWarpTerminal`
23+
24+
### Testing
25+
- [x] Add `TestConsole` implementations for all new members
26+
- [x] Add `TestTerminal` implementations for all new members
27+
- [x] Add mock stream support to test implementations
28+
- [x] Add mock TextReader/TextWriter support to test implementations
29+
- [x] Write unit tests for `OpenStandardInput()`
30+
- [x] Write unit tests for `OpenStandardOutput()`
31+
- [x] Write unit tests for `OpenStandardError()`
32+
- [x] Write unit tests for `In`/`Out`/`Error` properties
33+
- [x] Write unit tests for `SetIn()`/`SetOut()`/`SetError()`
34+
35+
## Session
36+
37+
- Created: ses_2f2ab32c3ffeoD0gwPTVU0agTi (2026-03-22)
38+
- Completed: ses_2e9f62f66ffeh05Tj3xKWlwLsS (2026-03-22)
39+
40+
## Notes
41+
42+
### Files to modify
43+
- `iconsole.cs` - add interface members
44+
- `timewarp-console.cs` - implement in TimeWarpConsole
45+
- `timewarp-terminal.cs` - implement in TimeWarpTerminal
46+
- `test-console.cs` - add test implementations
47+
- `test-terminal.cs` - add test implementations
48+
49+
### Design considerations
50+
- `OpenStandard*()` methods return `Stream` - test implementations need mock streams (e.g., `MemoryStream`)
51+
- `In`/`Out`/`Error` are `TextReader`/`TextWriter` - test implementations can use `StringReader`/`StringWriter`
52+
- RS0030 analyzer currently flags `Console.OpenStandard*` usage - this task satisfies that analyzer
53+
54+
### Reference
55+
- https://learn.microsoft.com/en-us/dotnet/api/system.console.openstandardinput
56+
57+
### Coding Standards
58+
Follow the `/csharp` skill for all implementation work.
59+
60+
## Results
61+
62+
### What was implemented
63+
Added 9 stream access members to `IConsole`:
64+
- `Stream OpenStandardInput()` - opens stdin as a stream
65+
- `Stream OpenStandardOutput()` - opens stdout as a stream
66+
- `Stream OpenStandardError()` - opens stderr as a stream
67+
- `TextReader In { get; }` - standard input reader
68+
- `TextWriter Out { get; }` - standard output writer
69+
- `TextWriter Error { get; }` - standard error writer
70+
- `void SetIn(TextReader)` - sets standard input
71+
- `void SetOut(TextWriter)` - sets standard output
72+
- `void SetError(TextWriter)` - sets standard error
73+
74+
### Files changed
75+
- `source/timewarp-terminal/iconsole.cs` - added 9 interface members
76+
- `source/timewarp-terminal/timewarp-console.cs` - implemented all 9 members
77+
- `source/timewarp-terminal/timewarp-terminal.cs` - implemented all 9 members
78+
- `source/timewarp-terminal/test-console.cs` - added mock streams and implementations
79+
- `source/timewarp-terminal/test-terminal.cs` - added mock streams and implementations
80+
- `Directory.Build.props` - added CA1716 to NoWarn (matching System.Console API names)
81+
- `tests/stream-access-01-basic.cs` - new test file (26 tests)
82+
83+
### Test results
84+
- All 26 new tests pass
85+
- All existing tests pass
86+
- Build succeeds with 0 warnings
87+
88+
### Design decisions
89+
- TestConsole/TestTerminal use MemoryStream for OpenStandard* methods
90+
- In/Out/Error properties use StringReader/StringWriter in test implementations
91+
- SetIn/SetOut/SetError update the internal readers/writers
92+
- Added CA1716 suppression for naming conflict with System.Console API (In/Out/Error/SetIn/SetOut/SetError)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Add encoding and redirection APIs to IConsole
2+
3+
## Description
4+
5+
Add encoding and redirection state properties to `IConsole` to match `System.Console` capabilities. This enables code to detect and control text encoding and check if streams are redirected.
6+
7+
Parent: #020
8+
9+
## Checklist
10+
11+
### Implementation
12+
- [x] Add `InputEncoding` get/set property to `IConsole`
13+
- [x] Add `OutputEncoding` get/set property to `IConsole`
14+
- [x] Add `IsInputRedirected` property to `IConsole`
15+
- [x] Add `IsOutputRedirected` property to `IConsole`
16+
- [x] Add `IsErrorRedirected` property to `IConsole`
17+
- [x] Implement in `TimeWarpConsole`
18+
- [x] Implement in `TimeWarpTerminal`
19+
- [x] Consider deprecating `IsInteractive` on `ITerminal` in favor of explicit `!IsInputRedirected`
20+
21+
### Testing
22+
- [x] Add `TestConsole` implementations for all new members
23+
- [x] Add `TestTerminal` implementations for all new members
24+
- [x] Add mock encoding support to test implementations (default to UTF-8)
25+
- [x] Add redirection state properties to test implementations (default to false)
26+
- [x] Write unit tests for `InputEncoding` get/set
27+
- [x] Write unit tests for `OutputEncoding` get/set
28+
- [x] Write unit tests for `IsInputRedirected`
29+
- [x] Write unit tests for `IsOutputRedirected`
30+
- [x] Write unit tests for `IsErrorRedirected`
31+
32+
## Session
33+
34+
- Created: ses_2f2ab32c3ffeoD0gwPTVU0agTi (2026-03-22)
35+
36+
## Notes
37+
38+
### Files to modify
39+
- `iconsole.cs` - add interface members
40+
- `iterminal.cs` - consider IsInteractive deprecation
41+
- `timewarp-console.cs` - implement in TimeWarpConsole
42+
- `timewarp-terminal.cs` - implement in TimeWarpTerminal
43+
- `test-console.cs` - add test implementations
44+
- `test-terminal.cs` - add test implementations
45+
46+
### Design considerations
47+
- Encoding properties should default to `Encoding.UTF8` in test implementations
48+
- Redirection properties should default to `false` in test implementations
49+
- `IsInteractive` on ITerminal currently returns `!Console.IsInputRedirected` - consider if this should be deprecated or kept as convenience
50+
51+
### Reference
52+
- https://learn.microsoft.com/en-us/dotnet/api/system.console.inputencoding
53+
- https://learn.microsoft.com/en-us/dotnet/api/system.console.isinputredirected
54+
55+
### Coding Standards
56+
Follow the `/csharp` skill for all implementation work.
57+
58+
## Results
59+
60+
### What was implemented
61+
- Added 5 new properties to `IConsole` interface:
62+
- `Encoding InputEncoding { get; set; }`
63+
- `Encoding OutputEncoding { get; set; }`
64+
- `bool IsInputRedirected { get; }`
65+
- `bool IsOutputRedirected { get; }`
66+
- `bool IsErrorRedirected { get; }`
67+
68+
- Implemented in `TimeWarpConsole` - delegates to Console properties
69+
- Implemented in `TimeWarpTerminal` - same as TimeWarpConsole
70+
- Implemented in `TestConsole` and `TestTerminal` with defaults:
71+
- InputEncoding/OutputEncoding default to Encoding.UTF8
72+
- IsInputRedirected/IsOutputRedirected/IsErrorRedirected default to false (settable)
73+
74+
### Files changed
75+
- `source/timewarp-terminal/iconsole.cs` - added interface members
76+
- `source/timewarp-terminal/timewarp-console.cs` - implemented properties
77+
- `source/timewarp-terminal/timewarp-terminal.cs` - implemented properties
78+
- `source/timewarp-terminal/test-console.cs` - added test implementation
79+
- `source/timewarp-terminal/test-terminal.cs` - added test implementation
80+
- `tests/console-encoding-01-basic.cs` - new test file (22 tests)
81+
82+
### Test results
83+
- All 22 new tests pass
84+
- All existing tests pass
85+
- Build succeeds with 0 warnings
86+
87+
### Design decisions
88+
- Kept `IsInteractive` on ITerminal (not deprecated) - it's a convenience property that users may prefer over `!IsInputRedirected`
89+
- Redirection properties on test implementations are settable to allow testing different scenarios
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Add rich input APIs to IConsole
2+
3+
## Description
4+
5+
Add character-level input methods to `IConsole` to match `System.Console` capabilities. This enables reading single characters and key presses without requiring a full line.
6+
7+
Parent: #020
8+
9+
## Checklist
10+
11+
### Implementation
12+
- [x] Add `Read()``int` method to `IConsole` (reads single character, returns -1 on EOF)
13+
- [x] Add `ReadKey()` overload without parameter to `IConsole` (defaults to intercept: false)
14+
- [x] Implement in `TimeWarpConsole`
15+
- [x] Implement in `TimeWarpTerminal`
16+
17+
### Testing
18+
- [x] Add `TestConsole` implementations for all new members
19+
- [x] Add `TestTerminal` implementations for all new members
20+
- [x] Add character queue support to `TestConsole` for `Read()`
21+
- [x] Write unit tests for `Read()` returning single character
22+
- [x] Write unit tests for `Read()` returning -1 on EOF
23+
- [x] Write unit tests for `ReadKey()` without parameter (intercept: false)
24+
- [x] Write unit tests for `ReadKey()` with intercept: true (existing)
25+
26+
## Session
27+
28+
- Created: ses_2f2ab32c3ffeoD0gwPTVU0agTi (2026-03-22)
29+
30+
## Notes
31+
32+
### Files to modify
33+
- `iconsole.cs` - add interface members
34+
- `timewarp-console.cs` - implement in TimeWarpConsole
35+
- `timewarp-terminal.cs` - implement in TimeWarpTerminal
36+
- `test-console.cs` - add test implementations
37+
- `test-terminal.cs` - add test implementations (may already have ReadKey support)
38+
39+
### Design considerations
40+
- `Read()` returns `int` to allow -1 for EOF (same as `Console.Read()`)
41+
- `ReadKey()` without parameter should default to `intercept: false` (display the key)
42+
- `TestConsole` already has `ReadLine()` - need to add character-level input support
43+
44+
### Reference
45+
- https://learn.microsoft.com/en-us/dotnet/api/system.console.read
46+
- https://learn.microsoft.com/en-us/dotnet/api/system.console.readkey
47+
48+
### Coding Standards
49+
Follow the `/csharp` skill for all implementation work.
50+
51+
## Results
52+
53+
### What was implemented
54+
- Added `int Read()` method to `IConsole` - reads single character, returns -1 on EOF
55+
- Added `ConsoleKeyInfo ReadKey()` overload to `IConsole` - defaults to intercept: false
56+
- Implemented in `TimeWarpConsole` - wraps Console.Read() and Console.ReadKey(false)
57+
- Implemented in `TimeWarpTerminal` - wraps Console.Read() and Console.ReadKey(false)
58+
- Implemented in `TestConsole` with character queue:
59+
- `QueueCharacters(string)` method to queue characters for Read()
60+
- `CharactersInQueue` property
61+
- `Read()` returns next char from queue, or -1 if empty
62+
- `ReadKey()` throws NotSupportedException (use TestTerminal for key input)
63+
- Implemented in `TestTerminal`:
64+
- `Read()` uses existing key queue
65+
- `ReadKey()` overload without parameter calls ReadKey(false)
66+
67+
### Files changed
68+
- `source/timewarp-terminal/iconsole.cs` - added interface members
69+
- `source/timewarp-terminal/timewarp-console.cs` - implemented Read/ReadKey
70+
- `source/timewarp-terminal/timewarp-terminal.cs` - implemented Read/ReadKey
71+
- `source/timewarp-terminal/test-console.cs` - added character queue and implementations
72+
- `source/timewarp-terminal/test-terminal.cs` - added Read/ReadKey implementations
73+
- `tests/rich-input-01-basic.cs` - new test file (15 tests)
74+
75+
### Test results
76+
- All 15 new tests pass
77+
- All existing tests pass
78+
- Build succeeds with 0 warnings
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Add cursor properties to ITerminal
2+
3+
## Description
4+
5+
Add cursor properties to `ITerminal` to match `System.Console` capabilities. Currently only have method pair `SetCursorPosition()`/`GetCursorPosition()`. Add direct property access and visibility/size control.
6+
7+
Parent: #020
8+
9+
## Checklist
10+
11+
### Implementation
12+
- [x] Add `CursorLeft` get/set property to `ITerminal`
13+
- [x] Add `CursorTop` get/set property to `ITerminal`
14+
- [x] Add `CursorVisible` get/set property to `ITerminal`
15+
- [x] Add `CursorSize` get/set property to `ITerminal` (1-100 percentage)
16+
- [x] Implement in `TimeWarpTerminal`
17+
18+
### Testing
19+
- [x] Add `TestTerminal` implementations for all new members
20+
- [x] Add cursor position tracking to `TestTerminal` (currently has fields but not properties)
21+
- [x] Add `CursorVisible` property to `TestTerminal` (default: true)
22+
- [x] Add `CursorSize` property to `TestTerminal` (default: 100)
23+
- [x] Write unit tests for `CursorLeft` get/set
24+
- [x] Write unit tests for `CursorTop` get/set
25+
- [x] Write unit tests for `CursorVisible` get/set
26+
- [x] Write unit tests for `CursorSize` get/set (validate 1-100 range)
27+
28+
## Session
29+
30+
- Created: ses_2f2ab32c3ffeoD0gwPTVU0agTi (2026-03-22)
31+
32+
## Notes
33+
34+
### Files to modify
35+
- `iterminal.cs` - add interface members
36+
- `timewarp-terminal.cs` - implement in TimeWarpTerminal
37+
- `test-terminal.cs` - add test implementations
38+
39+
### Design considerations
40+
- `CursorLeft`/`CursorTop` properties are more idiomatic than the existing method pair
41+
- Consider keeping `SetCursorPosition()`/`GetCursorPosition()` for backward compatibility
42+
- `CursorSize` is 1-100 percentage (size of cursor, 1=small line, 100=full block)
43+
- `TestTerminal` already has `CursorLeft`/`CursorTop` fields - convert to properties
44+
45+
### Reference
46+
- https://learn.microsoft.com/en-us/dotnet/api/system.console.cursorleft
47+
- https://learn.microsoft.com/en-us/dotnet/api/system.console.cursorvisible
48+
- https://learn.microsoft.com/en-us/dotnet/api/system.console.cursorsize
49+
50+
### Coding Standards
51+
Follow the `/csharp` skill for all implementation work.
52+
53+
## Results
54+
55+
### What was implemented
56+
- Added 4 cursor properties to `ITerminal`:
57+
- `int CursorLeft { get; set; }` - cursor column position
58+
- `int CursorTop { get; set; }` - cursor row position
59+
- `bool CursorVisible { get; set; }` - whether cursor is visible
60+
- `int CursorSize { get; set; }` - cursor size as percentage (1-100)
61+
62+
- Implemented in `TimeWarpTerminal`:
63+
- CursorLeft/CursorTop wrap Console properties with IOException handling
64+
- CursorVisible/CursorSize have Windows platform guards (throw PlatformNotSupportedException on non-Windows)
65+
66+
- Implemented in `TestTerminal`:
67+
- Converted existing CursorLeft/CursorTop fields to properties
68+
- Added CursorVisible property (default: true)
69+
- Added CursorSize property (default: 100, validates 1-100 range)
70+
- Backward compatibility: SetCursorPosition()/GetCursorPosition() still work
71+
72+
### Files changed
73+
- `source/timewarp-terminal/iterminal.cs` - added interface properties
74+
- `source/timewarp-terminal/timewarp-terminal.cs` - added implementations with platform guards
75+
- `source/timewarp-terminal/test-terminal.cs` - converted fields to properties, added new properties
76+
- `tests/terminal-cursor-properties.cs` - new test file (13 tests)
77+
78+
### Test results
79+
- All 13 new tests pass
80+
- All existing tests pass
81+
- Build succeeds with 0 warnings
82+
83+
### Design decisions
84+
- Kept SetCursorPosition()/GetCursorPosition() for backward compatibility
85+
- CursorVisible/CursorSize throw PlatformNotSupportedException on non-Windows (matches Console behavior)
86+
- TestTerminal validates CursorSize range (1-100)

0 commit comments

Comments
 (0)