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
Hide 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
import
Data.Textual.Encoding
import
Data.Textual.Encoding
import
Data.Aeson
import
Data.Aeson
import
Data.Aeson.Encode.Pretty
import
Data.Aeson.Encode.Pretty
import
Data.String.Here
import
Data.String.Here
import
IHaskell.Display
import
IHaskell.Display
instance
IHaskellDisplay
Value
where
instance
IHaskellDisplay
Value
where
display
renderable
=
return
$
Display
[
plain
json
,
html
dom
]
display
renderable
=
return
$
Display
[
plain
json
,
html
dom
]
where
where
json
=
unpack
$
decodeUtf8
$
encodePretty
renderable
json
=
unpack
$
decodeUtf8
$
encodePretty
renderable
dom
=
[
i
|
<div class="highlight-code" id="javascript">${json}</div>
|]
dom
=
[
i
|
<div class="highlight-code" id="javascript">${json}</div>
|]
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
import
Text.Printf
import
Text.Printf
instance
Show
a
=>
IHaskellDisplay
(
Maybe
a
)
where
instance
Show
a
=>
IHaskellDisplay
(
Maybe
a
)
where
display
just
=
return
$
Display
[
stringDisplay
,
htmlDisplay
]
display
just
=
return
$
Display
[
stringDisplay
,
htmlDisplay
]
where
where
stringDisplay
=
plain
(
show
just
)
stringDisplay
=
plain
(
show
just
)
htmlDisplay
=
html
str
htmlDisplay
=
html
str
str
=
case
just
of
str
=
Nothing
->
"<span style='color: red; font-weight: bold;'>Nothing</span>"
case
just
of
Just
x
->
printf
"<span style='color: green; font-weight: bold;'>Just</span><span style='font-family: monospace;'>%s</span>"
(
show
x
)
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
)
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
import
Text.Printf
import
Text.Printf
import
Text.Blaze.Html
import
Text.Blaze.Html
import
Text.Blaze.Renderer.Pretty
import
Text.Blaze.Renderer.Pretty
import
Text.Blaze.Internal
import
Text.Blaze.Internal
import
Control.Monad
import
Control.Monad
instance
IHaskellDisplay
(
MarkupM
a
)
where
instance
IHaskellDisplay
(
MarkupM
a
)
where
display
val
=
return
$
Display
[
stringDisplay
,
htmlDisplay
]
display
val
=
return
$
Display
[
stringDisplay
,
htmlDisplay
]
where
where
str
=
renderMarkup
(
void
val
)
str
=
renderMarkup
(
void
val
)
stringDisplay
=
plain
str
stringDisplay
=
plain
str
htmlDisplay
=
html
str
htmlDisplay
=
html
str
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
import
System.Directory
import
System.Directory
import
Data.Default.Class
import
Data.Default.Class
import
Graphics.Rendering.Chart.Renderable
import
Graphics.Rendering.Chart.Renderable
import
Graphics.Rendering.Chart.Backend.Cairo
import
Graphics.Rendering.Chart.Backend.Cairo
import
qualified
Data.ByteString.Char8
as
Char
import
qualified
Data.ByteString.Char8
as
Char
import
System.IO.Unsafe
import
System.IO.Unsafe
import
IHaskell.Display
import
IHaskell.Display
width
::
Width
width
::
Width
width
=
450
width
=
450
...
@@ -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
-- Convert to base64.
imgData
<-
readFile
$
fpFromString
filename
return
$
case
format
of
PNG
->
png
width
height
$
base64
imgData
SVG
->
svg
$
Char
.
unpack
imgData
#
if
MIN_VERSION_Chart_cairo
(
1
,
3
,
0
)
#
if
MIN_VERSION_Chart_cairo
(
1
,
3
,
0
)
toFile
filename
renderable
mkFile
opts
filename
renderable
=
renderableToFile
opts
filename
renderable
#
else
#
else
toFile
renderable
filename
mkFile
opts
filename
renderable
=
renderableToFile
opts
renderable
filename
#
endif
#
endif
-- Convert to base64.
imgData
<-
readFile
$
fpFromString
filename
return
$
case
format
of
PNG
->
png
width
height
$
base64
imgData
SVG
->
svg
$
Char
.
unpack
imgData
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
import
System.Directory
import
System.Directory
import
qualified
Data.ByteString.Char8
as
Char
import
qualified
Data.ByteString.Char8
as
Char
import
System.IO.Unsafe
import
System.IO.Unsafe
import
Diagrams.Prelude
import
Diagrams.Prelude
import
Diagrams.Backend.Cairo
import
Diagrams.Backend.Cairo
import
IHaskell.Display
import
IHaskell.Display
import
IHaskell.Display.Diagrams.Animation
import
IHaskell.Display.Diagrams.Animation
instance
IHaskellDisplay
(
QDiagram
Cairo
R2
Any
)
where
instance
IHaskellDisplay
(
QDiagram
Cairo
R2
Any
)
where
display
renderable
=
do
display
renderable
=
do
...
@@ -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
=
PNG
->
png
(
floor
imgWidth
)
(
floor
imgHeight
)
$
base64
imgData
case
format
of
SVG
->
svg
$
Char
.
unpack
imgData
PNG
->
png
(
floor
imgWidth
)
(
floor
imgHeight
)
$
base64
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
instance
IHaskellDisplay
(
QAnimation
Cairo
R2
Any
)
where
instance
IHaskellDisplay
(
QAnimation
Cairo
R2
Any
)
where
display
renderable
=
do
display
renderable
=
do
gif
<-
animationData
renderable
gif
<-
animationData
renderable
return
$
Display
[
html
$
"<img src=
\"
data:image/gif;base64,"
return
$
Display
[
html
$
"<img src=
\"
data:image/gif;base64,"
++
gif
++
"
\"
/>"
]
++
gif
++
"
\"
/>"
]
animationData
::
Animation
Cairo
R2
->
IO
String
animationData
::
Animation
Cairo
R2
->
IO
String
animationData
renderable
=
do
animationData
renderable
=
do
...
@@ -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
import
IHaskell.Display
import
IHaskell.Display
import
Text.LaTeX
import
Text.LaTeX
import
qualified
Data.Text
as
T
import
qualified
Data.Text
as
T
instance
IHaskellDisplay
LaTeX
where
instance
IHaskellDisplay
LaTeX
where
display
=
display
.
IHaskell
.
Display
.
latex
.
T
.
unpack
.
render
display
=
display
.
IHaskell
.
Display
.
latex
.
T
.
unpack
.
render
instance
(
a
~
()
,
IO
~
io
)
=>
IHaskellDisplay
(
LaTeXT
io
a
)
where
instance
(
a
~
()
,
IO
~
io
)
=>
IHaskellDisplay
(
LaTeXT
io
a
)
where
display
ma
=
display
=<<
execLaTeXT
ma
display
ma
=
display
=<<
execLaTeXT
ma
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
ClassyPrelude
import
Codec.Picture
import
IHaskell.Display
import
ClassyPrelude
import
System.Directory
import
IHaskell.Display
import
System.IO.Unsafe
import
System.Directory
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
displayImageAsJpg
renderable
=
do
displayImageAsJpg
renderable
=
do
switchToTmpDir
switchToTmpDir
...
@@ -40,30 +65,30 @@ displayImageAsJpg renderable = do
...
@@ -40,30 +65,30 @@ 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
)
imWidthHeight
(
ImageY8
im
)
=
imWH
im
imWidthHeight
(
ImageY8
im
)
=
imWH
im
imWidthHeight
(
ImageY16
im
)
=
imWH
im
imWidthHeight
(
ImageY16
im
)
=
imWH
im
imWidthHeight
(
ImageYF
im
)
=
imWH
im
imWidthHeight
(
ImageYF
im
)
=
imWH
im
imWidthHeight
(
ImageYA8
im
)
=
imWH
im
imWidthHeight
(
ImageYA8
im
)
=
imWH
im
imWidthHeight
(
ImageYA16
im
)
=
imWH
im
imWidthHeight
(
ImageYA16
im
)
=
imWH
im
imWidthHeight
(
ImageRGB8
im
)
=
imWH
im
imWidthHeight
(
ImageRGB8
im
)
=
imWH
im
imWidthHeight
(
ImageRGB16
im
)
=
imWH
im
imWidthHeight
(
ImageRGB16
im
)
=
imWH
im
imWidthHeight
(
ImageRGBF
im
)
=
imWH
im
imWidthHeight
(
ImageRGBF
im
)
=
imWH
im
imWidthHeight
(
ImageRGBA8
im
)
=
imWH
im
imWidthHeight
(
ImageRGBA8
im
)
=
imWH
im
imWidthHeight
(
ImageRGBA16
im
)
=
imWH
im
imWidthHeight
(
ImageRGBA16
im
)
=
imWH
im
imWidthHeight
(
ImageYCbCr8
im
)
=
imWH
im
imWidthHeight
(
ImageYCbCr8
im
)
=
imWH
im
imWidthHeight
(
ImageCMYK8
im
)
=
imWH
im
imWidthHeight
(
ImageCMYK8
im
)
=
imWH
im
imWidthHeight
(
ImageCMYK16
im
)
=
imWH
im
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
import
Magic
import
Magic
import
qualified
Data.ByteString
as
B
import
qualified
Data.ByteString
as
B
import
qualified
Data.ByteString.Unsafe
as
B
import
qualified
Data.ByteString.Unsafe
as
B
import
qualified
Data.ByteString.Base64
as
Base64
import
qualified
Data.ByteString.Base64
as
Base64
import
qualified
Data.ByteString.Char8
as
Char
import
qualified
Data.ByteString.Char8
as
Char
import
qualified
Data.ByteString.UTF8
as
B
import
qualified
Data.ByteString.UTF8
as
B
import
Text.Read
import
Text.Read
import
Data.Char
import
Data.Char
import
qualified
Data.Text
as
T
import
qualified
Data.Text
as
T
import
qualified
Data.Text.Encoding
as
T
import
qualified
Data.Text.Encoding
as
T
import
IHaskell.IPython.Types
(
MimeType
(
MimeSvg
))
import
IHaskell.IPython.Types
(
MimeType
(
MimeSvg
))
import
Data.ByteString.UTF8
import
Data.ByteString.UTF8
instance
IHaskellDisplay
T
.
Text
where
instance
IHaskellDisplay
T
.
Text
where
display
=
display
.
T
.
encodeUtf8
display
=
display
.
T
.
encodeUtf8
instance
IHaskellDisplay
B
.
ByteString
where
instance
IHaskellDisplay
B
.
ByteString
where
display
x
=
do
display
x
=
do
m
<-
magicOpen
[]
m
<-
magicOpen
[]
magicLoadDefault
m
magicLoadDefault
m
f
<-
B
.
unsafeUseAsCStringLen
x
(
magicCString
m
)
f
<-
B
.
unsafeUseAsCStringLen
x
(
magicCString
m
)
return
$
Display
[
withClass
(
parseMagic
f
)
x
]
return
$
Display
[
withClass
(
parseMagic
f
)
x
]
b64
::
B
.
ByteString
->
String
b64
::
B
.
ByteString
->
String
b64
=
Char
.
unpack
.
Base64
.
encode
b64
=
Char
.
unpack
.
Base64
.
encode
...
@@ -34,7 +35,7 @@ withClass :: MagicClass -> B.ByteString -> DisplayData
...
@@ -34,7 +35,7 @@ withClass :: MagicClass -> B.ByteString -> DisplayData
withClass
SVG
=
DisplayData
MimeSvg
.
T
.
decodeUtf8
withClass
SVG
=
DisplayData
MimeSvg
.
T
.
decodeUtf8
withClass
(
PNG
w
h
)
=
png
w
h
.
T
.
decodeUtf8
.
Base64
.
encode
withClass
(
PNG
w
h
)
=
png
w
h
.
T
.
decodeUtf8
.
Base64
.
encode
withClass
JPG
=
jpg
400
300
.
T
.
decodeUtf8
.
Base64
.
encode
withClass
JPG
=
jpg
400
300
.
T
.
decodeUtf8
.
Base64
.
encode
withClass
HTML
=
html
.
B
.
toString
withClass
HTML
=
html
.
B
.
toString
withClass
LaTeX
=
latex
.
B
.
toString
withClass
LaTeX
=
latex
.
B
.
toString
withClass
_
=
plain
.
B
.
toString
withClass
_
=
plain
.
B
.
toString
...
@@ -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
=
data
MagicClass
=
SVG
SVG
|
PNG
Int
Int
|
JPG
|
HTML
|
LaTeX
|
Unknown
|
PNG
Int
Int
deriving
Show
|
JPG
|
HTML
|
LaTeX
|
Unknown
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
)
import
System.Random
import
System.Random
import
Data.String.Here
import
Data.String.Here
import
Data.HashMap.Strict
as
Map
import
Data.HashMap.Strict
as
Map
import
Text.Parsec
(
parse
,
sourceLine
,
sourceColumn
)
import
Text.Parsec
(
parse
,
sourceLine
,
sourceColumn
)
import
Text.Parsec.String
(
Parser
)
import
Text.Parsec.String
(
Parser
)
import
Text.Parsec.Error
(
errorPos
,
ParseError
)
import
Text.Parsec.Error
(
errorPos
,
ParseError
)
import
Data.Aeson
import
Data.Aeson
import
IHaskell.Display
import
IHaskell.Display
instance
Show
a
=>
IHaskellDisplay
(
Parser
a
)
where
instance
Show
a
=>
IHaskellDisplay
(
Parser
a
)
where
display
renderable
=
return
$
many
[
Display
[
javascript
js
],
Display
[
html
dom
]]
display
renderable
=
return
$
many
[
Display
[
javascript
js
],
Display
[
html
dom
]]
where
where
dom
=
[
hereFile
|
widget.html
|]
dom
=
[
hereFile
|
widget.html
|]
js
=
[
hereFile
|
widget.js
|]
js
=
[
hereFile
|
widget.js
|]
...
@@ -25,25 +26,21 @@ data ParseText = ParseText String
...
@@ -25,25 +26,21 @@ data ParseText = ParseText String
instance
FromJSON
ParseText
where
instance
FromJSON
ParseText
where
parseJSON
(
Object
v
)
=
ParseText
<$>
v
.:
"text"
parseJSON
(
Object
v
)
=
ParseText
<$>
v
.:
"text"
parseJSON
_
=
fail
"Expecting object"
parseJSON
_
=
fail
"Expecting object"
-- | 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
[
toJSON
(
Right
result
)
=
object
[
"status"
.=
(
"success"
::
String
),
"result"
.=
show
result
]
"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
,
rOutput
,
rOutput
,
getPlotNames
,
getPlotNames
,
getCaptions
,
getCaptions
,
)
where
)
where
import
RlangQQ
import
RlangQQ
import
RlangQQ.ParseKnitted
import
RlangQQ.ParseKnitted
import
System.Directory
import
System.Directory
import
System.FilePath
import
System.FilePath
import
Data.Maybe
import
Data.Maybe
import
Data.List
import
Data.List
import
Text.Read
import
Text.Read
import
qualified
Data.ByteString
as
B
import
qualified
Data.ByteString
as
B
import
qualified
Data.ByteString.Char8
as
Char
import
qualified
Data.ByteString.Char8
as
Char
import
qualified
Data.ByteString.Base64
as
Base64
import
qualified
Data.ByteString.Base64
as
Base64
import
IHaskell.Display
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
import
Data.List.Split
import
Data.List.Split
import
Text.XFormat.Show
hiding
((
<>
))
import
Text.XFormat.Show
hiding
((
<>
))
import
Control.Applicative
import
Control.Applicative
import
Control.Concurrent
import
Control.Concurrent
import
Data.Monoid
import
Data.Monoid
import
Data.Typeable
import
Data.Typeable
import
Control.Concurrent.STM
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
...
@@ -62,35 +61,33 @@ rOutputParsed :: IO [KnitInteraction]
...
@@ -62,35 +61,33 @@ rOutputParsed :: IO [KnitInteraction]
rOutputParsed
=
do
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
display
(
mconcat
imgs
)
,
o
<-
os
]
display
(
mconcat
imgs
)
displayInteraction
::
KnitOutput
->
IO
Display
displayInteraction
::
KnitOutput
->
IO
Display
displayInteraction
(
KnitPrint
c
)
=
display
(
plain
c
)
displayInteraction
(
KnitPrint
c
)
=
display
(
plain
c
)
...
@@ -99,10 +96,11 @@ displayInteraction (KnitError c) = display (plain c)
...
@@ -99,10 +96,11 @@ displayInteraction (KnitError c) = display (plain c)
displayInteraction
(
KnitAsIs
c
)
=
display
(
plain
c
)
displayInteraction
(
KnitAsIs
c
)
=
display
(
plain
c
)
displayInteraction
(
KnitImage
cap
img
)
=
do
displayInteraction
(
KnitImage
cap
img
)
=
do
let
caption
let
caption
|
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
-- assumes you use the default device which is png
(
H
.
unsafeByteStringValue
(
Char
.
pack
"data:image/png;base64,"
<>
encoded
))
-- assumes you use the default device which is png
<>
caption
(
Char
.
pack
"data:image/png;base64,"
<>
encoded
))
<>
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
import
Data.Aeson
import
Data.Aeson
import
IHaskell.Widgets
import
IHaskell.Widgets
import
IHaskell.Display
import
IHaskell.Display
data
WidgetName
=
ButtonWidget
data
WidgetName
=
ButtonWidget
...
@@ -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
...
@@ -40,12 +42,11 @@ data ParseText = ParseText String
...
@@ -40,12 +42,11 @@ data ParseText = ParseText String
instance
FromJSON
ParseText
where
instance
FromJSON
ParseText
where
parseJSON
(
Object
v
)
=
ParseText
<$>
v
.:
"text"
parseJSON
(
Object
v
)
=
ParseText
<$>
v
.:
"text"
parseJSON
_
=
fail
"Expecting object"
parseJSON
_
=
fail
"Expecting object"
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
import
Control.Arrow
import
Control.Arrow
import
Control.Concurrent
(
MVar
,
newMVar
,
takeMVar
,
putMVar
,
threadDelay
)
import
Control.Concurrent
(
MVar
,
newMVar
,
takeMVar
,
putMVar
,
threadDelay
)
import
Control.Monad
(
guard
)
import
Control.Monad
(
guard
)
import
Control.Monad.IO.Class
(
MonadIO
(
..
))
import
Control.Monad.IO.Class
(
MonadIO
(
..
))
import
Control.Monad.State.Strict
(
StateT
,
get
,
modify
,
runStateT
)
import
Control.Monad.State.Strict
(
StateT
,
get
,
modify
,
runStateT
)
import
Data.Char
(
isDigit
)
import
Data.Char
(
isDigit
)
import
Data.List
(
isPrefixOf
)
import
Data.List
(
isPrefixOf
)
import
Data.Monoid
((
<>
))
import
Data.Monoid
((
<>
))
import
qualified
Data.Text
as
T
import
qualified
Data.Text
as
T
import
IHaskell.IPython.Kernel
import
IHaskell.IPython.Kernel
import
IHaskell.IPython.EasyKernel
(
installProfile
,
easyKernel
,
KernelConfig
(
..
))
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,34 +30,29 @@ import qualified Paths_ipython_kernel as Paths
...
@@ -28,34 +30,29 @@ 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
=
"(*"
,
P
.
commentEnd
=
"*)"
,
P
.
commentEnd
=
"*)"
,
P
.
commentLine
=
"//"
,
P
.
commentLine
=
"//"
,
P
.
nestedComments
=
True
,
P
.
nestedComments
=
True
,
P
.
identStart
=
letter
<|>
char
'_'
,
P
.
identStart
=
letter
<|>
char
'_'
,
P
.
identLetter
=
alphaNum
<|>
char
'_'
,
P
.
identLetter
=
alphaNum
<|>
char
'_'
,
P
.
opStart
=
oneOf
"+"
,
P
.
opStart
=
oneOf
"+"
,
P
.
opLetter
=
oneOf
"+"
,
P
.
opLetter
=
oneOf
"+"
,
P
.
reservedNames
=
[
"sleep"
,
"then"
,
"end"
,
"count"
]
,
P
.
reservedNames
=
[
"sleep"
,
"then"
,
"end"
,
"count"
]
,
P
.
reservedOpNames
=
[]
,
P
.
reservedOpNames
=
[]
,
P
.
caseSensitive
=
True
,
P
.
caseSensitive
=
True
}
}
lexer
::
Monad
m
=>
P
.
GenTokenParser
String
a
m
lexer
::
Monad
m
=>
P
.
GenTokenParser
String
a
m
...
@@ -83,39 +80,38 @@ literal :: Parsec String a Razor
...
@@ -83,39 +80,38 @@ 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
delay
<-
float
<?>
"seconds"
keyword
"sleep"
keyword
"then"
delay
<-
float
<?>
"seconds"
body
<-
expr
keyword
"then"
keyword
"end"
<?>
""
body
<-
expr
return
$
SleepThen
delay
body
keyword
"end"
<?>
""
return
$
SleepThen
delay
body
count
::
Parsec
String
a
Razor
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
guard
(
op
==
"+"
)
rest
<-
optionMaybe
expr
)
(
do
case
rest
of
op
<-
operator
Nothing
->
return
one
guard
(
op
==
"+"
)
Just
other
->
return
$
Plus
one
other
expr
)
case
rest
of
Nothing
->
return
one
Just
other
->
return
$
Plus
one
other
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
in
fmap
(
\
word
->
(
map
T
.
pack
.
matchesFor
$
T
.
unpack
word
,
word
,
word
))
in
fmap
(
\
word
->
(
map
T
.
pack
.
matchesFor
$
T
.
unpack
word
,
word
,
word
))
(
lastMaybe
(
T
.
words
before
))
(
lastMaybe
(
T
.
words
before
))
where
where
lastMaybe
::
[
a
]
->
Maybe
a
lastMaybe
::
[
a
]
->
Maybe
a
lastMaybe
[]
=
Nothing
lastMaybe
[]
=
Nothing
...
@@ -123,43 +119,41 @@ langCompletion _code line col =
...
@@ -123,43 +119,41 @@ 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"
sleepType
=
"sleep FLOAT then INT end"
sleepType
=
"sleep FLOAT then INT end"
plusDocs
=
"Perform addition"
plusDocs
=
"Perform addition"
plusType
=
"INT + INT"
plusType
=
"INT + INT"
intDocs
i
=
"The integer "
<>
i
intDocs
i
=
"The integer "
<>
i
intType
=
"INT"
intType
=
"INT"
floatDocs
f
=
"The floating point value "
<>
f
floatDocs
f
=
"The floating point value "
<>
f
floatType
=
"FLOAT"
floatType
=
"FLOAT"
countDocs
=
"Increment and return the current counter"
countDocs
=
"Increment and return the current counter"
countType
=
"INT"
countType
=
"INT"
-- | Messages sent to the frontend during evaluation will be lists of trace elements
-- | Messages sent to the frontend during evaluation will be lists of trace elements
data
IntermediateEvalRes
=
Got
Razor
Integer
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,53 +162,60 @@ execRazor :: MVar Integer -- ^ The global counter state
...
@@ -168,53 +162,60 @@ 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
x'
<-
execRazor
val
x
clear
send
modify
(
second
(
<>
T
.
pack
(
show
tm
)))
modify
(
first
$
consRes
(
Got
x
x'
))
x'
<-
execRazor
val
x
clear
send
sendState
modify
(
first
$
consRes
(
Got
x
x'
))
y'
<-
execRazor
val
y
clear
send
sendState
modify
(
first
$
consRes
(
Got
y
y'
))
y'
<-
execRazor
val
y
clear
send
sendState
modify
(
first
$
consRes
(
Got
y
y'
))
let
res
=
x'
+
y'
sendState
modify
(
first
$
consRes
(
Got
tm
res
))
let
res
=
x'
+
y'
sendState
modify
(
first
$
consRes
(
Got
tm
res
))
return
res
sendState
where
sendState
=
liftIO
clear
>>
fst
<$>
get
>>=
liftIO
.
send
return
res
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
sendState
modify
(
first
$
consRes
(
Waiting
delay
))
liftIO
$
threadDelay
100000
sendState
execRazor
val
(
SleepThen
(
delay
-
0.1
)
body
)
clear
send
liftIO
$
threadDelay
100000
|
otherwise
=
do
modify
(
first
$
consRes
(
Waiting
0
))
execRazor
val
(
SleepThen
(
delay
-
0.1
)
body
)
clear
send
sendState
|
otherwise
=
do
liftIO
$
threadDelay
(
floor
(
delay
*
1000000
))
modify
(
first
$
consRes
(
Waiting
0
))
execRazor
val
body
clear
send
sendState
where
sendState
=
liftIO
clear
>>
fst
<$>
get
>>=
liftIO
.
send
liftIO
$
threadDelay
(
floor
(
delay
*
1000000
))
execRazor
val
body
clear
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
,
completion
=
langCompletion
,
completion
=
langCompletion
,
objectInfo
=
langInfo
,
objectInfo
=
langInfo
,
run
=
parseAndRun
,
run
=
parseAndRun
,
debug
=
False
,
debug
=
False
}
}
where
where
displayRes
(
Left
err
)
=
displayRes
(
Left
err
)
=
...
@@ -235,15 +236,17 @@ mkConfig var = KernelConfig
...
@@ -235,15 +236,17 @@ 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
val
<-
newMVar
1
args
<-
getArgs
case
args
of
val
<-
newMVar
1
[
"kernel"
,
profileFile
]
->
case
args
of
easyKernel
profileFile
(
mkConfig
val
)
[
"kernel"
,
profileFile
]
->
[
"setup"
]
->
do
easyKernel
profileFile
(
mkConfig
val
)
putStrLn
"Installing profile..."
[
"setup"
]
->
do
installProfile
(
mkConfig
val
)
putStrLn
"Installing profile..."
_
->
do
installProfile
(
mkConfig
val
)
putStrLn
"Usage:"
_
->
do
putStrLn
"simple-calc-example setup -- set up the profile"
putStrLn
"Usage:"
putStrLn
"simple-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend"
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"
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,79 +38,73 @@
...
@@ -44,79 +38,73 @@
-- 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
)
import
qualified
Data.ByteString.Lazy
as
BL
import
qualified
Data.ByteString.Lazy
as
BL
import
qualified
Codec.Archive.Tar
as
Tar
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
)
import
qualified
Data.Text
as
T
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
,
import
System.FilePath
((
</>
))
getHomeDirectory
)
import
System.Exit
(
exitSuccess
)
import
System.FilePath
((
</>
))
import
System.IO
(
openFile
,
IOMode
(
ReadMode
))
import
System.Exit
(
exitSuccess
)
import
System.IO
(
openFile
,
IOMode
(
ReadMode
))
-- | The kernel configuration specifies the behavior that is specific
-- to your language. The type parameters provide the monad in which
-- | The kernel configuration specifies the behavior that is specific to your language. The type
-- your kernel will run, the type of intermediate outputs from running
-- parameters provide the monad in which your kernel will run, the type of intermediate outputs from
-- cells, and the type of final results of cells, respectively.
-- running cells, and the type of final results of cells, respectively.
data
KernelConfig
m
output
result
=
KernelConfig
data
KernelConfig
m
output
result
=
{
languageName
::
String
KernelConfig
-- ^ The name of the language. This field is used to calculate
{
-- the name of the profile, so it should contain characters that
-- | The name of the language. This field is used to calculate the name of the profile,
-- are reasonable to have in file names.
-- so it should contain characters that are reasonable to have in file names.
,
languageVersion
::
[
Int
]
-- ^ The version of the language
languageName
::
String
,
profileSource
::
IO
(
Maybe
FilePath
)
-- | The version of the language
-- ^ Determine the source of a profile to install using
,
languageVersion
::
[
Int
]
-- 'installProfile'. The source should be a tarball whose contents
-- | Determine the source of a profile to install using 'installProfile'. The source should be a
-- will be unpacked directly into the profile directory. For
-- tarball whose contents will be unpacked directly into the profile directory. For example, the
-- example, the file whose name is @ipython_config.py@ in the
-- file whose name is @ipython_config.py@ in the tar file for a language named @lang@ will end up in
-- tar file for a language named @lang@ will end up in
-- @~/.ipython/profile_lang/ipython_config.py@.
-- @~/.ipython/profile_lang/ipython_config.py@.
,
profileSource
::
IO
(
Maybe
FilePath
)
,
displayOutput
::
output
->
[
DisplayData
]
-- ^ How to render intermediate output
-- | How to render intermediate output
,
displayResult
::
result
->
[
DisplayData
]
-- ^ How to render final cell results
,
displayOutput
::
output
->
[
DisplayData
]
,
completion
::
T
.
Text
->
T
.
Text
->
Int
->
Maybe
([
T
.
Text
],
T
.
Text
,
T
.
Text
)
-- | How to render final cell results
-- ^ Perform completion. The returned tuple consists of the matches,
,
displayResult
::
result
->
[
DisplayData
]
-- the matched text, and the completion text. The arguments are the
-- | Perform completion. The returned tuple consists of the matches, the matched text, and the
-- code in the cell, the current line as text, and the column at
-- completion text. The arguments are the code in the cell, the current line as text, and the column
-- which the cursor is placed.
-- at which the cursor is placed.
,
objectInfo
::
T
.
Text
->
Maybe
(
T
.
Text
,
T
.
Text
,
T
.
Text
)
,
completion
::
T
.
Text
->
T
.
Text
->
Int
->
Maybe
([
T
.
Text
],
T
.
Text
,
T
.
Text
)
-- ^ Return the information or documentation for its argument. The
-- | Return the information or documentation for its argument. The returned tuple consists of the
-- returned tuple consists of the name, the documentation, and the
-- name, the documentation, and the type, respectively.
-- type, respectively.
,
objectInfo
::
T
.
Text
->
Maybe
(
T
.
Text
,
T
.
Text
,
T
.
Text
)
,
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
-- ^ Execute a cell. The arguments are the contents of the cell, an
-- current intermediate output, and an IO action that will add a new item to the intermediate
-- IO action that will clear the current intermediate output, and an
-- output. The result consists of the actual result, the status to be sent to IPython, and the
-- IO action that will add a new item to the intermediate
-- contents of the pager. Return the empty string to indicate that there is no pager output. Errors
-- output. The result consists of the actual result, the status to
-- should be handled by defining an appropriate error constructor in your result type.
-- be sent to IPython, and the contents of the pager. Return the
,
run
::
T
.
Text
->
IO
()
->
(
output
->
IO
()
)
->
m
(
result
,
ExecuteReplyStatus
,
String
)
-- empty string to indicate that there is no pager output. Errors
,
debug
::
Bool
-- ^ Whether to print extra debugging information to
-- should be handled by defining an appropriate error constructor in
}
-- your result type.
,
debug
::
Bool
-- ^ Whether to print extra debugging information to
-- the console | Attempt to install the IPython profile from the .tar file indicated by the
-- the console
-- 'profileSource' field of the configuration, if it is not already installed.
}
-- | Attempt to install the IPython profile from the .tar file
-- indicated by the 'profileSource' field of the configuration, if it
-- 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,10 +112,11 @@ installProfile config = do
...
@@ -124,10 +112,11 @@ 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
$
Tar
.
extract
profTgt
tar
liftIO
$
createDirectoryIfMissing
True
profTgt
else
liftIO
.
putStrLn
$
liftIO
$
Tar
.
extract
profTgt
tar
"The supplied profile source '"
++
tar
++
"' does not exist"
else
liftIO
.
putStrLn
$
"The supplied profile source '"
++
tar
++
"' does not exist"
where
where
profDir
=
do
profDir
=
do
...
@@ -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
-- | Execute an IPython kernel for a config. Your 'main' action should
-- it does.
-- 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,97 +181,79 @@ replyTo :: MonadIO m
...
@@ -192,97 +181,79 @@ replyTo :: MonadIO m
->
MessageHeader
->
MessageHeader
->
m
Message
->
m
Message
replyTo
config
_
_
KernelInfoRequest
{}
replyHeader
=
replyTo
config
_
_
KernelInfoRequest
{}
replyHeader
=
return
KernelInfoReply
return
{
header
=
replyHeader
KernelInfoReply
,
language
=
languageName
config
{
header
=
replyHeader
,
versionList
=
languageVersion
config
,
language
=
languageName
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
(
displayOutput
config
x
)
outputHeader
in
run
config
code
clearOutput
sendOutput
(
languageName
config
)
(
displayOutput
config
x
)
in
run
config
code
clearOutput
sendOutput
liftIO
.
send
$
PublishDisplayData
outputHeader
(
languageName
config
)
(
displayResult
config
res
)
liftIO
.
send
$
PublishDisplayData
outputHeader
(
languageName
config
)
(
displayResult
config
res
)
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
{
header
=
replyHeader
ExecuteReply
,
pagerOutput
=
pagerOut
{
header
=
replyHeader
,
executionCounter
=
fromIntegral
counter
,
pagerOutput
=
pagerOut
,
status
=
replyStatus
,
executionCounter
=
fromIntegral
counter
}
,
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
$
Just
(
name
,
docs
,
ty
)
->
ObjectInfoReply
case
objectInfo
config
obj
of
{
header
=
replyHeader
Just
(
name
,
docs
,
ty
)
->
ObjectInfoReply
,
objectName
=
obj
{
header
=
replyHeader
,
objectFound
=
True
,
objectName
=
obj
,
objectTypeString
=
ty
,
objectFound
=
True
,
objectDocString
=
docs
,
objectTypeString
=
ty
}
,
objectDocString
=
docs
Nothing
->
ObjectInfoReply
}
{
header
=
replyHeader
Nothing
->
ObjectInfoReply
,
objectName
=
obj
{
header
=
replyHeader
,
objectFound
=
False
,
objectName
=
obj
,
objectTypeString
=
""
,
objectFound
=
False
,
objectDocString
=
""
,
objectTypeString
=
""
}
,
objectDocString
=
""
}
replyTo
_
_
_
msg
_
=
do
replyTo
_
_
_
msg
_
=
do
liftIO
$
putStrLn
"Unknown message: "
liftIO
$
putStrLn
"Unknown message: "
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
import
IHaskell.IPython.Message.Parser
as
X
import
IHaskell.IPython.Message.Parser
as
X
import
IHaskell.IPython.Message.UUID
as
X
import
IHaskell.IPython.Message.UUID
as
X
import
IHaskell.IPython.ZeroMQ
as
X
import
IHaskell.IPython.ZeroMQ
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,26 +31,25 @@ parseMessage idents headerData parentHeader metadata content =
...
@@ -32,26 +31,25 @@ 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
,
parentHeader
=
parentResult
{
identifiers
=
idents
,
metadata
=
metadataMap
,
parentHeader
=
parentResult
,
messageId
=
messageUUID
,
metadata
=
metadataMap
,
sessionId
=
sessionUUID
,
messageId
=
messageUUID
,
username
=
username
,
sessionId
=
sessionUUID
,
msgType
=
messageType
,
username
=
username
}
,
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,27 +69,26 @@ noHeader :: MessageHeader
...
@@ -71,27 +69,26 @@ 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
parser
ObjectInfoRequestMessage
=
objectInfoRequestParser
parser
ObjectInfoRequestMessage
=
objectInfoRequestParser
parser
ShutdownRequestMessage
=
shutdownRequestParser
parser
ShutdownRequestMessage
=
shutdownRequestParser
parser
InputReplyMessage
=
inputReplyParser
parser
InputReplyMessage
=
inputReplyParser
parser
CommOpenMessage
=
commOpenParser
parser
CommOpenMessage
=
commOpenParser
parser
CommDataMessage
=
commDataParser
parser
CommDataMessage
=
commDataParser
parser
CommCloseMessage
=
commCloseParser
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.
...
@@ -99,22 +96,23 @@ kernelInfoRequestParser _ = KernelInfoRequest { header = noHeader }
...
@@ -99,22 +96,23 @@ kernelInfoRequestParser _ = KernelInfoRequest { header = noHeader }
executeRequestParser
::
LByteString
->
Message
executeRequestParser
::
LByteString
->
Message
executeRequestParser
content
=
executeRequestParser
content
=
let
parser
obj
=
do
let
parser
obj
=
do
code
<-
obj
.:
"code"
code
<-
obj
.:
"code"
silent
<-
obj
.:
"silent"
silent
<-
obj
.:
"silent"
storeHistory
<-
obj
.:
"store_history"
storeHistory
<-
obj
.:
"store_history"
allowStdin
<-
obj
.:
"allow_stdin"
allowStdin
<-
obj
.:
"allow_stdin"
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
,
getCode
=
code
{
header
=
noHeader
,
getSilent
=
silent
,
getCode
=
code
,
getAllowStdin
=
allowStdin
,
getSilent
=
silent
,
getStoreHistory
=
storeHistory
,
getAllowStdin
=
allowStdin
,
getUserVariables
=
[]
,
getStoreHistory
=
storeHistory
,
getUserExpressions
=
[]
,
getUserVariables
=
[]
}
,
getUserExpressions
=
[]
}
requestParser
parser
content
=
parsed
requestParser
parser
content
=
parsed
where
where
...
@@ -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
((
<$>
))
import
Data.Text
(
pack
)
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
)
import
Data.Text
(
Text
,
pack
)
import
Data.Text
(
Text
,
pack
)
import
Data.Monoid
(
mempty
)
import
Data.Monoid
(
mempty
)
import
qualified
Data.ByteString.Lazy
as
L
import
qualified
Data.ByteString.Lazy
as
L
import
qualified
Data.ByteString
as
B
import
qualified
Data.ByteString
as
B
import
Data.Text.Encoding
import
Data.Text.Encoding
import
IHaskell.IPython.Types
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
[
"source"
.=
string
"page"
,
"text"
.=
pager
]]
else
[
object
[
,
"user_variables"
.=
emptyMap
"source"
.=
string
"page"
,
,
"user_expressions"
.=
emptyMap
"text"
.=
pager
]
]],
toJSON
PublishStatus
{
executionState
=
executionState
}
=
"user_variables"
.=
emptyMap
,
object
[
"execution_state"
.=
executionState
]
"user_expressions"
.=
emptyMap
toJSON
PublishStream
{
streamType
=
streamType
,
streamContent
=
content
}
=
]
object
[
"data"
.=
content
,
"name"
.=
streamType
]
toJSON
PublishStatus
{
executionState
=
executionState
}
=
object
[
toJSON
PublishDisplayData
{
source
=
src
,
displayData
=
datas
}
=
"execution_state"
.=
executionState
object
]
[
"source"
.=
src
,
"metadata"
.=
toJSON
PublishStream
{
streamType
=
streamType
,
streamContent
=
content
}
=
object
[
object
[]
,
"data"
.=
"data"
.=
content
,
object
(
map
displayDataToJson
datas
)]
"name"
.=
streamType
]
toJSON
PublishOutput
{
executionCount
=
execCount
,
reprText
=
reprText
}
=
toJSON
PublishDisplayData
{
source
=
src
,
displayData
=
datas
}
=
object
[
object
"source"
.=
src
,
[
"data"
.=
"metadata"
.=
object
[]
,
object
[
"text/plain"
.=
reprText
],
"execution_count"
.=
execCount
,
"metadata"
.=
"data"
.=
object
(
map
displayDataToJson
datas
)
object
[]
]
]
toJSON
PublishInput
{
executionCount
=
execCount
,
inCode
=
code
}
=
object
[
"execution_count"
.=
execCount
,
"code"
.=
code
]
toJSON
PublishOutput
{
executionCount
=
execCount
,
reprText
=
reprText
}
=
object
[
toJSON
(
CompleteReply
_
matches
start
end
metadata
status
)
=
"data"
.=
object
[
"text/plain"
.=
reprText
],
object
"execution_count"
.=
execCount
,
[
"matches"
.=
matches
"metadata"
.=
object
[]
,
"cursor_start"
.=
start
]
,
"cursor_end"
.=
end
toJSON
PublishInput
{
executionCount
=
execCount
,
inCode
=
code
}
=
object
[
,
"metadata"
.=
metadata
"execution_count"
.=
execCount
,
,
"status"
.=
if
status
"code"
.=
code
then
string
"ok"
]
else
"error"
toJSON
(
CompleteReply
_
matches
start
end
metadata
status
)
=
object
[
]
"matches"
.=
matches
,
toJSON
o
@
ObjectInfoReply
{}
=
"cursor_start"
.=
start
,
object
"cursor_end"
.=
end
,
[
"oname"
.=
"metadata"
.=
metadata
,
objectName
o
"status"
.=
if
status
then
string
"ok"
else
"error"
,
"found"
.=
objectFound
o
]
,
"ismagic"
.=
False
toJSON
o
@
ObjectInfoReply
{}
=
object
[
,
"isalias"
.=
False
"oname"
.=
objectName
o
,
,
"type_name"
.=
objectTypeString
o
"found"
.=
objectFound
o
,
,
"docstring"
.=
objectDocString
o
"ismagic"
.=
False
,
]
"isalias"
.=
False
,
"type_name"
.=
objectTypeString
o
,
toJSON
ShutdownReply
{
restartPending
=
restart
}
=
"docstring"
.=
objectDocString
o
object
[
"restart"
.=
restart
]
]
toJSON
ClearOutput
{
wait
=
wait
}
=
toJSON
ShutdownReply
{
restartPending
=
restart
}
=
object
[
object
[
"wait"
.=
wait
]
"restart"
.=
restart
]
toJSON
RequestInput
{
inputPrompt
=
prompt
}
=
object
[
"prompt"
.=
prompt
]
toJSON
ClearOutput
{
wait
=
wait
}
=
object
[
"wait"
.=
wait
toJSON
req
@
CommOpen
{}
=
]
object
[
"comm_id"
.=
commUuid
req
,
"target_name"
.=
commTargetName
req
,
"data"
.=
commData
req
]
toJSON
RequestInput
{
inputPrompt
=
prompt
}
=
object
[
toJSON
req
@
CommData
{}
=
"prompt"
.=
prompt
object
[
"comm_id"
.=
commUuid
req
,
"data"
.=
commData
req
]
]
toJSON
req
@
CommClose
{}
=
toJSON
req
@
CommOpen
{}
=
object
[
object
[
"comm_id"
.=
commUuid
req
,
"data"
.=
commData
req
]
"comm_id"
.=
commUuid
req
,
"target_name"
.=
commTargetName
req
,
toJSON
req
@
HistoryReply
{}
=
"data"
.=
commData
req
object
[
"history"
.=
map
tuplify
(
historyReply
req
)]
]
where
tuplify
(
HistoryReplyElement
sess
linum
res
)
=
(
sess
,
linum
,
case
res
of
toJSON
req
@
CommData
{}
=
object
[
Left
inp
->
toJSON
inp
"comm_id"
.=
commUuid
req
,
Right
(
inp
,
out
)
->
toJSON
out
)
"data"
.=
commData
req
]
toJSON
req
@
CommClose
{}
=
object
[
"comm_id"
.=
commUuid
req
,
"data"
.=
commData
req
]
toJSON
req
@
HistoryReply
{}
=
object
[
"history"
.=
map
tuplify
(
historyReply
req
)
]
where
tuplify
(
HistoryReplyElement
sess
linum
res
)
=
(
sess
,
linum
,
case
res
of
Left
inp
->
toJSON
inp
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"
toJSON
Idle
=
String
"idle"
toJSON
Idle
=
String
"idle"
toJSON
Starting
=
String
"starting"
toJSON
Starting
=
String
"starting"
-- | Print a stream as "stdin" or "stdout" strings.
-- | Print a stream as "stdin" or "stdout" strings.
instance
ToJSON
StreamType
where
instance
ToJSON
StreamType
where
toJSON
Stdin
=
String
"stdin"
toJSON
Stdin
=
String
"stdin"
toJSON
Stdout
=
String
"stdout"
toJSON
Stdout
=
String
"stdout"
-- | Convert a MIME type and value into a JSON dictionary pair.
-- | Convert a MIME type and value into a JSON dictionary pair.
displayDataToJson
::
DisplayData
->
(
Text
,
Value
)
displayDataToJson
::
DisplayData
->
(
Text
,
Value
)
displayDataToJson
(
DisplayData
mimeType
dataStr
)
=
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
((
<$>
))
import
Control.Concurrent.Chan
import
Control.Concurrent.Chan
import
Control.Monad
import
Control.Monad
import
GHC.IO.Handle
import
GHC.IO.Handle
import
GHC.IO.Handle.Types
import
GHC.IO.Handle.Types
import
System.IO
import
System.IO
import
System.Posix.IO
import
System.Posix.IO
import
System.IO.Unsafe
import
System.IO.Unsafe
import
qualified
Data.Map
as
Map
import
qualified
Data.Map
as
Map
import
IHaskell.IPython.Types
import
IHaskell.IPython.Types
import
IHaskell.IPython.ZeroMQ
import
IHaskell.IPython.ZeroMQ
import
IHaskell.IPython.Message.UUID
as
UUID
import
IHaskell.IPython.Message.UUID
as
UUID
stdinInterface
::
MVar
ZeroMQStdin
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,17 +67,18 @@ stdinOnce dir = do
...
@@ -78,17 +67,18 @@ 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
threadDelay
$
150
*
1000
threadDelay
$
150
*
1000
empty
<-
isEmptyMVar
mvar
empty
<-
isEmptyMVar
mvar
if
not
empty
if
not
empty
then
loop
stdinInput
oldStdin
newStdin
then
loop
stdinInput
oldStdin
newStdin
else
do
else
do
line
<-
getInputLine
dir
line
<-
getInputLine
dir
hPutStr
stdinInput
$
line
++
"
\n
"
hPutStr
stdinInput
$
line
++
"
\n
"
loop
stdinInput
oldStdin
newStdin
loop
stdinInput
oldStdin
newStdin
-- | Get a line of input from the IPython frontend.
-- | Get a line of input from the IPython frontend.
getInputLine
::
String
->
IO
String
getInputLine
::
String
->
IO
String
...
@@ -98,15 +88,15 @@ getInputLine dir = do
...
@@ -98,15 +88,15 @@ 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
(
..
),
Transport
(
..
),
Transport
(
..
),
Port
(
..
),
Port
(
..
),
IP
(
..
),
IP
(
..
),
-- * IPython kernelspecs
-- * IPython kernelspecs
KernelSpec
(
..
),
KernelSpec
(
..
),
-- * IPython messaging protocol
-- * IPython messaging protocol
Message
(
..
),
Message
(
..
),
MessageHeader
(
..
),
MessageHeader
(
..
),
Username
(
..
),
Username
(
..
),
Metadata
(
..
),
Metadata
(
..
),
MessageType
(
..
),
MessageType
(
..
),
Width
(
..
),
Height
(
..
),
Width
(
..
),
StreamType
(
..
),
Height
(
..
),
ExecutionState
(
..
),
StreamType
(
..
),
ExecuteReplyStatus
(
..
),
ExecutionState
(
..
),
HistoryAccessType
(
..
),
ExecuteReplyStatus
(
..
),
HistoryReplyElement
(
..
),
HistoryAccessType
(
..
),
replyType
,
HistoryReplyElement
(
..
),
replyType
,
-- ** IPython display data message
DisplayData
(
..
),
-- ** IPython display data message
MimeType
(
..
),
DisplayData
(
..
),
extractPlain
MimeType
(
..
),
extractPlain
,
)
where
)
where
import
Data.Aeson
import
Data.Aeson
import
Control.Applicative
((
<$>
),
(
<*>
))
import
Control.Applicative
((
<$>
),
(
<*>
))
import
Data.ByteString
(
ByteString
)
import
Data.ByteString
(
ByteString
)
import
qualified
Data.Text
as
Text
import
qualified
Data.Text
as
Text
import
qualified
Data.Text.Encoding
as
Text
import
qualified
Data.Text.Encoding
as
Text
import
Data.Text
(
Text
)
import
Data.Text
(
Text
)
import
Data.Serialize
import
Data.Serialize
import
IHaskell.IPython.Message.UUID
import
IHaskell.IPython.Message.UUID
import
GHC.Generics
(
Generic
)
import
GHC.Generics
(
Generic
)
import
Data.Typeable
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,15 +58,17 @@ data Transport = TCP -- ^ Default transport mechanism via TCP.
...
@@ -57,15 +58,17 @@ 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
=
,
transport
::
Transport
-- ^ The transport mechanism.
Profile
,
stdinPort
::
Port
-- ^ The stdin channel port.
{
ip
::
IP
-- ^ The IP on which to listen.
,
controlPort
::
Port
-- ^ The control channel port.
,
transport
::
Transport
-- ^ The transport mechanism.
,
hbPort
::
Port
-- ^ The heartbeat channel port.
,
stdinPort
::
Port
-- ^ The stdin channel port.
,
shellPort
::
Port
-- ^ The shell command port.
,
controlPort
::
Port
-- ^ The control channel port.
,
iopubPort
::
Port
-- ^ The IOPub port.
,
hbPort
::
Port
-- ^ The heartbeat channel port.
,
signatureKey
::
ByteString
-- ^ The HMAC encryption key.
,
shellPort
::
Port
-- ^ The shell command port.
}
,
iopubPort
::
Port
-- ^ The IOPub port.
,
signatureKey
::
ByteString
-- ^ The HMAC encryption key.
}
deriving
(
Show
,
Read
)
deriving
(
Show
,
Read
)
-- Convert the kernel profile to and from JSON.
-- Convert the kernel profile to and from JSON.
...
@@ -87,35 +90,39 @@ instance FromJSON Profile where
...
@@ -87,35 +90,39 @@ instance FromJSON Profile where
instance
ToJSON
Profile
where
instance
ToJSON
Profile
where
toJSON
profile
=
object
toJSON
profile
=
object
[
"ip"
.=
ip
profile
[
"ip"
.=
ip
profile
,
"transport"
.=
transport
profile
,
"transport"
.=
transport
profile
,
"stdin_port"
.=
stdinPort
profile
,
"stdin_port"
.=
stdinPort
profile
,
"control_port"
.=
controlPort
profile
,
"control_port"
.=
controlPort
profile
,
"hb_port"
.=
hbPort
profile
,
"hb_port"
.=
hbPort
profile
,
"shell_port"
.=
shellPort
profile
,
"shell_port"
.=
shellPort
profile
,
"iopub_port"
.=
iopubPort
profile
,
"iopub_port"
.=
iopubPort
profile
,
"key"
.=
Text
.
decodeUtf8
(
signatureKey
profile
)
,
"key"
.=
Text
.
decodeUtf8
(
signatureKey
profile
)
]
]
instance
FromJSON
Transport
where
instance
FromJSON
Transport
where
parseJSON
(
String
mech
)
=
parseJSON
(
String
mech
)
=
case
mech
of
case
mech
of
"tcp"
->
return
TCP
"tcp"
->
return
TCP
_
->
fail
$
"Unknown transport mechanism "
++
Text
.
unpack
mech
_
->
fail
$
"Unknown transport mechanism "
++
Text
.
unpack
mech
parseJSON
_
=
fail
"Expected JSON string as transport."
parseJSON
_
=
fail
"Expected JSON string as transport."
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,29 +131,31 @@ instance ToJSON KernelSpec where
...
@@ -124,29 +131,31 @@ 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.
type
Username
=
Text
type
Username
=
Text
...
@@ -178,32 +187,32 @@ data MessageType = KernelInfoReplyMessage
...
@@ -178,32 +187,32 @@ data MessageType = KernelInfoReplyMessage
|
CommCloseMessage
|
CommCloseMessage
|
HistoryRequestMessage
|
HistoryRequestMessage
|
HistoryReplyMessage
|
HistoryReplyMessage
deriving
(
Show
,
Read
,
Eq
)
deriving
(
Show
,
Read
,
Eq
)
showMessageType
::
MessageType
->
String
showMessageType
::
MessageType
->
String
showMessageType
KernelInfoReplyMessage
=
"kernel_info_reply"
showMessageType
KernelInfoReplyMessage
=
"kernel_info_reply"
showMessageType
KernelInfoRequestMessage
=
"kernel_info_request"
showMessageType
KernelInfoRequestMessage
=
"kernel_info_request"
showMessageType
ExecuteReplyMessage
=
"execute_reply"
showMessageType
ExecuteReplyMessage
=
"execute_reply"
showMessageType
ExecuteRequestMessage
=
"execute_request"
showMessageType
ExecuteRequestMessage
=
"execute_request"
showMessageType
StatusMessage
=
"status"
showMessageType
StatusMessage
=
"status"
showMessageType
StreamMessage
=
"stream"
showMessageType
StreamMessage
=
"stream"
showMessageType
DisplayDataMessage
=
"display_data"
showMessageType
DisplayDataMessage
=
"display_data"
showMessageType
OutputMessage
=
"pyout"
showMessageType
OutputMessage
=
"pyout"
showMessageType
InputMessage
=
"pyin"
showMessageType
InputMessage
=
"pyin"
showMessageType
CompleteRequestMessage
=
"complete_request"
showMessageType
CompleteRequestMessage
=
"complete_request"
showMessageType
CompleteReplyMessage
=
"complete_reply"
showMessageType
CompleteReplyMessage
=
"complete_reply"
showMessageType
ObjectInfoRequestMessage
=
"object_info_request"
showMessageType
ObjectInfoRequestMessage
=
"object_info_request"
showMessageType
ObjectInfoReplyMessage
=
"object_info_reply"
showMessageType
ObjectInfoReplyMessage
=
"object_info_reply"
showMessageType
ShutdownRequestMessage
=
"shutdown_request"
showMessageType
ShutdownRequestMessage
=
"shutdown_request"
showMessageType
ShutdownReplyMessage
=
"shutdown_reply"
showMessageType
ShutdownReplyMessage
=
"shutdown_reply"
showMessageType
ClearOutputMessage
=
"clear_output"
showMessageType
ClearOutputMessage
=
"clear_output"
showMessageType
InputRequestMessage
=
"input_request"
showMessageType
InputRequestMessage
=
"input_request"
showMessageType
InputReplyMessage
=
"input_reply"
showMessageType
InputReplyMessage
=
"input_reply"
showMessageType
CommOpenMessage
=
"comm_open"
showMessageType
CommOpenMessage
=
"comm_open"
showMessageType
CommDataMessage
=
"comm_msg"
showMessageType
CommDataMessage
=
"comm_msg"
showMessageType
CommCloseMessage
=
"comm_close"
showMessageType
CommCloseMessage
=
"comm_close"
showMessageType
HistoryRequestMessage
=
"history_request"
showMessageType
HistoryRequestMessage
=
"history_request"
showMessageType
HistoryReplyMessage
=
"history_reply"
showMessageType
HistoryReplyMessage
=
"history_reply"
instance
FromJSON
MessageType
where
instance
FromJSON
MessageType
where
parseJSON
(
String
s
)
=
parseJSON
(
String
s
)
=
...
@@ -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.
|
|
KernelInfoReply
{
-- | A response to a KernelInfoRequest.
header
::
MessageHeader
,
KernelInfoReply
versionList
::
[
Int
],
-- ^ The version of the language, e.g. [7, 6, 3] for GHC 7.6.3
{
header
::
MessageHeader
language
::
String
-- ^ The language name, e.g. "haskell"
,
versionList
::
[
Int
]
-- ^ The version of the language, e.g. [7, 6, 3] for GHC
}
-- 7.6.3
,
language
::
String
-- ^ The language name, e.g. "haskell"
-- | A request from a frontend to execute some code.
}
|
ExecuteRequest
{
|
header
::
MessageHeader
,
-- | A request from a frontend to execute some code.
getCode
::
Text
,
-- ^ The code string.
ExecuteRequest
getSilent
::
Bool
,
-- ^ Whether this should be silently executed.
{
header
::
MessageHeader
getStoreHistory
::
Bool
,
-- ^ Whether to store this in history.
,
getCode
::
Text
-- ^ The code string.
getAllowStdin
::
Bool
,
-- ^ Whether this code can use stdin.
,
getSilent
::
Bool
-- ^ Whether this should be silently executed.
,
getStoreHistory
::
Bool
-- ^ Whether to store this in history.
getUserVariables
::
[
Text
],
-- ^ Unused.
,
getAllowStdin
::
Bool
-- ^ Whether this code can use stdin.
getUserExpressions
::
[
Text
]
-- ^ Unused.
,
getUserVariables
::
[
Text
]
-- ^ Unused.
}
,
getUserExpressions
::
[
Text
]
-- ^ Unused.
}
-- | A reply to an execute request.
|
|
ExecuteReply
{
-- | A reply to an execute request.
header
::
MessageHeader
,
ExecuteReply
status
::
ExecuteReplyStatus
,
-- ^ The status of the output.
{
header
::
MessageHeader
pagerOutput
::
String
,
-- ^ The help string to show in the pager.
,
status
::
ExecuteReplyStatus
-- ^ The status of the output.
executionCounter
::
Int
-- ^ The execution count, i.e. which output this is.
,
pagerOutput
::
String
-- ^ The help string to show in the pager.
}
,
executionCounter
::
Int
-- ^ The execution count, i.e. which output this is.
}
|
PublishStatus
{
|
header
::
MessageHeader
,
PublishStatus
executionState
::
ExecutionState
-- ^ The execution state of the kernel.
{
header
::
MessageHeader
}
,
executionState
::
ExecutionState
-- ^ The execution state of the kernel.
}
|
PublishStream
{
|
header
::
MessageHeader
,
PublishStream
streamType
::
StreamType
,
-- ^ Which stream to publish to.
{
header
::
MessageHeader
streamContent
::
String
-- ^ What to publish.
,
streamType
::
StreamType
-- ^ Which stream to publish to.
}
,
streamContent
::
String
-- ^ What to publish.
}
|
PublishDisplayData
{
|
header
::
MessageHeader
,
PublishDisplayData
source
::
String
,
-- ^ The name of the data source.
{
header
::
MessageHeader
displayData
::
[
DisplayData
]
-- ^ A list of data representations.
,
source
::
String
-- ^ The name of the data source.
}
,
displayData
::
[
DisplayData
]
-- ^ A list of data representations.
}
|
PublishOutput
{
|
header
::
MessageHeader
,
PublishOutput
reprText
::
String
,
-- ^ Printed output text.
{
header
::
MessageHeader
executionCount
::
Int
-- ^ Which output this is for.
,
reprText
::
String
-- ^ Printed output text.
}
,
executionCount
::
Int
-- ^ Which output this is for.
}
|
PublishInput
{
|
header
::
MessageHeader
,
PublishInput
inCode
::
String
,
-- ^ Submitted input code.
{
header
::
MessageHeader
executionCount
::
Int
-- ^ Which input this is.
,
inCode
::
String
-- ^ Submitted input code.
}
,
executionCount
::
Int
-- ^ Which input this is.
}
|
CompleteRequest
{
|
header
::
MessageHeader
,
CompleteRequest
getCode
::
Text
,
{- ^
{
header
::
MessageHeader
,
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
,
ShutdownReply
restartPending
::
Bool
-- ^ Whether this shutdown precedes a restart.
{
header
::
MessageHeader
}
,
restartPending
::
Bool
-- ^ Whether this shutdown precedes a restart.
}
|
ClearOutput
{
|
header
::
MessageHeader
,
ClearOutput
wait
::
Bool
-- ^ Whether to wait to redraw until there is more output.
{
header
::
MessageHeader
}
,
wait
::
Bool
-- ^ Whether to wait to redraw until there is more output.
}
|
RequestInput
{
|
RequestInput
{
header
::
MessageHeader
,
inputPrompt
::
String
}
header
::
MessageHeader
,
|
InputReply
{
header
::
MessageHeader
,
inputValue
::
String
}
inputPrompt
::
String
|
}
CommOpen
{
header
::
MessageHeader
|
InputReply
{
,
commTargetName
::
String
header
::
MessageHeader
,
,
commUuid
::
UUID
inputValue
::
String
,
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
|
CommData
{
-- transformed input.
header
::
MessageHeader
,
,
historyAccessType
::
HistoryAccessType
-- ^ What history is being requested.
commUuid
::
UUID
,
}
commData
::
Value
|
HistoryReply
{
header
::
MessageHeader
,
historyReply
::
[
HistoryReplyElement
]
}
}
|
SendNothing
-- Dummy message; nothing is sent.
deriving
Show
|
CommClose
{
header
::
MessageHeader
,
-- | Ways in which the frontend can request history. TODO: Implement fields as described in
commUuid
::
UUID
,
-- messaging spec.
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.
deriving
Show
-- | Ways in which the frontend can request history.
-- TODO: Implement fields as described in 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
=
,
historyReplyLineNumber
::
Int
HistoryReplyElement
,
historyReplyContent
::
Either
String
(
String
,
String
)
{
historyReplySession
::
Int
}
,
historyReplyLineNumber
::
Int
,
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,40 +406,49 @@ instance Show ExecuteReplyStatus where
...
@@ -413,40 +406,49 @@ 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
replyType
KernelInfoRequestMessage
=
Just
KernelInfoReplyMessage
replyType
KernelInfoRequestMessage
=
Just
KernelInfoReplyMessage
replyType
ExecuteRequestMessage
=
Just
ExecuteReplyMessage
replyType
ExecuteRequestMessage
=
Just
ExecuteReplyMessage
replyType
CompleteRequestMessage
=
Just
CompleteReplyMessage
replyType
CompleteRequestMessage
=
Just
CompleteReplyMessage
replyType
ObjectInfoRequestMessage
=
Just
ObjectInfoReplyMessage
replyType
ObjectInfoRequestMessage
=
Just
ObjectInfoReplyMessage
replyType
ShutdownRequestMessage
=
Just
ShutdownReplyMessage
replyType
ShutdownRequestMessage
=
Just
ShutdownReplyMessage
replyType
HistoryRequestMessage
=
Just
HistoryReplyMessage
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"
-- Allow DisplayData serialization
-- Allow DisplayData serialization
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
...
@@ -454,22 +456,22 @@ data MimeType = PlainText
...
@@ -454,22 +456,22 @@ data MimeType = PlainText
|
MimeSvg
|
MimeSvg
|
MimeLatex
|
MimeLatex
|
MimeJavascript
|
MimeJavascript
deriving
(
Eq
,
Typeable
,
Generic
)
deriving
(
Eq
,
Typeable
,
Generic
)
-- Extract the plain text from a list of displays.
-- Extract the plain text from a list of displays.
extractPlain
::
[
DisplayData
]
->
String
extractPlain
::
[
DisplayData
]
->
String
extractPlain
disps
=
extractPlain
disps
=
case
find
isPlain
disps
of
case
find
isPlain
disps
of
Nothing
->
""
Nothing
->
""
Just
(
DisplayData
PlainText
bytestr
)
->
Text
.
unpack
bytestr
Just
(
DisplayData
PlainText
bytestr
)
->
Text
.
unpack
bytestr
where
where
isPlain
(
DisplayData
mime
_
)
=
mime
==
PlainText
isPlain
(
DisplayData
mime
_
)
=
mime
==
PlainText
instance
Show
MimeType
where
instance
Show
MimeType
where
show
PlainText
=
"text/plain"
show
PlainText
=
"text/plain"
show
MimeHtml
=
"text/html"
show
MimeHtml
=
"text/html"
show
(
MimePng
_
_
)
=
"image/png"
show
(
MimePng
_
_
)
=
"image/png"
show
(
MimeJpg
_
_
)
=
"image/jpeg"
show
(
MimeJpg
_
_
)
=
"image/jpeg"
show
MimeSvg
=
"image/svg+xml"
show
MimeSvg
=
"image/svg+xml"
show
MimeLatex
=
"text/latex"
show
MimeLatex
=
"text/latex"
show
MimeJavascript
=
"application/javascript"
show
MimeJavascript
=
"application/javascript"
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.
-- | A channel populated with requests from the frontend.
shellReplyChannel
::
Chan
Message
,
-- ^ Writing to this channel causes a reply to be sent to the frontend.
shellRequestChannel
::
Chan
Message
controlRequestChannel
::
Chan
Message
,
-- ^ This channel is a duplicate of the shell request channel,
-- | Writing to this channel causes a reply to be sent to the frontend.
-- though using a different backend socket.
,
shellReplyChannel
::
Chan
Message
controlReplyChannel
::
Chan
Message
,
-- ^ This channel is a duplicate of the shell reply channel,
-- | This channel is a duplicate of the shell request channel, though using a different backend
-- though using a different backend socket.
-- socket.
iopubChannel
::
Chan
Message
,
-- ^ Writing to this channel sends an iopub message to the frontend.
,
controlRequestChannel
::
Chan
Message
hmacKey
::
ByteString
-- ^ Key used to sign messages.
-- | This channel is a duplicate of the shell reply channel, though using a different backend
}
-- socket.
,
controlReplyChannel
::
Chan
Message
data
ZeroMQStdin
=
StdinChannel
{
-- | Writing to this channel sends an iopub message to the frontend.
stdinRequestChannel
::
Chan
Message
,
,
iopubChannel
::
Chan
Message
stdinReplyChannel
::
Chan
Message
-- | Key used to sign messages.
}
,
hmacKey
::
ByteString
}
-- | Start responding on all ZeroMQ channels used to communicate with IPython
-- | via the provided profile. Return a set of channels which can be used to
data
ZeroMQStdin
=
-- | communicate with IPython in a more structured manner.
StdinChannel
{
stdinRequestChannel
::
Chan
Message
,
stdinReplyChannel
::
Chan
Message
}
-- | Start responding on all ZeroMQ channels used to communicate with IPython | via the provided
-- profile. Return a set of channels which can be used to | communicate with IPython in a more
-- 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,29 +66,28 @@ serveProfile profile debug = do
...
@@ -63,29 +66,28 @@ 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
serveStdin
::
Profile
->
IO
ZeroMQStdin
serveStdin
::
Profile
->
IO
ZeroMQStdin
serveStdin
profile
=
do
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.
...
@@ -143,11 +144,10 @@ control debug channels socket = do
...
@@ -143,11 +144,10 @@ control debug channels socket = do
where
where
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,19 +179,18 @@ receiveMessage debug socket = do
...
@@ -179,19 +179,18 @@ 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
then
do
then
do
remaining
<-
readUntil
str
remaining
<-
readUntil
str
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,10 +44,16 @@ except:
...
@@ -44,10 +44,16 @@ 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
filename
in
filenames
:
for
root
,
dirnames
,
filenames
in
os
.
walk
(
source_dir
):
if
filename
.
endswith
(
".hs"
):
# Skip cabal dist directories
sources
.
append
(
os
.
path
.
join
(
root
,
filename
))
if
"dist"
in
root
:
continue
for
filename
in
filenames
:
# Take Haskell files, but ignore the Cabal Setup.hs
if
filename
.
endswith
(
".hs"
)
and
filename
!=
"Setup.hs"
:
sources
.
append
(
os
.
path
.
join
(
root
,
filename
))
hindent_outputs
=
{}
hindent_outputs
=
{}
...
...
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