use*_*448 1 haskell haskell-turtle
在用于从密钥环获取密码的Turtle脚本中,ssh-add使用这些密码调用以便不必手动填写它们,具有以下功能:
processKey :: (T.Text, T.Text) -> Shell Line -> IO ()
processKey (kn, str) pwds = do
-- Not sure why (text str) is needed here, but it won't typecheck without
-- it (despite OverloadedStrings).
let expectArg = do
ml <- grep (contains (text str)) pwds
let pass = getPwd $ cut tab (format l ml)
return $ T.unlines [ "<< EOF"
, "spawn ssh-add"
, "expect \"Enter passphrase\""
, "send " <> pass
, "expect eof"
, "EOF"
]
view (inproc "expect" [] expectArg)
where
-- Safely get the third item `cut` from the list.
getPwd xs = getPwd' 0 xs
getPwd' _ [] = ""
getPwd' n (x:xs) = if n == 2
then x
else getPwd' (n+1) xs
Run Code Online (Sandbox Code Playgroud)
此函数采用一个元组(SSH密钥文件名,要在密钥环中存储的文本中搜索的字符串),pwds :: Shell Line这是从shell命令获取的密钥环的全部内容.
该功能的目的是grep密码,并ssh-add使用密钥文件名和密码调用.
问题是这个函数没有输入检查:
sshkeys-autopass.hs:45:30: error:
• Couldn't match type ‘Text’ with ‘Line’
Expected type: Shell Line
Actual type: Shell Text
• In the third argument of ‘inproc’, namely ‘expectArg’
In the first argument of ‘view’, namely
‘(inproc "expect" [] expectArg)’
In a stmt of a 'do' block: view (inproc "expect" [] expectArg)
|
45 | view (inproc "expect" [] expectArg)
| ^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
似乎Shell Line需要成为Shell Text,怎么能这样做,拜托?我对这种结构很糟糕或者不是惯用的Haskell(它确实有异味)的可能性持开放态度,如果有的话请告诉我这个功能如何更好.
虽然我现在无法尝试你的代码,但似乎通过Text(因为T.unlines强迫你)引导命令会导致不必要的麻烦.根据文件(强调我的):
阿
(Shell a)是一个受保护的流的a的副作用
作为一个Shell Line流,它可以提供多个Lines.当然,还有一个叫做select...... 的功能......
select :: Foldable f => f a -> Shell a
...将列表(或任何其他Foldable)转换为a Shell.您可以使用它Shell Line直接满足您的需求:
{-# LANGUAGE OverloadedStrings #-}
-- etc.
let expectArg = do
ml <- grep (contains (text str)) pwds
-- unsafeTextToLine is presumably safe here,
-- as ml was a Line to begin with.
let pass = unsafeTextToLine . getPwd $ cut tab (format l ml)
select [ "<< EOF"
, "spawn ssh-add"
, "expect \"Enter passphrase\""
, "send " <> pass
, "expect eof"
, "EOF"
]
view (inproc "expect" [] expectArg)
Run Code Online (Sandbox Code Playgroud)
附带问题:
不知道为什么
(text str)需要这里,但没有它就不会进行类型检查(尽管是OverloadedStrings).
唯一OverloadedStrings自动的是处理字符串文字.它不会以静默方式将Text值转换为其他实例IsString.用另一种text会改变你的签名,这样的类型str是Pattern Text而非Text.
安全地
cut从列表中获取第三项.
下面是一种编写方式,getPwd无需使用以下几个函数显式编写递归算法Data.Maybe:
getPwd = fromMaybe "" . listToMaybe . drop 2
Run Code Online (Sandbox Code Playgroud)
你可能还喜欢atDef从安全包:
getPwd xs = atDef "" xs 2
Run Code Online (Sandbox Code Playgroud)
但这导致另一个问题:
inproc不想要一个Shell (NonEmpty Line).我不知道该怎么做.
NonEmpty是保证至少有一个元素的列表的类型.在你的情况下,缺乏从去一个明智的方式NonEmpty Line来Line(串联的元素或者选择第一个,比如,不会在所有帮助)是一个信号的方法的改变是必要的.