Andrew Birkett's nobugs.org
The shell-command function in emacs prompts you for a command to run (eg. “ls”). It then runs that command and puts the output into a buffer called “Shell Command Output”.
I’d already started writing my own implementation when I noticed that yi already had one, doh.
In fact, yi’s shellCommandE is much more elegant than my attempt, I think it’s worth taking a look at:
shellCommandE = do withMinibuffer "Shell command:" return $ \command -> do pipeE command "" >>= newBufferE "*Shell Command Output*" >> return ()
The “withMiniBuffer” function takes arguments for:
Why not just make withMinibuffer have type YiM String instead? The reason is that it gives withMinibuffer an opportunity to do tidyup code after the callback has run. This is the same idea as with-temp-file in emacs (although that is implemented as a macro).
Next it uses the pipeE command to run the command on an empty input string. Notice that pipeE must be using the IO monad internally to do system i/o, but we don’t need to do anything special because it just returns a value of type “YiM String”. It then plugs that string straight into making a new buffer.
Internally, pipeE does indeed use the “lift” function we met earlier to convert IO values into YiM values.