Console ReadLine Intercept App
A .NET Class Enhancing Console.ReadLine(Intercept) Inputs.
Console.ReadLine(true) enables the class presented in this article to intercept keys —including cursor, function, and
modifier keys— making menu coding and input management easier.
Introduction
The main reason of this App is to provide a programming tool, when calling the shared method Cnsl.ReadLine()
,
so that user pressing key functions or, otherwise, entering a string can be easily managed.
Thus, clearly distinguishing a valid or to-be-validated input from a function input.
Functions F1
, F2
, ... are completely configurable -i.e. custom function keys,
so you may use more or less custom function keys accordingly to your needs.
This allows the normal flow of the program to be modified. In the present app, for example,
pressing F3
at any of the program's inputs returns the program to the beginning at the first entry,
or pressing F4
at any input returns the flow from any subroutine up to the first level (Sub Main()
) and terminates.
Program Flow
Initialization: The program starts by displaying a help message and then enters a loop where the user can interact with it through a series of questions.
(1) In the flow chart, if returning from Examples()
, line
contains a Fn
then
the flow continues at (*). Thus, F1?
, F2?
, F3?
,
F4?
are inside a loop exited when it is not F3
(calling Examples() again).
- Main Input Menu (
Menu
function): This is the main part of the program where the user is prompted to enter:
- CultureInfo: The culture setting that defines number formatting (for example,
en-US
or es-ES
).
- Number of Decimal Places: A number between 0 and 15.
- Unit Value: A numerical value that will be converted to engineering notation.
- Unit Name: The name of the unit (e.g., "V" for volts, "A" for amperes).
- If all inputs are valid, then takes place the Engineering Notation Conversion:
The function
ToEngineeringNotation
converts
the value provided by the user into engineering notation. It adjusts the value using metric
prefixes to make the number easier to read (e.g., converting 12345 volts to 12.345 kV).
- Handling Keys:
F1
: Displays help information.
F2
: Allows the user to restart the input process.
F3
: Provides examples of input values.
F4
: Clears the console screen.
F5
: Exits the program.
Esc
: Clears the current input.
- Key
up
: Recovers a previous input (if any).
- Key
down
: Recovers a next input (if any).
- Key
left
: moves cursor to previous input character (if any)
- Key
right
: moves cursor to next input character (if any)
- Key
delete
: delete the character ahead of the cursor (if any)
- Key
backspace
: moves the display cursor one position backwards and deletes the character at that position (if any)
- There are three types of messages.
DspHelp
. Displays help information, detailing the actions of each function key.
Display Eng. Notation
. Calls the conversion and, once converted, displays the engineering notation.
DspErrMsg
. Displays an error message for non valid inputs..
Function Menu
is as follows:
A screenshot of the user interface during input handling in Examples()
If the selected option inside line
is numeric and valid the flow will continue 'down', otherwise it
will display an error message and repeat the loop asking again for the same question.
In the above image, as in all the others inputs in this App, behind the scene, the code is
calling ReadLine()
it passes a string to display (before the input takes place).
Let's see all the arguments.
Public Shared Function ReadLine(strToWrite As String,
intercept As Boolean,
Optional saveInput As Boolean = True,
Optional defaultValue As String = "",
Optional minLength As Int32 = 1) As String
If Not intercept Then Return Console.ReadLine
.....
End Function
strToWrite
is the string to display before the input. (If ended with vbCrLf the input will be in the next line)
intercept
: if false a 'common' Console.ReadLine()
instruction will be executed and returned its value.
saveInput
: save (if true) the user input, so that in next calls to this method, user can recover previous inputs pressing key up
and key down, just like as the Command Window does.
defaultValue
: a string with the default value. The user may accept (pressing Enter
),
edit the defaultValue
or enter any other value
minLength
: the function will not end if the input string length is less than minLength
(or a funcition key F1
, F2
, ... is pressed)
We may define the allowed function keys depending on our needs. This is done in a JSON
file:
{ // FUNCTION KEYS
"DspHelp": "112",
"AskAgain": "113",
"Examples": "114",
"CLS": "115",
"Quit": " 116",
}
These pair values are read in class CnslFns
and stored in a Dictionary(Of String, String)
:
Public Class CnslFns
Shared config As String = _
IO.File.ReadAllText("FunctionKeys.json")
Public Shared functionKeys As Dictionary(Of String, String) = _
JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(config)
Public Shared Function IsNotAFunctKey(s As String) As Boolean
Return s.Length = 0 OrElse AscW(s) <> 27
End Function
End Class
Adding a new function
If you add a new function Fx
you just will have to add it to the JSON
file.
For example, to capture Shift+Control+Alt+A as a new custom function:
{ // FUNCTION KEYS
"DspHelp": "112",
"AskAgain": "113",
"Examples": "114",
"CLS": "115",
"Quit": " 116",
"MyCustomFn": "065SCA"
// The first character, always code 27 for ESC,
// Additionally, for MyCustomFn and as example added SCA modifiers:
// 065=A; and S for shift key, C for Control, A for Alt modifiers
}
Note
Although it is not strictly necessary the first character
(code 27) in for ex. "DspHelp": "112"
it is advisable to do it so, because if the user presses Esc
(code 27) the excecution will stay
inside ReadLine()
, and it will be guaranteed that a valid input will never match one of those constants.
Conclusion and Points of Interest
Until recently I was unaware of the ReadLine(intercept)
method, but I recognize that it is very useful.
I suggest the reader to try adding the Cnsl.vb
file to your new Console project and include
a menu like the one presented, modifying as necessary.
For JSON to work in a new VStudio2022 App, go to menu options path:
Tools/NuGet packages management/Solution Packages Administration
and install NuGet package Newtonsoft.Json.
Source download here.
Addendum. Enhancements.
- Validation:
Added CnslValidation class to handle different input types (e.g., Integer, Double) with customizable validation logic.
- Callback Functionality:
Introduced a delegate CnslCallback allowing for a callback function to be invoked when input is validated, enabling additional processing.
- Error Messages & Patterns:
Enhanced validation includes error messages and optional regex patterns for more specific input control.
- Culture Support:
Added optional CultureInfo for parsing numeric input.
The refactored Cnsl.ReadLine
method is:
Public Shared Function ReadLine(strToWrite As String,
intercept As Boolean,
Optional saveInput As Boolean = True,
Optional defaultValue As String = "",
Optional minLength As Int32 = 1,
Optional validation As CnslValidation = Nothing) As String
Where CnslValidation
constructor signature is:
Public Sub New(validationType As CnslValTypes,
displayErrMsg As Boolean,
Optional minLength As Int32 = 1,
Optional maxNumOfTries As Int32 = 25,
Optional regexPattern As String = "",
Optional cullture As Globalization.CultureInfo = Nothing,
Optional callback As CnslCallback = Nothing)
...and the delegate is defined:
Public Delegate Function CnslCallback(ByRef input As StringBuilder, objVal As CnslValidation) As Boolean
To download the latest example featuring enhanced validation and
callback handling directly, click here