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
a489c9bb
Commit
a489c9bb
authored
Mar 24, 2015
by
Andrew Gibiansky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #445 from gibiansky/format-all-src
Format all src
parents
c19a3bf2
7009eb0e
Changes
25
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
1104 additions
and
1129 deletions
+1104
-1129
.travis.yml
.travis.yml
+1
-1
Aeson.hs
ihaskell-display/ihaskell-aeson/IHaskell/Display/Aeson.hs
+8
-7
Basic.hs
ihaskell-display/ihaskell-basic/IHaskell/Display/Basic.hs
+10
-6
Blaze.hs
ihaskell-display/ihaskell-blaze/IHaskell/Display/Blaze.hs
+8
-7
Charts.hs
ihaskell-display/ihaskell-charts/IHaskell/Display/Charts.hs
+20
-19
Diagrams.hs
...ll-display/ihaskell-diagrams/IHaskell/Display/Diagrams.hs
+14
-11
Animation.hs
.../ihaskell-diagrams/IHaskell/Display/Diagrams/Animation.hs
+15
-18
Hatex.hs
ihaskell-display/ihaskell-hatex/IHaskell/Display/Hatex.hs
+4
-3
Juicypixels.hs
...play/ihaskell-juicypixels/IHaskell/Display/Juicypixels.hs
+64
-39
Magic.hs
ihaskell-display/ihaskell-magic/IHaskell/Display/Magic.hs
+30
-26
Parsec.hs
ihaskell-display/ihaskell-parsec/IHaskell/Display/Parsec.hs
+19
-22
Rlangqq.hs
...kell-display/ihaskell-rlangqq/IHaskell/Display/Rlangqq.hs
+53
-55
StaticCanvas.hs
...askell-static-canvas/src/IHaskell/Display/StaticCanvas.hs
+1
-4
Widgets.hs
...kell-display/ihaskell-widgets/IHaskell/Display/Widgets.hs
+19
-18
Widgets.hs
ihaskell-display/ihaskell-widgets/IHaskell/Widgets.hs
+1
-3
Calc.hs
ipython-kernel/examples/Calc.hs
+123
-120
EasyKernel.hs
ipython-kernel/src/IHaskell/IPython/EasyKernel.hs
+136
-165
Kernel.hs
ipython-kernel/src/IHaskell/IPython/Kernel.hs
+8
-11
Parser.hs
ipython-kernel/src/IHaskell/IPython/Message/Parser.hs
+46
-49
UUID.hs
ipython-kernel/src/IHaskell/IPython/Message/UUID.hs
+14
-17
Writer.hs
ipython-kernel/src/IHaskell/IPython/Message/Writer.hs
+92
-107
Stdin.hs
ipython-kernel/src/IHaskell/IPython/Stdin.hs
+50
-60
Types.hs
ipython-kernel/src/IHaskell/IPython/Types.hs
+293
-291
ZeroMQ.hs
ipython-kernel/src/IHaskell/IPython/ZeroMQ.hs
+65
-66
verify_formatting.py
verify_formatting.py
+10
-4
No files found.
.travis.yml
View file @
a489c9bb
...
@@ -36,7 +36,7 @@ install:
...
@@ -36,7 +36,7 @@ install:
if [ ${GHCVER%.*} = "7.8" ]; then
if [ ${GHCVER%.*} = "7.8" ]; then
travis_retry cabal install arithmoi==0.4.* -fllvm
travis_retry cabal install arithmoi==0.4.* -fllvm
travis_retry git clone http://www.github.com/gibiansky/hindent
travis_retry git clone http://www.github.com/gibiansky/hindent
cd hindent && cabal install && cd ..
cd hindent &&
travis_retry
cabal install && cd ..
fi
fi
# Here starts the actual work to be performed for the package under test; any command which exits with a non-zero exit code causes the build to fail.
# Here starts the actual work to be performed for the package under test; any command which exits with a non-zero exit code causes the build to fail.
...
...
ihaskell-display/ihaskell-aeson/IHaskell/Display/Aeson.hs
View file @
a489c9bb
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, QuasiQuotes #-}
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, QuasiQuotes #-}
module
IHaskell.Display.Aeson
()
where
module
IHaskell.Display.Aeson
()
where
import
ClassyPrelude
import
ClassyPrelude
...
...
ihaskell-display/ihaskell-basic/IHaskell/Display/Basic.hs
View file @
a489c9bb
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module
IHaskell.Display.Basic
()
where
module
IHaskell.Display.Basic
()
where
import
IHaskell.Display
import
IHaskell.Display
...
@@ -10,6 +11,9 @@ instance Show a => IHaskellDisplay (Maybe a) where
...
@@ -10,6 +11,9 @@ instance Show a => IHaskellDisplay (Maybe a) where
where
where
stringDisplay
=
plain
(
show
just
)
stringDisplay
=
plain
(
show
just
)
htmlDisplay
=
html
str
htmlDisplay
=
html
str
str
=
case
just
of
str
=
case
just
of
Nothing
->
"<span style='color: red; font-weight: bold;'>Nothing</span>"
Nothing
->
"<span style='color: red; font-weight: bold;'>Nothing</span>"
Just
x
->
printf
"<span style='color: green; font-weight: bold;'>Just</span><span style='font-family: monospace;'>%s</span>"
(
show
x
)
Just
x
->
printf
"<span style='color: green; font-weight: bold;'>Just</span><span style='font-family: monospace;'>%s</span>"
(
show
x
)
ihaskell-display/ihaskell-blaze/IHaskell/Display/Blaze.hs
View file @
a489c9bb
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module
IHaskell.Display.Blaze
()
where
module
IHaskell.Display.Blaze
()
where
import
IHaskell.Display
import
IHaskell.Display
...
...
ihaskell-display/ihaskell-charts/IHaskell/Display/Charts.hs
View file @
a489c9bb
{-# LANGUAGE NoImplicitPrelude, CPP #-}
{-# LANGUAGE NoImplicitPrelude, CPP #-}
module
IHaskell.Display.Charts
()
where
module
IHaskell.Display.Charts
()
where
import
ClassyPrelude
import
ClassyPrelude
...
@@ -22,8 +23,8 @@ instance IHaskellDisplay (Renderable a) where
...
@@ -22,8 +23,8 @@ instance IHaskellDisplay (Renderable a) where
display
renderable
=
do
display
renderable
=
do
pngDisp
<-
chartData
renderable
PNG
pngDisp
<-
chartData
renderable
PNG
-- We can add `svg svgDisplay` to the output of `display`,
-- We can add `svg svgDisplay` to the output of `display`,
but SVGs are not resizable in the IPython
--
but SVGs are not resizable in the IPython
notebook.
-- notebook.
svgDisp
<-
chartData
renderable
SVG
svgDisp
<-
chartData
renderable
SVG
return
$
Display
[
pngDisp
,
svgDisp
]
return
$
Display
[
pngDisp
,
svgDisp
]
...
@@ -34,17 +35,17 @@ chartData renderable format = do
...
@@ -34,17 +35,17 @@ chartData renderable format = do
-- Write the PNG image.
-- Write the PNG image.
let
filename
=
".ihaskell-chart.png"
let
filename
=
".ihaskell-chart.png"
opts
=
def
{
_fo_format
=
format
,
_fo_size
=
(
width
,
height
)}
opts
=
def
{
_fo_format
=
format
,
_fo_size
=
(
width
,
height
)
}
toFile
=
renderableToFile
opts
mkFile
opts
filename
renderable
#
if
MIN_VERSION_Chart_cairo
(
1
,
3
,
0
)
toFile
filename
renderable
#
else
toFile
renderable
filename
#
endif
-- Convert to base64.
-- Convert to base64.
imgData
<-
readFile
$
fpFromString
filename
imgData
<-
readFile
$
fpFromString
filename
return
$
case
format
of
return
$
case
format
of
PNG
->
png
width
height
$
base64
imgData
PNG
->
png
width
height
$
base64
imgData
SVG
->
svg
$
Char
.
unpack
imgData
SVG
->
svg
$
Char
.
unpack
imgData
#
if
MIN_VERSION_Chart_cairo
(
1
,
3
,
0
)
mkFile
opts
filename
renderable
=
renderableToFile
opts
filename
renderable
#
else
mkFile
opts
filename
renderable
=
renderableToFile
opts
renderable
filename
#
endif
ihaskell-display/ihaskell-diagrams/IHaskell/Display/Diagrams.hs
View file @
a489c9bb
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, FlexibleInstances #-}
module
IHaskell.Display.Diagrams
(
diagram
,
animation
)
where
module
IHaskell.Display.Diagrams
(
diagram
,
animation
)
where
import
ClassyPrelude
import
ClassyPrelude
...
@@ -36,11 +37,13 @@ diagramData renderable format = do
...
@@ -36,11 +37,13 @@ diagramData renderable format = do
-- Convert to base64.
-- Convert to base64.
imgData
<-
readFile
$
fpFromString
filename
imgData
<-
readFile
$
fpFromString
filename
let
value
=
case
format
of
let
value
=
case
format
of
PNG
->
png
(
floor
imgWidth
)
(
floor
imgHeight
)
$
base64
imgData
PNG
->
png
(
floor
imgWidth
)
(
floor
imgHeight
)
$
base64
imgData
SVG
->
svg
$
Char
.
unpack
imgData
SVG
->
svg
$
Char
.
unpack
imgData
return
value
return
value
where
where
extension
SVG
=
"svg"
extension
SVG
=
"svg"
extension
PNG
=
"png"
extension
PNG
=
"png"
...
...
ihaskell-display/ihaskell-diagrams/IHaskell/Display/Diagrams/Animation.hs
View file @
a489c9bb
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, FlexibleInstances #-}
module
IHaskell.Display.Diagrams.Animation
(
animation
)
where
module
IHaskell.Display.Diagrams.Animation
(
animation
)
where
import
ClassyPrelude
hiding
(
filename
)
import
ClassyPrelude
hiding
(
filename
)
import
Diagrams.Prelude
import
Diagrams.Prelude
import
Diagrams.Backend.Cairo
import
Diagrams.Backend.Cairo
import
Diagrams.Backend.Cairo.CmdLine
(
GifOpts
(
..
))
import
Diagrams.Backend.Cairo.CmdLine
(
GifOpts
(
..
))
import
Diagrams.Backend.CmdLine
(
DiagramOpts
(
..
),
mainRender
)
import
Diagrams.Backend.CmdLine
(
DiagramOpts
(
..
),
mainRender
)
import
IHaskell.Display
import
IHaskell.Display
...
@@ -37,16 +38,12 @@ animationData renderable = do
...
@@ -37,16 +38,12 @@ animationData renderable = do
-- Write the image.
-- Write the image.
let
filename
=
".ihaskell-diagram.gif"
let
filename
=
".ihaskell-diagram.gif"
diagOpts
=
DiagramOpts
{
diagOpts
=
DiagramOpts
_width
=
Just
.
ceiling
$
imgWidth
{
_width
=
Just
.
ceiling
$
imgWidth
,
_height
=
Just
.
ceiling
$
imgHeight
,
_height
=
Just
.
ceiling
$
imgHeight
,
_output
=
filename
,
_output
=
filename
}
}
gifOpts
=
GifOpts
{
gifOpts
=
GifOpts
{
_dither
=
True
,
_noLooping
=
False
,
_loopRepeat
=
Nothing
}
_dither
=
True
,
_noLooping
=
False
,
_loopRepeat
=
Nothing
}
mainRender
(
diagOpts
,
gifOpts
)
frameSet
mainRender
(
diagOpts
,
gifOpts
)
frameSet
-- Convert to ascii represented base64 encoding
-- Convert to ascii represented base64 encoding
...
...
ihaskell-display/ihaskell-hatex/IHaskell/Display/Hatex.hs
View file @
a489c9bb
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleInstances #-}
-- | Provides 'IHaskellDisplay' instances for 'LaTeX' and 'LaTeXT'.
-- | Provides 'IHaskellDisplay' instances for 'LaTeX' and 'LaTeXT'.
module
IHaskell.Display.Hatex
()
where
module
IHaskell.Display.Hatex
()
where
...
...
ihaskell-display/ihaskell-juicypixels/IHaskell/Display/Juicypixels.hs
View file @
a489c9bb
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, FlexibleInstances #-}
module
IHaskell.Display.Juicypixels
(
module
IHaskell
.
Display
module
IHaskell.Display.Juicypixels
(
module
IHaskell
.
Display
,
module
Codec
.
Picture
)
where
,
module
Codec
.
Picture
)
where
import
Codec.Picture
import
Codec.Picture
import
ClassyPrelude
import
ClassyPrelude
...
@@ -11,20 +9,47 @@ import System.Directory
...
@@ -11,20 +9,47 @@ import System.Directory
import
System.IO.Unsafe
import
System.IO.Unsafe
-- instances
-- instances
instance
IHaskellDisplay
DynamicImage
where
display
=
displayImageAsJpg
instance
IHaskellDisplay
DynamicImage
where
instance
IHaskellDisplay
(
Image
Pixel8
)
where
display
=
displayImageAsJpg
.
ImageY8
display
=
displayImageAsJpg
instance
IHaskellDisplay
(
Image
Pixel16
)
where
display
=
displayImageAsJpg
.
ImageY16
instance
IHaskellDisplay
(
Image
PixelF
)
where
display
=
displayImageAsJpg
.
ImageYF
instance
IHaskellDisplay
(
Image
Pixel8
)
where
instance
IHaskellDisplay
(
Image
PixelYA8
)
where
display
=
displayImageAsJpg
.
ImageYA8
display
=
displayImageAsJpg
.
ImageY8
instance
IHaskellDisplay
(
Image
PixelYA16
)
where
display
=
displayImageAsJpg
.
ImageYA16
instance
IHaskellDisplay
(
Image
PixelRGB8
)
where
display
=
displayImageAsJpg
.
ImageRGB8
instance
IHaskellDisplay
(
Image
Pixel16
)
where
instance
IHaskellDisplay
(
Image
PixelRGB16
)
where
display
=
displayImageAsJpg
.
ImageRGB16
display
=
displayImageAsJpg
.
ImageY16
instance
IHaskellDisplay
(
Image
PixelRGBF
)
where
display
=
displayImageAsJpg
.
ImageRGBF
instance
IHaskellDisplay
(
Image
PixelRGBA8
)
where
display
=
displayImageAsJpg
.
ImageRGBA8
instance
IHaskellDisplay
(
Image
PixelF
)
where
instance
IHaskellDisplay
(
Image
PixelRGBA16
)
where
display
=
displayImageAsJpg
.
ImageRGBA16
display
=
displayImageAsJpg
.
ImageYF
instance
IHaskellDisplay
(
Image
PixelYCbCr8
)
where
display
=
displayImageAsJpg
.
ImageYCbCr8
instance
IHaskellDisplay
(
Image
PixelCMYK8
)
where
display
=
displayImageAsJpg
.
ImageCMYK8
instance
IHaskellDisplay
(
Image
PixelYA8
)
where
instance
IHaskellDisplay
(
Image
PixelCMYK16
)
where
display
=
displayImageAsJpg
.
ImageCMYK16
display
=
displayImageAsJpg
.
ImageYA8
instance
IHaskellDisplay
(
Image
PixelYA16
)
where
display
=
displayImageAsJpg
.
ImageYA16
instance
IHaskellDisplay
(
Image
PixelRGB8
)
where
display
=
displayImageAsJpg
.
ImageRGB8
instance
IHaskellDisplay
(
Image
PixelRGB16
)
where
display
=
displayImageAsJpg
.
ImageRGB16
instance
IHaskellDisplay
(
Image
PixelRGBF
)
where
display
=
displayImageAsJpg
.
ImageRGBF
instance
IHaskellDisplay
(
Image
PixelRGBA8
)
where
display
=
displayImageAsJpg
.
ImageRGBA8
instance
IHaskellDisplay
(
Image
PixelRGBA16
)
where
display
=
displayImageAsJpg
.
ImageRGBA16
instance
IHaskellDisplay
(
Image
PixelYCbCr8
)
where
display
=
displayImageAsJpg
.
ImageYCbCr8
instance
IHaskellDisplay
(
Image
PixelCMYK8
)
where
display
=
displayImageAsJpg
.
ImageCMYK8
instance
IHaskellDisplay
(
Image
PixelCMYK16
)
where
display
=
displayImageAsJpg
.
ImageCMYK16
-- main rendering function
-- main rendering function
displayImageAsJpg
::
DynamicImage
->
IO
Display
displayImageAsJpg
::
DynamicImage
->
IO
Display
...
@@ -41,11 +66,13 @@ displayImageAsJpg renderable = do
...
@@ -41,11 +66,13 @@ displayImageAsJpg renderable = do
-- The type DynamicImage does not have a function to extract width and height
-- The type DynamicImage does not have a function to extract width and height
imWidth
::
DynamicImage
->
Int
imWidth
::
DynamicImage
->
Int
imWidth
img
=
w
imWidth
img
=
w
where
(
w
,
h
)
=
imWidthHeight
img
where
(
w
,
h
)
=
imWidthHeight
img
imHeight
::
DynamicImage
->
Int
imHeight
::
DynamicImage
->
Int
imHeight
img
=
h
imHeight
img
=
h
where
(
w
,
h
)
=
imWidthHeight
img
where
(
w
,
h
)
=
imWidthHeight
img
-- Helper functions to pattern match on the DynamicImage Constructors
-- Helper functions to pattern match on the DynamicImage Constructors
imWidthHeight
::
DynamicImage
->
(
Int
,
Int
)
imWidthHeight
::
DynamicImage
->
(
Int
,
Int
)
...
@@ -65,5 +92,3 @@ imWidthHeight (ImageCMYK16 im) = imWH im
...
@@ -65,5 +92,3 @@ imWidthHeight (ImageCMYK16 im) = imWH im
imWH
::
(
Image
a
)
->
(
Int
,
Int
)
imWH
::
(
Image
a
)
->
(
Int
,
Int
)
imWH
im
=
(
imageWidth
im
,
imageHeight
im
)
imWH
im
=
(
imageWidth
im
,
imageHeight
im
)
ihaskell-display/ihaskell-magic/IHaskell/Display/Magic.hs
View file @
a489c9bb
{-# LANGUAGE ViewPatterns, TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE ViewPatterns, TypeSynonymInstances, FlexibleInstances #-}
module
IHaskell.Display.Magic
()
where
module
IHaskell.Display.Magic
()
where
import
IHaskell.Display
import
IHaskell.Display
...
@@ -54,17 +55,20 @@ JPG
...
@@ -54,17 +55,20 @@ JPG
-}
-}
parseMagic
::
String
->
MagicClass
parseMagic
::
String
->
MagicClass
parseMagic
f
=
case
words
f
of
parseMagic
f
=
"SVG"
:
_
->
SVG
case
words
f
of
"
PNG"
:
_image
:
_data
:
"
SVG"
:
_
->
SVG
(
readMaybe
->
Just
w
)
:
_x
:
"PNG"
:
_image
:
_data
:
(
readMaybe
->
Just
w
)
:
_x
:
(
readMaybe
.
takeWhile
isDigit
->
Just
h
)
:
_
->
PNG
w
(
readMaybe
.
takeWhile
isDigit
->
Just
h
)
:
_
->
PNG
w
h
h
"LaTeX"
:
_
->
LaTeX
"LaTeX"
:
_
->
LaTeX
"HTML"
:
_
->
HTML
"HTML"
:
_
->
HTML
"JPEG"
:
_
->
JPG
"JPEG"
:
_
->
JPG
_
->
Unknown
_
->
Unknown
data
MagicClass
=
SVG
data
MagicClass
=
|
PNG
Int
Int
SVG
|
PNG
Int
Int
|
JPG
|
HTML
|
LaTeX
|
Unknown
|
JPG
|
HTML
|
LaTeX
|
Unknown
deriving
Show
deriving
Show
ihaskell-display/ihaskell-parsec/IHaskell/Display/Parsec.hs
View file @
a489c9bb
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, QuasiQuotes, FlexibleInstances, OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, QuasiQuotes, FlexibleInstances, OverloadedStrings #-}
module
IHaskell.Display.Parsec
()
where
module
IHaskell.Display.Parsec
()
where
import
ClassyPrelude
hiding
(
fromList
)
import
ClassyPrelude
hiding
(
fromList
)
...
@@ -29,21 +30,17 @@ instance FromJSON ParseText where
...
@@ -29,21 +30,17 @@ instance FromJSON ParseText where
-- | Output of parsing.
-- | Output of parsing.
instance
Show
a
=>
ToJSON
(
Either
ParseError
a
)
where
instance
Show
a
=>
ToJSON
(
Either
ParseError
a
)
where
toJSON
(
Left
err
)
=
object
[
toJSON
(
Left
err
)
=
object
"status"
.=
(
"error"
::
String
),
[
"status"
.=
(
"error"
::
String
)
"line"
.=
sourceLine
(
errorPos
err
),
,
"line"
.=
sourceLine
(
errorPos
err
)
"col"
.=
sourceColumn
(
errorPos
err
),
,
"col"
.=
sourceColumn
(
errorPos
err
)
"msg"
.=
show
err
,
"msg"
.=
show
err
]
toJSON
(
Right
result
)
=
object
[
"status"
.=
(
"success"
::
String
),
"result"
.=
show
result
]
]
toJSON
(
Right
result
)
=
object
[
"status"
.=
(
"success"
::
String
),
"result"
.=
show
result
]
instance
Show
a
=>
IHaskellWidget
(
Parser
a
)
where
instance
Show
a
=>
IHaskellWidget
(
Parser
a
)
where
-- Name for this widget.
-- Name for this widget.
targetName
_
=
"parsec"
targetName
_
=
"parsec"
-- When we rece
-- When we rece
comm
widget
(
Object
dict
)
publisher
=
do
comm
widget
(
Object
dict
)
publisher
=
do
let
key
=
"text"
::
Text
let
key
=
"text"
::
Text
...
...
ihaskell-display/ihaskell-rlangqq/IHaskell/Display/Rlangqq.hs
View file @
a489c9bb
{-# OPTIONS_GHC -fno-warn-missing-fields #-}
{-# OPTIONS_GHC -fno-warn-missing-fields #-}
{-# LANGUAGE TupleSections, TemplateHaskell #-}
{-# LANGUAGE TupleSections, TemplateHaskell #-}
module
IHaskell.Display.Rlangqq
(
module
RlangQQ
,
module
IHaskell.Display.Rlangqq
(
module
RlangQQ
,
rDisp
,
rDisp
,
rDisplayAll
,
rDisplayAll
,
rOutputParsed
,
rOutputParsed
,
...
@@ -25,7 +26,6 @@ import IHaskell.Display
...
@@ -25,7 +26,6 @@ import IHaskell.Display
import
IHaskell.Display.Blaze
()
-- to confirm it's installed
import
IHaskell.Display.Blaze
()
-- to confirm it's installed
import
qualified
Text.Blaze.Html5
as
H
import
qualified
Text.Blaze.Html5
as
H
import
qualified
Text.Blaze.Html5.Attributes
as
H
import
qualified
Text.Blaze.Html5.Attributes
as
H
import
Data.Monoid
import
Data.Char
import
Data.Char
import
Control.Monad
import
Control.Monad
import
Data.Ord
import
Data.Ord
...
@@ -40,18 +40,17 @@ import Control.Concurrent.STM
...
@@ -40,18 +40,17 @@ import Control.Concurrent.STM
import
Language.Haskell.TH.Quote
import
Language.Haskell.TH.Quote
-- | same as 'RlangQQ.r', but displays plots at the end too
-- | same as 'RlangQQ.r', but displays plots at the end too
rDisp
=
QuasiQuoter
{
quoteExp
=
\
s
->
[
|
do
rDisp
=
QuasiQuoter
{
quoteExp
=
\
s
->
[
|
do
result
<-
$
(
quoteExp
r
s
)
result
<-
$
(
quoteExp
r
s
)
p
<-
rDisplayAll
p
<-
rDisplayAll
printDisplay
p
printDisplay
p
return
result
return
result
|
]
}
|
]
}
rOutput
::
IO
[
Int
]
rOutput
::
IO
[
Int
]
rOutput
=
do
rOutput
=
do
fs
<-
mapMaybe
(
readMaybe
<=<
stripPrefix
"raw"
<=<
stripSuffix
".md"
)
fs
<-
mapMaybe
(
readMaybe
<=<
stripPrefix
"raw"
<=<
stripSuffix
".md"
)
<$>
getDirectoryContents
"Rtmp"
<$>
getDirectoryContents
"Rtmp"
fs'
<-
forM
fs
$
\
f
->
(,
f
)
<$>
getModificationTime
(
showf
(
"Rtmp/raw"
%
Int
%
".md"
)
f
)
fs'
<-
forM
fs
$
\
f
->
(,
f
)
<$>
getModificationTime
(
showf
(
"Rtmp/raw"
%
Int
%
".md"
)
f
)
return
$
map
snd
$
sortBy
(
flip
(
comparing
fst
))
fs'
return
$
map
snd
$
sortBy
(
flip
(
comparing
fst
))
fs'
-- | like 'stripPrefix' except on the end
-- | like 'stripPrefix' except on the end
...
@@ -63,35 +62,33 @@ rOutputParsed = do
...
@@ -63,35 +62,33 @@ rOutputParsed = do
ns
<-
rOutput
ns
<-
rOutput
case
ns
of
case
ns
of
[]
->
return
[]
[]
->
return
[]
n
:
_
->
parseKnitted
<$>
readFile
(
showf
(
"Rtmp/raw"
%
Int
%
".md"
)
n
)
n
:
_
->
parseKnitted
<$>
readFile
(
showf
(
"Rtmp/raw"
%
Int
%
".md"
)
n
)
getPlotNames
::
IO
[
String
]
getPlotNames
::
IO
[
String
]
getPlotNames
=
do
getPlotNames
=
do
interactions
<-
rOutputParsed
interactions
<-
rOutputParsed
return
[
p
|
KnitInteraction
_
is
<-
interactions
,
KnitImage
_
p
<-
is
]
return
[
p
|
KnitInteraction
_
is
<-
interactions
,
KnitImage
_
p
<-
is
]
getCaptions
::
IO
[
String
]
getCaptions
::
IO
[
String
]
getCaptions
=
do
getCaptions
=
do
interactions
<-
rOutputParsed
interactions
<-
rOutputParsed
return
[
c
|
KnitInteraction
_
is
<-
interactions
,
return
KnitImage
c
_
<-
is
,
[
c
|
KnitInteraction
_
is
<-
interactions
not
(
isBoringCaption
c
)
]
,
KnitImage
c
_
<-
is
,
not
(
isBoringCaption
c
)]
-- | true when the caption name looks like one knitr will automatically
-- | true when the caption name looks like one knitr will automatically generate
-- generate
isBoringCaption
::
String
->
Bool
isBoringCaption
::
String
->
Bool
isBoringCaption
s
=
maybe
False
isBoringCaption
s
=
maybe
False
(
all
isDigit
)
(
stripPrefix
"plot of chunk unnamed-chunk-"
s
)
(
all
isDigit
)
(
stripPrefix
"plot of chunk unnamed-chunk-"
s
)
rDisplayAll
::
IO
Display
rDisplayAll
::
IO
Display
rDisplayAll
=
do
rDisplayAll
=
do
ns
<-
rOutputParsed
ns
<-
rOutputParsed
imgs
<-
sequence
[
displayInteraction
o
|
KnitInteraction
_
os
<-
ns
,
o
<-
os
]
imgs
<-
sequence
[
displayInteraction
o
|
KnitInteraction
_
os
<-
ns
,
o
<-
os
]
display
(
mconcat
imgs
)
display
(
mconcat
imgs
)
displayInteraction
::
KnitOutput
->
IO
Display
displayInteraction
::
KnitOutput
->
IO
Display
displayInteraction
(
KnitPrint
c
)
=
display
(
plain
c
)
displayInteraction
(
KnitPrint
c
)
=
display
(
plain
c
)
displayInteraction
(
KnitWarning
c
)
=
display
(
plain
c
)
displayInteraction
(
KnitWarning
c
)
=
display
(
plain
c
)
...
@@ -102,7 +99,8 @@ displayInteraction (KnitImage cap img) = do
...
@@ -102,7 +99,8 @@ displayInteraction (KnitImage cap img) = do
|
isBoringCaption
cap
=
mempty
|
isBoringCaption
cap
=
mempty
|
otherwise
=
H
.
p
(
H
.
toMarkup
cap
)
|
otherwise
=
H
.
p
(
H
.
toMarkup
cap
)
encoded
<-
Base64
.
encode
<$>
B
.
readFile
img
encoded
<-
Base64
.
encode
<$>
B
.
readFile
img
display
$
H
.
img
H
.!
H
.
src
(
H
.
unsafeByteStringValue
display
$
H
.
img
H
.!
H
.
src
(
H
.
unsafeByteStringValue
-- assumes you use the default device which is png
-- assumes you use the default device which is png
(
Char
.
pack
"data:image/png;base64,"
<>
encoded
))
(
Char
.
pack
"data:image/png;base64,"
<>
encoded
))
<>
caption
<>
caption
ihaskell-display/ihaskell-static-canvas/src/IHaskell/Display/StaticCanvas.hs
View file @
a489c9bb
...
@@ -23,10 +23,7 @@ getUniqueName = do
...
@@ -23,10 +23,7 @@ getUniqueName = do
putMVar
uniqueCounter
val'
putMVar
uniqueCounter
val'
return
$
pack
$
"ihaskellStaticCanvasUniqueID"
++
show
val
return
$
pack
$
"ihaskellStaticCanvasUniqueID"
++
show
val
data
Canvas
=
Canvas
{
width
::
Int
data
Canvas
=
Canvas
{
width
::
Int
,
height
::
Int
,
canvas
::
CanvasFree
()
}
,
height
::
Int
,
canvas
::
CanvasFree
()
}
instance
IHaskellDisplay
Canvas
where
instance
IHaskellDisplay
Canvas
where
display
cnv
=
do
display
cnv
=
do
...
...
ihaskell-display/ihaskell-widgets/IHaskell/Display/Widgets.hs
View file @
a489c9bb
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings #-}
module
IHaskell.Display.Widgets
()
where
module
IHaskell.Display.Widgets
()
where
import
ClassyPrelude
import
ClassyPrelude
...
@@ -17,18 +18,19 @@ instance ToJSON WidgetName where
...
@@ -17,18 +18,19 @@ instance ToJSON WidgetName where
toJSON
ButtonWidget
=
"ButtonView"
toJSON
ButtonWidget
=
"ButtonView"
instance
ToJSON
WidgetMessage
where
instance
ToJSON
WidgetMessage
where
toJSON
DisplayWidget
=
object
[
"method"
.=
str
"display"
]
toJSON
DisplayWidget
=
object
[
"method"
.=
str
"display"
]
toJSON
(
InitialState
name
)
=
object
[
toJSON
(
InitialState
name
)
=
object
"method"
.=
str
"update"
,
[
"method"
.=
str
"update"
"state"
.=
object
[
,
"state"
.=
object
"_view_name"
.=
name
,
[
"_view_name"
.=
name
"visible"
.=
True
,
,
"visible"
.=
True
"_css"
.=
object
[]
,
,
"_css"
.=
object
[]
"msg_throttle"
.=
(
3
::
Int
),
,
"msg_throttle"
.=
(
3
::
Int
)
"disabled"
.=
False
,
,
"disabled"
.=
False
"description"
.=
str
"Button"
,
"description"
.=
str
"Button"
]
]
]
]
str
::
String
->
String
str
::
String
->
String
str
=
id
str
=
id
...
@@ -45,7 +47,6 @@ instance FromJSON ParseText where
...
@@ -45,7 +47,6 @@ instance FromJSON ParseText where
instance
IHaskellWidget
Slider
where
instance
IHaskellWidget
Slider
where
-- Name for this widget.
-- Name for this widget.
targetName
_
=
"WidgetModel"
targetName
_
=
"WidgetModel"
-- Start by sending messages to set up the widget.
-- Start by sending messages to set up the widget.
open
widget
send
=
do
open
widget
send
=
do
putStrLn
"Sending widgets!"
putStrLn
"Sending widgets!"
...
...
ihaskell-display/ihaskell-widgets/IHaskell/Widgets.hs
View file @
a489c9bb
module
IHaskell.Widgets
(
module
IHaskell.Widgets
(
Slider
(
..
))
where
Slider
(
..
)
)
where
data
Slider
=
Slider
data
Slider
=
Slider
ipython-kernel/examples/Calc.hs
View file @
a489c9bb
{-# LANGUAGE FlexibleContexts, FlexibleInstances, OverloadedStrings, MultiWayIf #-}
{-# LANGUAGE FlexibleContexts, FlexibleInstances, OverloadedStrings, MultiWayIf #-}
module
Main
where
module
Main
where
import
Control.Applicative
import
Control.Applicative
...
@@ -20,7 +21,8 @@ import IHaskell.IPython.EasyKernel (installProfile, easyKernel, KernelConfig(..)
...
@@ -20,7 +21,8 @@ import IHaskell.IPython.EasyKernel (installProfile, easyKernel, KernelConfig(..)
import
System.Environment
(
getArgs
)
import
System.Environment
(
getArgs
)
import
System.FilePath
((
</>
))
import
System.FilePath
((
</>
))
import
Text.Parsec
(
Parsec
,
ParseError
,
alphaNum
,
char
,
letter
,
oneOf
,
optionMaybe
,
runParser
,
(
<?>
))
import
Text.Parsec
(
Parsec
,
ParseError
,
alphaNum
,
char
,
letter
,
oneOf
,
optionMaybe
,
runParser
,
(
<?>
))
import
qualified
Text.Parsec.Token
as
P
import
qualified
Text.Parsec.Token
as
P
import
qualified
Paths_ipython_kernel
as
Paths
import
qualified
Paths_ipython_kernel
as
Paths
...
@@ -28,21 +30,16 @@ import qualified Paths_ipython_kernel as Paths
...
@@ -28,21 +30,16 @@ import qualified Paths_ipython_kernel as Paths
---------------------------------------------------------
---------------------------------------------------------
-- Hutton's Razor, plus time delays, plus a global state
-- Hutton's Razor, plus time delays, plus a global state
---------------------------------------------------------
---------------------------------------------------------
--
-- | This language is Hutton's Razor with two added operations that
-- | This language is Hutton's Razor with two added operations that are needed to demonstrate the
-- are needed to demonstrate the kernel features: a global state,
-- kernel features: a global state, accessed and modified using Count, and a sleep operation.
-- accessed and modified using Count, and a sleep operation.
data
Razor
=
I
Integer
data
Razor
=
I
Integer
|
Plus
Razor
Razor
|
Plus
Razor
Razor
|
SleepThen
Double
Razor
|
SleepThen
Double
Razor
|
Count
|
Count
deriving
(
Read
,
Show
,
Eq
)
deriving
(
Read
,
Show
,
Eq
)
-- ------- Parser -------
---------
-- Parser
---------
razorDef
::
Monad
m
=>
P
.
GenLanguageDef
String
a
m
razorDef
::
Monad
m
=>
P
.
GenLanguageDef
String
a
m
razorDef
=
P
.
LanguageDef
razorDef
=
P
.
LanguageDef
{
P
.
commentStart
=
"(*"
{
P
.
commentStart
=
"(*"
...
@@ -83,7 +80,8 @@ literal :: Parsec String a Razor
...
@@ -83,7 +80,8 @@ literal :: Parsec String a Razor
literal
=
I
<$>
integer
literal
=
I
<$>
integer
sleepThen
::
Parsec
String
a
Razor
sleepThen
::
Parsec
String
a
Razor
sleepThen
=
do
keyword
"sleep"
sleepThen
=
do
keyword
"sleep"
delay
<-
float
<?>
"seconds"
delay
<-
float
<?>
"seconds"
keyword
"then"
keyword
"then"
body
<-
expr
body
<-
expr
...
@@ -94,8 +92,11 @@ count :: Parsec String a Razor
...
@@ -94,8 +92,11 @@ count :: Parsec String a Razor
count
=
keyword
"count"
>>
return
Count
count
=
keyword
"count"
>>
return
Count
expr
::
Parsec
String
a
Razor
expr
::
Parsec
String
a
Razor
expr
=
do
one
<-
parens
expr
<|>
literal
<|>
sleepThen
<|>
count
expr
=
do
rest
<-
optionMaybe
(
do
op
<-
operator
one
<-
parens
expr
<|>
literal
<|>
sleepThen
<|>
count
rest
<-
optionMaybe
(
do
op
<-
operator
guard
(
op
==
"+"
)
guard
(
op
==
"+"
)
expr
)
expr
)
case
rest
of
case
rest
of
...
@@ -105,12 +106,7 @@ expr = do one <- parens expr <|> literal <|> sleepThen <|> count
...
@@ -105,12 +106,7 @@ expr = do one <- parens expr <|> literal <|> sleepThen <|> count
parse
::
String
->
Either
ParseError
Razor
parse
::
String
->
Either
ParseError
Razor
parse
=
runParser
expr
()
"(input)"
parse
=
runParser
expr
()
"(input)"
-- -------------------- Language operations -------------------- | Completion
----------------------
-- Language operations
----------------------
-- | Completion
langCompletion
::
T
.
Text
->
T
.
Text
->
Int
->
Maybe
([
T
.
Text
],
T
.
Text
,
T
.
Text
)
langCompletion
::
T
.
Text
->
T
.
Text
->
Int
->
Maybe
([
T
.
Text
],
T
.
Text
,
T
.
Text
)
langCompletion
_code
line
col
=
langCompletion
_code
line
col
=
let
(
before
,
_
)
=
T
.
splitAt
col
line
let
(
before
,
_
)
=
T
.
splitAt
col
line
...
@@ -123,20 +119,18 @@ langCompletion _code line col =
...
@@ -123,20 +119,18 @@ langCompletion _code line col =
lastMaybe
(
_
:
xs
)
=
lastMaybe
xs
lastMaybe
(
_
:
xs
)
=
lastMaybe
xs
matchesFor
::
String
->
[
String
]
matchesFor
::
String
->
[
String
]
matchesFor
input
=
filter
(
isPrefixOf
input
)
available
matchesFor
input
=
filter
(
isPrefixOf
input
)
available
available
=
[
"sleep"
,
"then"
,
"end"
,
"count"
]
++
map
show
[(
-
1000
::
Int
)
..
1000
]
available
=
[
"sleep"
,
"then"
,
"end"
,
"count"
]
++
map
show
[(
-
1000
::
Int
)
..
1000
]
-- | Documentation lookup
-- | Documentation lookup
langInfo
::
T
.
Text
->
Maybe
(
T
.
Text
,
T
.
Text
,
T
.
Text
)
langInfo
::
T
.
Text
->
Maybe
(
T
.
Text
,
T
.
Text
,
T
.
Text
)
langInfo
obj
=
langInfo
obj
=
if
|
any
(
T
.
isPrefixOf
obj
)
[
"sleep"
,
"then"
,
"end"
]
->
if
|
any
(
T
.
isPrefixOf
obj
)
[
"sleep"
,
"then"
,
"end"
]
->
Just
(
obj
,
sleepDocs
,
sleepType
)
Just
(
obj
,
sleepDocs
,
sleepType
)
|
T
.
isPrefixOf
obj
"count"
->
Just
(
obj
,
countDocs
,
countType
)
|
T
.
isPrefixOf
obj
"count"
->
Just
(
obj
,
countDocs
,
countType
)
|
obj
==
"+"
->
Just
(
obj
,
plusDocs
,
plusType
)
|
obj
==
"+"
->
Just
(
obj
,
plusDocs
,
plusType
)
|
T
.
all
isDigit
obj
->
Just
(
obj
,
intDocs
obj
,
intType
)
|
T
.
all
isDigit
obj
->
Just
(
obj
,
intDocs
obj
,
intType
)
|
[
x
,
y
]
<-
T
.
splitOn
"."
obj
,
|
[
x
,
y
]
<-
T
.
splitOn
"."
obj
T
.
all
isDigit
x
,
,
T
.
all
isDigit
x
T
.
all
isDigit
y
->
Just
(
obj
,
floatDocs
obj
,
floatType
)
,
T
.
all
isDigit
y
->
Just
(
obj
,
floatDocs
obj
,
floatType
)
|
otherwise
->
Nothing
|
otherwise
->
Nothing
where
where
sleepDocs
=
"sleep DURATION then VALUE end: sleep DURATION seconds, then eval VALUE"
sleepDocs
=
"sleep DURATION then VALUE end: sleep DURATION seconds, then eval VALUE"
...
@@ -155,11 +149,11 @@ data IntermediateEvalRes = Got Razor Integer
...
@@ -155,11 +149,11 @@ data IntermediateEvalRes = Got Razor Integer
|
Waiting
Double
|
Waiting
Double
deriving
Show
deriving
Show
-- | Cons for lists of trace elements - in this case, "sleeping"
-- | Cons for lists of trace elements - in this case, "sleeping"
messages should replace old ones to
--
messages should replace old ones to
create a countdown effect.
-- create a countdown effect.
consRes
::
IntermediateEvalRes
->
[
IntermediateEvalRes
]
->
[
IntermediateEvalRes
]
consRes
::
IntermediateEvalRes
->
[
IntermediateEvalRes
]
->
[
IntermediateEvalRes
]
consRes
r
@
(
Waiting
_
)
(
Waiting
_
:
s
)
=
r
:
s
consRes
r
@
(
Waiting
_
)
(
Waiting
_
:
s
)
=
r
:
s
consRes
r
s
=
r
:
s
consRes
r
s
=
r
:
s
-- | Execute an expression.
-- | Execute an expression.
execRazor
::
MVar
Integer
-- ^ The global counter state
execRazor
::
MVar
Integer
-- ^ The global counter state
...
@@ -168,9 +162,10 @@ execRazor :: MVar Integer -- ^ The global counter state
...
@@ -168,9 +162,10 @@ execRazor :: MVar Integer -- ^ The global counter state
->
([
IntermediateEvalRes
]
->
IO
()
)
-- ^ Callback for intermediate results
->
([
IntermediateEvalRes
]
->
IO
()
)
-- ^ Callback for intermediate results
->
StateT
([
IntermediateEvalRes
],
T
.
Text
)
IO
Integer
->
StateT
([
IntermediateEvalRes
],
T
.
Text
)
IO
Integer
execRazor
_
x
@
(
I
i
)
_
_
=
execRazor
_
x
@
(
I
i
)
_
_
=
modify
(
second
(
<>
(
T
.
pack
(
show
x
)
)))
>>
return
i
modify
(
second
(
<>
T
.
pack
(
show
x
)))
>>
return
i
execRazor
val
tm
@
(
Plus
x
y
)
clear
send
=
execRazor
val
tm
@
(
Plus
x
y
)
clear
send
=
do
modify
(
second
(
<>
(
T
.
pack
(
show
tm
))))
do
modify
(
second
(
<>
T
.
pack
(
show
tm
)))
x'
<-
execRazor
val
x
clear
send
x'
<-
execRazor
val
x
clear
send
modify
(
first
$
consRes
(
Got
x
x'
))
modify
(
first
$
consRes
(
Got
x
x'
))
sendState
sendState
...
@@ -181,33 +176,39 @@ execRazor val tm@(Plus x y) clear send =
...
@@ -181,33 +176,39 @@ execRazor val tm@(Plus x y) clear send =
modify
(
first
$
consRes
(
Got
tm
res
))
modify
(
first
$
consRes
(
Got
tm
res
))
sendState
sendState
return
res
return
res
where
sendState
=
liftIO
clear
>>
fst
<$>
get
>>=
liftIO
.
send
where
sendState
=
liftIO
clear
>>
fst
<$>
get
>>=
liftIO
.
send
execRazor
val
(
SleepThen
delay
body
)
clear
send
execRazor
val
(
SleepThen
delay
body
)
clear
send
|
delay
<=
0.0
=
execRazor
val
body
clear
send
|
delay
<=
0.0
=
execRazor
val
body
clear
send
|
delay
>
0.1
=
do
modify
(
first
$
consRes
(
Waiting
delay
))
|
delay
>
0.1
=
do
modify
(
first
$
consRes
(
Waiting
delay
))
sendState
sendState
liftIO
$
threadDelay
100000
liftIO
$
threadDelay
100000
execRazor
val
(
SleepThen
(
delay
-
0.1
)
body
)
clear
send
execRazor
val
(
SleepThen
(
delay
-
0.1
)
body
)
clear
send
|
otherwise
=
do
modify
(
first
$
consRes
(
Waiting
0
))
|
otherwise
=
do
modify
(
first
$
consRes
(
Waiting
0
))
sendState
sendState
liftIO
$
threadDelay
(
floor
(
delay
*
1000000
))
liftIO
$
threadDelay
(
floor
(
delay
*
1000000
))
execRazor
val
body
clear
send
execRazor
val
body
clear
send
where
sendState
=
liftIO
clear
>>
fst
<$>
get
>>=
liftIO
.
send
where
sendState
=
liftIO
clear
>>
fst
<$>
get
>>=
liftIO
.
send
execRazor
val
Count
clear
send
=
do
execRazor
val
Count
clear
send
=
do
i
<-
liftIO
$
takeMVar
val
i
<-
liftIO
$
takeMVar
val
modify
(
first
$
consRes
(
Got
Count
i
))
modify
(
first
$
consRes
(
Got
Count
i
))
sendState
sendState
liftIO
$
putMVar
val
(
i
+
1
)
liftIO
$
putMVar
val
(
i
+
1
)
return
i
return
i
where
sendState
=
liftIO
clear
>>
fst
<$>
get
>>=
liftIO
.
send
where
sendState
=
liftIO
clear
>>
fst
<$>
get
>>=
liftIO
.
send
-- | Generate a language configuration for some initial state
-- | Generate a language configuration for some initial state
mkConfig
::
MVar
Integer
-- ^ The internal state of the execution
mkConfig
::
MVar
Integer
-- ^ The internal state of the execution
->
KernelConfig
IO
[
IntermediateEvalRes
]
(
Either
ParseError
Integer
)
->
KernelConfig
IO
[
IntermediateEvalRes
]
(
Either
ParseError
Integer
)
mkConfig
var
=
KernelConfig
mkConfig
var
=
KernelConfig
{
languageName
=
"expanded_huttons_razor"
{
languageName
=
"expanded_huttons_razor"
,
languageVersion
=
[
0
,
1
,
0
]
,
languageVersion
=
[
0
,
1
,
0
]
,
profileSource
=
Just
.
(
</>
"calc_profile.tar"
)
<$>
Paths
.
getDataDir
,
profileSource
=
Just
.
(
</>
"calc_profile.tar"
)
<$>
Paths
.
getDataDir
,
displayResult
=
displayRes
,
displayResult
=
displayRes
,
displayOutput
=
displayOut
,
displayOutput
=
displayOut
...
@@ -235,7 +236,8 @@ mkConfig var = KernelConfig
...
@@ -235,7 +236,8 @@ mkConfig var = KernelConfig
return
(
Right
res
,
Ok
,
T
.
unpack
pager
)
return
(
Right
res
,
Ok
,
T
.
unpack
pager
)
main
::
IO
()
main
::
IO
()
main
=
do
args
<-
getArgs
main
=
do
args
<-
getArgs
val
<-
newMVar
1
val
<-
newMVar
1
case
args
of
case
args
of
[
"kernel"
,
profileFile
]
->
[
"kernel"
,
profileFile
]
->
...
@@ -246,4 +248,5 @@ main = do args <- getArgs
...
@@ -246,4 +248,5 @@ main = do args <- getArgs
_
->
do
_
->
do
putStrLn
"Usage:"
putStrLn
"Usage:"
putStrLn
"simple-calc-example setup -- set up the profile"
putStrLn
"simple-calc-example setup -- set up the profile"
putStrLn
"simple-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend"
putStrLn
"simple-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend"
ipython-kernel/src/IHaskell/IPython/EasyKernel.hs
View file @
a489c9bb
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Description : Easy IPython kernels
-- | Description : Easy IPython kernels = Overview This module provides automation for writing
-- = Overview
-- simple IPython kernels. In particular, it provides a record type that defines configurations and
-- This module provides automation for writing simple IPython
-- a function that interprets a configuration as an action in some monad that can do IO.
-- kernels. In particular, it provides a record type that defines
-- configurations and a function that interprets a configuration as an
-- action in some monad that can do IO.
--
--
-- The configuration consists primarily of functions that implement
-- The configuration consists primarily of functions that implement the various features of a
-- the various features of a kernel, such as running code, looking up
-- kernel, such as running code, looking up documentation, and performing completion. An example for
-- documentation, and performing completion. An example for a simple
-- a simple language that nevertheless has side effects, global state, and timing effects is
-- language that nevertheless has side effects, global state, and
-- included in the examples directory.
-- timing effects is included in the examples directory.
--
--
-- = Profiles
-- = Profiles To run your kernel, you will need an IPython profile that causes the frontend to run
-- To run your kernel, you will need an IPython profile that causes
-- it. To generate a fresh profile, run the command
-- the frontend to run it. To generate a fresh profile, run the command
--
--
-- > ipython profile create NAME
-- > ipython profile create NAME
--
--
-- This will create a fresh IPython profile in @~\/.ipython\/profile_NAME@.
-- This will create a fresh IPython profile in @~\/.ipython\/profile_NAME@.
This profile must be
--
This profile must be
modified in two ways:
-- modified in two ways:
--
--
-- 1. It needs to run your kernel instead of the default ipython
-- 1. It needs to run your kernel instead of the default ipython
2. It must have message signing
--
2. It must have message signing
turned off, because 'easyKernel' doesn't support it
-- turned off, because 'easyKernel' doesn't support it
--
--
-- == Setting the executable
-- == Setting the executable To set the executable, modify the configuration object's
-- To set the executable, modify the configuration object's
-- @KernelManager.kernel_cmd@ property. For example:
-- @KernelManager.kernel_cmd@ property. For example:
--
--
-- > c.KernelManager.kernel_cmd = ['my_kernel', '{connection_file}']
-- > c.KernelManager.kernel_cmd = ['my_kernel', '{connection_file}']
...
@@ -44,7 +38,6 @@
...
@@ -44,7 +38,6 @@
-- Consult the IPython documentation along with the generated profile
-- Consult the IPython documentation along with the generated profile
-- source code for further configuration of the frontend, including
-- source code for further configuration of the frontend, including
-- syntax highlighting, logos, help text, and so forth.
-- syntax highlighting, logos, help text, and so forth.
module
IHaskell.IPython.EasyKernel
(
easyKernel
,
installProfile
,
KernelConfig
(
..
))
where
module
IHaskell.IPython.EasyKernel
(
easyKernel
,
installProfile
,
KernelConfig
(
..
))
where
import
Data.Aeson
(
decode
)
import
Data.Aeson
(
decode
)
...
@@ -55,7 +48,7 @@ import qualified Codec.Archive.Tar as Tar
...
@@ -55,7 +48,7 @@ import qualified Codec.Archive.Tar as Tar
import
Control.Concurrent
(
MVar
,
readChan
,
writeChan
,
newMVar
,
readMVar
,
modifyMVar_
)
import
Control.Concurrent
(
MVar
,
readChan
,
writeChan
,
newMVar
,
readMVar
,
modifyMVar_
)
import
Control.Monad.IO.Class
(
MonadIO
(
..
))
import
Control.Monad.IO.Class
(
MonadIO
(
..
))
import
Control.Monad
(
forever
,
when
)
import
Control.Monad
(
forever
,
when
,
unless
)
import
qualified
Data.Map
as
Map
import
qualified
Data.Map
as
Map
import
Data.Maybe
(
fromMaybe
)
import
Data.Maybe
(
fromMaybe
)
...
@@ -64,59 +57,54 @@ import qualified Data.Text as T
...
@@ -64,59 +57,54 @@ import qualified Data.Text as T
import
IHaskell.IPython.Kernel
import
IHaskell.IPython.Kernel
import
IHaskell.IPython.Message.UUID
as
UUID
import
IHaskell.IPython.Message.UUID
as
UUID
import
System.Directory
(
createDirectoryIfMissing
,
doesDirectoryExist
,
doesFileExist
,
getHomeDirectory
)
import
System.Directory
(
createDirectoryIfMissing
,
doesDirectoryExist
,
doesFileExist
,
getHomeDirectory
)
import
System.FilePath
((
</>
))
import
System.FilePath
((
</>
))
import
System.Exit
(
exitSuccess
)
import
System.Exit
(
exitSuccess
)
import
System.IO
(
openFile
,
IOMode
(
ReadMode
))
import
System.IO
(
openFile
,
IOMode
(
ReadMode
))
-- | The kernel configuration specifies the behavior that is specific
-- | The kernel configuration specifies the behavior that is specific to your language. The type
-- to your language. The type parameters provide the monad in which
-- parameters provide the monad in which your kernel will run, the type of intermediate outputs from
-- your kernel will run, the type of intermediate outputs from running
-- running cells, and the type of final results of cells, respectively.
-- cells, and the type of final results of cells, respectively.
data
KernelConfig
m
output
result
=
data
KernelConfig
m
output
result
=
KernelConfig
KernelConfig
{
languageName
::
String
{
-- ^ The name of the language. This field is used to calculate
-- | The name of the language. This field is used to calculate the name of the profile,
-- the name of the profile, so it should contain characters that
-- so it should contain characters that are reasonable to have in file names.
-- are reasonable to have in file names.
languageName
::
String
,
languageVersion
::
[
Int
]
-- ^ The version of the language
-- | The version of the language
,
profileSource
::
IO
(
Maybe
FilePath
)
,
languageVersion
::
[
Int
]
-- ^ Determine the source of a profile to install using
-- | Determine the source of a profile to install using 'installProfile'. The source should be a
-- 'installProfile'. The source should be a tarball whose contents
-- tarball whose contents will be unpacked directly into the profile directory. For example, the
-- will be unpacked directly into the profile directory. For
-- file whose name is @ipython_config.py@ in the tar file for a language named @lang@ will end up in
-- example, the file whose name is @ipython_config.py@ in the
-- tar file for a language named @lang@ will end up in
-- @~/.ipython/profile_lang/ipython_config.py@.
-- @~/.ipython/profile_lang/ipython_config.py@.
,
displayOutput
::
output
->
[
DisplayData
]
-- ^ How to render intermediate output
,
profileSource
::
IO
(
Maybe
FilePath
)
,
displayResult
::
result
->
[
DisplayData
]
-- ^ How to render final cell results
-- | How to render intermediate output
,
displayOutput
::
output
->
[
DisplayData
]
-- | How to render final cell results
,
displayResult
::
result
->
[
DisplayData
]
-- | Perform completion. The returned tuple consists of the matches, the matched text, and the
-- completion text. The arguments are the code in the cell, the current line as text, and the column
-- at which the cursor is placed.
,
completion
::
T
.
Text
->
T
.
Text
->
Int
->
Maybe
([
T
.
Text
],
T
.
Text
,
T
.
Text
)
,
completion
::
T
.
Text
->
T
.
Text
->
Int
->
Maybe
([
T
.
Text
],
T
.
Text
,
T
.
Text
)
-- ^ Perform completion. The returned tuple consists of the matches,
-- | Return the information or documentation for its argument. The returned tuple consists of the
-- the matched text, and the completion text. The arguments are the
-- name, the documentation, and the type, respectively.
-- code in the cell, the current line as text, and the column at
-- which the cursor is placed.
,
objectInfo
::
T
.
Text
->
Maybe
(
T
.
Text
,
T
.
Text
,
T
.
Text
)
,
objectInfo
::
T
.
Text
->
Maybe
(
T
.
Text
,
T
.
Text
,
T
.
Text
)
-- ^ Return the information or documentation for its argument. The
-- | Execute a cell. The arguments are the contents of the cell, an IO action that will clear the
-- returned tuple consists of the name, the documentation, and the
-- current intermediate output, and an IO action that will add a new item to the intermediate
-- type, respectively.
-- output. The result consists of the actual result, the status to be sent to IPython, and the
-- contents of the pager. Return the empty string to indicate that there is no pager output. Errors
-- should be handled by defining an appropriate error constructor in your result type.
,
run
::
T
.
Text
->
IO
()
->
(
output
->
IO
()
)
->
m
(
result
,
ExecuteReplyStatus
,
String
)
,
run
::
T
.
Text
->
IO
()
->
(
output
->
IO
()
)
->
m
(
result
,
ExecuteReplyStatus
,
String
)
-- ^ Execute a cell. The arguments are the contents of the cell, an
-- IO action that will clear the current intermediate output, and an
-- IO action that will add a new item to the intermediate
-- output. The result consists of the actual result, the status to
-- be sent to IPython, and the contents of the pager. Return the
-- empty string to indicate that there is no pager output. Errors
-- should be handled by defining an appropriate error constructor in
-- your result type.
,
debug
::
Bool
-- ^ Whether to print extra debugging information to
,
debug
::
Bool
-- ^ Whether to print extra debugging information to
-- the console
}
}
-- | Attempt to install the IPython profile from the .tar file
-- the console | Attempt to install the IPython profile from the .tar file indicated by the
-- indicated by the 'profileSource' field of the configuration, if it
-- 'profileSource' field of the configuration, if it is not already installed.
-- is not already installed.
installProfile
::
MonadIO
m
=>
KernelConfig
m
output
result
->
m
()
installProfile
::
MonadIO
m
=>
KernelConfig
m
output
result
->
m
()
installProfile
config
=
do
installProfile
config
=
do
installed
<-
isInstalled
installed
<-
isInstalled
when
(
not
installed
)
$
do
unless
installed
$
do
profSrc
<-
liftIO
$
profileSource
config
profSrc
<-
liftIO
$
profileSource
config
case
profSrc
of
case
profSrc
of
Nothing
->
liftIO
(
putStrLn
"No IPython profile is installed or specified"
)
Nothing
->
liftIO
(
putStrLn
"No IPython profile is installed or specified"
)
...
@@ -124,7 +112,8 @@ installProfile config = do
...
@@ -124,7 +112,8 @@ installProfile config = do
profExists
<-
liftIO
$
doesFileExist
tar
profExists
<-
liftIO
$
doesFileExist
tar
profTgt
<-
profDir
profTgt
<-
profDir
if
profExists
if
profExists
then
do
liftIO
$
createDirectoryIfMissing
True
profTgt
then
do
liftIO
$
createDirectoryIfMissing
True
profTgt
liftIO
$
Tar
.
extract
profTgt
tar
liftIO
$
Tar
.
extract
profTgt
tar
else
liftIO
.
putStrLn
$
else
liftIO
.
putStrLn
$
"The supplied profile source '"
++
tar
++
"' does not exist"
"The supplied profile source '"
++
tar
++
"' does not exist"
...
@@ -153,28 +142,29 @@ createReplyHeader parent = do
...
@@ -153,28 +142,29 @@ createReplyHeader parent = do
let
repType
=
fromMaybe
err
(
replyType
$
msgType
parent
)
let
repType
=
fromMaybe
err
(
replyType
$
msgType
parent
)
err
=
error
$
"No reply for message "
++
show
(
msgType
parent
)
err
=
error
$
"No reply for message "
++
show
(
msgType
parent
)
return
MessageHeader
{
return
identifiers
=
identifiers
parent
,
MessageHeader
parentHeader
=
Just
parent
,
{
identifiers
=
identifiers
parent
metadata
=
Map
.
fromList
[]
,
,
parentHeader
=
Just
parent
messageId
=
newMessageId
,
,
metadata
=
Map
.
fromList
[]
sessionId
=
sessionId
parent
,
,
messageId
=
newMessageId
username
=
username
parent
,
,
sessionId
=
sessionId
parent
msgType
=
repType
,
username
=
username
parent
,
msgType
=
repType
}
}
-- | Execute an IPython kernel for a config. Your 'main' action should call this as the last thing
-- it does.
-- | Execute an IPython kernel for a config. Your 'main' action should
-- call this as the last thing it does.
easyKernel
::
(
MonadIO
m
)
easyKernel
::
(
MonadIO
m
)
=>
FilePath
-- ^ The connection file provided by the IPython frontend
=>
FilePath
-- ^ The connection file provided by the IPython frontend
->
KernelConfig
m
output
result
-- ^ The kernel configuration specifying how to react to messages
->
KernelConfig
m
output
result
-- ^ The kernel configuration specifying how to react to
-- messages
->
m
()
->
m
()
easyKernel
profileFile
config
=
do
easyKernel
profileFile
config
=
do
prof
<-
liftIO
$
getProfile
profileFile
prof
<-
liftIO
$
getProfile
profileFile
zmq
@
(
Channels
shellReqChan
shellRepChan
ctrlReqChan
ctrlRepChan
iopubChan
_
)
<-
zmq
@
(
Channels
shellReqChan
shellRepChan
ctrlReqChan
ctrlRepChan
iopubChan
_
)
<-
liftIO
$
serveProfile
liftIO
$
serveProfile
prof
False
prof
False
execCount
<-
liftIO
$
newMVar
0
execCount
<-
liftIO
$
newMVar
0
forever
$
do
forever
$
do
req
<-
liftIO
$
readChan
shellReqChan
req
<-
liftIO
$
readChan
shellReqChan
...
@@ -183,7 +173,6 @@ easyKernel profileFile config = do
...
@@ -183,7 +173,6 @@ easyKernel profileFile config = do
reply
<-
replyTo
config
execCount
zmq
req
repHeader
reply
<-
replyTo
config
execCount
zmq
req
repHeader
liftIO
$
writeChan
shellRepChan
reply
liftIO
$
writeChan
shellRepChan
reply
replyTo
::
MonadIO
m
replyTo
::
MonadIO
m
=>
KernelConfig
m
output
result
=>
KernelConfig
m
output
result
->
MVar
Integer
->
MVar
Integer
...
@@ -192,28 +181,31 @@ replyTo :: MonadIO m
...
@@ -192,28 +181,31 @@ replyTo :: MonadIO m
->
MessageHeader
->
MessageHeader
->
m
Message
->
m
Message
replyTo
config
_
_
KernelInfoRequest
{}
replyHeader
=
replyTo
config
_
_
KernelInfoRequest
{}
replyHeader
=
return
KernelInfoReply
return
KernelInfoReply
{
header
=
replyHeader
{
header
=
replyHeader
,
language
=
languageName
config
,
language
=
languageName
config
,
versionList
=
languageVersion
config
,
versionList
=
languageVersion
config
}
}
replyTo
config
_
interface
ShutdownRequest
{
restartPending
=
pending
}
replyHeader
=
do
replyTo
config
_
interface
ShutdownRequest
{
restartPending
=
pending
}
replyHeader
=
do
liftIO
$
writeChan
(
shellReplyChannel
interface
)
$
ShutdownReply
replyHeader
pending
liftIO
$
writeChan
(
shellReplyChannel
interface
)
$
ShutdownReply
replyHeader
pending
liftIO
exitSuccess
liftIO
exitSuccess
replyTo
config
execCount
interface
req
@
ExecuteRequest
{
getCode
=
code
}
replyHeader
=
do
replyTo
config
execCount
interface
req
@
ExecuteRequest
{
getCode
=
code
}
replyHeader
=
do
let
send
msg
=
writeChan
(
iopubChannel
interface
)
msg
let
send
=
writeChan
(
iopubChannel
interface
)
busyHeader
<-
dupHeader
replyHeader
StatusMessage
busyHeader
<-
dupHeader
replyHeader
StatusMessage
liftIO
.
send
$
PublishStatus
busyHeader
Busy
liftIO
.
send
$
PublishStatus
busyHeader
Busy
outputHeader
<-
dupHeader
replyHeader
DisplayDataMessage
outputHeader
<-
dupHeader
replyHeader
DisplayDataMessage
(
res
,
replyStatus
,
pagerOut
)
<-
(
res
,
replyStatus
,
pagerOut
)
<-
let
clearOutput
=
do
let
clearOutput
=
do
clearHeader
<-
dupHeader
replyHeader
clearHeader
<-
dupHeader
replyHeader
ClearOutputMessage
ClearOutputMessage
send
$
ClearOutput
clearHeader
False
send
$
ClearOutput
clearHeader
False
sendOutput
x
=
sendOutput
x
=
send
$
PublishDisplayData
outputHeader
(
languageName
config
)
send
$
PublishDisplayData
outputHeader
(
languageName
config
)
(
displayOutput
config
x
)
(
displayOutput
config
x
)
in
run
config
code
clearOutput
sendOutput
in
run
config
code
clearOutput
sendOutput
liftIO
.
send
$
PublishDisplayData
outputHeader
(
languageName
config
)
(
displayResult
config
res
)
liftIO
.
send
$
PublishDisplayData
outputHeader
(
languageName
config
)
(
displayResult
config
res
)
...
@@ -222,45 +214,24 @@ replyTo config execCount interface req@ExecuteRequest { getCode = code } replyHe
...
@@ -222,45 +214,24 @@ replyTo config execCount interface req@ExecuteRequest { getCode = code } replyHe
idleHeader
<-
dupHeader
replyHeader
StatusMessage
idleHeader
<-
dupHeader
replyHeader
StatusMessage
liftIO
.
send
$
PublishStatus
idleHeader
Idle
liftIO
.
send
$
PublishStatus
idleHeader
Idle
liftIO
$
modifyMVar_
execCount
(
return
.
(
+
1
))
liftIO
$
modifyMVar_
execCount
(
return
.
(
+
1
))
counter
<-
liftIO
$
readMVar
execCount
counter
<-
liftIO
$
readMVar
execCount
return
ExecuteReply
return
ExecuteReply
{
header
=
replyHeader
{
header
=
replyHeader
,
pagerOutput
=
pagerOut
,
pagerOutput
=
pagerOut
,
executionCounter
=
fromIntegral
counter
,
executionCounter
=
fromIntegral
counter
,
status
=
replyStatus
,
status
=
replyStatus
}
}
replyTo
config
_
_
req
@
CompleteRequest
{}
replyHeader
=
do
replyTo
config
_
_
req
@
CompleteRequest
{}
replyHeader
=
-- TODO: FIX
-- TODO: FIX
error
"Unimplemented in IPython 3.0"
error
"Unimplemented in IPython 3.0"
{-
let code = getCode req
line = getCodeLine req
col = getCursorPos req
return $ case completion config code line col of
Nothing ->
CompleteReply
{ header = replyHeader
, completionMatches = []
, completionMatchedText = ""
, completionText = ""
, completionStatus = False
}
Just (matches, matchedText, cmplText) ->
CompleteReply
{ header = replyHeader
, completionMatches = matches
, completionMatchedText = matchedText
, completionText = cmplText
, completionStatus = True
}
-}
replyTo
config
_
_
ObjectInfoRequest
{
objectName
=
obj
}
replyHeader
=
replyTo
config
_
_
ObjectInfoRequest
{
objectName
=
obj
}
replyHeader
=
return
$
case
objectInfo
config
obj
of
return
$
case
objectInfo
config
obj
of
Just
(
name
,
docs
,
ty
)
->
ObjectInfoReply
Just
(
name
,
docs
,
ty
)
->
ObjectInfoReply
{
header
=
replyHeader
{
header
=
replyHeader
,
objectName
=
obj
,
objectName
=
obj
...
@@ -281,8 +252,8 @@ replyTo _ _ _ msg _ = do
...
@@ -281,8 +252,8 @@ replyTo _ _ _ msg _ = do
liftIO
$
print
msg
liftIO
$
print
msg
return
msg
return
msg
dupHeader
::
MonadIO
m
=>
MessageHeader
->
MessageType
->
m
MessageHeader
dupHeader
::
MonadIO
m
=>
MessageHeader
->
MessageType
->
m
MessageHeader
dupHeader
hdr
mtype
=
dupHeader
hdr
mtype
=
do
uuid
<-
liftIO
UUID
.
random
do
return
hdr
{
messageId
=
uuid
,
msgType
=
mtype
}
uuid
<-
liftIO
UUID
.
random
return
hdr
{
messageId
=
uuid
,
msgType
=
mtype
}
ipython-kernel/src/IHaskell/IPython/Kernel.hs
View file @
a489c9bb
-- | This module exports all the types and functions necessary to create an
-- | This module exports all the types and functions necessary to create an IPython language kernel
-- IPython language kernel that supports the @ipython console@ and @ipython
-- that supports the @ipython console@ and @ipython notebook@ frontends.
-- notebook@ frontends.
module
IHaskell.IPython.Kernel
(
module
X
)
where
module
IHaskell.IPython.Kernel
(
module
X
,
)
where
import
IHaskell.IPython.Types
as
X
import
IHaskell.IPython.Types
as
X
import
IHaskell.IPython.Message.Writer
as
X
import
IHaskell.IPython.Message.Writer
as
X
...
...
ipython-kernel/src/IHaskell/IPython/Message/Parser.hs
View file @
a489c9bb
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Description : Parsing messages received from IPython
-- | Description : Parsing messages received from IPython
--
--
-- This module is responsible for converting from low-level ByteStrings
-- This module is responsible for converting from low-level ByteStrings
obtained from the 0MQ
--
obtained from the 0MQ sockets into Messages. The only exposed function is
--
sockets into Messages. The only exposed function is `parseMessage`, which should only be used in
--
`parseMessage`, which should only be used in
the low-level 0MQ interface.
-- the low-level 0MQ interface.
module
IHaskell.IPython.Message.Parser
(
parseMessage
)
where
module
IHaskell.IPython.Message.Parser
(
parseMessage
)
where
import
Data.Aeson
((
.:
),
decode
,
Result
(
..
),
Object
)
import
Data.Aeson
((
.:
),
decode
,
Result
(
..
),
Object
)
...
@@ -17,9 +18,7 @@ import IHaskell.IPython.Types
...
@@ -17,9 +18,7 @@ import IHaskell.IPython.Types
type
LByteString
=
Lazy
.
ByteString
type
LByteString
=
Lazy
.
ByteString
----- External interface -----
-- --- External interface ----- | Parse a message from its ByteString components into a Message.
-- | Parse a message from its ByteString components into a Message.
parseMessage
::
[
ByteString
]
-- ^ The list of identifiers sent with the message.
parseMessage
::
[
ByteString
]
-- ^ The list of identifiers sent with the message.
->
ByteString
-- ^ The header data.
->
ByteString
-- ^ The header data.
->
ByteString
-- ^ The parent header, which is just "{}" if there is no header.
->
ByteString
-- ^ The parent header, which is just "{}" if there is no header.
...
@@ -32,16 +31,15 @@ parseMessage idents headerData parentHeader metadata content =
...
@@ -32,16 +31,15 @@ parseMessage idents headerData parentHeader metadata content =
messageWithoutHeader
=
parser
messageType
$
Lazy
.
fromStrict
content
messageWithoutHeader
=
parser
messageType
$
Lazy
.
fromStrict
content
in
messageWithoutHeader
{
header
=
header
}
in
messageWithoutHeader
{
header
=
header
}
----- Module internals -----
-- --- Module internals ----- | Parse a header from its ByteString components into a MessageHeader.
-- | Parse a header from its ByteString components into a MessageHeader.
parseHeader
::
[
ByteString
]
-- ^ The list of identifiers.
parseHeader
::
[
ByteString
]
-- ^ The list of identifiers.
->
ByteString
-- ^ The header data.
->
ByteString
-- ^ The header data.
->
ByteString
-- ^ The parent header, or "{}" for Nothing.
->
ByteString
-- ^ The parent header, or "{}" for Nothing.
->
ByteString
-- ^ The metadata, or "{}" for an empty map.
->
ByteString
-- ^ The metadata, or "{}" for an empty map.
->
MessageHeader
-- The resulting message header.
->
MessageHeader
-- The resulting message header.
parseHeader
idents
headerData
parentHeader
metadata
=
parseHeader
idents
headerData
parentHeader
metadata
=
MessageHeader
{
identifiers
=
idents
MessageHeader
{
identifiers
=
idents
,
parentHeader
=
parentResult
,
parentHeader
=
parentResult
,
metadata
=
metadataMap
,
metadata
=
metadataMap
,
messageId
=
messageUUID
,
messageId
=
messageUUID
...
@@ -50,8 +48,8 @@ parseHeader idents headerData parentHeader metadata =
...
@@ -50,8 +48,8 @@ parseHeader idents headerData parentHeader metadata =
,
msgType
=
messageType
,
msgType
=
messageType
}
}
where
where
-- Decode the header data and the parent header data into JSON objects.
-- Decode the header data and the parent header data into JSON objects.
If the parent header data is
--
If the parent header data is
absent, just have Nothing instead.
-- absent, just have Nothing instead.
Just
result
=
decode
$
Lazy
.
fromStrict
headerData
::
Maybe
Object
Just
result
=
decode
$
Lazy
.
fromStrict
headerData
::
Maybe
Object
parentResult
=
if
parentHeader
==
"{}"
parentResult
=
if
parentHeader
==
"{}"
then
Nothing
then
Nothing
...
@@ -71,8 +69,8 @@ noHeader :: MessageHeader
...
@@ -71,8 +69,8 @@ noHeader :: MessageHeader
noHeader
=
error
"No header created"
noHeader
=
error
"No header created"
parser
::
MessageType
-- ^ The message type being parsed.
parser
::
MessageType
-- ^ The message type being parsed.
->
LByteString
->
Message
-- ^ The parser that converts the body into a message.
->
LByteString
->
Message
-- ^ The parser that converts the body into a message.
This message
--
This message
should have an undefined header.
-- should have an undefined header.
parser
KernelInfoRequestMessage
=
kernelInfoRequestParser
parser
KernelInfoRequestMessage
=
kernelInfoRequestParser
parser
ExecuteRequestMessage
=
executeRequestParser
parser
ExecuteRequestMessage
=
executeRequestParser
parser
CompleteRequestMessage
=
completeRequestParser
parser
CompleteRequestMessage
=
completeRequestParser
...
@@ -85,13 +83,12 @@ parser CommCloseMessage = commCloseParser
...
@@ -85,13 +83,12 @@ parser CommCloseMessage = commCloseParser
parser
HistoryRequestMessage
=
historyRequestParser
parser
HistoryRequestMessage
=
historyRequestParser
parser
other
=
error
$
"Unknown message type "
++
show
other
parser
other
=
error
$
"Unknown message type "
++
show
other
-- | Parse a kernel info request.
-- | Parse a kernel info request.
A kernel info request has no auxiliary information, so ignore the
--
A kernel info request has no auxiliary information, so ignore the
body.
-- body.
kernelInfoRequestParser
::
LByteString
->
Message
kernelInfoRequestParser
::
LByteString
->
Message
kernelInfoRequestParser
_
=
KernelInfoRequest
{
header
=
noHeader
}
kernelInfoRequestParser
_
=
KernelInfoRequest
{
header
=
noHeader
}
-- | Parse an execute request.
-- | Parse an execute request. Fields used are:
-- Fields used are:
-- 1. "code": the code to execute.
-- 1. "code": the code to execute.
-- 2. "silent": whether to execute silently.
-- 2. "silent": whether to execute silently.
-- 3. "store_history": whether to include this in history.
-- 3. "store_history": whether to include this in history.
...
@@ -107,7 +104,8 @@ executeRequestParser content =
...
@@ -107,7 +104,8 @@ executeRequestParser content =
return
(
code
,
silent
,
storeHistory
,
allowStdin
)
return
(
code
,
silent
,
storeHistory
,
allowStdin
)
Just
decoded
=
decode
content
Just
decoded
=
decode
content
Success
(
code
,
silent
,
storeHistory
,
allowStdin
)
=
parse
parser
decoded
Success
(
code
,
silent
,
storeHistory
,
allowStdin
)
=
parse
parser
decoded
in
ExecuteRequest
{
header
=
noHeader
in
ExecuteRequest
{
header
=
noHeader
,
getCode
=
code
,
getCode
=
code
,
getSilent
=
silent
,
getSilent
=
silent
,
getAllowStdin
=
allowStdin
,
getAllowStdin
=
allowStdin
...
@@ -147,7 +145,6 @@ objectInfoRequestParser = requestParser $ \obj -> do
...
@@ -147,7 +145,6 @@ objectInfoRequestParser = requestParser $ \obj -> do
dlevel
<-
obj
.:
"detail_level"
dlevel
<-
obj
.:
"detail_level"
return
$
ObjectInfoRequest
noHeader
oname
dlevel
return
$
ObjectInfoRequest
noHeader
oname
dlevel
shutdownRequestParser
::
LByteString
->
Message
shutdownRequestParser
::
LByteString
->
Message
shutdownRequestParser
=
requestParser
$
\
obj
->
do
shutdownRequestParser
=
requestParser
$
\
obj
->
do
code
<-
obj
.:
"restart"
code
<-
obj
.:
"restart"
...
...
ipython-kernel/src/IHaskell/IPython/Message/UUID.hs
View file @
a489c9bb
-- | Description : UUID generator and data structure
-- | Description : UUID generator and data structure
--
--
-- Generate, parse, and pretty print UUIDs for use with IPython.
-- Generate, parse, and pretty print UUIDs for use with IPython.
module
IHaskell.IPython.Message.UUID
(
module
IHaskell.IPython.Message.UUID
(
UUID
,
random
,
randoms
)
where
UUID
,
random
,
randoms
,
)
where
import
Control.Monad
(
mzero
,
replicateM
)
import
Control.Monad
(
mzero
,
replicateM
)
import
Control.Applicative
((
<$>
))
import
Control.Applicative
((
<$>
))
...
@@ -12,15 +9,15 @@ import Data.Text (pack)
...
@@ -12,15 +9,15 @@ import Data.Text (pack)
import
Data.Aeson
import
Data.Aeson
import
Data.UUID.V4
(
nextRandom
)
import
Data.UUID.V4
(
nextRandom
)
-- We use an internal string representation because for the purposes of
-- IPython, it matters whether the letters are uppercase or lowercase and
-- whether the dashes are present in the correct locations. For the
-- purposes of new UUIDs, it does not matter, but IPython expects UUIDs
-- passed to kernels to be returned unchanged, so we cannot actually parse
-- them.
-- | A UUID (universally unique identifier).
-- | A UUID (universally unique identifier).
data
UUID
=
UUID
String
deriving
(
Show
,
Read
,
Eq
,
Ord
)
data
UUID
=
-- We use an internal string representation because for the purposes of IPython, it
-- matters whether the letters are uppercase or lowercase and whether the dashes are
-- present in the correct locations. For the purposes of new UUIDs, it does not matter,
-- but IPython expects UUIDs passed to kernels to be returned unchanged, so we cannot
-- actually parse them.
UUID
String
deriving
(
Show
,
Read
,
Eq
,
Ord
)
-- | Generate a list of random UUIDs.
-- | Generate a list of random UUIDs.
randoms
::
Int
-- ^ Number of UUIDs to generate.
randoms
::
Int
-- ^ Number of UUIDs to generate.
...
...
ipython-kernel/src/IHaskell/IPython/Message/Writer.hs
View file @
a489c9bb
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Description : @ToJSON@ for Messages
-- | Description : @ToJSON@ for Messages
--
--
-- This module contains the @ToJSON@ instance for @Message@.
-- This module contains the @ToJSON@ instance for @Message@.
module
IHaskell.IPython.Message.Writer
(
module
IHaskell.IPython.Message.Writer
(
ToJSON
(
..
))
where
ToJSON
(
..
)
)
where
import
Data.Aeson
import
Data.Aeson
import
Data.Map
(
Map
)
import
Data.Map
(
Map
)
...
@@ -19,99 +18,86 @@ import IHaskell.IPython.Types
...
@@ -19,99 +18,86 @@ import IHaskell.IPython.Types
-- Convert message bodies into JSON.
-- Convert message bodies into JSON.
instance
ToJSON
Message
where
instance
ToJSON
Message
where
toJSON
KernelInfoReply
{
versionList
=
vers
,
language
=
language
}
=
object
[
toJSON
KernelInfoReply
{
versionList
=
vers
,
language
=
language
}
=
"protocol_version"
.=
string
"5.0"
,
-- current protocol version, major and minor
object
[
"protocol_version"
.=
string
"5.0"
-- current protocol version, major and minor
"language_version"
.=
vers
,
,
"language_version"
.=
vers
,
"language"
.=
language
]
"language"
.=
language
]
toJSON
ExecuteReply
{
status
=
status
,
executionCounter
=
counter
,
pagerOutput
=
pager
}
=
object
toJSON
ExecuteReply
{
status
=
status
,
executionCounter
=
counter
,
pagerOutput
=
pager
}
=
object
[
[
"status"
.=
show
status
"status"
.=
show
status
,
,
"execution_count"
.=
counter
"execution_count"
.=
counter
,
,
"payload"
.=
"payload"
.=
if
null
pager
if
null
pager
then
[]
then
[]
else
[
object
[
else
[
object
[
"source"
.=
string
"page"
,
"text"
.=
pager
]]
"source"
.=
string
"page"
,
,
"user_variables"
.=
emptyMap
"text"
.=
pager
,
"user_expressions"
.=
emptyMap
]],
"user_variables"
.=
emptyMap
,
"user_expressions"
.=
emptyMap
]
]
toJSON
PublishStatus
{
executionState
=
executionState
}
=
object
[
toJSON
PublishStatus
{
executionState
=
executionState
}
=
"execution_state"
.=
executionState
object
[
"execution_state"
.=
executionState
]
toJSON
PublishStream
{
streamType
=
streamType
,
streamContent
=
content
}
=
object
[
"data"
.=
content
,
"name"
.=
streamType
]
toJSON
PublishDisplayData
{
source
=
src
,
displayData
=
datas
}
=
object
[
"source"
.=
src
,
"metadata"
.=
object
[]
,
"data"
.=
object
(
map
displayDataToJson
datas
)]
toJSON
PublishOutput
{
executionCount
=
execCount
,
reprText
=
reprText
}
=
object
[
"data"
.=
object
[
"text/plain"
.=
reprText
],
"execution_count"
.=
execCount
,
"metadata"
.=
object
[]
]
toJSON
PublishInput
{
executionCount
=
execCount
,
inCode
=
code
}
=
object
[
"execution_count"
.=
execCount
,
"code"
.=
code
]
toJSON
(
CompleteReply
_
matches
start
end
metadata
status
)
=
object
[
"matches"
.=
matches
,
"cursor_start"
.=
start
,
"cursor_end"
.=
end
,
"metadata"
.=
metadata
,
"status"
.=
if
status
then
string
"ok"
else
"error"
]
]
toJSON
PublishStream
{
streamType
=
streamType
,
streamContent
=
content
}
=
object
[
toJSON
o
@
ObjectInfoReply
{}
=
"data"
.=
content
,
object
"name"
.=
streamType
[
"oname"
.=
]
objectName
o
toJSON
PublishDisplayData
{
source
=
src
,
displayData
=
datas
}
=
object
[
,
"found"
.=
objectFound
o
"source"
.=
src
,
,
"ismagic"
.=
False
"metadata"
.=
object
[]
,
,
"isalias"
.=
False
"data"
.=
object
(
map
displayDataToJson
datas
)
,
"type_name"
.=
objectTypeString
o
,
"docstring"
.=
objectDocString
o
]
]
toJSON
PublishOutput
{
executionCount
=
execCount
,
reprText
=
reprText
}
=
object
[
toJSON
ShutdownReply
{
restartPending
=
restart
}
=
"data"
.=
object
[
"text/plain"
.=
reprText
],
object
[
"restart"
.=
restart
]
"execution_count"
.=
execCount
,
"metadata"
.=
object
[]
]
toJSON
PublishInput
{
executionCount
=
execCount
,
inCode
=
code
}
=
object
[
"execution_count"
.=
execCount
,
"code"
.=
code
]
toJSON
(
CompleteReply
_
matches
start
end
metadata
status
)
=
object
[
"matches"
.=
matches
,
"cursor_start"
.=
start
,
"cursor_end"
.=
end
,
"metadata"
.=
metadata
,
"status"
.=
if
status
then
string
"ok"
else
"error"
]
toJSON
o
@
ObjectInfoReply
{}
=
object
[
"oname"
.=
objectName
o
,
"found"
.=
objectFound
o
,
"ismagic"
.=
False
,
"isalias"
.=
False
,
"type_name"
.=
objectTypeString
o
,
"docstring"
.=
objectDocString
o
]
toJSON
ShutdownReply
{
restartPending
=
restart
}
=
object
[
toJSON
ClearOutput
{
wait
=
wait
}
=
"restart"
.=
restart
object
[
"wait"
.=
wait
]
]
toJSON
ClearOutput
{
wait
=
wait
}
=
object
[
toJSON
RequestInput
{
inputPrompt
=
prompt
}
=
"wait"
.=
wait
object
[
"prompt"
.=
prompt
]
]
toJSON
RequestInput
{
inputPrompt
=
prompt
}
=
object
[
"prompt"
.=
prompt
]
toJSON
req
@
CommOpen
{}
=
object
[
toJSON
req
@
CommOpen
{}
=
"comm_id"
.=
commUuid
req
,
object
[
"comm_id"
.=
commUuid
req
,
"target_name"
.=
commTargetName
req
,
"data"
.=
commData
req
]
"target_name"
.=
commTargetName
req
,
"data"
.=
commData
req
]
toJSON
req
@
CommData
{}
=
object
[
toJSON
req
@
CommData
{}
=
"comm_id"
.=
commUuid
req
,
object
[
"comm_id"
.=
commUuid
req
,
"data"
.=
commData
req
]
"data"
.=
commData
req
]
toJSON
req
@
CommClose
{}
=
object
[
toJSON
req
@
CommClose
{}
=
"comm_id"
.=
commUuid
req
,
object
[
"comm_id"
.=
commUuid
req
,
"data"
.=
commData
req
]
"data"
.=
commData
req
]
toJSON
req
@
HistoryReply
{}
=
object
[
"history"
.=
map
tuplify
(
historyReply
req
)
]
toJSON
req
@
HistoryReply
{}
=
where
tuplify
(
HistoryReplyElement
sess
linum
res
)
=
(
sess
,
linum
,
case
res
of
object
[
"history"
.=
map
tuplify
(
historyReply
req
)]
where
tuplify
(
HistoryReplyElement
sess
linum
res
)
=
(
sess
,
linum
,
case
res
of
Left
inp
->
toJSON
inp
Left
inp
->
toJSON
inp
Right
(
inp
,
out
)
->
toJSON
out
)
Right
(
inp
,
out
)
->
toJSON
out
)
toJSON
body
=
error
$
"Do not know how to convert to JSON for message "
++
show
body
toJSON
body
=
error
$
"Do not know how to convert to JSON for message "
++
show
body
-- | Print an execution state as "busy", "idle", or "starting".
-- | Print an execution state as "busy", "idle", or "starting".
instance
ToJSON
ExecutionState
where
instance
ToJSON
ExecutionState
where
toJSON
Busy
=
String
"busy"
toJSON
Busy
=
String
"busy"
...
@@ -129,7 +115,6 @@ displayDataToJson (DisplayData mimeType dataStr) =
...
@@ -129,7 +115,6 @@ displayDataToJson (DisplayData mimeType dataStr) =
pack
(
show
mimeType
)
.=
String
dataStr
pack
(
show
mimeType
)
.=
String
dataStr
----- Constants -----
----- Constants -----
emptyMap
::
Map
String
String
emptyMap
::
Map
String
String
emptyMap
=
mempty
emptyMap
=
mempty
...
...
ipython-kernel/src/IHaskell/IPython/Stdin.hs
View file @
a489c9bb
{-# LANGUAGE OverloadedStrings, DoAndIfThenElse #-}
{-# LANGUAGE OverloadedStrings, DoAndIfThenElse #-}
-- | This module provides a way in which the Haskell standard input may be
--
forwarded to the IPython frontend and thus allows the notebook to use
--
| This module provides a way in which the Haskell standard input may be forwarded to the IPython
-- the standard input.
--
frontend and thus allows the notebook to use
the standard input.
--
--
-- This relies on the implementation of file handles in GHC, and is
-- This relies on the implementation of file handles in GHC, and is generally unsafe and terrible.
-- generally unsafe and terrible. However, it is difficult to find another
-- However, it is difficult to find another way to do it, as file handles are generally meant to
-- way to do it, as file handles are generally meant to point to streams
-- point to streams and files, and not networked communication protocols.
-- and files, and not networked communication protocols.
--
--
-- In order to use this module, it must first be initialized with two
-- In order to use this module, it must first be initialized with two things. First of all, in order
-- things. First of all, in order to know how to communicate with the
-- to know how to communicate with the IPython frontend, it must know the kernel profile used for
-- IPython frontend, it must know the kernel profile used for
-- communication. For this, use @recordKernelProfile@ once the profile is known. Both this and
-- communication. For this, use @recordKernelProfile@ once the profile is
-- @recordParentHeader@ take a directory name where they can store this data.
-- known. Both this and @recordParentHeader@ take a directory name where
-- they can store this data.
--
--
-- Finally, the module must know what @execute_request@ message is
-- Finally, the module must know what @execute_request@ message is currently being replied to (which
-- currently being replied to (which will request the input). Thus, every
-- will request the input). Thus, every time the language kernel receives an @execute_request@
-- time the language kernel receives an @execute_request@ message, it
-- message, it should inform this module via @recordParentHeader@, so that the module may generate
-- should inform this module via @recordParentHeader@, so that the module
-- messages with an appropriate parent header set. If this is not done, the IPython frontends will
-- may generate messages with an appropriate parent header set. If this is
-- not recognize the target of the communication.
-- not done, the IPython frontends will not recognize the target of the
-- communication.
--
--
-- Finally, in order to activate this module, @fixStdin@ must be called
-- Finally, in order to activate this module, @fixStdin@ must be called once. It must be passed the
-- once. It must be passed the same directory name as @recordParentHeader@
-- same directory name as @recordParentHeader@ and @recordKernelProfile@. Note that if this is being
-- and @recordKernelProfile@. Note that if this is being used from within
-- used from within the GHC API, @fixStdin@ /must/ be called from within the GHC session not from
-- the GHC API, @fixStdin@ /must/ be called from within the GHC session
-- the host code.
-- not from the host code.
module
IHaskell.IPython.Stdin
(
fixStdin
,
recordParentHeader
,
recordKernelProfile
)
where
module
IHaskell.IPython.Stdin
(
fixStdin
,
recordParentHeader
,
recordKernelProfile
)
where
import
Control.Concurrent
import
Control.Concurrent
import
Control.Applicative
((
<$>
))
import
Control.Applicative
((
<$>
))
...
@@ -53,9 +43,8 @@ stdinInterface :: MVar ZeroMQStdin
...
@@ -53,9 +43,8 @@ stdinInterface :: MVar ZeroMQStdin
{-# NOINLINE stdinInterface #-}
{-# NOINLINE stdinInterface #-}
stdinInterface
=
unsafePerformIO
newEmptyMVar
stdinInterface
=
unsafePerformIO
newEmptyMVar
-- | Manipulate standard input so that it is sourced from the IPython
-- | Manipulate standard input so that it is sourced from the IPython frontend. This function is
-- frontend. This function is build on layers of deep magical hackery, so
-- build on layers of deep magical hackery, so be careful modifying it.
-- be careful modifying it.
fixStdin
::
String
->
IO
()
fixStdin
::
String
->
IO
()
fixStdin
dir
=
do
fixStdin
dir
=
do
-- Initialize the stdin interface.
-- Initialize the stdin interface.
...
@@ -78,6 +67,7 @@ stdinOnce dir = do
...
@@ -78,6 +67,7 @@ stdinOnce dir = do
hDuplicateTo
newStdin
stdin
hDuplicateTo
newStdin
stdin
loop
stdinInput
oldStdin
newStdin
loop
stdinInput
oldStdin
newStdin
where
where
loop
stdinInput
oldStdin
newStdin
=
do
loop
stdinInput
oldStdin
newStdin
=
do
let
FileHandle
_
mvar
=
stdin
let
FileHandle
_
mvar
=
stdin
...
@@ -98,14 +88,14 @@ getInputLine dir = do
...
@@ -98,14 +88,14 @@ getInputLine dir = do
-- Send a request for input.
-- Send a request for input.
uuid
<-
UUID
.
random
uuid
<-
UUID
.
random
parentHeader
<-
read
<$>
readFile
(
dir
++
"/.last-req-header"
)
parentHeader
<-
read
<$>
readFile
(
dir
++
"/.last-req-header"
)
let
header
=
MessageHeader
{
let
header
=
MessageHeader
username
=
username
parentHeader
,
{
username
=
username
parentHeader
identifiers
=
identifiers
parentHeader
,
,
identifiers
=
identifiers
parentHeader
parentHeader
=
Just
parentHeader
,
,
parentHeader
=
Just
parentHeader
messageId
=
uuid
,
,
messageId
=
uuid
sessionId
=
sessionId
parentHeader
,
,
sessionId
=
sessionId
parentHeader
metadata
=
Map
.
fromList
[]
,
,
metadata
=
Map
.
fromList
[]
msgType
=
InputRequestMessage
,
msgType
=
InputRequestMessage
}
}
let
msg
=
RequestInput
header
""
let
msg
=
RequestInput
header
""
writeChan
req
msg
writeChan
req
msg
...
...
ipython-kernel/src/IHaskell/IPython/Types.hs
View file @
a489c9bb
{-# LANGUAGE OverloadedStrings, DeriveDataTypeable, DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings, DeriveDataTypeable, DeriveGeneric #-}
-- | This module contains all types used to create an IPython language
-- kernel.
--
| This module contains all types used to create an IPython language
kernel.
module
IHaskell.IPython.Types
(
module
IHaskell.IPython.Types
(
-- * IPython kernel profile
-- * IPython kernel profile
Profile
(
..
),
Profile
(
..
),
...
@@ -17,7 +17,8 @@ module IHaskell.IPython.Types (
...
@@ -17,7 +17,8 @@ module IHaskell.IPython.Types (
Username
(
..
),
Username
(
..
),
Metadata
(
..
),
Metadata
(
..
),
MessageType
(
..
),
MessageType
(
..
),
Width
(
..
),
Height
(
..
),
Width
(
..
),
Height
(
..
),
StreamType
(
..
),
StreamType
(
..
),
ExecutionState
(
..
),
ExecutionState
(
..
),
ExecuteReplyStatus
(
..
),
ExecuteReplyStatus
(
..
),
...
@@ -28,8 +29,7 @@ module IHaskell.IPython.Types (
...
@@ -28,8 +29,7 @@ module IHaskell.IPython.Types (
-- ** IPython display data message
-- ** IPython display data message
DisplayData
(
..
),
DisplayData
(
..
),
MimeType
(
..
),
MimeType
(
..
),
extractPlain
extractPlain
,
)
where
)
where
import
Data.Aeson
import
Data.Aeson
...
@@ -45,7 +45,8 @@ import Data.Typeable
...
@@ -45,7 +45,8 @@ import Data.Typeable
import
Data.List
(
find
)
import
Data.List
(
find
)
import
Data.Map
(
Map
)
import
Data.Map
(
Map
)
-------------------- IPython Kernel Profile Types ----------------------
------------------ IPython Kernel Profile Types ----------------------
--
-- | A TCP port.
-- | A TCP port.
type
Port
=
Int
type
Port
=
Int
...
@@ -57,7 +58,9 @@ data Transport = TCP -- ^ Default transport mechanism via TCP.
...
@@ -57,7 +58,9 @@ data Transport = TCP -- ^ Default transport mechanism via TCP.
deriving
(
Show
,
Read
)
deriving
(
Show
,
Read
)
-- | A kernel profile, specifying how the kernel communicates.
-- | A kernel profile, specifying how the kernel communicates.
data
Profile
=
Profile
{
ip
::
IP
-- ^ The IP on which to listen.
data
Profile
=
Profile
{
ip
::
IP
-- ^ The IP on which to listen.
,
transport
::
Transport
-- ^ The transport mechanism.
,
transport
::
Transport
-- ^ The transport mechanism.
,
stdinPort
::
Port
-- ^ The stdin channel port.
,
stdinPort
::
Port
-- ^ The stdin channel port.
,
controlPort
::
Port
-- ^ The control channel port.
,
controlPort
::
Port
-- ^ The control channel port.
...
@@ -107,15 +110,19 @@ instance FromJSON Transport where
...
@@ -107,15 +110,19 @@ instance FromJSON Transport where
instance
ToJSON
Transport
where
instance
ToJSON
Transport
where
toJSON
TCP
=
String
"tcp"
toJSON
TCP
=
String
"tcp"
-------------------- IPython Kernelspec Types ----------------------
-------------------- IPython Kernelspec Types ----------------------
data
KernelSpec
=
KernelSpec
{
data
KernelSpec
=
kernelDisplayName
::
String
,
-- ^ Name shown to users to describe this kernel (e.g. "Haskell")
KernelSpec
kernelLanguage
::
String
,
-- ^ Name for the kernel; unique kernel identifier (e.g. "haskell")
{
kernelCommand
::
[
String
]
-- ^ Command to run to start the kernel. One of the strings may be
-- | Name shown to users to describe this kernel (e.g. "Haskell")
-- @"{connection_file}"@, which will be replaced by the path to a
kernelDisplayName
::
String
-- kernel profile file (see @Profile@) when the command is run.
-- | Name for the kernel; unique kernel identifier (e.g. "haskell")
}
deriving
(
Eq
,
Show
)
,
kernelLanguage
::
String
-- | Command to run to start the kernel. One of the strings maybe @"{connection_file}"@, which will
-- be replaced by the path to a kernel profile file (see @Profile@) when the command is run.
,
kernelCommand
::
[
String
]
}
deriving
(
Eq
,
Show
)
instance
ToJSON
KernelSpec
where
instance
ToJSON
KernelSpec
where
toJSON
kernelspec
=
object
toJSON
kernelspec
=
object
...
@@ -124,28 +131,30 @@ instance ToJSON KernelSpec where
...
@@ -124,28 +131,30 @@ instance ToJSON KernelSpec where
,
"language"
.=
kernelLanguage
kernelspec
,
"language"
.=
kernelLanguage
kernelspec
]
]
------------------
-- IPython Message Types --
--------------------
------------------
IPython Message Types
--------------------
--
-- | A message header with some metadata.
-- | A message header with some metadata.
data
MessageHeader
=
MessageHeader
{
data
MessageHeader
=
identifiers
::
[
ByteString
],
-- ^ The identifiers sent with the message.
MessageHeader
parentHeader
::
Maybe
MessageHeader
,
-- ^ The parent header, if present.
{
identifiers
::
[
ByteString
]
-- ^ The identifiers sent with the message.
metadata
::
Metadata
,
-- ^ A dict of metadata.
,
parentHeader
::
Maybe
MessageHeader
-- ^ The parent header, if present.
messageId
::
UUID
,
-- ^ A unique message UUID.
,
metadata
::
Metadata
-- ^ A dict of metadata.
sessionId
::
UUID
,
-- ^ A unique session UUID.
,
messageId
::
UUID
-- ^ A unique message UUID.
username
::
Username
,
-- ^ The user who sent this message.
,
sessionId
::
UUID
-- ^ A unique session UUID.
msgType
::
MessageType
-- ^ The message type.
,
username
::
Username
-- ^ The user who sent this message.
}
deriving
(
Show
,
Read
)
,
msgType
::
MessageType
-- ^ The message type.
}
-- Convert a message header into the JSON field for the header.
deriving
(
Show
,
Read
)
-- This field does not actually have all the record fields.
-- Convert a message header into the JSON field for the header. This field does not actually have
-- all the record fields.
instance
ToJSON
MessageHeader
where
instance
ToJSON
MessageHeader
where
toJSON
header
=
object
[
toJSON
header
=
object
"msg_id"
.=
messageId
header
,
[
"msg_id"
.=
messageId
header
"session"
.=
sessionId
header
,
,
"session"
.=
sessionId
header
"username"
.=
username
header
,
,
"username"
.=
username
header
"version"
.=
(
"5.0"
::
String
),
,
"version"
.=
(
"5.0"
::
String
)
"msg_type"
.=
showMessageType
(
msgType
header
)
,
"msg_type"
.=
showMessageType
(
msgType
header
)
]
]
-- | A username for the source of a message.
-- | A username for the source of a message.
...
@@ -235,177 +244,161 @@ instance FromJSON MessageType where
...
@@ -235,177 +244,161 @@ instance FromJSON MessageType where
_
->
fail
(
"Unknown message type: "
++
show
s
)
_
->
fail
(
"Unknown message type: "
++
show
s
)
parseJSON
_
=
fail
"Must be a string."
parseJSON
_
=
fail
"Must be a string."
-- | A message used to communicate with the IPython frontend.
-- | A message used to communicate with the IPython frontend.
data
Message
data
Message
=
-- | A request from a frontend for information about the kernel.
-- | A request from a frontend for information about the kernel.
=
KernelInfoRequest
{
header
::
MessageHeader
}
KernelInfoRequest
{
header
::
MessageHeader
}
|
-- | A response to a KernelInfoRequest.
-- | A response to a KernelInfoRequest.
|
KernelInfoReply
{
KernelInfoReply
header
::
MessageHeader
,
{
header
::
MessageHeader
versionList
::
[
Int
],
-- ^ The version of the language, e.g. [7, 6, 3] for GHC 7.6.3
,
versionList
::
[
Int
]
-- ^ The version of the language, e.g. [7, 6, 3] for GHC
language
::
String
-- ^ The language name, e.g. "haskell"
-- 7.6.3
,
language
::
String
-- ^ The language name, e.g. "haskell"
}
}
|
-- | A request from a frontend to execute some code.
-- | A request from a frontend to execute some code.
|
ExecuteRequest
{
ExecuteRequest
header
::
MessageHeader
,
{
header
::
MessageHeader
getCode
::
Text
,
-- ^ The code string.
,
getCode
::
Text
-- ^ The code string.
getSilent
::
Bool
,
-- ^ Whether this should be silently executed.
,
getSilent
::
Bool
-- ^ Whether this should be silently executed.
getStoreHistory
::
Bool
,
-- ^ Whether to store this in history.
,
getStoreHistory
::
Bool
-- ^ Whether to store this in history.
getAllowStdin
::
Bool
,
-- ^ Whether this code can use stdin.
,
getAllowStdin
::
Bool
-- ^ Whether this code can use stdin.
,
getUserVariables
::
[
Text
]
-- ^ Unused.
getUserVariables
::
[
Text
],
-- ^ Unused.
,
getUserExpressions
::
[
Text
]
-- ^ Unused.
getUserExpressions
::
[
Text
]
-- ^ Unused.
}
}
|
-- | A reply to an execute request.
-- | A reply to an execute request.
|
ExecuteReply
{
ExecuteReply
header
::
MessageHeader
,
{
header
::
MessageHeader
status
::
ExecuteReplyStatus
,
-- ^ The status of the output.
,
status
::
ExecuteReplyStatus
-- ^ The status of the output.
pagerOutput
::
String
,
-- ^ The help string to show in the pager.
,
pagerOutput
::
String
-- ^ The help string to show in the pager.
executionCounter
::
Int
-- ^ The execution count, i.e. which output this is.
,
executionCounter
::
Int
-- ^ The execution count, i.e. which output this is.
}
}
|
|
PublishStatus
{
PublishStatus
header
::
MessageHeader
,
{
header
::
MessageHeader
executionState
::
ExecutionState
-- ^ The execution state of the kernel.
,
executionState
::
ExecutionState
-- ^ The execution state of the kernel.
}
}
|
|
PublishStream
{
PublishStream
header
::
MessageHeader
,
{
header
::
MessageHeader
streamType
::
StreamType
,
-- ^ Which stream to publish to.
,
streamType
::
StreamType
-- ^ Which stream to publish to.
streamContent
::
String
-- ^ What to publish.
,
streamContent
::
String
-- ^ What to publish.
}
}
|
|
PublishDisplayData
{
PublishDisplayData
header
::
MessageHeader
,
{
header
::
MessageHeader
source
::
String
,
-- ^ The name of the data source.
,
source
::
String
-- ^ The name of the data source.
displayData
::
[
DisplayData
]
-- ^ A list of data representations.
,
displayData
::
[
DisplayData
]
-- ^ A list of data representations.
}
}
|
|
PublishOutput
{
PublishOutput
header
::
MessageHeader
,
{
header
::
MessageHeader
reprText
::
String
,
-- ^ Printed output text.
,
reprText
::
String
-- ^ Printed output text.
executionCount
::
Int
-- ^ Which output this is for.
,
executionCount
::
Int
-- ^ Which output this is for.
}
}
|
|
PublishInput
{
PublishInput
header
::
MessageHeader
,
{
header
::
MessageHeader
inCode
::
String
,
-- ^ Submitted input code.
,
inCode
::
String
-- ^ Submitted input code.
executionCount
::
Int
-- ^ Which input this is.
,
executionCount
::
Int
-- ^ Which input this is.
}
}
|
|
CompleteRequest
{
CompleteRequest
header
::
MessageHeader
,
{
header
::
MessageHeader
getCode
::
Text
,
{- ^
,
getCode
::
Text
{- ^
The entire block of text where the line is. This may be useful in the
The entire block of text where the line is. This may be useful in the
case of multiline completions where more context may be needed. Note: if
case of multiline completions where more context may be needed. Note: if
in practice this field proves unnecessary, remove it to lighten the
in practice this field proves unnecessary, remove it to lighten the
messages. json field @code@ -}
messages. json field @code@ -}
getCursorPos
::
Int
-- ^ Position of the cursor in unicode characters. json field @cursor_pos@
,
getCursorPos
::
Int
-- ^ Position of the cursor in unicode characters. json field
-- @cursor_pos@
}
}
|
|
CompleteReply
{
CompleteReply
header
::
MessageHeader
,
{
header
::
MessageHeader
completionMatches
::
[
Text
],
,
completionMatches
::
[
Text
]
completionCursorStart
::
Int
,
,
completionCursorStart
::
Int
completionCursorEnd
::
Int
,
,
completionCursorEnd
::
Int
completionMetadata
::
Metadata
,
,
completionMetadata
::
Metadata
completionStatus
::
Bool
,
completionStatus
::
Bool
}
}
|
|
ObjectInfoRequest
{
ObjectInfoRequest
header
::
MessageHeader
,
{
header
::
MessageHeader
objectName
::
Text
,
-- ^
Name of object being searched for.
-- |
Name of object being searched for.
detailLevel
::
Int
-- ^ Level of detail desired (defaults to 0).
,
objectName
::
Text
-- 0 is equivalent to foo?, 1 is equivalent
-- | Level of detail desired (defaults to 0). 0 is equivalent to foo?, 1 is equivalent to foo??.
-- to foo??.
,
detailLevel
::
Int
}
}
|
|
ObjectInfoReply
{
ObjectInfoReply
header
::
MessageHeader
,
{
header
::
MessageHeader
objectName
::
Text
,
-- ^ Name of object which was searched for.
,
objectName
::
Text
-- ^ Name of object which was searched for.
objectFound
::
Bool
,
-- ^ Whether the object was found.
,
objectFound
::
Bool
-- ^ Whether the object was found.
objectTypeString
::
Text
,
-- ^ Object type.
,
objectTypeString
::
Text
-- ^ Object type.
objectDocString
::
Text
,
objectDocString
::
Text
}
}
|
|
ShutdownRequest
{
ShutdownRequest
header
::
MessageHeader
,
{
header
::
MessageHeader
restartPending
::
Bool
-- ^ Whether this shutdown precedes a restart.
,
restartPending
::
Bool
-- ^ Whether this shutdown precedes a restart.
}
|
ShutdownReply
{
header
::
MessageHeader
,
restartPending
::
Bool
-- ^ Whether this shutdown precedes a restart.
}
}
|
|
ClearOutput
{
ShutdownReply
header
::
MessageHeader
,
{
header
::
MessageHeader
wait
::
Bool
-- ^ Whether to wait to redraw until there is more outpu
t.
,
restartPending
::
Bool
-- ^ Whether this shutdown precedes a restar
t.
}
}
|
|
RequestInput
{
ClearOutput
header
::
MessageHeader
,
{
header
::
MessageHeader
inputPrompt
::
String
,
wait
::
Bool
-- ^ Whether to wait to redraw until there is more output.
}
}
|
RequestInput
{
header
::
MessageHeader
,
inputPrompt
::
String
}
|
InputReply
{
|
InputReply
{
header
::
MessageHeader
,
inputValue
::
String
}
header
::
MessageHeader
,
|
inputValue
::
String
CommOpen
{
header
::
MessageHeader
,
commTargetName
::
String
,
commUuid
::
UUID
,
commData
::
Value
}
}
|
CommData
{
header
::
MessageHeader
,
commUuid
::
UUID
,
commData
::
Value
}
|
CommOpen
{
|
CommClose
{
header
::
MessageHeader
,
commUuid
::
UUID
,
commData
::
Value
}
header
::
MessageHeader
,
|
commTargetName
::
String
,
HistoryRequest
commUuid
::
UUID
,
{
header
::
MessageHeader
commData
::
Value
,
historyGetOutput
::
Bool
-- ^ If True, also return output history in the resulting
-- dict.
,
historyRaw
::
Bool
-- ^ If True, return the raw input history, else the
-- transformed input.
,
historyAccessType
::
HistoryAccessType
-- ^ What history is being requested.
}
}
|
HistoryReply
{
header
::
MessageHeader
,
historyReply
::
[
HistoryReplyElement
]
}
|
CommData
{
header
::
MessageHeader
,
commUuid
::
UUID
,
commData
::
Value
}
|
CommClose
{
header
::
MessageHeader
,
commUuid
::
UUID
,
commData
::
Value
}
|
HistoryRequest
{
header
::
MessageHeader
,
historyGetOutput
::
Bool
,
-- ^ If True, also return output history in the resulting dict.
historyRaw
::
Bool
,
-- ^ If True, return the raw input history, else the transformed input.
historyAccessType
::
HistoryAccessType
-- ^ What history is being requested.
}
|
HistoryReply
{
header
::
MessageHeader
,
historyReply
::
[
HistoryReplyElement
]
}
|
SendNothing
-- Dummy message; nothing is sent.
|
SendNothing
-- Dummy message; nothing is sent.
deriving
Show
deriving
Show
-- | Ways in which the frontend can request history.
-- | Ways in which the frontend can request history.
TODO: Implement fields as described in
--
TODO: Implement fields as described in
messaging spec.
-- messaging spec.
data
HistoryAccessType
=
HistoryRange
data
HistoryAccessType
=
HistoryRange
|
HistoryTail
|
HistoryTail
|
HistorySearch
|
HistorySearch
deriving
(
Eq
,
Show
)
deriving
(
Eq
,
Show
)
-- | Reply to history requests.
-- | Reply to history requests.
data
HistoryReplyElement
=
HistoryReplyElement
{
historyReplySession
::
Int
data
HistoryReplyElement
=
HistoryReplyElement
{
historyReplySession
::
Int
,
historyReplyLineNumber
::
Int
,
historyReplyLineNumber
::
Int
,
historyReplyContent
::
Either
String
(
String
,
String
)
,
historyReplyContent
::
Either
String
(
String
,
String
)
}
}
deriving
(
Eq
,
Show
)
deriving
(
Eq
,
Show
)
-- | Possible statuses in the execution reply messages.
-- | Possible statuses in the execution reply messages.
data
ExecuteReplyStatus
=
Ok
|
Err
|
Abort
data
ExecuteReplyStatus
=
Ok
|
Err
|
Abort
instance
Show
ExecuteReplyStatus
where
instance
Show
ExecuteReplyStatus
where
show
Ok
=
"ok"
show
Ok
=
"ok"
...
@@ -413,10 +406,15 @@ instance Show ExecuteReplyStatus where
...
@@ -413,10 +406,15 @@ instance Show ExecuteReplyStatus where
show
Abort
=
"abort"
show
Abort
=
"abort"
-- | The execution state of the kernel.
-- | The execution state of the kernel.
data
ExecutionState
=
Busy
|
Idle
|
Starting
deriving
Show
data
ExecutionState
=
Busy
|
Idle
|
Starting
deriving
Show
-- | Input and output streams.
-- | Input and output streams.
data
StreamType
=
Stdin
|
Stdout
deriving
Show
data
StreamType
=
Stdin
|
Stdout
deriving
Show
-- | Get the reply message type for a request message type.
-- | Get the reply message type for a request message type.
replyType
::
MessageType
->
Maybe
MessageType
replyType
::
MessageType
->
Maybe
MessageType
...
@@ -429,11 +427,11 @@ replyType HistoryRequestMessage = Just HistoryReplyMessage
...
@@ -429,11 +427,11 @@ replyType HistoryRequestMessage = Just HistoryReplyMessage
replyType
_
=
Nothing
replyType
_
=
Nothing
-- | Data for display: a string with associated MIME type.
-- | Data for display: a string with associated MIME type.
data
DisplayData
=
DisplayData
MimeType
Text
deriving
(
Typeable
,
Generic
)
data
DisplayData
=
DisplayData
MimeType
Text
deriving
(
Typeable
,
Generic
)
-- We can't print the actual data, otherwise this will be printed every
-- We can't print the actual data, otherwise this will be printed every time it gets computed
-- time it gets computed because of the way the evaluator is structured.
-- because of the way the evaluator is structured. See how `displayExpr` is computed.
-- See how `displayExpr` is computed.
instance
Show
DisplayData
where
instance
Show
DisplayData
where
show
_
=
"DisplayData"
show
_
=
"DisplayData"
...
@@ -441,12 +439,16 @@ instance Show DisplayData where
...
@@ -441,12 +439,16 @@ instance Show DisplayData where
instance
Serialize
Text
where
instance
Serialize
Text
where
put
str
=
put
(
Text
.
encodeUtf8
str
)
put
str
=
put
(
Text
.
encodeUtf8
str
)
get
=
Text
.
decodeUtf8
<$>
get
get
=
Text
.
decodeUtf8
<$>
get
instance
Serialize
DisplayData
instance
Serialize
DisplayData
instance
Serialize
MimeType
instance
Serialize
MimeType
-- | Possible MIME types for the display data.
-- | Possible MIME types for the display data.
type
Width
=
Int
type
Width
=
Int
type
Height
=
Int
type
Height
=
Int
data
MimeType
=
PlainText
data
MimeType
=
PlainText
|
MimeHtml
|
MimeHtml
|
MimePng
Width
Height
|
MimePng
Width
Height
...
...
ipython-kernel/src/IHaskell/IPython/ZeroMQ.hs
View file @
a489c9bb
{-# LANGUAGE OverloadedStrings, DoAndIfThenElse #-}
{-# LANGUAGE OverloadedStrings, DoAndIfThenElse #-}
-- | Description : Low-level ZeroMQ communication wrapper.
-- | Description : Low-level ZeroMQ communication wrapper.
--
--
-- The "ZeroMQ" module abstracts away the low-level 0MQ based interface with IPython,
-- The "ZeroMQ" module abstracts away the low-level 0MQ based interface with IPython, replacing it
-- replacing it instead with a Haskell Channel based interface. The `serveProfile` function
-- instead with a Haskell Channel based interface. The `serveProfile` function takes a IPython
-- takes a IPython profile specification and returns the channel interface to use.
-- profile specification and returns the channel interface to use.
module
IHaskell.IPython.ZeroMQ
(
module
IHaskell.IPython.ZeroMQ
(
ZeroMQInterface
(
..
),
ZeroMQStdin
(
..
),
serveProfile
,
serveStdin
)
where
ZeroMQInterface
(
..
),
ZeroMQStdin
(
..
),
serveProfile
,
serveStdin
,
)
where
import
qualified
Data.ByteString.Lazy
as
LBS
import
qualified
Data.ByteString.Lazy
as
LBS
import
Data.ByteString
(
ByteString
)
import
Data.ByteString
(
ByteString
)
...
@@ -26,30 +22,37 @@ import IHaskell.IPython.Types
...
@@ -26,30 +22,37 @@ import IHaskell.IPython.Types
import
IHaskell.IPython.Message.Parser
import
IHaskell.IPython.Message.Parser
import
IHaskell.IPython.Message.Writer
import
IHaskell.IPython.Message.Writer
-- | The channel interface to the ZeroMQ sockets. All communication is done via
-- | The channel interface to the ZeroMQ sockets. All communication is done via Messages, which are
-- Messages, which are encoded and decoded into a lower level form before being
-- encoded and decoded into a lower level form before being transmitted to IPython. These channels
-- transmitted to IPython. These channels should functionally serve as
-- should functionally serve as high-level sockets which speak Messages instead of ByteStrings.
-- high-level sockets which speak Messages instead of ByteStrings.
data
ZeroMQInterface
=
data
ZeroMQInterface
=
Channels
{
Channels
shellRequestChannel
::
Chan
Message
,
-- ^ A channel populated with requests from the frontend.
{
shellReplyChannel
::
Chan
Message
,
-- ^ Writing to this channel causes a reply to be sent to the frontend.
-- | A channel populated with requests from the frontend.
controlRequestChannel
::
Chan
Message
,
-- ^ This channel is a duplicate of the shell request channel,
shellRequestChannel
::
Chan
Message
-- though using a different backend socket.
-- | Writing to this channel causes a reply to be sent to the frontend.
controlReplyChannel
::
Chan
Message
,
-- ^ This channel is a duplicate of the shell reply channel,
,
shellReplyChannel
::
Chan
Message
-- though using a different backend socket.
-- | This channel is a duplicate of the shell request channel, though using a different backend
iopubChannel
::
Chan
Message
,
-- ^ Writing to this channel sends an iopub message to the frontend.
-- socket.
hmacKey
::
ByteString
-- ^ Key used to sign messages.
,
controlRequestChannel
::
Chan
Message
-- | This channel is a duplicate of the shell reply channel, though using a different backend
-- socket.
,
controlReplyChannel
::
Chan
Message
-- | Writing to this channel sends an iopub message to the frontend.
,
iopubChannel
::
Chan
Message
-- | Key used to sign messages.
,
hmacKey
::
ByteString
}
}
data
ZeroMQStdin
=
StdinChannel
{
data
ZeroMQStdin
=
stdinRequestChannel
::
Chan
Message
,
StdinChannel
stdinReplyChannel
::
Chan
Message
{
stdinRequestChannel
::
Chan
Message
,
stdinReplyChannel
::
Chan
Message
}
}
-- | Start responding on all ZeroMQ channels used to communicate with IPython
-- | Start responding on all ZeroMQ channels used to communicate with IPython
| via the provided
--
| via the provided profile. Return a set of channels which can be used to
--
profile. Return a set of channels which can be used to | communicate with IPython in a more
--
| communicate with IPython in a more structured manner.
--
structured manner.
serveProfile
::
Profile
-- ^ The profile specifying which ports and transport mechanisms to use.
serveProfile
::
Profile
-- ^ The profile specifying which ports and transport mechanisms to use.
->
Bool
-- ^ Print debug output
->
Bool
-- ^ Print debug output
->
IO
ZeroMQInterface
-- ^ The Message-channel based interface to the sockets.
->
IO
ZeroMQInterface
-- ^ The Message-channel based interface to the sockets.
...
@@ -63,18 +66,17 @@ serveProfile profile debug = do
...
@@ -63,18 +66,17 @@ serveProfile profile debug = do
let
channels
=
Channels
shellReqChan
shellRepChan
controlReqChan
controlRepChan
iopubChan
let
channels
=
Channels
shellReqChan
shellRepChan
controlReqChan
controlRepChan
iopubChan
(
signatureKey
profile
)
(
signatureKey
profile
)
-- Create the context in a separate thread that never finishes. If
-- Create the context in a separate thread that never finishes. If
withContext or withSocket
--
withContext or withSocket
complete, the context or socket become invalid.
-- complete, the context or socket become invalid.
forkIO
$
withContext
$
\
context
->
do
forkIO
$
withContext
$
\
context
->
do
-- Serve on all sockets.
-- Serve on all sockets.
forkIO
$
serveSocket
context
Rep
(
hbPort
profile
)
$
heartbeat
channels
forkIO
$
serveSocket
context
Rep
(
hbPort
profile
)
$
heartbeat
channels
forkIO
$
serveSocket
context
Router
(
controlPort
profile
)
$
control
debug
channels
forkIO
$
serveSocket
context
Router
(
controlPort
profile
)
$
control
debug
channels
forkIO
$
serveSocket
context
Router
(
shellPort
profile
)
$
shell
debug
channels
forkIO
$
serveSocket
context
Router
(
shellPort
profile
)
$
shell
debug
channels
-- The context is reference counted in this thread only. Thus, the last
-- The context is reference counted in this thread only. Thus, the last serveSocket cannot be
-- serveSocket cannot be asynchronous, because otherwise context would
-- asynchronous, because otherwise context would be garbage collectable - since it would only be
-- be garbage collectable - since it would only be used in other
-- used in other threads. Thus, keep the last serveSocket in this thread.
-- threads. Thus, keep the last serveSocket in this thread.
serveSocket
context
Pub
(
iopubPort
profile
)
$
iopub
debug
channels
serveSocket
context
Pub
(
iopubPort
profile
)
$
iopub
debug
channels
return
channels
return
channels
...
@@ -84,8 +86,8 @@ serveStdin profile = do
...
@@ -84,8 +86,8 @@ serveStdin profile = do
reqChannel
<-
newChan
reqChannel
<-
newChan
repChannel
<-
newChan
repChannel
<-
newChan
-- Create the context in a separate thread that never finishes. If
-- Create the context in a separate thread that never finishes. If
withContext or withSocket
--
withContext or withSocket
complete, the context or socket become invalid.
-- complete, the context or socket become invalid.
forkIO
$
withContext
$
\
context
->
forkIO
$
withContext
$
\
context
->
-- Serve on all sockets.
-- Serve on all sockets.
serveSocket
context
Router
(
stdinPort
profile
)
$
\
socket
->
do
serveSocket
context
Router
(
stdinPort
profile
)
$
\
socket
->
do
...
@@ -97,9 +99,8 @@ serveStdin profile = do
...
@@ -97,9 +99,8 @@ serveStdin profile = do
return
$
StdinChannel
reqChannel
repChannel
return
$
StdinChannel
reqChannel
repChannel
-- | Serve on a given socket in a separate thread. Bind the socket in the
-- | Serve on a given socket in a separate thread. Bind the socket in the | given context and then
-- | given context and then loop the provided action, which should listen
-- loop the provided action, which should listen | on the socket and respond to any events.
-- | on the socket and respond to any events.
serveSocket
::
SocketType
a
=>
Context
->
a
->
Port
->
(
Socket
a
->
IO
b
)
->
IO
()
serveSocket
::
SocketType
a
=>
Context
->
a
->
Port
->
(
Socket
a
->
IO
b
)
->
IO
()
serveSocket
context
socketType
port
action
=
void
$
serveSocket
context
socketType
port
action
=
void
$
withSocket
context
socketType
$
\
socket
->
do
withSocket
context
socketType
$
\
socket
->
do
...
@@ -115,9 +116,9 @@ heartbeat _ socket = do
...
@@ -115,9 +116,9 @@ heartbeat _ socket = do
-- Send it back.
-- Send it back.
send
socket
[]
request
send
socket
[]
request
-- | Listener on the shell port. Reads messages and writes them to
-- | Listener on the shell port. Reads messages and writes them to
| the shell request channel. For
--
| the shell request channel. For each message, reads a response from the
--
each message, reads a response from the | shell reply channel of the interface and sends it back
--
| shell reply channel of the interface and sends it back to the frontend.
--
to the frontend.
shell
::
Bool
->
ZeroMQInterface
->
Socket
Router
->
IO
()
shell
::
Bool
->
ZeroMQInterface
->
Socket
Router
->
IO
()
shell
debug
channels
socket
=
do
shell
debug
channels
socket
=
do
-- Receive a message and write it to the interface channel.
-- Receive a message and write it to the interface channel.
...
@@ -130,9 +131,9 @@ shell debug channels socket = do
...
@@ -130,9 +131,9 @@ shell debug channels socket = do
requestChannel
=
shellRequestChannel
channels
requestChannel
=
shellRequestChannel
channels
replyChannel
=
shellReplyChannel
channels
replyChannel
=
shellReplyChannel
channels
-- | Listener on the shell port. Reads messages and writes them to
-- | Listener on the shell port. Reads messages and writes them to
| the shell request channel. For
--
| the shell request channel. For each message, reads a response from the
--
each message, reads a response from the | shell reply channel of the interface and sends it back
--
| shell reply channel of the interface and sends it back to the frontend.
--
to the frontend.
control
::
Bool
->
ZeroMQInterface
->
Socket
Router
->
IO
()
control
::
Bool
->
ZeroMQInterface
->
Socket
Router
->
IO
()
control
debug
channels
socket
=
do
control
debug
channels
socket
=
do
-- Receive a message and write it to the interface channel.
-- Receive a message and write it to the interface channel.
...
@@ -145,9 +146,8 @@ control debug channels socket = do
...
@@ -145,9 +146,8 @@ control debug channels socket = do
requestChannel
=
controlRequestChannel
channels
requestChannel
=
controlRequestChannel
channels
replyChannel
=
controlReplyChannel
channels
replyChannel
=
controlReplyChannel
channels
-- | Send messages via the iopub channel.
-- | Send messages via the iopub channel. | This reads messages from the ZeroMQ iopub interface
-- | This reads messages from the ZeroMQ iopub interface channel
-- channel | and then writes the messages to the socket.
-- | and then writes the messages to the socket.
iopub
::
Bool
->
ZeroMQInterface
->
Socket
Pub
->
IO
()
iopub
::
Bool
->
ZeroMQInterface
->
Socket
Pub
->
IO
()
iopub
debug
channels
socket
=
iopub
debug
channels
socket
=
readChan
(
iopubChannel
channels
)
>>=
sendMessage
debug
(
hmacKey
channels
)
socket
readChan
(
iopubChannel
channels
)
>>=
sendMessage
debug
(
hmacKey
channels
)
socket
...
@@ -179,8 +179,8 @@ receiveMessage debug socket = do
...
@@ -179,8 +179,8 @@ receiveMessage debug socket = do
-- Receive the next piece of data from the socket.
-- Receive the next piece of data from the socket.
next
=
receive
socket
next
=
receive
socket
-- Read data from the socket until we hit an ending string.
-- Read data from the socket until we hit an ending string.
Return all data as a list, which does
--
Return all data as a list, which does
not include the ending string.
-- not include the ending string.
readUntil
str
=
do
readUntil
str
=
do
line
<-
next
line
<-
next
if
line
/=
str
if
line
/=
str
...
@@ -189,9 +189,8 @@ receiveMessage debug socket = do
...
@@ -189,9 +189,8 @@ receiveMessage debug socket = do
return
$
line
:
remaining
return
$
line
:
remaining
else
return
[]
else
return
[]
-- | Encode a message in the IPython ZeroMQ communication protocol
-- | Encode a message in the IPython ZeroMQ communication protocol and send it through the provided
-- and send it through the provided socket. Sign it using HMAC
-- socket. Sign it using HMAC with SHA-256 using the provided key.
-- with SHA-256 using the provided key.
sendMessage
::
Sender
a
=>
Bool
->
ByteString
->
Socket
a
->
Message
->
IO
()
sendMessage
::
Sender
a
=>
Bool
->
ByteString
->
Socket
a
->
Message
->
IO
()
sendMessage
_
_
_
SendNothing
=
return
()
sendMessage
_
_
_
SendNothing
=
return
()
sendMessage
debug
hmacKey
socket
message
=
do
sendMessage
debug
hmacKey
socket
message
=
do
...
...
verify_formatting.py
View file @
a489c9bb
...
@@ -44,9 +44,15 @@ except:
...
@@ -44,9 +44,15 @@ except:
# Find all the source files
# Find all the source files
sources
=
[]
sources
=
[]
for
root
,
dirnames
,
filenames
in
os
.
walk
(
"src"
):
for
source_dir
in
[
"src"
,
"ipython-kernel"
,
"ihaskell-display"
]:
for
root
,
dirnames
,
filenames
in
os
.
walk
(
source_dir
):
# Skip cabal dist directories
if
"dist"
in
root
:
continue
for
filename
in
filenames
:
for
filename
in
filenames
:
if
filename
.
endswith
(
".hs"
):
# Take Haskell files, but ignore the Cabal Setup.hs
if
filename
.
endswith
(
".hs"
)
and
filename
!=
"Setup.hs"
:
sources
.
append
(
os
.
path
.
join
(
root
,
filename
))
sources
.
append
(
os
.
path
.
join
(
root
,
filename
))
...
...
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