如何在XMonad中调用Shell命令并获取输出以实现关机菜单?
XMonad 关机菜单实现与 IO/X Monad 转换方案
核心问题解决:在 X Monad 中使用 getCommandOutput
getCommandOutput 返回 IO String,而 X Monad 的操作在 X monad 中执行。由于 X 是 MonadIO 的实例,你可以用 liftIO(来自 Control.Monad.IO.Class)将 IO 操作提升到 X monad 中,直接实现你需要的 String -> X String 函数:
import Control.Monad.IO.Class (liftIO) import XMonad.Util.Run (getCommandOutput) runMenu :: String -> X String runMenu cmd = liftIO $ getCommandOutput cmd
完整实现步骤
调用菜单工具并捕获用户选择
用你偏好的菜单工具(比如 rofi 或 dmenu),通过runMenu获取用户选择:-- 示例:用 rofi 显示关机选项菜单 getPowerChoice :: X String getPowerChoice = runMenu "rofi -dmenu -p 'Power Menu:' <<< 'shutdown\nreboot\nlogout'"选择到命令的纯映射
写一个纯函数将用户选择转换为对应的系统命令,同时处理菜单输出的空白字符:import Data.Char (isSpace) -- 去除字符串首尾空格(处理菜单输出的换行/空白) trim :: String -> String trim = reverse . dropWhile isSpace . reverse . dropWhile isSpace choiceToCmd :: String -> String choiceToCmd "shutdown" = "systemctl poweroff" choiceToCmd "reboot" = "systemctl reboot" choiceToCmd "logout" = "xmonad --exit" choiceToCmd _ = "" -- 忽略无效选择组合逻辑并执行命令
将上述步骤组合成完整的关机菜单操作,用spawn(X Monad 内置的命令执行函数)运行最终命令:import XMonad (spawn) import Control.Monad (unless) powerMenu :: X () powerMenu = do rawChoice <- getPowerChoice let choice = trim rawChoice cmd = choiceToCmd choice unless (null cmd) $ spawn cmd
绑定快捷键
在你的 XMonad 配置的 keys 部分,为关机菜单绑定快捷键(示例:Mod+Shift+Q):
import XMonad (modMask, xK_q, shiftMask) myKeys conf = [ -- 其他快捷键... , ((modMask conf .|. shiftMask, xK_q), powerMenu) ]
补充说明
getCommandOutput会捕获命令的标准输出,正好适配菜单工具返回用户选择的场景;- 如果需要更灵活的进程交互,也可以用
XMonad.Util.Run中的runProcessWithInput,同样通过liftIO嵌入Xmonad; - 若使用 dmenu,只需将
getPowerChoice中的命令替换为:"echo -e 'shutdown\nreboot\nlogout' | dmenu -p 'Power Menu:'"
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

