How to getCh on MS Windows command line?

What I mean by getCh is the non-buffered non-echoed version of getChar, which Hugs used to provided as an extension but not any more. Is there any way to have a non-buffered non-echoed single character input function on MS Windows command line using only the libraries in the MS Windows distribution packages of either GHC or Hugs? The reason to why this is important for me is because I am translating Graham Hutton's "Programming in Haskell" into Korean (soon to be published), which illustrates interactive programming with the example of a calculator that responds instantly for every keystroke of numbers and arithmetic operations running on text mode. It is very important to consider the readers who only have access to MS Windows systems, because Korean OS market share is completely skewed towards MS Windows for very embarrassing reasons that I do not even want to mention. And, isn't GHC developed in MSR anyway? :-) I remember that this is an old problem for both of the two most widely used Haskell implementation, Hugs and GHC. In ghc 6.8 getChar had a bit strange behavior. As far as I remember it always worked as if it were NoBuffering. Fortunately, in the recently released ghc 6.10, this has been fixed. We now actually have to set the buffering mode to NoBuffering with hSetBufferring to get the non-buffered behavior of getChar. But, it still isn't working on MS Windows. In Hugs, hSetBuffering neither works on Unix terminal nor on MS Windows command line. Surprisingly, it works in WinHugs. However, I cannot use WinHugs for my purpose because the interactive calculator example in the book also uses beep characters and ANSI codes which do not work in WinHugs. Thanks for any hacks or suggestions, -- Ahn, Ki Yung

흐壹o 鉅, 工賊嫂, 膠墮將奄 굅, 껐갭, 맏굡별9 죌, 闔u 破訂佯
羸受 I 張灑 戌 銳遷h 稶 淸e 全縡醇連奄抑 全縡憶寥抑 墮膣旭n 湞 銳遷矮枳 婆芋h 흽奧 出抑 剃 倧貞藕抑 修 灑 予輒塡旭n 醇t 全t 灑y 獐鎭.
괼 派姪s 烈r 張 彧 預屎 銳凸藕鴨狙矮r = 一厭M ⓦ嶢.說碇퇀蹴) 伸銳諜h 烈鎭遇n 勖卒蛭 娠刷l 軸愴蓮 ㏂禎旭.h 銳諜熬 伸銳諜h 볶 IO 촁塼 껍 暢踐祝蓮侄蹟工鴨 彩昻n 膠찢連奄彧g 全t 輒彩抑 낟 出e 彧輒賑辛. i 鴨鳶迹輒稔 鎭張將奄 淸受 i 矮d 臆蓮辛 闔u 赤抑 淸稶 投陂 倧汀飡稔 郁 投s 巴淸 蒼張 撓奧 墮膣旭災 醇t i 埃材t 鎭張橓r 鴨疊雩s 눔 淸掩e 闇姮 郁's 全t 墮朕 矮進 剃 彧彩刷l 說檍 怒狸鎭 其嫂奄, 銳t 倧彦塡疊壹抑 一奠x 勖淞e 灑d 彧彩刷l 撓奧/預c 淸奄e -- 쭤彩 鎭詣進差 찢藺t 奬雩剃봔蹙受.槃詣塡僥樗午誦怡薪m

