How do I use the output of readProcess in an xmonad keybinding?

做~自己de王妃 提交于 2019-12-14 04:08:54

问题


Ok, so some time ago I was thinking of basing the effect of a keybinding in my xmonad based on the output of a script on my box. I eventually decided not to do that for unrelated reasons but I did recently try to do something similar just as an exercise in learning Haskell.

So, given the function:

test = readProcess "echo" ["-n", "gvim"] []

This throws up because test returns IO String and spawn expects a String.

((modm, xK_y), spawn ("xmessage " ++ test))

Ok. That's cool. I get it that IO operations are unpredictable and so they should be kept separate. Fine. So I did some poking around online and got to this (dropped the xmessage and just want to pass the output of test by itself):

((modm, xK_y), liftIO test >>= spawn)

This is worse. It annoyingly compiles but nothing happens when I try out the binding. (I also replaced it with just spawn "xmessage test" and that worked)

So, then I thought "Maybe there's something wrong with my function" so I repl it but from GCHi I get "gvim" which is correct. So then I write it to a haskell file:

main = test >>= putStrLn
test = readProcess "echo" ["-n", "gvim"] []

Also works correctly.

So, where did I go wrong?

EDIT: Solution was to use runProcessWithInput instead of readProcess. Related link: https://ghc.haskell.org/trac/ghc/ticket/5212 xmonad io binding not working


回答1:


Update

Apparently the solution (see the comments below) is to use readProcessWithInput

Original Answer

You said that:

liftIO test >>= spawn

didn't work, but how about:

liftIO test >>= (\m -> spawn ("xmessage " ++ m))

Also note that the string returned by readProcess likely will have a newline at the end, and that may be affecting things.

Some more things to try in this vein:

return "gvim" >>= (\m -> spawn ("xmessage " ++ m))


import Data.Char

do { m <- liftIO test;  spawn ("xmessage " ++ (filter isAlpha m)) }

The first one should succeed since it is equivalent to spawn "xmessage grim". The second one will strip any newlines (indeed, any non-letters) from the output of test.

Some further things which might shed light on what is going on:

  1. Create a script called /tmp/report with these contents:

    #!/bin/sh
    ( date; echo "/tmp/report was called with args" "$@") >> /tmp/output
    
  2. Make /tmp/report executable.

  3. Run /tmp/report and verify that two lines was appended to /tmp/output
  4. In your monad config, make the action spawn "/tmp/report A". Test the action by seeing if the expected line is appended to /tmp/output.
  5. Try making the monad action this:

    liftIO (readProcess "/tmp/report" ["B"] "") >> spawn "/tmp/report A"
    

    (Note we are using >> here, not >>=.) When you trigger the action you should see a report line for the B call and also one for the A call.

Based on what you see in the file /tmp/output you should be able to determine whether the readProcess command is even being executed as well as the spawn command is triggering.



来源:https://stackoverflow.com/questions/37174160/how-do-i-use-the-output-of-readprocess-in-an-xmonad-keybinding

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!