提示输入哈斯克尔命令行应用程序
下面的Haskell程序的密码提示用户在终端输入密码,并继续他是否已经进入了正确的:提示输入哈斯克尔命令行应用程序
main = do
putStrLn "Password:"
password <- getLine
case hash password `member` database of
False -> putStrLn "Unauthorized use!"
True -> do
...
不幸的是,密码将出现在当用户键入它时,我想要避免。
如何在不显示屏幕的情况下阅读用户键入的字符序列?为此目的,相当于
getLine
?
我在MacOS X上,但我希望它能在Windows和Linux上工作。
尝试了下:
module Main
where
import System.IO
import Control.Exception
main :: IO()
main = getPassword >>= putStrLn . ("Entered: " ++)
getPassword :: IO String
getPassword = do
putStr "Password: "
hFlush stdout
pass <- withEcho False getLine
putChar '\n'
return pass
withEcho :: Bool -> IO a -> IO a
withEcho echo action = do
old <- hGetEcho stdin
bracket_ (hSetEcho stdin echo) (hSetEcho stdin old) action
工程就像一个魅力!你可以把它变成一个小的完整的'getPassword :: IO String'的例子,所以我可以让这个接受的答案? – 2010-10-31 19:48:42
我编辑过的片段 – Yuras 2010-10-31 20:50:19
太棒了,谢谢! – 2010-11-01 08:18:42
使用the System.Posix.Terminal
module可以在终端中禁用回声。但是,这需要POSIX支持,所以可能无法在Windows上工作(我没有检查)。
import System.Posix.Terminal
import System.Posix.IO (stdInput)
getPassword :: IO String
getPassword = do
tc <- getTerminalAttributes stdInput
setTerminalAttributes stdInput (withoutMode tc EnableEcho) Immediately
password <- getLine
setTerminalAttributes stdInput tc Immediately
return password
main = do
putStrLn "Password:"
password <- getPassword
putStrLn "Name:"
name <- getLine
putStrLn $ "Your password is " ++ password ++ " and your name is " ++ name
注意,标准输入是行缓冲,所以如果你使用putStr "Password:"
而不是putStrLn
,你需要先刷新缓冲区,否则提示会也有抑制作用。
不错,有一个upvote!虽然,看起来来自'System.IO'的谦逊的'hSetEcho'会起作用。 :-) – 2010-10-31 20:02:13
@海因里希:啊。太谦卑,值得注意:P – kennytm 2010-10-31 20:21:47
有在System.Console.Haskeline
一个getPassword
。可能对你的情况有点矫枉过正,但有人会觉得它很有用。
一个例子:
> runInputT defaultSettings $ do {p <- getPassword (Just '*') "pass:"; outputStrLn $ fromJust p}
pass:***
asd
不错!我不知道'haskeline'库。 – 2010-11-01 08:21:03
任何想法为什么所有的Haskeline函数都返回'Maybe String'而不是'String'?没有关于它的文档,在我看来,它应该总是返回'String',就像标准的'getLine'一样。 – jameshfisher 2013-12-23 23:25:16
这是因为标准'getLine'是一个局部函数,当接收到一个'EOT'时会引发异常。 haskeline会返回'Nothing',允许你在有空行的时候做一些不同的事情,而不是'^ D' – berdario 2016-10-14 09:41:37
正如我上面的评论,我建议你使用haskeline,这是一个完整的提示图书馆。我愉快地使用它LambdaCalculator没有投诉。
任何想法为什么所有的Haskeline函数都返回'Maybe String'而不是'String'?没有关于它的文档,在我看来,它应该总是返回'String',就像标准的'getLine'一样。 – jameshfisher 2013-12-23 23:25:32
@ jameshfisher这对我来说并不是显而易见的,不。这需要挖掘一些源头。 – 2013-12-23 23:55:38
withEcho可以用少一点在降噪被写成:
withEcho :: Bool -> IO a -> IO a
withEcho echo action =
bracket (hGetEcho stdin)
(hSetEcho stdin)
(const $ hSetEcho stdin echo >> action)
我认为这对我来说太聪明了,我必须很难弄清楚它是如何工作的。更好的解决办法可能是将“暂时更改设置的行为动作”行为分解为类似于'withTemp :: a - > IO a - >(a - > IO b) - > IO c - > IO c', withtemmp tempValue getter setter action = ...'以便您可以定义'withEcho echo = withTemp echo(hGetEcho stdin)(hSetEcho stdin)'。 – 2014-02-22 23:40:50
使用[haskeline](http://hackage.haskell.org/packages/archive/haskeline/0.6.3.1/doc/html/System -console-Haskeline.html#五:getPassword来)。 – 2010-10-31 22:02:18
@TomMd:您的评论是对该问题的适当答案。为什么不把它作为一个真正的答案,以便它可以被投票,评论,接受,等等? – 2010-11-01 02:40:06