如何将 `Shell Text` 转换为 `Shell Line`?
How can a `Shell Text` be converted to `Shell Line`?
在用于从密钥环中获取密码的 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
此函数采用元组(SSH 密钥文件名、要在密钥环中存储的文本中搜索的字符串)和 pwds :: Shell Line
,即从 [=31 中获取的密钥环的全部内容=]命令。
该函数的目的是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)
| ^^^^^^^^^
好像Shell Line
需要变成Shell Text
,请问怎么办?我愿意接受这种结构错误或不惯用的可能性 Haskell(它确实有味道),如果是这样,请告知如何改进此功能。
虽然我现在无法试用您的代码,但似乎通过 Text
来回传递您的命令(因为 T.unlines
迫使您这样做)会造成不必要的麻烦。根据 to the documentation(强调我的):
A (Shell a)
is a protected stream of a
's with side effects
由于 Shell Line
是一个流,它可以提供多个 Line
。果然,有一个函数叫做 select
...
select :: Foldable f => f a -> Shell a
... 这会将列表(或任何其他 Foldable
)转换为 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)
附带问题:
Not sure why (text str)
is needed here, but it won't typecheck without it (despite OverloadedStrings).
OverloadedStrings
唯一自动做的事情就是处理字符串文字。它不会默默地将 Text
值转换为 IsString
的其他实例。使用 text
的替代方法是更改您的签名,以便 str
的类型是 Pattern Text
而不是 Text
.
Safely get the third item cut
from the list.
这是一种不用显式编写递归算法就可以编写 getPwd
的方法,它使用了 Data.Maybe
中的几个函数:
getPwd = fromMaybe "" . listToMaybe . drop 2
您可能还喜欢 safe 包中的 atDef
:
getPwd xs = atDef "" xs 2
But that causes another problem: inproc
does not want a Shell (NonEmpty Line)
. I have no idea what to do about this.
NonEmpty
是一种保证至少有一个元素的列表类型。在您的情况下,缺乏从 NonEmpty Line
到 Line
的明智方法(例如,连接元素或选择第一个元素根本无济于事)是一个变化的信号方法是必要的。
在用于从密钥环中获取密码的 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
此函数采用元组(SSH 密钥文件名、要在密钥环中存储的文本中搜索的字符串)和 pwds :: Shell Line
,即从 [=31 中获取的密钥环的全部内容=]命令。
该函数的目的是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)
| ^^^^^^^^^
好像Shell Line
需要变成Shell Text
,请问怎么办?我愿意接受这种结构错误或不惯用的可能性 Haskell(它确实有味道),如果是这样,请告知如何改进此功能。
虽然我现在无法试用您的代码,但似乎通过 Text
来回传递您的命令(因为 T.unlines
迫使您这样做)会造成不必要的麻烦。根据 to the documentation(强调我的):
A
(Shell a)
is a protected stream ofa
's with side effects
由于 Shell Line
是一个流,它可以提供多个 Line
。果然,有一个函数叫做 select
...
select :: Foldable f => f a -> Shell a
... 这会将列表(或任何其他 Foldable
)转换为 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)
附带问题:
Not sure why
(text str)
is needed here, but it won't typecheck without it (despite OverloadedStrings).
OverloadedStrings
唯一自动做的事情就是处理字符串文字。它不会默默地将 Text
值转换为 IsString
的其他实例。使用 text
的替代方法是更改您的签名,以便 str
的类型是 Pattern Text
而不是 Text
.
Safely get the third item
cut
from the list.
这是一种不用显式编写递归算法就可以编写 getPwd
的方法,它使用了 Data.Maybe
中的几个函数:
getPwd = fromMaybe "" . listToMaybe . drop 2
您可能还喜欢 safe 包中的 atDef
:
getPwd xs = atDef "" xs 2
But that causes another problem:
inproc
does not want aShell (NonEmpty Line)
. I have no idea what to do about this.
NonEmpty
是一种保证至少有一个元素的列表类型。在您的情况下,缺乏从 NonEmpty Line
到 Line
的明智方法(例如,连接元素或选择第一个元素根本无济于事)是一个变化的信号方法是必要的。