Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
gargantext-ihaskell
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
gargantext-ihaskell
Commits
145ebb52
Commit
145ebb52
authored
Jan 08, 2014
by
Andrew Gibiansky
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fix_111_tilde_completion' of
https://github.com/edechter/IHaskell
Conflicts: IHaskell.cabal
parents
55187484
ab55621d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
190 additions
and
26 deletions
+190
-26
IHaskell.cabal
IHaskell.cabal
+11
-3
Hspec.hs
src/Hspec.hs
+84
-14
Completion.hs
src/IHaskell/Eval/Completion.hs
+19
-9
ParseShell.hs
src/IHaskell/Eval/ParseShell.hs
+76
-0
No files found.
IHaskell.cabal
View file @
145ebb52
...
@@ -80,7 +80,9 @@ library
...
@@ -80,7 +80,9 @@ library
text >=0.11,
text >=0.11,
mtl >= 2.1,
mtl >= 2.1,
transformers,
transformers,
haskeline
haskeline,
HUnit,
parsec
exposed-modules: IHaskell.Display
exposed-modules: IHaskell.Display
IHaskell.Eval.Completion
IHaskell.Eval.Completion
...
@@ -90,6 +92,7 @@ library
...
@@ -90,6 +92,7 @@ library
IHaskell.Eval.Parser
IHaskell.Eval.Parser
IHaskell.Eval.Stdin
IHaskell.Eval.Stdin
IHaskell.Eval.Hoogle
IHaskell.Eval.Hoogle
IHaskell.Eval.ParseShell
IHaskell.IPython
IHaskell.IPython
IHaskell.Message.Parser
IHaskell.Message.Parser
IHaskell.Message.UUID
IHaskell.Message.UUID
...
@@ -114,6 +117,7 @@ executable IHaskell
...
@@ -114,6 +117,7 @@ executable IHaskell
IHaskell.Eval.Parser
IHaskell.Eval.Parser
IHaskell.Eval.Stdin
IHaskell.Eval.Stdin
IHaskell.Eval.Hoogle
IHaskell.Eval.Hoogle
IHaskell.Eval.ParseShell
IHaskell.IPython
IHaskell.IPython
IHaskell.Message.Parser
IHaskell.Message.Parser
IHaskell.Message.UUID
IHaskell.Message.UUID
...
@@ -158,7 +162,9 @@ executable IHaskell
...
@@ -158,7 +162,9 @@ executable IHaskell
text >=0.11,
text >=0.11,
mtl >= 2.1,
mtl >= 2.1,
transformers,
transformers,
haskeline
haskeline,
HUnit,
parsec
Test-Suite hspec
Test-Suite hspec
hs-source-dirs: src
hs-source-dirs: src
...
@@ -199,7 +205,9 @@ Test-Suite hspec
...
@@ -199,7 +205,9 @@ Test-Suite hspec
mtl >= 2.1,
mtl >= 2.1,
transformers,
transformers,
haskeline,
haskeline,
HUnit
HUnit,
setenv,
parsec
extensions: DoAndIfThenElse
extensions: DoAndIfThenElse
OverloadedStrings
OverloadedStrings
...
...
src/Hspec.hs
View file @
145ebb52
...
@@ -13,6 +13,7 @@ import Shelly (Sh, shelly, cmd, (</>), toTextIgnore, cd, withTmpDir, mkdir_p,
...
@@ -13,6 +13,7 @@ import Shelly (Sh, shelly, cmd, (</>), toTextIgnore, cd, withTmpDir, mkdir_p,
touchfile
)
touchfile
)
import
qualified
Shelly
import
qualified
Shelly
import
Filesystem.Path.CurrentOS
(
encodeString
)
import
Filesystem.Path.CurrentOS
(
encodeString
)
import
System.SetEnv
(
setEnv
)
import
Data.String.Here
import
Data.String.Here
import
Data.String.Utils
(
strip
,
replace
)
import
Data.String.Utils
(
strip
,
replace
)
import
Data.Monoid
import
Data.Monoid
...
@@ -24,12 +25,13 @@ import IHaskell.Eval.Evaluate as Eval hiding (liftIO)
...
@@ -24,12 +25,13 @@ import IHaskell.Eval.Evaluate as Eval hiding (liftIO)
import
qualified
IHaskell.Eval.Evaluate
as
Eval
(
liftIO
)
import
qualified
IHaskell.Eval.Evaluate
as
Eval
(
liftIO
)
import
IHaskell.Eval.Completion
import
IHaskell.Eval.Completion
import
IHaskell.Eval.ParseShell
import
Debug.Trace
import
Debug.Trace
import
Test.Hspec
import
Test.Hspec
import
Test.Hspec.HUnit
import
Test.Hspec.HUnit
import
Test.HUnit
(
assertBool
)
import
Test.HUnit
(
assertBool
,
assertFailure
)
doGhc
=
runGhc
(
Just
libdir
)
doGhc
=
runGhc
(
Just
libdir
)
...
@@ -88,33 +90,38 @@ pages string expected = evaluationComparing comparison string
...
@@ -88,33 +90,38 @@ pages string expected = evaluationComparing comparison string
comparison
(
results
,
pageOut
)
=
comparison
(
results
,
pageOut
)
=
strip
pageOut
`
shouldBe
`
strip
(
unlines
expected
)
strip
pageOut
`
shouldBe
`
strip
(
unlines
expected
)
completes
string
expected
=
completionTarget
newString
cursorloc
`
shouldBe
`
expected
readCompletePrompt
::
String
->
(
String
,
Int
)
where
(
newString
,
cursorloc
)
=
case
elemIndex
'*'
string
of
-- | @readCompletePrompt "xs*ys"@ return @(xs, i)@ where i is the location of
-- @'*'@ in the input string.
readCompletePrompt
string
=
case
elemIndex
'*'
string
of
Nothing
->
error
"Expected cursor written as '*'."
Nothing
->
error
"Expected cursor written as '*'."
Just
idx
->
(
replace
"*"
""
string
,
idx
)
Just
idx
->
(
replace
"*"
""
string
,
idx
)
completionEvent
::
String
->
[
String
]
->
Interpreter
(
String
,
[
String
])
completes
string
expected
=
completionTarget
newString
cursorloc
`
shouldBe
`
expected
completionEvent
string
expected
=
where
(
newString
,
cursorloc
)
=
readCompletePrompt
string
completionEvent
::
String
->
Interpreter
(
String
,
[
String
])
completionEvent
string
=
do
complete
newString
cursorloc
complete
newString
cursorloc
where
(
newString
,
cursorloc
)
=
case
elemIndex
'*'
string
of
where
(
newString
,
cursorloc
)
=
case
elemIndex
'*'
string
of
Nothing
->
error
"Expected cursor written as '*'."
Nothing
->
error
"Expected cursor written as '*'."
Just
idx
->
(
replace
"*"
""
string
,
idx
)
Just
idx
->
(
replace
"*"
""
string
,
idx
)
completionEventInDirectory
::
String
->
[
String
]
->
IO
(
String
,
[
String
])
completionEventInDirectory
::
String
->
IO
(
String
,
[
String
])
completionEventInDirectory
string
expected
completionEventInDirectory
string
=
withHsDirectory
$
co
mpletionEvent
string
expected
=
withHsDirectory
$
co
nst
$
completionEvent
string
shouldHaveCompletionsInDirectory
::
String
->
[
String
]
->
IO
()
shouldHaveCompletionsInDirectory
::
String
->
[
String
]
->
IO
()
shouldHaveCompletionsInDirectory
string
expected
shouldHaveCompletionsInDirectory
string
expected
=
do
(
matched
,
completions
)
<-
completionEventInDirectory
string
expected
=
do
(
matched
,
completions
)
<-
completionEventInDirectory
string
let
existsInCompletion
=
(`
elem
`
completions
)
let
existsInCompletion
=
(`
elem
`
completions
)
unmatched
=
filter
(
not
.
existsInCompletion
)
expected
unmatched
=
filter
(
not
.
existsInCompletion
)
expected
expected
`
shouldBeAmong
`
completions
expected
`
shouldBeAmong
`
completions
completionHas
string
expected
completionHas
string
expected
=
do
(
matched
,
completions
)
<-
doGhc
$
do
initCompleter
=
do
(
matched
,
completions
)
<-
doGhc
$
do
initCompleter
completionEvent
string
expected
completionEvent
string
let
existsInCompletion
=
(`
elem
`
completions
)
let
existsInCompletion
=
(`
elem
`
completions
)
unmatched
=
filter
(
not
.
existsInCompletion
)
expected
unmatched
=
filter
(
not
.
existsInCompletion
)
expected
expected
`
shouldBeAmong
`
completions
expected
`
shouldBeAmong
`
completions
...
@@ -133,7 +140,7 @@ initCompleter = do
...
@@ -133,7 +140,7 @@ initCompleter = do
inDirectory
::
[
Shelly
.
FilePath
]
-- ^ directories relative to temporary directory
inDirectory
::
[
Shelly
.
FilePath
]
-- ^ directories relative to temporary directory
->
[
Shelly
.
FilePath
]
-- ^ files relative to temporary directory
->
[
Shelly
.
FilePath
]
-- ^ files relative to temporary directory
->
Interpreter
a
->
(
Shelly
.
FilePath
->
Interpreter
a
)
->
IO
a
->
IO
a
-- | Run an Interpreter action, but first make a temporary directory
-- | Run an Interpreter action, but first make a temporary directory
-- with some files and folder and cd to it.
-- with some files and folder and cd to it.
...
@@ -141,7 +148,7 @@ inDirectory dirs files action = shelly $ withTmpDir $ \dirPath ->
...
@@ -141,7 +148,7 @@ inDirectory dirs files action = shelly $ withTmpDir $ \dirPath ->
do
cd
dirPath
do
cd
dirPath
mapM_
mkdir_p
dirs
mapM_
mkdir_p
dirs
mapM_
touchfile
files
mapM_
touchfile
files
liftIO
$
doGhc
$
wrap
(
encodeString
dirPath
)
action
liftIO
$
doGhc
$
wrap
(
encodeString
dirPath
)
(
action
dirPath
)
where
noPublish
=
const
$
return
()
where
noPublish
=
const
$
return
()
cdEvent
path
=
Eval
.
evaluate
defaultKernelState
(
":! cd "
++
path
)
noPublish
cdEvent
path
=
Eval
.
evaluate
defaultKernelState
(
":! cd "
++
path
)
noPublish
wrap
::
FilePath
->
Interpreter
a
->
Interpreter
a
wrap
::
FilePath
->
Interpreter
a
->
Interpreter
a
...
@@ -153,7 +160,7 @@ inDirectory dirs files action = shelly $ withTmpDir $ \dirPath ->
...
@@ -153,7 +160,7 @@ inDirectory dirs files action = shelly $ withTmpDir $ \dirPath ->
cdEvent
pwd
-- change back to the original directory
cdEvent
pwd
-- change back to the original directory
return
out
return
out
withHsDirectory
::
Interpreter
a
->
IO
a
withHsDirectory
::
(
Shelly
.
FilePath
->
Interpreter
a
)
->
IO
a
withHsDirectory
=
inDirectory
[
""
</>
"dir"
,
"dir"
</>
"dir1"
]
withHsDirectory
=
inDirectory
[
""
</>
"dir"
,
"dir"
</>
"dir1"
]
[
""
</>
"file1.hs"
,
"dir"
</>
"file2.hs"
,
[
""
</>
"file1.hs"
,
"dir"
</>
"file2.hs"
,
""
</>
"file1.lhs"
,
"dir"
</>
"file2.lhs"
]
""
</>
"file1.lhs"
,
"dir"
</>
"file2.lhs"
]
...
@@ -165,6 +172,7 @@ main = hspec $ do
...
@@ -165,6 +172,7 @@ main = hspec $ do
completionTests
completionTests
completionTests
=
do
completionTests
=
do
parseShellTests
describe
"Completion"
$
do
describe
"Completion"
$
do
it
"correctly gets the completion identifier without dots"
$
do
it
"correctly gets the completion identifier without dots"
$
do
"hello*"
`
completes
`
[
"hello"
]
"hello*"
`
completes
`
[
"hello"
]
...
@@ -191,7 +199,9 @@ completionTests = do
...
@@ -191,7 +199,9 @@ completionTests = do
completionType
"a.x"
3
[
"a"
,
"x"
]
`
shouldBe
`
Identifier
"x"
completionType
"a.x"
3
[
"a"
,
"x"
]
`
shouldBe
`
Identifier
"x"
completionType
"pri"
3
[
"pri"
]
`
shouldBe
`
Identifier
"pri"
completionType
"pri"
3
[
"pri"
]
`
shouldBe
`
Identifier
"pri"
completionType
":load A"
7
[
"A"
]
`
shouldBe
`
HsFilePath
":load A"
completionType
":load A"
7
[
"A"
]
`
shouldBe
`
HsFilePath
":load A"
completionType
":! cd "
6
[
""
]
`
shouldBe
`
FilePath
":! cd "
"A"
completionType
":! cd "
6
[
""
]
`
shouldBe
`
FilePath
":! cd "
""
it
"properly completes identifiers"
$
do
it
"properly completes identifiers"
$
do
...
@@ -235,6 +245,45 @@ completionTests = do
...
@@ -235,6 +245,45 @@ completionTests = do
,
""
</>
"file1.hs"
,
""
</>
"file1.hs"
,
""
</>
"file1.lhs"
])
,
""
</>
"file1.lhs"
])
it
"correctly interprets ~ as the environment HOME variable"
$
let
shouldHaveCompletions
::
String
->
[
String
]
->
IO
()
shouldHaveCompletions
string
expected
=
do
(
matched
,
completions
)
<-
withHsDirectory
$
\
dirPath
->
do
setHomeEvent
dirPath
completionEvent
string
let
existsInCompletion
=
(`
elem
`
completions
)
unmatched
=
filter
(
not
.
existsInCompletion
)
expected
expected
`
shouldBeAmong
`
completions
setHomeEvent
path
=
liftIO
$
setEnv
"HOME"
(
encodeString
path
)
in
do
":! cd ~/*"
`
shouldHaveCompletions
`
[
"~/dir/"
]
":! ~/*"
`
shouldHaveCompletions
`
[
"~/dir/"
]
":load ~/*"
`
shouldHaveCompletions
`
[
"~/dir/"
]
":l ~/*"
`
shouldHaveCompletions
`
[
"~/dir/"
]
let
shouldHaveMatchingText
::
String
->
String
->
IO
()
shouldHaveMatchingText
string
expected
=
do
matchText
<-
withHsDirectory
$
\
dirPath
->
do
setHomeEvent
dirPath
(
matchText
,
_
)
<-
uncurry
complete
(
readCompletePrompt
string
)
return
matchText
matchText
`
shouldBe
`
expected
setHomeEvent
path
=
liftIO
$
setEnv
"HOME"
(
encodeString
path
)
it
"generates the correct matchingText on `:! cd ~/*` "
$
do
":! cd ~/*"
`
shouldHaveMatchingText
`
(
"~/"
::
String
)
it
"generates the correct matchingText on `:load ~/*` "
$
do
":load ~/*"
`
shouldHaveMatchingText
`
(
"~/"
::
String
)
it
"generates the correct matchingText on `:l ~/*` "
$
do
":l ~/*"
`
shouldHaveMatchingText
`
(
"~/"
::
String
)
evalTests
=
do
evalTests
=
do
describe
"Code Evaluation"
$
do
describe
"Code Evaluation"
$
do
it
"evaluates expressions"
$
do
it
"evaluates expressions"
$
do
...
@@ -492,6 +541,27 @@ parseStringTests = describe "Parser" $ do
...
@@ -492,6 +541,27 @@ parseStringTests = describe "Parser" $ do
Located
4
(
Expression
"second"
)])
Located
4
(
Expression
"second"
)])
testParseShell
string
expected
=
do
describe
"parseShell"
$
do
it
(
"parses "
++
string
++
" correctly:
\n\t
"
++
show
expected
)
$
do
string
`
shouldParseTo
`
expected
where
shouldParseTo
::
String
->
[
String
]
->
Expectation
shouldParseTo
xs
ys
=
fun
ys
(
parseShell
xs
)
where
fun
ys
(
Right
xs'
)
=
xs'
`
shouldBe
`
ys
fun
ys
(
Left
e
)
=
assertFailure
$
"parseShell returned error:
\n
"
++
show
e
parseShellTests
=
do
testParseShell
"A"
[
"A"
]
testParseShell
":load A"
[
":load"
,
"A"
]
testParseShell
":!l ~/Downloads/MyFile
\\
Has
\\
Spaces.txt"
[
":!l"
,
"~/Downloads/MyFile
\\
Has
\\
Spaces.txt"
]
testParseShell
":!l
\"
~/Downloads/MyFile Has Spaces.txt
\"
/Another/File
\\
WithSpaces.doc"
[
":!l"
,
"~/Downloads/MyFile Has Spaces.txt"
,
"/Another/File
\\
WithSpaces.doc"
]
-- Useful HSpec expectations ----
-- Useful HSpec expectations ----
---------------------------------
---------------------------------
...
...
src/IHaskell/Eval/Completion.hs
View file @
145ebb52
...
@@ -40,6 +40,7 @@ import System.Console.Haskeline.Completion
...
@@ -40,6 +40,7 @@ import System.Console.Haskeline.Completion
import
IHaskell.Types
import
IHaskell.Types
import
IHaskell.Eval.Evaluate
(
Interpreter
)
import
IHaskell.Eval.Evaluate
(
Interpreter
)
import
IHaskell.Eval.ParseShell
(
parseShell
)
data
CompletionType
data
CompletionType
...
@@ -48,8 +49,8 @@ data CompletionType
...
@@ -48,8 +49,8 @@ data CompletionType
|
Extension
String
|
Extension
String
|
Qualified
String
String
|
Qualified
String
String
|
ModuleName
String
String
|
ModuleName
String
String
|
HsFilePath
String
|
HsFilePath
String
String
|
FilePath
String
|
FilePath
String
String
deriving
(
Show
,
Eq
)
deriving
(
Show
,
Eq
)
complete
::
String
->
Int
->
Interpreter
(
String
,
[
String
])
complete
::
String
->
Int
->
Interpreter
(
String
,
[
String
])
...
@@ -66,7 +67,11 @@ complete line pos = do
...
@@ -66,7 +67,11 @@ complete line pos = do
moduleNames
=
nub
$
concatMap
getNames
db
moduleNames
=
nub
$
concatMap
getNames
db
let
target
=
completionTarget
line
pos
let
target
=
completionTarget
line
pos
matchedText
=
intercalate
"."
target
let
matchedText
=
case
completionType
line
pos
target
of
HsFilePath
_
match
->
match
FilePath
_
match
->
match
otherwise
->
intercalate
"."
target
options
<-
options
<-
case
completionType
line
pos
target
of
case
completionType
line
pos
target
of
...
@@ -94,9 +99,9 @@ complete line pos = do
...
@@ -94,9 +99,9 @@ complete line pos = do
nonames
=
map
(
"No"
++
)
names
nonames
=
map
(
"No"
++
)
names
return
$
filter
(
ext
`
isPrefixOf
`)
$
names
++
nonames
return
$
filter
(
ext
`
isPrefixOf
`)
$
names
++
nonames
HsFilePath
path
->
completePathWithExtensions
[
".hs"
,
".lhs"
]
path
HsFilePath
lineUpToCursor
match
->
completePathWithExtensions
[
".hs"
,
".lhs"
]
lineUpToCursor
FilePath
path
->
completePath
path
FilePath
lineUpToCursor
match
->
completePath
lineUpToCursor
return
(
matchedText
,
options
)
return
(
matchedText
,
options
)
...
@@ -126,9 +131,13 @@ completionType :: String -- ^ The line on which the completion is bei
...
@@ -126,9 +131,13 @@ completionType :: String -- ^ The line on which the completion is bei
completionType
line
loc
target
completionType
line
loc
target
-- File and directory completions are special
-- File and directory completions are special
|
startswith
":!"
stripped
|
startswith
":!"
stripped
=
FilePath
lineUpToCursor
=
case
parseShell
lineUpToCursor
of
Right
xs
->
FilePath
lineUpToCursor
$
if
endswith
(
last
xs
)
lineUpToCursor
then
(
last
xs
)
else
[]
Left
_
->
Empty
|
startswith
":l"
stripped
|
startswith
":l"
stripped
=
HsFilePath
lineUpToCursor
=
case
parseShell
lineUpToCursor
of
Right
xs
->
HsFilePath
lineUpToCursor
$
if
endswith
(
last
xs
)
lineUpToCursor
then
(
last
xs
)
else
[]
Left
_
->
Empty
-- Use target for other completions.
-- Use target for other completions.
-- If it's empty, no completion.
-- If it's empty, no completion.
|
null
target
|
null
target
...
@@ -149,6 +158,7 @@ completionType line loc target
...
@@ -149,6 +158,7 @@ completionType line loc target
isCapitalized
=
isUpper
.
head
isCapitalized
=
isUpper
.
head
lineUpToCursor
=
take
loc
line
lineUpToCursor
=
take
loc
line
-- | Get the word under a given cursor location.
-- | Get the word under a given cursor location.
completionTarget
::
String
->
Int
->
[
String
]
completionTarget
::
String
->
Int
->
[
String
]
completionTarget
code
cursor
=
expandCompletionPiece
pieceToComplete
completionTarget
code
cursor
=
expandCompletionPiece
pieceToComplete
...
@@ -164,8 +174,8 @@ completionTarget code cursor = expandCompletionPiece pieceToComplete
...
@@ -164,8 +174,8 @@ completionTarget code cursor = expandCompletionPiece pieceToComplete
delimPolicy
=
Drop
delimPolicy
=
Drop
}
}
isDelim
::
Char
->
Int
->
Bool
isDelim
::
Char
->
Int
->
Bool
isDelim
char
idx
=
char
`
elem
`
neverIdent
||
isSymbol
char
isDelim
char
idx
=
char
`
elem
`
neverIdent
||
isSymbol
char
splitAlongCursor
::
[[(
Char
,
Int
)]]
->
[[(
Char
,
Int
)]]
splitAlongCursor
::
[[(
Char
,
Int
)]]
->
[[(
Char
,
Int
)]]
splitAlongCursor
[]
=
[]
splitAlongCursor
[]
=
[]
...
...
src/IHaskell/Eval/ParseShell.hs
0 → 100644
View file @
145ebb52
-- | This module splits a shell command line into a list of strings,
-- one for each command / filename
module
IHaskell.Eval.ParseShell
(
parseShell
)
where
import
Prelude
hiding
(
words
)
import
Text.ParserCombinators.Parsec
hiding
(
manyTill
)
import
Control.Applicative
hiding
((
<|>
),
many
,
optional
)
import
Debug.Trace
import
Test.Hspec
import
Test.Hspec.HUnit
import
Test.HUnit
(
assertBool
,
assertFailure
)
debug
=
False
trace'
x
a
=
if
debug
then
trace
x
a
else
a
eol
::
Parser
Char
eol
=
do
x
<-
oneOf
"
\n\r
"
return
x
<?>
"end of line"
quote
::
Parser
Char
quote
=
char
'
\"
'
manyTill
::
Parser
a
->
Parser
[
a
]
->
Parser
[
a
]
-- | @manyTill p end@ from hidden @manyTill@ in that it appends the result of @end@
manyTill
p
end
=
do
scan
where
scan
=
do
{
x
<-
end
;
return
x
}
<|>
do
{
x
<-
p
;
xs
<-
scan
;
return
$
x
:
xs
}
manyTill1
p
end
=
do
x
<-
p
xs
<-
manyTill
p
end
return
$
x
:
xs
unescapedChar
::
Parser
Char
->
Parser
String
unescapedChar
p
=
try
$
do
x
<-
noneOf
[
'
\\
'
]
lookAhead
p
return
$
x
:
[]
quotedString
=
(
trace'
"in quotedString"
)
(
do
quote
<?>
"expected starting quote"
manyTill
anyChar
end
<*
quote
)
<?>
"unexpected in quoted String "
where
end
=
unescapedChar
quote
unquotedString
=
(
trace'
"in unquotedString"
)
manyTill1
anyChar
end
where
end
=
unescapedChar
space
<|>
do
x
<-
lookAhead
eol
return
[]
word
=
quotedString
<|>
unquotedString
<?>
"word"
separator
::
Parser
String
separator
=
many1
space
<?>
"separator"
words
::
Parser
[
String
]
-- | Input must terminate in a space character (like a \n)
words
=
try
(
eof
*>
return
[]
)
<|>
do
x
<-
word
rest1
<-
trace'
(
"word: "
++
show
x
)
lookAhead
(
many
anyToken
)
ss
<-
trace'
(
"rest1: "
++
show
rest1
)
separator
rest2
<-
trace'
(
"spaces: "
++
show
ss
)
lookAhead
(
many
anyToken
)
xs
<-
trace'
(
"rest2: "
++
show
rest2
)
words
return
$
x
:
xs
parseShell
::
String
->
Either
ParseError
[
String
]
parseShell
string
=
parse
words
"shell"
(
string
++
"
\n
"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment