From 48531f73dd86eed5e36cd3db7ed8eda0eeebf15d Mon Sep 17 00:00:00 2001 From: Zoe Stafford Date: Sun, 5 Mar 2023 11:06:05 +0000 Subject: [PATCH 1/2] Fix typo --- src/Compiler/Common.idr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Common.idr b/src/Compiler/Common.idr index 397ffb4a1..0fad2994f 100644 --- a/src/Compiler/Common.idr +++ b/src/Compiler/Common.idr @@ -561,7 +561,8 @@ record ConstantPrimitives' str where intToInt : IntKind -> IntKind -> str -> Core str public export -ConstantPrimitives : Type = ConstantPrimitives' String +ConstantPrimitives : Type +ConstantPrimitives = ConstantPrimitives' String ||| Implements casts from and to integral types by using ||| the implementations from the provided `ConstantPrimitives`. From 081938bad87f42af6a0eb9106e1b3600b59b55d2 Mon Sep 17 00:00:00 2001 From: Steve Dunham Date: Sun, 5 Mar 2023 08:33:33 -0800 Subject: [PATCH 2/2] [ base ] Add support for unbuffered stdin --- CHANGELOG.md | 2 ++ libs/base/System.idr | 41 +++++++++++++++++++++++++++++++++++++++ support/c/idris_support.c | 33 +++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e62218bc0..c6a572edc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -122,6 +122,8 @@ * Adds `Vect.allFins` for generating all the `Fin` elements as a `Vect` with matching length to the number of elements. +* Add `withRawMode`, `enableRawMode`, `resetRawMode` for character at a time input on stdin. + #### System * Changes `getNProcessors` to return the number of online processors rather than diff --git a/libs/base/System.idr b/libs/base/System.idr index 78d9a1ce0..b55623944 100644 --- a/libs/base/System.idr +++ b/libs/base/System.idr @@ -98,6 +98,47 @@ prim__setEnv : String -> String -> Int -> PrimIO Int supportNode "unsetEnv" prim__unsetEnv : String -> PrimIO Int +%foreign "C:idris2_enableRawMode, libidris2_support, idris_support.h" +prim__enableRawMode : (1 x : %World) -> IORes Int + +%foreign "C:idris2_resetRawMode, libidris2_support, idris_support.h" +prim__resetRawMode : (1 x : %World) -> IORes () + +||| `enableRawMode` enables raw mode for stdin, allowing characters +||| to be read one at a time, without buffering or echoing. +||| If `enableRawMode` is used, the program should call `resetRawMode` before +||| exiting. Consider using `withRawMode` instead to ensure the tty is reset. +||| +||| This is not supported on windows. +export +enableRawMode : HasIO io => io (Either FileError ()) +enableRawMode = + case !(primIO prim__enableRawMode) of + 0 => pure $ Right () + _ => returnError + +||| `resetRawMode` resets stdin raw mode to original state if +||| `enableRawMode` had been previously called. +export +resetRawMode : HasIO io => io () +resetRawMode = primIO prim__resetRawMode + +||| `withRawMode` performs a given operation after setting stdin to raw mode +||| and ensure that stdin is reset to its original state afterwards. +||| +||| This is not supported on windows. +export +withRawMode : HasIO io => + (onError : FileError -> io a) -> + (onSuccess : () -> io a) -> + io a +withRawMode onError onSuccess = do + Right () <- enableRawMode + | Left err => onError err + result <- onSuccess () + resetRawMode + pure result + ||| Retrieve the specified environment variable's value string, or `Nothing` if ||| there is no such environment variable. ||| diff --git a/support/c/idris_support.c b/support/c/idris_support.c index bf24981f8..dc1c57756 100644 --- a/support/c/idris_support.c +++ b/support/c/idris_support.c @@ -5,6 +5,9 @@ #include #include #include +#ifndef _WIN32 +#include +#endif #include #include @@ -98,6 +101,36 @@ int idris2_setenv(const char *name, const char *value, int overwrite) { #endif } +#ifndef _WIN32 +// The initial state of stdin is stored here if enableRawMode is called. +struct termios *initial_termios = NULL; +#endif + +int idris2_enableRawMode() { +#ifndef _WIN32 + struct termios ti; + int rval = tcgetattr(STDIN_FILENO, &ti); + if (rval != 0) + return rval; + if (!initial_termios) { + initial_termios = malloc(sizeof(struct termios)); + *initial_termios = ti; + } + ti.c_lflag &= ~(ECHO | ICANON); + return tcsetattr(STDIN_FILENO, TCSAFLUSH, &ti); +#else + return -1; +#endif +} + +void idris2_resetRawMode() { +#ifndef _WIN32 + if (initial_termios != NULL) { + tcsetattr(STDIN_FILENO, TCSAFLUSH, initial_termios); + } +#endif +} + int idris2_unsetenv(const char *name) { #ifdef _WIN32 return win32_modenv(name, "", 1);