diff --git a/build.sh b/build.sh
index 2d5cf121..e24f3a22 100755
--- a/build.sh
+++ b/build.sh
@@ -11,3 +11,6 @@ do
cabal install || return 1
cd ..
done
+
+# Remove my profile
+rm -rf ~/.ipython/profile_haskell
diff --git a/profile/static/custom/custom.js b/profile/static/custom/custom.js
index 873669b5..85ab5f38 100644
--- a/profile/static/custom/custom.js
+++ b/profile/static/custom/custom.js
@@ -39,6 +39,9 @@ $([IPython.events]).on('app_initialized.NotebookApp', function(){
$([IPython.events]).on('shell_reply.Kernel', function() {
// Add logic here that should be run once per reply.
+
+ // Highlight things with a .highlight-code class
+ // The id is the mode with with to highlight
$('.highlight-code').each(function() {
var $this = $(this),
$code = $this.html(),
diff --git a/src/IHaskell/Eval/Evaluate.hs b/src/IHaskell/Eval/Evaluate.hs
index 48cfbb5d..f0c640d6 100644
--- a/src/IHaskell/Eval/Evaluate.hs
+++ b/src/IHaskell/Eval/Evaluate.hs
@@ -84,7 +84,7 @@ globalImports :: [String]
globalImports =
[ "import IHaskell.Display"
, "import Control.Applicative ((<$>))"
- , "import GHC.IO.Handle (hDuplicateTo, hDuplicate)"
+ , "import GHC.IO.Handle (hDuplicateTo, hDuplicate, hClose)"
, "import System.Posix.IO"
, "import System.Posix.Files"
, "import System.IO"
@@ -100,6 +100,11 @@ interpret action = runGhc (Just libdir) $ do
void $ setSessionDynFlags $ dflags { hscTarget = HscInterpreted, ghcLink = LinkInMemory }
initializeImports
+
+ -- Close stdin so it can't be used.
+ -- Otherwise it'll block the kernel forever.
+ runStmt "System.IO.hClose System.IO.stdin" RunToCompletion
+
initializeItVariable
-- Run the rest of the interpreter
@@ -550,7 +555,7 @@ evalCommand output (Statement stmt) state = wrapExecution state $ do
return $ name ++ " :: " ++ theType
let joined = unlines types
- htmled = formatGetType joined
+ htmled = unlines $ map formatGetType types
return $ case output of
[] -> [html htmled]
@@ -558,7 +563,7 @@ evalCommand output (Statement stmt) state = wrapExecution state $ do
-- Return plain and html versions.
-- Previously there was only a plain version.
[Display PlainText text] ->
- [plain $ joined ++ "n" ++ text,
+ [plain $ joined ++ "\n" ++ text,
html $ htmled ++ mono text]
RunException exception -> throw exception
@@ -676,10 +681,23 @@ evalCommand output (Expression expr) state = do
evalCommand _ (Declaration decl) state = wrapExecution state $ do
write $ "Declaration:\n" ++ decl
- runDecls decl
+ names <- runDecls decl
- -- Do not display any output
- return []
+ dflags <- getSessionDynFlags
+ let boundNames = map (replace ":Interactive." "" . showPpr dflags) names
+ nonDataNames = filter (not . isUpper . head) boundNames
+
+ -- Display the types of all bound names if the option is on.
+ -- This is similar to GHCi :set +t.
+ if not $ useShowTypes state
+ then return []
+ else do
+ -- Get all the type strings.
+ types <- forM nonDataNames $ \name -> do
+ theType <- showSDocUnqual dflags . ppr <$> exprType name
+ return $ name ++ " :: " ++ theType
+
+ return [html $ unlines $ map formatGetType types]
evalCommand _ (TypeSignature sig) state = wrapExecution state $
-- We purposefully treat this as a "success" because that way execution
@@ -888,6 +906,7 @@ formatErrorWithClass cls =
printf "%s" cls .
replace "\n" "
" .
fixLineWrapping .
+ fixStdinError .
replace useDashV "" .
rstrip .
typeCleaner
@@ -935,7 +954,16 @@ formatType :: String -> [DisplayData]
formatType typeStr = [plain typeStr, html $ formatGetType typeStr]
displayError :: ErrMsg -> [DisplayData]
-displayError msg = [plain . typeCleaner $ msg, html $ formatError msg]
+displayError msg = [plain . fixStdinError . typeCleaner $ msg, html $ formatError msg]
+
+fixStdinError :: ErrMsg -> ErrMsg
+fixStdinError err =
+ if isStdinErr err
+ then " is not available in IHaskell. Use special `inputLine` instead of `getLine`."
+ else err
+ where
+ isStdinErr err = startswith "" err
+ && "illegal operation (handle is closed)" `isInfixOf` err
mono :: String -> String
mono = printf "%s"