[Xmonad] a safer ghci prompt

Andrea Rossato mailing_list at istitutocolli.org
Thu Aug 30 14:21:41 EDT 2007


Hi,

attached you'll find a safer ghci prompt, that uses an external
program to evaluate haskell expression.

This is still work in progress, but you can have an idea of what I'd
like to do.

Feedback highly appreciated!

ciao
andrea

ps: to use:

1. save the attached file as GhcPrompt.hs and follow the install
   instruction;

2. save and compile the uitlity you'll find at the end of the file.

3. enjoy.
-------------- next part --------------
-----------------------------------------------------------------------------
-- |
-- Module      :  XMonadContrib.GhcPrompt
-- Copyright   :  (C) 2007 Andrea Rossato
-- License     :  BSD3
-- 
-- Maintainer  :  andrea.rossato at unibz.it
-- Stability   :  unstable
-- Portability :  unportable
--
-- A ssh prompt for XMonad
--
-----------------------------------------------------------------------------

module XMonadContrib.GhcPrompt (
                             -- * Usage
                             -- $usage
                             ghcPrompt
                              ) where

import Data.List

import XMonad
import XMonadContrib.XPrompt

import Control.Concurrent
import Control.Exception
import System.Process
import System.IO
import System.Exit

-- $usage
-- 1. In Config.hs add:
--
-- > import XMonadContrib.XPrompt
-- > import XMonadContrib.GhcPrompt
--
-- 2. In your keybindings add something like:
--
-- >   , ((modMask .|. controlMask, xK_h), ghcPrompt defaultXPConfig)
--
-- You also need the utility commented out at the end of this file.

data Ghc = Ghc

instance XPrompt Ghc where
    showXPrompt Ghc = "Eval:   "
                     
ghcPrompt :: XPConfig -> X ()
ghcPrompt c = do
  mkXPrompt Ghc c (mkComplFunFromList []) (ghc c [])

type Expr = String

ghc :: XPConfig -> [Expr] -> String -> X ()
ghc conf exps s 
    | s == ":quit" || s == ":q" || s == [] = return ()
    | otherwise = do
  let exps' = exps ++ [s]
      run = "heval \'" ++ show exps' ++ "\'"
  (i,o,e,p) <- io $ runInteractiveCommand $ run
  exit <- io $ waitForProcess p
  case exit of
    ExitSuccess -> do
              err <- io $ hGetContents e
              out <- io $ hGetContents o
              -- get err and out
              oMVar <- io $ newEmptyMVar
              eMVar <- io $ newEmptyMVar
              io $ forkIO $ evaluate (length out) >> putMVar oMVar ()
              io $ forkIO $ evaluate (length err) >> putMVar eMVar ()
              -- wait
              io $ takeMVar oMVar
              io $ takeMVar eMVar
              let res = if out == [] then err else out
              io $ mapM_ hClose [i,o,e]
              mkXPrompt Ghc conf (\_ -> return $ lines res) (ghc conf exps')
    _ -> do io $ mapM_ hClose [i,o,e]
            mkXPrompt Ghc conf (mkComplFunFromList []) (ghc conf exps') 
            
{-

You need this in you path: save it as Heval.hs, but first EDIT ghcPath
to fit your system!!

Then compile with
ghc --make Heval.hs -o heval -package ghc


--------------------- file starts here --------------------
module Main where

import GHC
import DynFlags
import PackageConfig
import System.Environment

import Data.Dynamic
import Data.List
import Data.Maybe



ghcPath :: String
ghcPath = "/usr/lib/ghc-6.6.1"

main :: IO ()
main = defaultErrorHandler defaultDynFlags $ do
  args <- getArgs
  let exps = case args of
               [] -> []
               x -> read (x !! 0) :: [String]
  session <- newSession Interactive (Just ghcPath)
  setSessionDynFlags session =<< getSessionDynFlags session
  setContext session [] [mkModule (stringToPackageId "base") (mkModuleName "Prelude")]
  case exps of
    [] -> return ()
    x -> do updateSession session x
            runExp session $ last x

updateSession :: Session ->  [String] ->  IO ()
updateSession ses l =
    mapM_ (runStmt ses) l

runExp :: Session -> String -> IO ()
runExp ses s
    -- "let: " update session
    | "let " `isPrefixOf` s = do
  runStmt ses s
  return ()
    -- something to eval
    | otherwise = do
  res <- catch (dynCompileExpr ses ("show $ "++ s)) (\e -> return $ Just $ toDyn $ show e)
  case res of
    Just x -> do 
        let res' = fromDynamic x :: Maybe String
        putStrLn (fromMaybe "" res')
    _ -> return ()

-}


More information about the Xmonad mailing list