从 dmenu 块启动进程 XMonad

Launching a process from dmenu blocks XMonad

我从 XMonad.Util.Dmenu 获取的函数有问题,即 dmenuXinerama(见下文)。好像是这样:

These functions block xmonad's event loop until dmenu exits; this means that programs will not be able to open new windows and you will not be able to change workspaces or input focus until you have responded to the prompt one way or another.

发生的事情是我生成了一个菜单实例并且它出现了,但是一旦我从那里 运行 一些东西,一切都被阻止了,我什么也做不了。

这是函数:

dmenuXinerama :: [String] -> X String
dmenuXinerama opts = do
    curscreen <- (fromIntegral . W.screen . W.current) `fmap` gets windowset :: X Int
    io $ runProcessWithInput "dmenu_run" ["-m", show curscreen] (unlines opts)

...和绑定:

-- Spawn dmenu
, ((modMask, xK_p), void $ dmenuXinerama [])

我也试过这个:

dmenuXinerama :: [String] -> X String
dmenuXinerama opts = do
    curscreen <-
      (fromIntegral . W.screen . W.current) `fmap` gets windowset :: X Int
    _ <-
      runProcessWithInput "dmenu_run" ["-m", show curscreen] (unlines opts)
    menuArgs "dmenu_run" ["-m", show curscreen] opts

-- | Like 'menu' but also takes a list of command line arguments.
menuArgs :: MonadIO m => String -> [String] -> [String] -> m String
menuArgs menuCmd args opts = liftM (filter (/='\n')) $
  runProcessWithInput menuCmd args (unlines opts)

如果有人能解释发生了什么以及我该如何解决这个问题,我将不胜感激。

我认为 dmenu_run 不会退出(直到您使用它启动的程序退出),因此它不适合与 runProcessWithInput 一起使用。使用 dmenu_pathdmenu 代替,然后 spawn 结果。

pickExe :: X ()
pickExe = do
    exes <- runProcessWithInput "dmenu_path" [] ""
    exe <- dmenuXinerama (lines exes)
    spawn exe

上面片段中的 dmenuXinerama 是您可以从 XMonad.Util.Dmenu 导入的片段,而不是您从问题中修改的片段。 (spawn 来自 XMonad.Core。)

如果您对 Monad 界面感到满意,您可能更愿意这样写而不使用临时名称:

pickExe = spawn =<< dmenuXinerama . lines =<< runProcessWithInput "dmenu_path" [] ""