Commit 322c7725 authored by Andrew Gibiansky's avatar Andrew Gibiansky Committed by Adam Vogt

fixing tests and line numbering of code blocks

parent 4ebe3434
......@@ -202,16 +202,31 @@ parserTests = do
layoutChunkerTests = describe "Layout Chunk" $ do
it "chunks 'a string'" $
layoutChunks "a string" `shouldBe` ["a string"]
map unloc (layoutChunks "a string") `shouldBe` ["a string"]
it "chunks 'a\\nstring'" $
layoutChunks "a\n string" `shouldBe` ["a\n string"]
it "chunks 'a\\n string'" $
map unloc (layoutChunks "a\n string") `shouldBe` ["a\n string"]
it "chunks 'a\\n string\\nextra'" $
layoutChunks "a\n string\nextra" `shouldBe` ["a\n string","extra"]
map unloc (layoutChunks "a\n string\nextra") `shouldBe` ["a\n string","extra"]
it "chunks strings with too many lines" $
layoutChunks "a\n\nstring" `shouldBe` ["a","string"]
map unloc (layoutChunks "a\n\nstring") `shouldBe` ["a","string"]
it "parses multiple exprs" $ do
let text = [hereLit|
first
second
third
fourth
|]
layoutChunks text `shouldBe`
[Located 2 "first",
Located 4 "second",
Located 5 "third",
Located 7 "fourth"]
moduleNameTests = describe "Get Module Name" $ do
it "parses simple module names" $
......@@ -379,6 +394,6 @@ parseStringTests = describe "Parser" $ do
first
second
|] >>= (`shouldBe` [Located 1 (Expression "first"),
Located 2 (Expression "second")])
|] >>= (`shouldBe` [Located 2 (Expression "first"),
Located 4 (Expression "second")])
......@@ -51,6 +51,8 @@ data CodeBlock
-- | Store locations along with a value.
data Located a = Located LineNumber a deriving (Eq, Show)
instance Functor Located where
fmap f (Located line a) = Located line $ f a
-- | Directive types. Each directive is associated with a string in the
-- directive code block.
......@@ -83,7 +85,7 @@ parseString codeString = do
Failure {} ->
-- Split input into chunks based on indentation.
let chunks = layoutChunks $ dropComments codeString in
joinFunctions <$> processChunks 1 [] chunks
joinFunctions <$> processChunks [] chunks
where
parseChunk :: GhcMonad m => String -> LineNumber -> m (Located CodeBlock)
parseChunk chunk line = Located line <$>
......@@ -91,16 +93,16 @@ parseString codeString = do
then return $ parseDirective chunk line
else parseCodeChunk chunk line
processChunks :: GhcMonad m => LineNumber -> [Located CodeBlock] -> [String] -> m [Located CodeBlock]
processChunks line accum remaining =
processChunks :: GhcMonad m => [Located CodeBlock] -> [Located String] -> m [Located CodeBlock]
processChunks accum remaining =
case remaining of
-- If we have no more remaining lines, return the accumulated results.
[] -> return $ reverse accum
-- If we have more remaining, parse the current chunk and recurse.
chunk:remaining -> do
Located line chunk:remaining -> do
block <- parseChunk chunk line
processChunks (line + nlines chunk) (block : accum) remaining
processChunks (block : accum) remaining
-- Test wither a given chunk is a directive.
isDirective :: String -> Bool
......@@ -248,25 +250,29 @@ parseDirective _ _ = error "Directive must start with colon!"
-- A chunk is a line and all lines immediately following that are indented
-- 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) $ map strip $ layoutLines $ lines string
layoutChunks :: String -> [Located String]
layoutChunks = go 1
where
layoutLines :: [String] -> [String]
go :: LineNumber -> String -> [Located String]
go line = filter (not . null . unloc) . map (fmap strip) . layoutLines line . lines
layoutLines :: LineNumber -> [String] -> [Located String]
-- Empty string case. If there's no input, output is empty.
layoutLines [] = []
layoutLines _ [] = []
-- Use the indent of the first line to find the end of the first block.
layoutLines (firstLine:rest) =
layoutLines lineIdx all@(firstLine:rest) =
let firstIndent = indentLevel firstLine
blockEnded line = indentLevel line <= firstIndent in
case findIndex blockEnded rest of
-- If the first block doesn't end, return the whole string, since
-- that just means the block takes up the entire string.
Nothing -> [string]
Nothing -> [Located lineIdx $ intercalate "\n" all]
-- We found the end of the block. Split this bit out and recurse.
Just idx ->
joinLines (firstLine:take idx rest) : layoutChunks (joinLines $ drop idx rest)
let (before, after) = splitAt idx rest in
Located lineIdx (joinLines $ firstLine:before) : go (lineIdx + idx + 1) (joinLines after)
-- Compute indent level of a string as number of leading spaces.
indentLevel :: String -> Int
......
{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"import \n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"no Python documentation found for 'PATH'\n",
"\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}
\ No newline at end of file
No preview for this file type
/*
Custom IHaskell CSS.
*/
table.suggestion-table {
border: 0px;
text-align: center;
}
tr.suggestion-row {
border: 0px;
}
td.suggestion-cell {
border: 0px;
.highlight-code {
white-space: pre;
font-family: monospace;
}
.suggestion-warning {
font-weight: bold;
......
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