Commit 9158525f authored by Andrew Gibiansky's avatar Andrew Gibiansky

Adding other mime types, fixing parser to avoid breaking on newlines with implied indentation.

parent 1a50748b
......@@ -25,7 +25,7 @@ like parser desired = parser >>= (`shouldBe` desired)
is string blockType = do
result <- doGhc $ parseString string
result `shouldBe` [blockType string]
result `shouldBe` [blockType $ strip string]
eval string = do
outputAccum <- newIORef []
......@@ -370,6 +370,14 @@ parseStringTests = describe "Parser" $ do
Import "import X",
Expression "print 3"
]
it "ignores blank lines properly" $
[hereLit|
test arg = hello
where
x = y
z = w
|] `is` Declaration
it "doesn't break on long strings" $ do
let longString = concat $ replicate 20 "hello "
("img ! src \"" ++ longString ++ "\" ! width \"500\"") `is` Expression
......
......@@ -2,8 +2,7 @@
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module IHaskell.Display (
IHaskellDisplay(..),
plain,
html,
plain, html, png, jpg, svg, latex,
serializeDisplay
) where
......@@ -26,5 +25,17 @@ plain = Display PlainText . rstrip
html :: String -> DisplayData
html = Display MimeHtml
png :: String -> DisplayData
png = Display MimePng
jpg :: String -> DisplayData
jpg = Display MimeJpg
svg :: String -> DisplayData
svg = Display MimeSvg
latex :: String -> DisplayData
latex = Display MimeLatex
serializeDisplay :: [DisplayData] -> ByteString
serializeDisplay = Serialize.encode
......@@ -54,7 +54,7 @@ import IHaskell.Display
data ErrorOccurred = Success | Failure deriving Show
debug :: Bool
debug = False
debug = True
ignoreTypePrefixes :: [String]
ignoreTypePrefixes = ["GHC.Types", "GHC.Base", "GHC.Show", "System.IO",
......@@ -127,6 +127,7 @@ initializeImports = do
let implicitPrelude = importDecl { ideclImplicit = True }
-- Import modules.
mapM_ (write . ("Importing " ++ )) displayImports
imports <- mapM parseImportDecl $ globalImports ++ displayImports
setContext $ map IIDecl $ implicitPrelude : imports
......@@ -188,6 +189,7 @@ evalCommand _ (Import importStr) = wrapExecution $ do
implicitImportOf imp (IIDecl decl) = ideclImplicit decl && ((==) `on` (unLoc . ideclName)) decl imp
evalCommand _ (Module contents) = wrapExecution $ do
write $ "Module:\n" ++ contents
-- Write the module contents to a temporary file in our work directory
namePieces <- getModuleName contents
let directory = "./" ++ intercalate "/" (init namePieces) ++ "/"
......@@ -256,10 +258,11 @@ evalCommand _ (Module contents) = wrapExecution $ do
Failed -> return $ displayError $ "Failed to load module " ++ modName
evalCommand _ (Directive SetExtension exts) = wrapExecution $ do
results <- mapM setExtension (words exts)
case catMaybes results of
[] -> return []
errors -> return $ displayError $ intercalate "\n" errors
write $ "Extension: " ++ exts
results <- mapM setExtension (words exts)
case catMaybes results of
[] -> return []
errors -> return $ displayError $ intercalate "\n" errors
where
-- Set an extension and update flags.
-- Return Nothing on success. On failure, return an error message.
......@@ -290,13 +293,16 @@ evalCommand _ (Directive SetExtension exts) = wrapExecution $ do
flagMatchesNo ext (name, _, _) = ext == "No" ++ name
evalCommand _ (Directive GetType expr) = wrapExecution $ do
write $ "Type: " ++ expr
result <- exprType expr
flags <- getSessionDynFlags
let typeStr = showSDocUnqual flags $ ppr result
return [plain typeStr, html $ formatGetType typeStr]
-- This is taken largely from GHCi's info section in InteractiveUI.
evalCommand _ (Directive HelpForSet _) = return (Success, [out])
evalCommand _ (Directive HelpForSet _) = do
write "Help for :set."
return (Success, [out])
where out = plain $ intercalate "\n"
[":set is not implemented in IHaskell."
," Use :extension <Extension> to enable a GHC extension."
......@@ -304,7 +310,9 @@ evalCommand _ (Directive HelpForSet _) = return (Success, [out])
]
-- This is taken largely from GHCi's info section in InteractiveUI.
evalCommand _ (Directive GetHelp _) = return (Success, [out])
evalCommand _ (Directive GetHelp _) = do
write "Help via :help or :?."
return (Success, [out])
where out = plain $ intercalate "\n"
["The following commands are available:"
," :extension <Extension> - enable a GHC extension."
......@@ -318,6 +326,7 @@ evalCommand _ (Directive GetHelp _) = return (Success, [out])
-- This is taken largely from GHCi's info section in InteractiveUI.
evalCommand _ (Directive GetInfo str) = wrapExecution $ do
write $ "Info: " ++ str
-- Get all the info for all the names we're given.
names <- parseName str
maybeInfos <- mapM getInfo names
......@@ -349,7 +358,7 @@ evalCommand _ (Directive GetInfo str) = wrapExecution $ do
return [plain $ intercalate "\n" strings]
evalCommand output (Statement stmt) = wrapExecution $ do
write $ "Statement: " ++ stmt
write $ "Statement:\n" ++ stmt
let outputter str = output False [plain str]
(printed, result) <- capturedStatement outputter stmt
case result of
......@@ -362,6 +371,7 @@ evalCommand output (Statement stmt) = wrapExecution $ do
RunBreak{} -> error "Should not break."
evalCommand output (Expression expr) = do
write $ "Expression:\n" ++ expr
-- Evaluate this expression as though it's just a statement.
-- The output is bound to 'it', so we can then use it.
(success, out) <- evalCommand output (Statement expr)
......@@ -372,6 +382,9 @@ evalCommand output (Expression expr) = do
-- return False, and we just resort to plaintext.
let displayExpr = printf "(IHaskell.Display.display (%s))" expr
canRunDisplay <- attempt $ exprType displayExpr
write $ printf "%s: Attempting %s" (if canRunDisplay then "Success" else "Failure") displayExpr
write $ "Show Error: " ++ show (isShowError out)
write $ show out
-- If evaluation failed, return the failure. If it was successful, we
-- may be able to use the IHaskellDisplay typeclass.
......@@ -395,7 +408,7 @@ evalCommand output (Expression expr) = do
-- implement the Show typeclass.
isShowError errs = case find isPlain errs of
Just (Display PlainText msg) ->
startswith "No instance for (GHC.Show.Show " msg &&
startswith "No instance for (GHC.Show.Show" msg &&
isInfixOf " arising from a use of `System.IO.print'" msg
Nothing -> False
where isPlain (Display mime _) = mime == PlainText
......@@ -421,12 +434,14 @@ evalCommand output (Expression expr) = do
evalCommand _ (Declaration decl) = wrapExecution $ do
write $ "Declaration:\n" ++ decl
runDecls decl
-- Do not display any output
return []
evalCommand _ (ParseError loc err) = wrapExecution $
evalCommand _ (ParseError loc err) = wrapExecution $ do
write $ "Parse Error."
return $ displayError $ formatParseError loc err
capturedStatement :: (String -> IO ()) -- ^ Function used to publish intermediate output.
......
......@@ -301,7 +301,7 @@ splitAtLoc line col string =
-- beyond the indentation of the first line. This parses Haskell layout
-- rules properly, and allows using multiline expressions via indentation.
layoutChunks :: String -> [String]
layoutChunks string = filter (not . null . strip) $ layoutLines $ lines string
layoutChunks string = filter (not . null) $ map strip $ layoutLines $ lines string
where
layoutLines :: [String] -> [String]
-- Empty string case. If there's no input, output is empty.
......@@ -323,6 +323,13 @@ layoutChunks string = filter (not . null . strip) $ layoutLines $ lines string
-- Compute indent level of a string as number of leading spaces.
indentLevel :: String -> Int
indentLevel (' ':str) = 1 + indentLevel str
-- Count a tab as two spaces.
indentLevel ('\t':str) = 2 + indentLevel str
-- Count empty lines as a large indent level, so they're always with the previous expression.
indentLevel "" = 100000
indentLevel _ = 0
-- Not the same as 'unlines', due to trailing \n
......
......@@ -277,12 +277,22 @@ instance Serialize DisplayData
instance Serialize MimeType
-- | Possible MIME types for the display data.
data MimeType = PlainText | MimeHtml deriving (Eq, Typeable, Generic)
data MimeType = PlainText
| MimeHtml
| MimePng
| MimeJpg
| MimeSvg
| MimeLatex
deriving (Eq, Typeable, Generic)
instance Show MimeType where
show PlainText = "text/plain"
show MimeHtml = "text/html"
show MimePng = "image/png"
show MimeJpg = "image/jpeg"
show MimeSvg = "image/svg+xml"
show MimeLatex = "text/latex"
-- | Input and output streams.
data StreamType = Stdin | Stdout deriving Show
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment