我的~/.xmonad/xmonad.hs
文件中的一个关键绑定是:
((modMask .|. shiftMask, xK_q), io (exitWith ExitSuccess))
所以,我尝试使用这个模式来制作一个循环键盘布局的绑定。我有cycleKLayouts :: IO ()
,从ghci
开始运行时效果很好。然后,我写道:
((modMask, xK_minus), io cycleKLayouts)
这个编译很好,但是当我尝试键时,唯一发生的事情是当前终端和鼠标所在的终端(两个术语)都会闪烁。这与未绑定密钥的情况不同,后者只是将字母传递给应用程序。
我还尝试了liftIO
而不是io
,结果相同。我也有直接spawn
绑定:
((modMask, xK_equal), spawn "setxkbmap -v gb -variant colemak")
有效,但提供了不同的行为。 (cycleKLayouts
在某些时候运行setxkbmap
。
修改:cycleKLayouts
的定义:
module Keyboards where
import System.Process
import Control.Applicative
kLayouts = [("gb(colemak)", "UK-CO")
,("gb", "UK-QW")
,("us(colemak)", "US-CO")
,("us", "US-QW")]
getKLayout :: IO String
getKLayout = f . (!! 4) . lines <$> readProcess "setxkbmap" ["-print"] []
where
f ('+':cs) = g cs
f (_:cs) = f cs
f _ = ""
g ('+':_) = ""
g (c:cs) = c:g cs
g _ = ""
getNextKLayout :: IO String
getNextKLayout = do
l <- getKLayout
let kLayoutNames = map fst kLayouts
let f (x:y:xs) = if x == l then y else f (y:xs)
f _ = head kLayoutNames
return $ f kLayoutNames
setKLayout :: String -> IO ()
setKLayout l = readProcess "setxkbmap" ["-v", l] [] >> return ()
cycleKLayouts :: IO ()
cycleKLayouts = setKLayout =<< getNextKLayout
答案 0 :(得分:2)
以cycleKLayouts
类型重写X ()
并使用spawn
运行命令,当然应该有所帮助。我想问题在于cycleKLayouts
运行命令的方式。结果setxkbmap
可能无法访问您的环境变量,或者分叉然后终止。
如果您发布cycleKLayouts
的来源,我可能会提供更具体的答案。
更新
好吧,我刚尝试将其添加到我的配置中:
((modMask, xK_a), liftIO (readProcess "setxkbmap" ["-print"] "" >>= putStrLn))
每当我按M-a
时出现错误消息&#34; waitForProcess:不存在(没有子进程)&#34;。我无法解释其中的原因,但我想这与Xmonad产生键绑定操作的方式有关(可能它是一个潜在的错误)。
但是,将readProcess
替换为runProcessWithInput
(来自Xmonad.Util.Run)可以完全解决问题:
((modMask, xK_a), liftIO (runProcessWithInput "setxkbmap" ["-print"] "" >>= putStrLn))
尝试这一点以确保我们抓住了同样的问题。