From: glasgow-haskell-users-bounces@haskell.org [mailto:glasgow-haskell-users-bounces@haskell.org] On Behalf Of Simon Marlow
Bulat Ziganshin wrote:
흐壹o 鉅,
工賊嫂, 膠墮將奄 굅, 껐갭, 맏굡별9 죌, 闔u 破訂佯
Please stick to English on this list, thanks.
Simon
Actualy it was english, it's just that the encoding was wrong. In Outlook I manually changed the encoding to US-ASCII, and got the message below. I'm not sure why other 8-bit encoding options failed (like Western Europen (ISO). Alistair Hello Ki, Monday, November 10, 2008, 8:16:09 AM, you wrote:
What I mean by getCh is the non-buffered non-echoed version of getChar, which Hugs used to provided as an extension but not any more.
1. works for me in ghc: getHiddenChar = liftM (chr.fromEnum) c_getch foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt 2. setBufferingMode stdin NoBuffering not tested 3. use interact. i definitely remember that i had effect you need this way. probably it was with some hugs version, but i don't remeber details 4. these days it's not very hard to install free VMWare Player, get preinstalled linux image and install hugs/ghc there -- Best regards, Bulat ***************************************************************** Confidentiality Note: The information contained in this message, and any attachments, may contain confidential and/or privileged material. It is intended solely for the person(s) or entity to which it is addressed. Any review, retransmission, dissemination, or taking of any action in reliance upon this information by persons or entities other than the intended recipient(s) is prohibited. If you received this in error, please contact the sender and delete the material from any computer. *****************************************************************

Bulat Ziganshin wrote:
1. works for me in ghc:
getHiddenChar = liftM (chr.fromEnum) c_getch foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt
Depending on your use case, that's an okay workaround. (And probably suitable for the OP as well.) But unfortunately conio doesn't mix well with ordinary IO. For one, it always reads from the console and not stdin, so redirecting stdin won't work. Another problem is illustrated in the following: main = do a <- getChar b <- getHiddenChar c <- getChar print a print b print c Type a, then press enter, then b. The result (including the echoed input): a 'a' 'b' '\n' I don't know where that '\n' came from but it certainly shouldn't be there. Yet another example: type abcd, then press enter, giving: abcd 'a' '\r' 'b' The fact that newlines are reported as '\r' and not '\n' is easy enough to deal with, but I wonder why getch chose to give '\r' and not 'b'?

Matti Niemenmaa 쓴 글:
Bulat Ziganshin wrote:
1. works for me in ghc:
getHiddenChar = liftM (chr.fromEnum) c_getch foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt
Thanks to Bulat, Bayley, and Matti for suggestions and discussions. At least for my purpose of running the particular example I had "conio.h getch" is good enough because the entire example only depends on the getCh for its input. I defined getCh as follows and it seems to works OK on windows cmd. \begin{code} {-# LANGUAGE ForeignFunctionInterface#-} import Monad import Char import Foreign.C getCh = liftM (chr . fromEnum) c_getch foreign import ccall "conio.h getch" c_getch :: IO CInt \end{code} Just want to make a comment that this "conio.h getch" will only work on windows cmd but not on linux terminals. Both on ghc 6.8.2 and ghc 6.10.1 throws an error when I try to do getCh kyagrd@kyagrd:~/MyDoc$ ghci-6.8.2 Main GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. [1 of 1] Compiling Main ( Main.hs, interpreted ) Ok, modules loaded: Main. *Main> getCh *** Exception: Prelude.chr: bad argument I hope we can have more portable way of handling command line buffering in the future releases GHC. Thanks, for you all again.
Depending on your use case, that's an okay workaround. (And probably suitable for the OP as well.)
But unfortunately conio doesn't mix well with ordinary IO. For one, it always reads from the console and not stdin, so redirecting stdin won't work. Another problem is illustrated in the following:
main = do a <- getChar b <- getHiddenChar c <- getChar print a print b print c
Type a, then press enter, then b. The result (including the echoed input):
a 'a' 'b' '\n'
I don't know where that '\n' came from but it certainly shouldn't be there.
Yet another example: type abcd, then press enter, giving:
abcd 'a' '\r' 'b'
The fact that newlines are reported as '\r' and not '\n' is easy enough to deal with, but I wonder why getch chose to give '\r' and not 'b'?

Hello Ki, Tuesday, November 11, 2008, 4:04:11 AM, you wrote: i have also linux getCh if you need it, although afaik it's not perfect and actually you should use something inside Unix package -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Bulat Ziganshin wrote:
Hello Ki,
Tuesday, November 11, 2008, 4:04:11 AM, you wrote:
i have also linux getCh if you need it, although afaik it's not perfect and actually you should use something inside Unix package
On Unix it is not a problem. We can just use the hSetBuffering and hSetEcho functions in the System.IO module to get no buffering and no echoing the behavior. -- Ahn, Ki Yung

Ahn, Ki Yung wrote:
What I mean by getCh is the non-buffered non-echoed version of getChar, which Hugs used to provided as an extension but not any more.
Is there any way to have a non-buffered non-echoed single character input function on MS Windows command line using only the libraries in the MS Windows distribution packages of either GHC or Hugs?
The reason to why this is important for me is because I am translating Graham Hutton's "Programming in Haskell" into Korean (soon to be published), which illustrates interactive programming with the example of a calculator that responds instantly for every keystroke of numbers and arithmetic operations running on text mode. It is very important to consider the readers who only have access to MS Windows systems, because Korean OS market share is completely skewed towards MS Windows for very embarrassing reasons that I do not even want to mention. And, isn't GHC developed in MSR anyway? :-)
I remember that this is an old problem for both of the two most widely used Haskell implementation, Hugs and GHC.
In ghc 6.8 getChar had a bit strange behavior. As far as I remember it always worked as if it were NoBuffering. Fortunately, in the recently released ghc 6.10, this has been fixed. We now actually have to set the buffering mode to NoBuffering with hSetBufferring to get the non-buffered behavior of getChar. But, it still isn't working on MS Windows.
Here's the ticket: http://hackage.haskell.org/trac/ghc/ticket/2189 This needs somebody familiar with the intricacies of Windows Consoles to fix. Any takers? Cheers, Simon
participants (5)
-
Ahn, Ki Yung
-
Bayley, Alistair
-
Bulat Ziganshin
-
Matti Niemenmaa
-
Simon Marlow