Commit 6d3afb9e authored by Tom McLaughlin's avatar Tom McLaughlin

Merge master

parents e14d003d 346c4960
...@@ -44,10 +44,8 @@ install: ...@@ -44,10 +44,8 @@ install:
# 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.
script: script:
- | - |
if [ ${GHCVER%.*} = "7.8" ]; then if [[ ${GHCVER%.*} == "7.8" || ${GHCVER%.*} == "7.10" ]]; then
travis_retry ./build.sh all travis_retry ./build.sh all
elif [ ${GHCVER%.*} = "7.10" ]; then
travis_retry ./build.sh all no-widgets
else else
travis_retry ./build.sh ihaskell travis_retry ./build.sh ihaskell
fi fi
......
...@@ -29,6 +29,8 @@ install instructions. ...@@ -29,6 +29,8 @@ install instructions.
**How to get help:** Feel free to open an issue [on Github](https://github.com/gibiansky/IHaskell/issues?direction=desc&sort=updated&state=open) or join the [Gitter channel](https://gitter.im/gibiansky/IHaskell?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). **How to get help:** Feel free to open an issue [on Github](https://github.com/gibiansky/IHaskell/issues?direction=desc&sort=updated&state=open) or join the [Gitter channel](https://gitter.im/gibiansky/IHaskell?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge).
Arch Linux has a package for IHaskell: https://aur.archlinux.org/packages/ihaskell-git/
### Install Using Installation Scripts ### Install Using Installation Scripts
#### Ubuntu: #### Ubuntu:
...@@ -63,17 +65,23 @@ Once this is done, running `ipython --version` should print out `3.0` or above. ...@@ -63,17 +65,23 @@ Once this is done, running `ipython --version` should print out `3.0` or above.
Note that IHaskell *requires* 3.0 or above; IHaskell *will not work* with IPython 2 or earlier. Note that IHaskell *requires* 3.0 or above; IHaskell *will not work* with IPython 2 or earlier.
#### Install Haskell #### Install Haskell
Install GHC and Cabal. You must have appropriate versions of both:
You can let [Stack](http://www.stackage.org/) take care of everything by running `stack setup` from within the IHaskell folder. Stack can also be used to build IHaskell later and will manage dependencies better than cabal (like in issue #578).
Or you can install GHC and Cabal manually. You must have appropriate versions of both:
```bash ```bash
ghc --numeric-version # Should be 7.6.* or 7.8.* ghc --numeric-version # Should be 7.6.* or 7.8.* or 7.10.*
cabal --version # Should be 1.18.* or newer cabal --version # Should be 1.18.* or newer
``` ```
These may be installed in a number of ways, including the [Haskell Platform](http://www.haskell.org/platform/), as a [standalone Mac app](https://github.com/ghcformacosx/ghc-dot-app), via Homebrew with `brew install ghc cabal-install`, and so on. GHC and Cabal may be installed in a number of other ways, including the [Haskell Platform](http://www.haskell.org/platform/), as a [standalone Mac app](https://github.com/ghcformacosx/ghc-dot-app), via Homebrew with `brew install ghc cabal-install`, and so on.
#### Install ZeroMQ #### Install ZeroMQ
Install ZeroMQ, a library IHaskell uses for asynchronous communication. Install ZeroMQ, a library IHaskell uses for asynchronous communication.
- **Mac OS X**: With [Homebrew](http://brew.sh/) installed, run `brew install zeromq`. (If using 32-bit Haskell Platform, you *may* need to use `brew install zeromq --universal`. YMMV.) - **Mac OS X**:
- With [Homebrew](http://brew.sh/) installed, run `brew install zeromq`. (If using 32-bit Haskell Platform, you *may* need to use `brew install zeromq --universal`. YMMV.)
- With [MacPorts](https://www.macports.org/) installed, run `ports install zmq`
- **Ubuntu**: Run `sudo apt-get install libzmq3-dev`. - **Ubuntu**: Run `sudo apt-get install libzmq3-dev`.
- **Other**: You can install ZeroMQ from source or use another package manager: - **Other**: You can install ZeroMQ from source or use another package manager:
```bash ```bash
...@@ -87,6 +95,9 @@ sudo ldconfig ...@@ -87,6 +95,9 @@ sudo ldconfig
If your own platform has a package and I haven't included instructions for it, feel free to send me an email or a PR on this README. If your own platform has a package and I haven't included instructions for it, feel free to send me an email or a PR on this README.
#### Install Haskell Tools #### Install Haskell Tools
*(This section can be skipped when using stack)*
First, make sure that executables installed by `cabal` are on your shell `PATH`: First, make sure that executables installed by `cabal` are on your shell `PATH`:
```bash ```bash
# If you have a ~/.cabal/bin folder: # If you have a ~/.cabal/bin folder:
...@@ -102,7 +113,12 @@ cabal install happy cpphs ...@@ -102,7 +113,12 @@ cabal install happy cpphs
``` ```
#### Build IHaskell #### Build IHaskell
Install IHaskell! You may install it from Hackage via `cabal install`: Install IHaskell! You may install it from Stackage via `stack install` (check the latest version on [http://www.stackage.org/lts-3.8]:
```bash
stack install ihaskell-0.6.5.0
```
Or you may install it from Hackage via `cabal install`:
```bash ```bash
cabal install ihaskell --reorder-goals cabal install ihaskell --reorder-goals
``` ```
...@@ -144,6 +160,14 @@ The above will install `ihaskell`, all support libraries (specified in `stack.ya ...@@ -144,6 +160,14 @@ The above will install `ihaskell`, all support libraries (specified in `stack.ya
stack install ihaskell ihaskell-aeson ihaskell-diagrams stack install ihaskell ihaskell-aeson ihaskell-diagrams
``` ```
Mac OS X users using MacPorts may run into an [issue involving libiconv](http://blog.omega-prime.co.uk/?p=96). A solution is to add the following lines in the file stack.yaml:
```
extra-lib-dirs:
- /usr/lib
extra-include-dirs:
- /usr/include
```
#### Run IHaskell #### Run IHaskell
Run IHaskell: Run IHaskell:
- `ihaskell install` to install the IHaskell kernel into Jupyter. - `ihaskell install` to install the IHaskell kernel into Jupyter.
......
...@@ -32,9 +32,6 @@ fi ...@@ -32,9 +32,6 @@ fi
# What to install. # What to install.
INSTALLS="" INSTALLS=""
# Remove my kernelspec
rm -rf ~/.ipython/kernels/haskell
# Compile dependencies. # Compile dependencies.
if [ $# -gt 0 ]; then if [ $# -gt 0 ]; then
if [ $1 = "all" ] || [ $1 = "ihaskell" ]; then if [ $1 = "all" ] || [ $1 = "ihaskell" ]; then
...@@ -47,7 +44,7 @@ INSTALLS="$INSTALLS ." ...@@ -47,7 +44,7 @@ INSTALLS="$INSTALLS ."
# Install ihaskell-display packages. # Install ihaskell-display packages.
if [ $# -gt 0 ]; then if [ $# -gt 0 ]; then
if [ $1 = "display" ] || [ $1 = "all" ]; then if [ $1 = "display" ] || [ $1 = "all" ]; then
# Install all the display libraries # Install all the display libraries
cd ihaskell-display cd ihaskell-display
for dir in `ls | grep -v ihaskell-widgets` for dir in `ls | grep -v ihaskell-widgets`
...@@ -58,25 +55,46 @@ if [ $# -gt 0 ]; then ...@@ -58,25 +55,46 @@ if [ $# -gt 0 ]; then
fi fi
fi fi
# Clean all required directories, just in case. cleanup () {
TOP=`pwd` # Remove old kernelspec
for pkg in $INSTALLS rm -rf ~/.ipython/kernels/haskell
do
cd ./$pkg
cabal clean
cd $TOP
done
# Stick a "./" before everything. # Clean all required directories, just in case.
INSTALL_DIRS=`echo $INSTALLS | tr ' ' '\n' | sed 's#^#./#' | tr ' ' '\n'` TOP=`pwd`
for pkg in $INSTALLS
do
cd ./$pkg
cabal clean
cd $TOP
done
}
echo CMD: cabal install --constraint "arithmoi -llvm" -j $INSTALL_DIRS --force-reinstalls --max-backjumps=-1 --reorder-goals install_selected () {
cabal install --constraint "arithmoi -llvm" -j $INSTALL_DIRS --force-reinstalls --max-backjumps=-1 --reorder-goals # Stick a "./" before everything.
INSTALL_DIRS=`echo $INSTALLS | tr ' ' '\n' | sed 's#^#./#' | tr ' ' '\n'`
if [ $2 = "no-widgets" ]; then echo CMD: cabal install --constraint "arithmoi -llvm" -j $INSTALL_DIRS --force-reinstalls --max-backjumps=-1 --reorder-goals
echo 'Not installing ihaskell-widgets' cabal install --constraint "arithmoi -llvm" -j $INSTALL_DIRS --force-reinstalls --max-backjumps=-1 --reorder-goals
elif [ $1 = "display" ] || [ $1 = "all" ]; then }
install_widgets () {
echo CMD: cabal install ihaskell-display/ihaskell-widgets
cabal install ihaskell-display/ihaskell-widgets cabal install ihaskell-display/ihaskell-widgets
}
# Check if arguments are correct, and proceed as required
if [ -z $2 ]; then
cleanup
install_selected
if [ $1 = "display" ] || [ $1 = "all" ]; then
install_widgets
fi
elif [ $2 = "no-widgets" ]; then
cleanup
install_selected
else
print_help
exit 1
fi fi
if hash ihaskell 2>/dev/null; then if hash ihaskell 2>/dev/null; then
......
import Distribution.Simple import Distribution.Simple
import System.Cmd import System.Process
main = defaultMainWithHooks main = defaultMainWithHooks
simpleUserHooks { preConf = \args confFlags -> do simpleUserHooks { preConf = \args confFlags -> do
......
...@@ -7,7 +7,7 @@ name: ihaskell-diagrams ...@@ -7,7 +7,7 @@ name: ihaskell-diagrams
-- PVP summary: +-+------- breaking API changes -- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions -- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change -- | | | +--- code changes with no API change
version: 0.3.0.0 version: 0.3.1.0
-- A short (one-line) description of the package. -- A short (one-line) description of the package.
synopsis: IHaskell display instances for diagram types synopsis: IHaskell display instances for diagram types
......
{-# LANGUAGE TypeSynonymInstances, QuasiQuotes, FlexibleInstances, OverloadedStrings #-}
module IHaskell.Display.Parsec () where
import System.Random
import Data.String.Here
import Data.HashMap.Strict as Map
import Control.Applicative ((<$>))
import qualified Data.Text as T
import Data.Text (Text)
import Text.Parsec (parse, sourceLine, sourceColumn)
import Text.Parsec.String (Parser)
import Text.Parsec.Error (errorPos, ParseError)
import Data.Aeson
import IHaskell.Display
instance Show a => IHaskellDisplay (Parser a) where
display renderable = return $ many [Display [javascript js], Display [html dom]]
where
dom = [hereFile|widget.html|]
js = [hereFile|widget.js|]
-- | Text to parse.
data ParseText = ParseText String
instance FromJSON ParseText where
parseJSON (Object v) = ParseText <$> v .: "text"
parseJSON _ = fail "Expecting object"
-- | Output of parsing.
instance Show a => ToJSON (Either ParseError a) where
toJSON (Left err) = object
[ "status" .= ("error" :: String)
, "line" .= sourceLine (errorPos err)
, "col" .= sourceColumn (errorPos err)
, "msg" .= show err
]
toJSON (Right result) = object ["status" .= ("success" :: String), "result" .= show result]
instance Show a => IHaskellWidget (Parser a) where
-- Name for this widget.
targetName _ = "parsec"
-- When we rece
comm widget (Object dict) publisher = do
let key = "text" :: Text
Just (String text) = Map.lookup key dict
result = parse widget "<interactive>" $ T.unpack text
publisher $ toJSON result
The MIT License (MIT)
Copyright (c) 2013 Andrew Gibiansky
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import Distribution.Simple
main = defaultMain
-- The name of the package.
name: ihaskell-parsec
-- The package version. See the Haskell package versioning policy (PVP)
-- for standards guiding when and how versions should be incremented.
-- http://www.haskell.org/haskellwiki/Package_versioning_policy
-- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.3.0.0
-- A short (one-line) description of the package.
synopsis: IHaskell display instances for Parsec
-- A longer description of the package.
-- description:
-- URL for the project homepage or repository.
homepage: http://www.github.com/gibiansky/ihaskell
-- The license under which the package is released.
license: MIT
-- The file containing the license text.
license-file: LICENSE
-- The package author(s).
author: Andrew Gibiansky
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: andrew.gibiansky@gmail.com
-- A copyright notice.
-- copyright:
category: Development
build-type: Simple
extra-source-files: widget.html, widget.js
-- Extra files to be distributed with the package, such as examples or a
-- README.
-- extra-source-files:
-- Constraint on the version of Cabal needed to build this package.
cabal-version: >=1.16
library
-- Modules exported by the library.
exposed-modules: IHaskell.Display.Parsec
-- Modules included in this library but not exported.
-- other-modules:
-- Language extensions.
default-extensions: DoAndIfThenElse
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.6 && <4.9,
aeson >=0.7 && <0.10,
text,
unordered-containers,
random >= 1,
parsec,
here,
ihaskell >= 0.5
-- Directories containing source files.
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010
<!-- CodeMirror component -->
<link rel="stylesheet" href="/static/components/codemirror/addon/lint/lint.css">
<!-- Parsec widget DOM -->
<form><textarea id="parsec-editor">Insert parser text here...</textarea></form>
<pre id="parsec-output"></pre>
// Only load this script once.
var kernel = IPython.notebook.kernel;
var initialized = kernel !== undefined && kernel != null;
console.log("Initialized", initialized);
if (initialized && window.parsecWidgetRegistered === undefined) {
// Do not load this script again.
window.parsecWidgetRegistered = true;
// Codemirror lint.js
// Must be included here, otherwise linting cannot happen the first time the widget is loaded.
(function() {
"use strict";
var GUTTER_ID = "CodeMirror-lint-markers";
var SEVERITIES = /^(?:error|warning)$/;
function showTooltip(e, content) {
var tt = document.createElement("div");
tt.className = "CodeMirror-lint-tooltip";
tt.appendChild(content.cloneNode(true));
document.body.appendChild(tt);
function position(e) {
if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px";
tt.style.left = (e.clientX + 5) + "px";
}
CodeMirror.on(document, "mousemove", position);
position(e);
if (tt.style.opacity != null) tt.style.opacity = 1;
return tt;
}
function rm(elt) {
if (elt.parentNode) elt.parentNode.removeChild(elt);
}
function hideTooltip(tt) {
if (!tt.parentNode) return;
if (tt.style.opacity == null) rm(tt);
tt.style.opacity = 0;
setTimeout(function() { rm(tt); }, 600);
}
function showTooltipFor(e, content, node) {
var tooltip = showTooltip(e, content);
function hide() {
CodeMirror.off(node, "mouseout", hide);
if (tooltip) { hideTooltip(tooltip); tooltip = null; }
}
var poll = setInterval(function() {
if (tooltip) for (var n = node;; n = n.parentNode) {
if (n == document.body) return;
if (!n) { hide(); break; }
}
if (!tooltip) return clearInterval(poll);
}, 400);
CodeMirror.on(node, "mouseout", hide);
}
function LintState(cm, options, hasGutter) {
this.marked = [];
this.options = options;
this.timeout = null;
this.hasGutter = hasGutter;
this.onMouseOver = function(e) { onMouseOver(cm, e); };
}
function parseOptions(cm, options) {
if (options instanceof Function) return {getAnnotations: options};
if (!options || options === true) options = {};
if (!options.getAnnotations) options.getAnnotations = cm.getHelper(CodeMirror.Pos(0, 0), "lint");
if (!options.getAnnotations) throw new Error("Required option 'getAnnotations' missing (lint addon)");
return options;
}
function clearMarks(cm) {
var state = cm.state.lint;
if (state.hasGutter) cm.clearGutter(GUTTER_ID);
for (var i = 0; i < state.marked.length; ++i)
state.marked[i].clear();
state.marked.length = 0;
}
function makeMarker(labels, severity, multiple, tooltips) {
var marker = document.createElement("div"), inner = marker;
marker.className = "CodeMirror-lint-marker-" + severity;
if (multiple) {
inner = marker.appendChild(document.createElement("div"));
inner.className = "CodeMirror-lint-marker-multiple";
}
if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
showTooltipFor(e, labels, inner);
});
return marker;
}
function getMaxSeverity(a, b) {
if (a == "error") return a;
else return b;
}
function groupByLine(annotations) {
var lines = [];
for (var i = 0; i < annotations.length; ++i) {
var ann = annotations[i], line = ann.from.line;
(lines[line] || (lines[line] = [])).push(ann);
}
return lines;
}
function annotationTooltip(ann) {
var severity = ann.severity;
if (!SEVERITIES.test(severity)) severity = "error";
var tip = document.createElement("div");
tip.className = "CodeMirror-lint-message-" + severity;
tip.appendChild(document.createTextNode(ann.message));
return tip;
}
function startLinting(cm) {
var state = cm.state.lint, options = state.options;
if (options.async)
options.getAnnotations(cm, updateLinting, options);
else
updateLinting(cm, options.getAnnotations(cm.getValue(), options.options));
}
function updateLinting(cm, annotationsNotSorted) {
clearMarks(cm);
var state = cm.state.lint, options = state.options;
var annotations = groupByLine(annotationsNotSorted);
for (var line = 0; line < annotations.length; ++line) {
var anns = annotations[line];
if (!anns) continue;
var maxSeverity = null;
var tipLabel = state.hasGutter && document.createDocumentFragment();
for (var i = 0; i < anns.length; ++i) {
var ann = anns[i];
var severity = ann.severity;
if (!SEVERITIES.test(severity)) severity = "error";
maxSeverity = getMaxSeverity(maxSeverity, severity);
if (options.formatAnnotation) ann = options.formatAnnotation(ann);
if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
className: "CodeMirror-lint-mark-" + severity,
__annotation: ann
}));
}
if (state.hasGutter)
cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,
state.options.tooltips));
}
if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
}
function onChange(cm) {
var state = cm.state.lint;
clearTimeout(state.timeout);
state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
}
function popupSpanTooltip(ann, e) {
var target = e.target || e.srcElement;
showTooltipFor(e, annotationTooltip(ann), target);
}
// When the mouseover fires, the cursor might not actually be over
// the character itself yet. These pairs of x,y offsets are used to
// probe a few nearby points when no suitable marked range is found.
var nearby = [0, 0, 0, 5, 0, -5, 5, 0, -5, 0];
function onMouseOver(cm, e) {
if (!/\bCodeMirror-lint-mark-/.test((e.target || e.srcElement).className)) return;
for (var i = 0; i < nearby.length; i += 2) {
var spans = cm.findMarksAt(cm.coordsChar({left: e.clientX + nearby[i],
top: e.clientY + nearby[i + 1]}));
for (var j = 0; j < spans.length; ++j) {
var span = spans[j], ann = span.__annotation;
if (ann) return popupSpanTooltip(ann, e);
}
}
}
function optionHandler(cm, val, old) {
if (old && old != CodeMirror.Init) {
clearMarks(cm);
cm.off("change", onChange);
CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
delete cm.state.lint;
}
if (val) {
var gutters = cm.getOption("gutters"), hasLintGutter = false;
for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
cm.on("change", onChange);
if (state.options.tooltips != false)
CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
startLinting(cm);
}
}
CodeMirror.defineOption("lintWith", false, optionHandler); // deprecated
CodeMirror.defineOption("lint", false, optionHandler); // deprecated
})();
var parsecWidgetCounter = 0;
// Register the comm target.
var ParsecWidget = function (comm) {
this.comm = comm;
this.comm.on_msg($.proxy(this.handler, this));
// Get the cell that was probably executed.
// The msg_id:cell mapping will make this possible without guessing.
this.cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);
// Store this widget so we can use it from callbacks.
var widget = this;
// Editor options.
var options = {
lineNumbers: true,
// Show parsec errors as lint errors.
gutters: ["CodeMirror-lint-markers"],
lintWith: {
"getAnnotations": function(cm, update, opts) {
var errs = [];
if (widget.hasError) {
var col = widget.error["col"];
var line = widget.error["line"];
errs = [{
from: CodeMirror.Pos(line - 1, col - 1),
to: CodeMirror.Pos(line - 1, col),
message: widget.error["msg"],
severity: "error"
}];
}
update(cm, errs);
},
"async": true,
}
};
// Create the editor.
var out = this.cell.output_area.element;
this.textarea = out.find("#parsec-editor")[0];
this.output = out.find("#parsec-output")[0];
// Give the elements a different name.
this.textarea.id += parsecWidgetCounter;
this.output.id += parsecWidgetCounter;
parsecWidgetCounter++;
var editor = CodeMirror.fromTextArea(this.textarea, options);
var editor = editor;
// Update every key press.
editor.on("keyup", function() {
var text = editor.getDoc().getValue();
comm.send({"text": text});
});
};
ParsecWidget.prototype.handler = function(msg) {
var data = msg.content.data;
this.hasError = (data["status"] == "error");
console.log(this.hasError);
if (this.hasError) {
this.output.innerHTML = data["msg"];
this.error = data;
} else {
this.output.innerHTML = data["result"];
}
};
// Register this widget.
IPython.notebook.kernel.comm_manager.register_target('parsec', IPython.utils.always_new(ParsecWidget));
console.log("Registering Parsec widget.");
}
...@@ -61,6 +61,7 @@ library ...@@ -61,6 +61,7 @@ library
build-depends: base >=4.6 && <4.9, build-depends: base >=4.6 && <4.9,
plot, plot,
bytestring, bytestring,
hmatrix >= 0.10,
ihaskell >= 0.6.2 ihaskell >= 0.6.2
-- Directories containing source files. -- Directories containing source files.
......
# ChangeLog for `ihaskell-widgets`
## `v0.2.2.1`
+ The `properties` function now prints types associated with widget fields.
## `v0.2.2.0`
+ Bump aeson upper bound to `<0.11`.
## `v0.2.0.0`
> Complete version with full fleshed out API.
Major additions:
+ Added `interactive` support under `IHaskell.Display.Widgets.Interactive`.
+ Add `PlaceProxy`, `Proxy` and `Valid` widgets.
+ Support for IPython 4.0.
## `v0.1.*.*` (Experimental)
> All IPython widgets and related functionality, but no support for `interactive`.
...@@ -22,13 +22,14 @@ ...@@ -22,13 +22,14 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"{-# LANGUAGE OverloadedStrings #-}\n", "{-# LANGUAGE OverloadedStrings #-}\n",
"{-# LANGUAGE FlexibleContexts #-}\n",
"import IHaskell.Display.Widgets\n", "import IHaskell.Display.Widgets\n",
"import Data.Text (pack, unpack)\n", "import Data.Text (pack, unpack)\n",
"import Text.Printf (printf)" "import Text.Printf (printf)"
...@@ -43,18 +44,20 @@ ...@@ -43,18 +44,20 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"-- Constructors\n", "-- Check box\n",
"chk <- mkCheckBox\n", "chk <- mkCheckBox\n",
"\n",
"-- Toggle button\n",
"tgb <- mkToggleButton\n", "tgb <- mkToggleButton\n",
"\n", "\n",
"-- For demonstration\n", "-- Valid widget: Displaying booleans conveniently\n",
"o <- mkHTMLWidget" "vld <- mkValidWidget"
] ]
}, },
{ {
...@@ -66,16 +69,16 @@ ...@@ -66,16 +69,16 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"-- Display\n", "-- Display the widgets\n",
"chk\n", "chk\n",
"tgb\n", "tgb\n",
"o" "vld"
] ]
}, },
{ {
...@@ -87,38 +90,23 @@ ...@@ -87,38 +90,23 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField chk Description \"Bool 1: \"\n", "setField chk Description \"Bool 1: \"\n",
"setField tgb Description \"Bool 2\"\n", "setField tgb Description \"Bool 2\"\n",
"\n", "\n",
"-- Helper function\n",
"refresh b =\n",
" let stat = if b then \"green\" else \"red\"\n",
" fmt = \"<div style=\\\"background:%s;color:#ffffff\\\"><b>%s</b></div>\"\n",
" in setField o StringValue $ pack $ printf fmt stat (show b)\n",
"\n",
" -- Cosmetic changes\n", " -- Cosmetic changes\n",
"setField o Description \"Bool 1 && Bool 2\"\n", "setField vld Description \"Bool 1 && Bool 2\"\n",
"setField o Padding 10\n",
"\n", "\n",
" -- And (&&) the two values, and send output to html widget\n", " -- And (&&) the two values, and send output to html widget\n",
"setHandler w = setField w ChangeHandler $ do\n", "setHandler w = setField w ChangeHandler $ do\n",
" b1 <- getField chk BoolValue\n", " b1 <- getField chk BoolValue\n",
" b2 <- getField tgb BoolValue\n", " b2 <- getField tgb BoolValue\n",
" refresh (b1 && b2)\n", " setField vld BoolValue (b1 && b2)\n",
"\n", "\n",
"setHandler chk\n", "setHandler chk\n",
"setHandler tgb" "setHandler tgb"
...@@ -142,7 +130,7 @@ ...@@ -142,7 +130,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -163,19 +151,11 @@ ...@@ -163,19 +151,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"sign <- mkCheckBox\n", "sign <- mkCheckBox\n",
"bits <- replicateM 7 mkToggleButton\n", "bits <- replicateM 7 mkToggleButton\n",
...@@ -195,19 +175,11 @@ ...@@ -195,19 +175,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"box <- mkFlexBox\n", "box <- mkFlexBox\n",
"out <- mkHTMLWidget\n", "out <- mkHTMLWidget\n",
...@@ -248,19 +220,11 @@ ...@@ -248,19 +220,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"import Control.Arrow (first, second)\n", "import Control.Arrow (first, second)\n",
"\n", "\n",
...@@ -295,6 +259,12 @@ ...@@ -295,6 +259,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -42,121 +42,12 @@ ...@@ -42,121 +42,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>ChildWidget :: forall (w :: WidgetType). (RecAll Attr (WidgetFields w) ToPairs) => IPythonWidget w -> ChildWidget</span>"
],
"text/plain": [
"ChildWidget :: forall (w :: WidgetType). (RecAll Attr (WidgetFields w) ToPairs) => IPythonWidget w -> ChildWidget"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
":t ChildWidget" ":t ChildWidget"
] ]
...@@ -170,7 +61,7 @@ ...@@ -170,7 +61,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -190,19 +81,11 @@ ...@@ -190,19 +81,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"import Control.Monad (replicateM)\n", "import Control.Monad (replicateM)\n",
"\n", "\n",
...@@ -236,125 +119,12 @@ ...@@ -236,125 +119,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='err-msg'>No instance for (Data.Vinyl.Lens.RElem<br/> 'ihaskell-widgets-0.1.0.0:IHaskell.Display.Widgets.Singletons.Orientation '[] (Data.Vinyl.TypeLevel.RIndex 'ihaskell-widgets-0.1.0.0:IHaskell.Display.Widgets.Singletons.Orientation '[]))<br/> arising from a use of ‘setField’<br/>In the expression: setField box Orientation VerticalOrientation<br/>In an equation for ‘it’: it = setField box Orientation VerticalOrientation</span>"
],
"text/plain": [
"No instance for (Data.Vinyl.Lens.RElem\n",
" 'ihaskell-widgets-0.1.0.0:IHaskell.Display.Widgets.Singletons.Orientation '[] (Data.Vinyl.TypeLevel.RIndex 'ihaskell-widgets-0.1.0.0:IHaskell.Display.Widgets.Singletons.Orientation '[]))\n",
" arising from a use of ‘setField’\n",
"In the expression: setField box Orientation VerticalOrientation\n",
"In an equation for ‘it’: it = setField box Orientation VerticalOrientation"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- Trying to set orientation for Boxes\n", "-- Trying to set orientation for Boxes\n",
"setField box Orientation VerticalOrientation" "setField box Orientation VerticalOrientation"
...@@ -369,24 +139,115 @@ ...@@ -369,24 +139,115 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- Trying to set orientation for FlexBox\n", "-- Trying to set orientation for FlexBox\n",
"setField flx Orientation VerticalOrientation" "setField flx Orientation VerticalOrientation"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### ProxyWidget and PlaceProxy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `ProxyWidget` widget allows for zero-or-one widgets to be placed inside it.\n",
"\n",
"From the IHaskell perspective, this is similar to the `Output` widget, but supports only widgets inside it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"[b1, b2, b3] <- replicateM 3 mkButton\n",
"\n",
"setField b1 Description \"Button 1\"\n",
"setField b2 Description \"Button 2\"\n",
"setField b3 Description \"Button 3\"\n",
"\n",
"-- A proxy widget to display one button at a time\n",
"proxy <- mkProxyWidget\n",
"\n",
"-- b1 ~> b2\n",
"setField b1 ClickHandler $ setField proxy Child (Just $ ChildWidget b2)\n",
"\n",
"-- b2 ~> b3\n",
"setField b2 ClickHandler $ setField proxy Child (Just $ ChildWidget b3)\n",
"\n",
"-- b3 ~> b1\n",
"setField b3 ClickHandler $ setField proxy Child (Just $ ChildWidget b1)\n",
"\n",
"-- Set initial child, and display\n",
"setField proxy Child (Just $ ChildWidget b1)\n",
"\n",
"proxy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `PlaceProxy` widget allows for more flexible use-cases involving arbitrary widgets. It is similar to `ProxyWidget`, but allows more control over where the widget is displayed.\n",
"\n",
"This widget can be used to display widgets inside markdown cells, among other places such as custom widgets or custom html elements. For example, we can create a html `div` inside this markdown cell, and cause the child widget to display in it using its CSS selector.\n",
"\n",
"`<div id=\"widget_out\"></div>`\n",
"\n",
"<div id=\"widget_out\"></div>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": false
},
"outputs": [],
"source": [
"pp <- mkPlaceProxy\n",
"button <- mkButton\n",
"setField button Description \"(0,0)\"\n",
"\n",
"-- Put button inside the place proxy widget\n",
"setField pp Child (Just $ ChildWidget button)\n",
"\n",
"-- Output to the div created above\n",
"setField pp Selector \"#widget_out\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The widget doesn't yet display, but when we try to display it, the child widget shows in the div as expected."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"pp"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
...@@ -403,7 +264,7 @@ ...@@ -403,7 +264,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -422,19 +283,11 @@ ...@@ -422,19 +283,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"buttons' <- replicateM 5 mkButton\n", "buttons' <- replicateM 5 mkButton\n",
"\n", "\n",
...@@ -460,6 +313,12 @@ ...@@ -460,6 +313,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
"jpg <- get \"http://imgs.xkcd.com/comics/functional.png\"\n", "jpg <- get \"http://imgs.xkcd.com/comics/functional.png\"\n",
"\n", "\n",
"img <- mkImageWidget\n", "img <- mkImageWidget\n",
"setField img SB64Value (encode64 jpg)\n", "setField img B64Value (encode64 jpg)\n",
"img" "img"
] ]
}, },
...@@ -104,6 +104,12 @@ ...@@ -104,6 +104,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -103,7 +103,7 @@ ...@@ -103,7 +103,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -139,120 +139,11 @@ ...@@ -139,120 +139,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>setField :: forall (w :: WidgetType) (f :: Field). (RElem f (WidgetFields w) (RIndex f (WidgetFields w)), ToPairs (Attr f), IHaskellWidget (IPythonWidget w)) => IPythonWidget w -> SField f -> FieldType f -> IO ()</span>"
],
"text/plain": [
"setField :: forall (w :: WidgetType) (f :: Field). (RElem f (WidgetFields w) (RIndex f (WidgetFields w)), ToPairs (Attr f), IHaskellWidget (IPythonWidget w)) => IPythonWidget w -> SField f -> FieldType f -> IO ()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
":t setField" ":t setField"
] ]
...@@ -270,121 +161,12 @@ ...@@ -270,121 +161,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>getField :: forall (w :: WidgetType) (f :: Field). RElem f (WidgetFields w) (RIndex f (WidgetFields w)) => IPythonWidget w -> SField f -> IO (FieldType f)</span>"
],
"text/plain": [
"getField :: forall (w :: WidgetType) (f :: Field). RElem f (WidgetFields w) (RIndex f (WidgetFields w)) => IPythonWidget w -> SField f -> IO (FieldType f)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
":t getField" ":t getField"
] ]
...@@ -405,120 +187,11 @@ ...@@ -405,120 +187,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>properties :: forall (w :: WidgetType). IPythonWidget w -> IO ()</span>"
],
"text/plain": [
"properties :: forall (w :: WidgetType). IPythonWidget w -> IO ()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
":t properties" ":t properties"
] ]
...@@ -534,30 +207,11 @@ ...@@ -534,30 +207,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"3"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"abc\""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- Showables\n", "-- Showables\n",
"1 + 2\n", "1 + 2\n",
...@@ -573,120 +227,11 @@ ...@@ -573,120 +227,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>display :: forall a. IHaskellDisplay a => a -> IO Display</span>"
],
"text/plain": [
"display :: forall a. IHaskellDisplay a => a -> IO Display"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"import IHaskell.Display\n", "import IHaskell.Display\n",
":t display" ":t display"
...@@ -714,120 +259,11 @@ ...@@ -714,120 +259,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>closeWidget :: forall w. IHaskellWidget w => w -> IO ()</span>"
],
"text/plain": [
"closeWidget :: forall w. IHaskellWidget w => w -> IO ()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
":t closeWidget" ":t closeWidget"
] ]
...@@ -850,120 +286,11 @@ ...@@ -850,120 +286,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>button :: Button</span>"
],
"text/plain": [
"button :: Button"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"button <- mkButton -- Construct a Button\n", "button <- mkButton -- Construct a Button\n",
":t button" ":t button"
...@@ -978,7 +305,7 @@ ...@@ -978,7 +305,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -991,54 +318,17 @@ ...@@ -991,54 +318,17 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"To view a widget's properties, we use the `properties` function:" "To view a widget's properties, we use the `properties` function. It also shows the type represented by the `Field`, which generally are not visible in type signatures due to high levels of type-hackery."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": false "scrolled": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"ViewModule\n",
"ViewName\n",
"MsgThrottle\n",
"Version\n",
"DisplayHandler\n",
"Visible\n",
"CSS\n",
"DOMClasses\n",
"Width\n",
"Height\n",
"Padding\n",
"Margin\n",
"Color\n",
"BackgroundColor\n",
"BorderColor\n",
"BorderWidth\n",
"BorderRadius\n",
"BorderStyle\n",
"FontStyle\n",
"FontWeight\n",
"FontSize\n",
"FontFamily\n",
"Description\n",
"Tooltip\n",
"Disabled\n",
"Icon\n",
"ButtonStyle\n",
"ClickHandler"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- The button widget has many properties.\n", "-- The button widget has many properties.\n",
"properties button" "properties button"
...@@ -1053,19 +343,11 @@ ...@@ -1053,19 +343,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- 250 pixels wide\n", "-- 250 pixels wide\n",
"setField button Width 250" "setField button Width 250"
...@@ -1080,20 +362,12 @@ ...@@ -1080,20 +362,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField button Description \"Click Me (._.\\\")\"\n", "setField button Description \"Click Me (._.\\\")\"\n",
"setField button ButtonStyle SuccessButton\n", "setField button ButtonStyle SuccessButton\n",
...@@ -1115,19 +389,11 @@ ...@@ -1115,19 +389,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 13, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField button ClickHandler $ putStrLn \"fO_o\"\n", "setField button ClickHandler $ putStrLn \"fO_o\"\n",
"button -- Displaying again for convenience" "button -- Displaying again for convenience"
...@@ -1142,19 +408,11 @@ ...@@ -1142,19 +408,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 14, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField button ClickHandler $ getLine >>= putStrLn" "setField button ClickHandler $ getLine >>= putStrLn"
] ]
...@@ -1165,6 +423,12 @@ ...@@ -1165,6 +423,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -46,9 +46,9 @@ ...@@ -46,9 +46,9 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": false
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -77,19 +77,11 @@ ...@@ -77,19 +77,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField bit MaxInt 20\n", "setField bit MaxInt 20\n",
"setField bit MinInt 10\n", "setField bit MinInt 10\n",
...@@ -119,7 +111,7 @@ ...@@ -119,7 +111,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -131,7 +123,7 @@ ...@@ -131,7 +123,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -143,21 +135,11 @@ ...@@ -143,21 +135,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"(25,75)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"getField irs IntPairValue" "getField irs IntPairValue"
] ]
...@@ -178,7 +160,7 @@ ...@@ -178,7 +160,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -190,19 +172,11 @@ ...@@ -190,19 +172,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField inp IntValue 42" "setField inp IntValue 42"
] ]
...@@ -213,6 +187,12 @@ ...@@ -213,6 +187,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -16,769 +16,12 @@ ...@@ -16,769 +16,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>plain :: String -> DisplayData</span>"
],
"text/plain": [
"plain :: String -> DisplayData"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>html :: String -> DisplayData</span>"
],
"text/plain": [
"html :: String -> DisplayData"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>jpg :: Width -> Height -> Base64 -> DisplayData</span>"
],
"text/plain": [
"jpg :: Width -> Height -> Base64 -> DisplayData"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>svg :: String -> DisplayData</span>"
],
"text/plain": [
"svg :: String -> DisplayData"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>latex :: String -> DisplayData</span>"
],
"text/plain": [
"latex :: String -> DisplayData"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>javascript :: String -> DisplayData</span>"
],
"text/plain": [
"javascript :: String -> DisplayData"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre-wrap;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>many :: [Display] -> Display</span>"
],
"text/plain": [
"many :: [Display] -> Display"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"{-# LANGUAGE OverloadedStrings #-}\n", "{-# LANGUAGE OverloadedStrings #-}\n",
"import IHaskell.Display.Widgets\n", "import IHaskell.Display.Widgets\n",
...@@ -806,7 +49,7 @@ ...@@ -806,7 +49,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -838,6 +81,12 @@ ...@@ -838,6 +81,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -13,13 +13,14 @@ ...@@ -13,13 +13,14 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"{-# LANGUAGE OverloadedStrings #-}\n", "{-# LANGUAGE OverloadedStrings #-}\n",
"{-# LANGUAGE FlexibleContexts #-}\n",
"import IHaskell.Display.Widgets" "import IHaskell.Display.Widgets"
] ]
}, },
...@@ -32,7 +33,7 @@ ...@@ -32,7 +33,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -83,19 +84,11 @@ ...@@ -83,19 +84,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"import Data.IORef\n", "import Data.IORef\n",
"import Graphics.Rendering.Chart.Easy hiding (tan)\n", "import Graphics.Rendering.Chart.Easy hiding (tan)\n",
...@@ -164,19 +157,11 @@ ...@@ -164,19 +157,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"divBox <- mkFlexBox\n", "divBox <- mkFlexBox\n",
"setField divBox Orientation HorizontalOrientation\n", "setField divBox Orientation HorizontalOrientation\n",
...@@ -204,20 +189,12 @@ ...@@ -204,20 +189,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"slBox <- mkFlexBox\n", "slBox <- mkFlexBox\n",
"\n", "\n",
...@@ -244,19 +221,11 @@ ...@@ -244,19 +221,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- The four FlexBox widgets.\n", "-- The four FlexBox widgets.\n",
"import Control.Monad (replicateM, forM_)\n", "import Control.Monad (replicateM, forM_)\n",
...@@ -302,19 +271,11 @@ ...@@ -302,19 +271,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- A FlexBox with ToggleButtons\n", "-- A FlexBox with ToggleButtons\n",
"buttonBox <- mkFlexBox\n", "buttonBox <- mkFlexBox\n",
...@@ -339,19 +300,11 @@ ...@@ -339,19 +300,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"import Control.Arrow (first, second)\n", "import Control.Arrow (first, second)\n",
"\n", "\n",
...@@ -384,19 +337,11 @@ ...@@ -384,19 +337,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField tlBox Children $ map ChildWidget $ boxes ++ [buttonBox] ++ rangeBoxes" "setField tlBox Children $ map ChildWidget $ boxes ++ [buttonBox] ++ rangeBoxes"
] ]
...@@ -410,19 +355,11 @@ ...@@ -410,19 +355,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField tlBox Titles [\"Plot title\", \"X-Label\", \"Y-Label\", \"Grid\", \"X-range\", \"Y-range\"]" "setField tlBox Titles [\"Plot title\", \"X-Label\", \"Y-Label\", \"Grid\", \"X-range\", \"Y-range\"]"
] ]
...@@ -436,19 +373,11 @@ ...@@ -436,19 +373,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"let syncVal widget value fieldGetter = readIORef plotState >>= setField widget value . fieldGetter\n", "let syncVal widget value fieldGetter = readIORef plotState >>= setField widget value . fieldGetter\n",
" in do\n", " in do\n",
...@@ -478,7 +407,7 @@ ...@@ -478,7 +407,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -500,22 +429,11 @@ ...@@ -500,22 +429,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 13, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- Spurious update to display empty plot instead of empty image initially\n", "-- Spurious update to display empty plot instead of empty image initially\n",
"update return\n", "update return\n",
...@@ -532,7 +450,7 @@ ...@@ -532,7 +450,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 14, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -543,7 +461,7 @@ ...@@ -543,7 +461,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 15, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -554,7 +472,7 @@ ...@@ -554,7 +472,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 16, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -569,6 +487,12 @@ ...@@ -569,6 +487,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -49,19 +49,11 @@ ...@@ -49,19 +49,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField msel Description \"Functions to show (One or more)\"\n", "setField msel Description \"Functions to show (One or more)\"\n",
"setField msel Options (OptionLabels [\"sin\", \"cos\"])\n", "setField msel Options (OptionLabels [\"sin\", \"cos\"])\n",
...@@ -79,20 +71,12 @@ ...@@ -79,20 +71,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"import Graphics.Rendering.Chart.Easy hiding (tan)\n", "import Graphics.Rendering.Chart.Easy hiding (tan)\n",
"import Graphics.Rendering.Chart.Backend.Cairo\n", "import Graphics.Rendering.Chart.Backend.Cairo\n",
...@@ -140,92 +124,11 @@ ...@@ -140,92 +124,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- Display the widgets\n", "-- Display the widgets\n",
"msel\n", "msel\n",
...@@ -246,6 +149,12 @@ ...@@ -246,6 +149,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -21,19 +21,20 @@ ...@@ -21,19 +21,20 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"{-# LANGUAGE OverloadedStrings #-}\n", "{-# LANGUAGE OverloadedStrings #-}\n",
"{-# LANGUAGE FlexibleContexts #-}\n",
"import IHaskell.Display.Widgets" "import IHaskell.Display.Widgets"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -69,7 +70,7 @@ ...@@ -69,7 +70,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -82,7 +83,7 @@ ...@@ -82,7 +83,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -94,7 +95,7 @@ ...@@ -94,7 +95,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -116,7 +117,7 @@ ...@@ -116,7 +117,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -142,7 +143,7 @@ ...@@ -142,7 +143,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
...@@ -154,20 +155,12 @@ ...@@ -154,20 +155,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false, "collapsed": false,
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"-- Some padding\n", "-- Some padding\n",
"setField text Padding 5" "setField text Padding 5"
...@@ -182,19 +175,11 @@ ...@@ -182,19 +175,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField text Placeholder \"Enter your text here...\"\n", "setField text Placeholder \"Enter your text here...\"\n",
"setField area Placeholder \"Parsed output will appear here...\"" "setField area Placeholder \"Parsed output will appear here...\""
...@@ -216,7 +201,7 @@ ...@@ -216,7 +201,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -239,7 +224,7 @@ ...@@ -239,7 +224,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -300,19 +285,11 @@ ...@@ -300,19 +285,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": null,
"metadata": { "metadata": {
"collapsed": false "collapsed": false
}, },
"outputs": [ "outputs": [],
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"setField text ChangeHandler $ do\n", "setField text ChangeHandler $ do\n",
" input <- unpack <$> getField text StringValue\n", " input <- unpack <$> getField text StringValue\n",
...@@ -338,7 +315,7 @@ ...@@ -338,7 +315,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 13, "execution_count": null,
"metadata": { "metadata": {
"collapsed": true "collapsed": true
}, },
...@@ -354,6 +331,12 @@ ...@@ -354,6 +331,12 @@
"display_name": "Haskell", "display_name": "Haskell",
"language": "haskell", "language": "haskell",
"name": "haskell" "name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -8,26 +8,17 @@ ...@@ -8,26 +8,17 @@
## Creating widgets ## Creating widgets
Let's say the user types in some code, and the only effect of that code is the creation of a widget. Let's say the user types in some code, and the only effect of that code is the creation of a widget.
The kernel will open a comm for the widget, and store a reference to that comm inside it. Then, to The kernel will open a comm for the widget, and store a reference to that comm. The comm_open message
notify the frontend about the creation of a widget, an initial state update is sent on the widget's also holds the initial state of the widget in it, which is used by the frontend to create a model for
comm. the widget.
> The comm should be opened with a `target_name` of `"ipython.widget"`. > The comm should be opened with a `target_name` of `"ipython.widget"`.
The initial state update message looks like this:
```json
{
"method": "update",
"state": { "<some/all widget properties>" }
}
```
Any *numeric* property initialized with the empty string is provided the default value by the Any *numeric* property initialized with the empty string is provided the default value by the
frontend. Some numbers need to be sent as actual numbers (when non-null), whereas some (especially frontend. Some numbers need to be sent as actual numbers (when non-null), whereas the ones representing
those used by sliders) need to be sent as strings. lengths in CSS units need to be sent as strings.
The initial state update must *at least* have the following fields: The initial state must *at least* have the following fields:
- `msg_throttle` (default 3): To prevent the kernel from flooding with messages, the messages from - `msg_throttle` (default 3): To prevent the kernel from flooding with messages, the messages from
the widget to the kernel are throttled. If `msg_throttle` messages were sent, and all are still the widget to the kernel are throttled. If `msg_throttle` messages were sent, and all are still
...@@ -43,8 +34,8 @@ The initial state update must *at least* have the following fields: ...@@ -43,8 +34,8 @@ The initial state update must *at least* have the following fields:
- Rest of the properties as required initially. - Rest of the properties as required initially.
This state update is also used with fragments of the overall state to sync changes between the This state is also used with fragments of the overall state to sync changes between the frontend and
frontend and the kernel. the kernel.
## Displaying widgets ## Displaying widgets
...@@ -111,7 +102,7 @@ If this were not so, the frontend would not be able to determine under which cel ...@@ -111,7 +102,7 @@ If this were not so, the frontend would not be able to determine under which cel
input widget, when an `input_request` is received. input widget, when an `input_request` is received.
Now, widgets cannot send `execute_request` messages. They can only send `comm_data` messages, which Now, widgets cannot send `execute_request` messages. They can only send `comm_data` messages, which
means that it's not possible to fetch input through widget events. means that it's not possible to fetch input inside widget event handlers.
--- ---
......
...@@ -10,7 +10,7 @@ name: ihaskell-widgets ...@@ -10,7 +10,7 @@ name: ihaskell-widgets
-- PVP summary: +-+------- breaking API changes -- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions -- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change -- | | | +--- code changes with no API change
version: 0.1.0.0 version: 0.2.2.1
-- A short (one-line) description of the package. -- A short (one-line) description of the package.
synopsis: IPython standard widgets for IHaskell. synopsis: IPython standard widgets for IHaskell.
...@@ -57,11 +57,14 @@ library ...@@ -57,11 +57,14 @@ library
-- Modules included in this library but not exported. -- Modules included in this library but not exported.
other-modules: IHaskell.Display.Widgets.Button other-modules: IHaskell.Display.Widgets.Button
IHaskell.Display.Widgets.Box.Box IHaskell.Display.Widgets.Box.Box
IHaskell.Display.Widgets.Box.Proxy
IHaskell.Display.Widgets.Box.PlaceProxy
IHaskell.Display.Widgets.Box.FlexBox IHaskell.Display.Widgets.Box.FlexBox
IHaskell.Display.Widgets.Box.SelectionContainer.Accordion IHaskell.Display.Widgets.Box.SelectionContainer.Accordion
IHaskell.Display.Widgets.Box.SelectionContainer.Tab IHaskell.Display.Widgets.Box.SelectionContainer.Tab
IHaskell.Display.Widgets.Bool.CheckBox IHaskell.Display.Widgets.Bool.CheckBox
IHaskell.Display.Widgets.Bool.ToggleButton IHaskell.Display.Widgets.Bool.ToggleButton
IHaskell.Display.Widgets.Bool.Valid
IHaskell.Display.Widgets.Int.IntText IHaskell.Display.Widgets.Int.IntText
IHaskell.Display.Widgets.Int.BoundedInt.BoundedIntText IHaskell.Display.Widgets.Int.BoundedInt.BoundedIntText
IHaskell.Display.Widgets.Int.BoundedInt.IntProgress IHaskell.Display.Widgets.Int.BoundedInt.IntProgress
...@@ -92,20 +95,35 @@ library ...@@ -92,20 +95,35 @@ library
-- other-extensions: -- other-extensions:
-- Other library packages from which modules are imported. -- Other library packages from which modules are imported.
build-depends: aeson >=0.7 && < 0.10 -- singletons 2.* require ghc 7.10.2
, base >=4.7 && <4.9 if impl(ghc >= 7.10.2)
, containers >= 0.5 build-depends: aeson >=0.7 && < 0.11
, ipython-kernel >= 0.6.1.2 , base >=4.7 && <4.9
, text >= 0.11 , containers >= 0.5
, unordered-containers -any , ipython-kernel >= 0.6.1.2
, nats -any , text >= 0.11
, vinyl >= 0.5 , unordered-containers -any
, vector -any , nats -any
, singletons >= 0.9.0 , vinyl >= 0.5
, scientific -any , vector -any
, unix -any , singletons >= 0.9.0
, scientific -any
, ihaskell >= 0.6.4.1 , unix -any
, ihaskell >= 0.6.4.1
else
build-depends: aeson >=0.7 && < 0.11
, base >=4.7 && <4.9
, containers >= 0.5
, ipython-kernel >= 0.6.1.2
, text >= 0.11
, unordered-containers -any
, nats -any
, vinyl >= 0.5
, vector -any
, singletons >= 0.9.0 && <2.0
, scientific -any
, unix -any
, ihaskell >= 0.6.4.1
-- Directories containing source files. -- Directories containing source files.
hs-source-dirs: src hs-source-dirs: src
...@@ -120,3 +138,8 @@ library ...@@ -120,3 +138,8 @@ library
-- ghc-7.10.* = 100 -- ghc-7.10.* = 100
if impl(ghc == 7.8.*) if impl(ghc == 7.8.*)
ghc-options: -fcontext-stack=100 ghc-options: -fcontext-stack=100
-- compile without optimizations not to run out of memory on travis
if impl(ghc == 7.10.*)
ghc-options: -O0
...@@ -3,12 +3,15 @@ module IHaskell.Display.Widgets (module X) where ...@@ -3,12 +3,15 @@ module IHaskell.Display.Widgets (module X) where
import IHaskell.Display.Widgets.Button as X import IHaskell.Display.Widgets.Button as X
import IHaskell.Display.Widgets.Box.Box as X import IHaskell.Display.Widgets.Box.Box as X
import IHaskell.Display.Widgets.Box.Proxy as X
import IHaskell.Display.Widgets.Box.PlaceProxy as X
import IHaskell.Display.Widgets.Box.FlexBox as X import IHaskell.Display.Widgets.Box.FlexBox as X
import IHaskell.Display.Widgets.Box.SelectionContainer.Accordion as X import IHaskell.Display.Widgets.Box.SelectionContainer.Accordion as X
import IHaskell.Display.Widgets.Box.SelectionContainer.Tab as X import IHaskell.Display.Widgets.Box.SelectionContainer.Tab as X
import IHaskell.Display.Widgets.Bool.CheckBox as X import IHaskell.Display.Widgets.Bool.CheckBox as X
import IHaskell.Display.Widgets.Bool.ToggleButton as X import IHaskell.Display.Widgets.Bool.ToggleButton as X
import IHaskell.Display.Widgets.Bool.Valid as X
import IHaskell.Display.Widgets.Int.IntText as X import IHaskell.Display.Widgets.Int.IntText as X
import IHaskell.Display.Widgets.Int.BoundedInt.BoundedIntText as X import IHaskell.Display.Widgets.Int.BoundedInt.BoundedIntText as X
...@@ -38,8 +41,6 @@ import IHaskell.Display.Widgets.String.Text as X ...@@ -38,8 +41,6 @@ import IHaskell.Display.Widgets.String.Text as X
import IHaskell.Display.Widgets.String.TextArea as X import IHaskell.Display.Widgets.String.TextArea as X
import IHaskell.Display.Widgets.Common as X import IHaskell.Display.Widgets.Common as X
import IHaskell.Display.Widgets.Types as X (setField, getField, properties) import IHaskell.Display.Widgets.Types as X (setField, getField, properties, triggerDisplay,
triggerChange, triggerClick, triggerSelection,
import IHaskell.Display.Widgets.Types as X (triggerDisplay, triggerChange, triggerClick, triggerSubmit, ChildWidget(..))
triggerSelection, triggerSubmit,
ChildWidget(..))
...@@ -12,12 +12,10 @@ CheckBox, ...@@ -12,12 +12,10 @@ CheckBox,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text) import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -40,11 +38,9 @@ mkCheckBox = do ...@@ -40,11 +38,9 @@ mkCheckBox = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Checkbox"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the image widget -- Return the image widget
return widget return widget
......
...@@ -12,7 +12,6 @@ ToggleButton, ...@@ -12,7 +12,6 @@ ToggleButton,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -45,11 +44,9 @@ mkToggleButton = do ...@@ -45,11 +44,9 @@ mkToggleButton = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.ToggleButton"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the image widget -- Return the image widget
return widget return widget
......
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeSynonymInstances #-}
module IHaskell.Display.Widgets.Bool.Valid (
-- * The Valid Widget
ValidWidget,
-- * Constructor
mkValidWidget) where
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Data.Aeson
import Data.IORef (newIORef)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
import IHaskell.IPython.Message.UUID as U
import IHaskell.Display.Widgets.Types
import IHaskell.Display.Widgets.Common
-- | A 'ValidWidget' represents a Valid widget from IPython.html.widgets.
type ValidWidget = IPythonWidget ValidType
-- | Create a new output widget
mkValidWidget :: IO ValidWidget
mkValidWidget = do
-- Default properties, with a random uuid
uuid <- U.random
let boolState = defaultBoolWidget "ValidView"
validState = (ReadOutMsg =:: "") :& RNil
widgetState = WidgetState $ boolState <+> validState
stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO
-- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget $ toJSON widgetState
-- Return the image widget
return widget
instance IHaskellDisplay ValidWidget where
display b = do
widgetSendView b
return $ Display []
instance IHaskellWidget ValidWidget where
getCommUUID = uuid
...@@ -12,19 +12,14 @@ Box, ...@@ -12,19 +12,14 @@ Box,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
import IHaskell.IPython.Message.UUID as U import IHaskell.IPython.Message.UUID as U
import IHaskell.Display.Widgets.Types import IHaskell.Display.Widgets.Types
import IHaskell.Display.Widgets.Common
-- | A 'Box' represents a Box widget from IPython.html.widgets. -- | A 'Box' represents a Box widget from IPython.html.widgets.
type Box = IPythonWidget BoxType type Box = IPythonWidget BoxType
...@@ -40,10 +35,9 @@ mkBox = do ...@@ -40,10 +35,9 @@ mkBox = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let box = IPythonWidget uuid stateIO let box = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Box"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen box initData $ toJSON widgetState widgetSendOpen box $ toJSON widgetState
-- Return the widget -- Return the widget
return box return box
......
...@@ -12,11 +12,8 @@ FlexBox, ...@@ -12,11 +12,8 @@ FlexBox,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>)) import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
...@@ -46,10 +43,9 @@ mkFlexBox = do ...@@ -46,10 +43,9 @@ mkFlexBox = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let box = IPythonWidget uuid stateIO let box = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.FlexBox"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen box initData $ toJSON widgetState widgetSendOpen box $ toJSON widgetState
-- Return the widget -- Return the widget
return box return box
......
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeSynonymInstances #-}
module IHaskell.Display.Widgets.Box.PlaceProxy (
-- * The PlaceProxy widget
PlaceProxy,
-- * Constructor
mkPlaceProxy) where
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Data.Aeson
import Data.IORef (newIORef)
import Data.Vinyl (Rec(..), (<+>))
import Data.Vinyl.Lens (rput)
import IHaskell.Display
import IHaskell.Eval.Widgets
import IHaskell.IPython.Message.UUID as U
import IHaskell.Display.Widgets.Types
import IHaskell.Display.Widgets.Common
-- | A 'Box' represents a Box widget from IPython.html.widgets.
type PlaceProxy = IPythonWidget PlaceProxyType
-- | Create a new box
mkPlaceProxy :: IO PlaceProxy
mkPlaceProxy = do
-- Default properties, with a random uuid
uuid <- U.random
let widgetClassState = defaultWidget "PlaceProxyView"
baseState = rput (ModelName =:: "ProxyModel") widgetClassState
proxyState = (Child =:: Nothing) :& (Selector =:: "") :& RNil
widgetState = WidgetState $ baseState <+> proxyState
stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO
-- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
instance IHaskellDisplay PlaceProxy where
display b = do
widgetSendView b
return $ Display []
instance IHaskellWidget PlaceProxy where
getCommUUID = uuid
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeSynonymInstances #-}
module IHaskell.Display.Widgets.Box.Proxy (
-- * The Proxy widget
ProxyWidget,
-- * Constructor
mkProxyWidget) where
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Data.Aeson
import Data.IORef (newIORef)
import Data.Vinyl (Rec(..), (<+>))
import Data.Vinyl.Lens (rput)
import IHaskell.Display
import IHaskell.Eval.Widgets
import IHaskell.IPython.Message.UUID as U
import IHaskell.Display.Widgets.Types
import IHaskell.Display.Widgets.Common
-- | A 'Box' represents a Box widget from IPython.html.widgets.
type ProxyWidget = IPythonWidget ProxyType
-- | Create a new box
mkProxyWidget :: IO ProxyWidget
mkProxyWidget = do
-- Default properties, with a random uuid
uuid <- U.random
let widgetClassState = defaultWidget "ProxyView"
baseState = rput (ModelName =:: "ProxyModel") widgetClassState
proxyState = (Child =:: Nothing) :& RNil
widgetState = WidgetState $ baseState <+> proxyState
stateIO <- newIORef widgetState
let proxy = IPythonWidget uuid stateIO
-- Open a comm for this widget, and store it in the kernel state
widgetSendOpen proxy $ toJSON widgetState
-- Return the widget
return proxy
instance IHaskellDisplay ProxyWidget where
display b = do
widgetSendView b
return $ Display []
instance IHaskellWidget ProxyWidget where
getCommUUID = uuid
...@@ -12,13 +12,11 @@ Accordion, ...@@ -12,13 +12,11 @@ Accordion,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import qualified Data.Scientific as Sci import qualified Data.Scientific as Sci
import Data.Text (Text) import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -41,11 +39,9 @@ mkAccordion = do ...@@ -41,11 +39,9 @@ mkAccordion = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let box = IPythonWidget uuid stateIO let box = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Accordion"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen box initData $ toJSON widgetState widgetSendOpen box $ toJSON widgetState
-- Return the widget -- Return the widget
return box return box
......
...@@ -12,13 +12,11 @@ TabWidget, ...@@ -12,13 +12,11 @@ TabWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import qualified Data.Scientific as Sci import qualified Data.Scientific as Sci
import Data.Text (Text) import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -41,10 +39,9 @@ mkTabWidget = do ...@@ -41,10 +39,9 @@ mkTabWidget = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let box = IPythonWidget uuid stateIO let box = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Tab"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen box initData $ toJSON widgetState widgetSendOpen box $ toJSON widgetState
-- Return the widget -- Return the widget
return box return box
......
...@@ -12,7 +12,7 @@ Button, ...@@ -12,7 +12,7 @@ Button,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join) import Control.Monad (when)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -49,10 +49,8 @@ mkButton = do ...@@ -49,10 +49,8 @@ mkButton = do
let button = IPythonWidget uuid stateIO let button = IPythonWidget uuid stateIO
let initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Button"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen button initData $ toJSON buttonState widgetSendOpen button $ toJSON buttonState
-- Return the button widget -- Return the button widget
return button return button
......
...@@ -4,12 +4,15 @@ ...@@ -4,12 +4,15 @@
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-} {-# LANGUAGE GADTs #-}
{-# LANGUAGE AutoDeriveTypeable #-}
{-# LANGUAGE DeriveDataTypeable #-}
module IHaskell.Display.Widgets.Common where module IHaskell.Display.Widgets.Common where
import Data.Aeson import Data.Aeson
import Data.Aeson.Types (emptyObject) import Data.Aeson.Types (emptyObject)
import Data.Text (pack, Text) import Data.Text (pack, Text)
import Data.Typeable (Typeable)
import IHaskell.Display (IHaskellWidget) import IHaskell.Display (IHaskellWidget)
import IHaskell.Eval.Widgets (widgetSendClose) import IHaskell.Eval.Widgets (widgetSendClose)
...@@ -18,6 +21,8 @@ import qualified IHaskell.Display.Widgets.Singletons as S ...@@ -18,6 +21,8 @@ import qualified IHaskell.Display.Widgets.Singletons as S
pattern ViewModule = S.SViewModule pattern ViewModule = S.SViewModule
pattern ViewName = S.SViewName pattern ViewName = S.SViewName
pattern ModelModule = S.SModelModule
pattern ModelName = S.SModelName
pattern MsgThrottle = S.SMsgThrottle pattern MsgThrottle = S.SMsgThrottle
pattern Version = S.SVersion pattern Version = S.SVersion
pattern DisplayHandler = S.SDisplayHandler pattern DisplayHandler = S.SDisplayHandler
...@@ -87,16 +92,19 @@ pattern Pack = S.SPack ...@@ -87,16 +92,19 @@ pattern Pack = S.SPack
pattern Align = S.SAlign pattern Align = S.SAlign
pattern Titles = S.STitles pattern Titles = S.STitles
pattern SelectedIndex = S.SSelectedIndex pattern SelectedIndex = S.SSelectedIndex
pattern ReadOutMsg = S.SReadOutMsg
pattern Child = S.SChild
pattern Selector = S.SSelector
-- | Close a widget's comm -- | Close a widget's comm
closeWidget :: IHaskellWidget w => w -> IO () closeWidget :: IHaskellWidget w => w -> IO ()
closeWidget w = widgetSendClose w emptyObject closeWidget w = widgetSendClose w emptyObject
newtype StrInt = StrInt Integer newtype PixCount = PixCount Integer
deriving (Num, Ord, Eq, Enum) deriving (Num, Ord, Eq, Enum, Typeable)
instance ToJSON StrInt where instance ToJSON PixCount where
toJSON (StrInt x) = toJSON . pack $ show x toJSON (PixCount x) = toJSON . pack $ show x ++ "px"
-- | Pre-defined border styles -- | Pre-defined border styles
data BorderStyleValue = NoBorder data BorderStyleValue = NoBorder
...@@ -196,7 +204,7 @@ instance ToJSON BarStyleValue where ...@@ -196,7 +204,7 @@ instance ToJSON BarStyleValue where
data ImageFormatValue = PNG data ImageFormatValue = PNG
| SVG | SVG
| JPG | JPG
deriving Eq deriving (Eq, Typeable)
instance Show ImageFormatValue where instance Show ImageFormatValue where
show PNG = "png" show PNG = "png"
......
...@@ -13,13 +13,11 @@ BoundedFloatText, ...@@ -13,13 +13,11 @@ BoundedFloatText,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import qualified Data.Scientific as Sci import qualified Data.Scientific as Sci
import Data.Text (Text) import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -42,13 +40,9 @@ mkBoundedFloatText = do ...@@ -42,13 +40,9 @@ mkBoundedFloatText = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
[ "model_name" .= str "WidgetModel"
, "widget_class" .= str "IPython.BoundedFloatText"
]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,13 +12,8 @@ FloatProgress, ...@@ -12,13 +12,8 @@ FloatProgress,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Exception (throw, ArithException(LossOfPrecision))
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>)) import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
...@@ -38,19 +33,17 @@ mkFloatProgress = do ...@@ -38,19 +33,17 @@ mkFloatProgress = do
uuid <- U.random uuid <- U.random
let boundedFloatAttrs = defaultBoundedFloatWidget "ProgressView" let boundedFloatAttrs = defaultBoundedFloatWidget "ProgressView"
progressAttrs = (BarStyle =:: DefaultBar) :& RNil progressAttrs = (Orientation =:: HorizontalOrientation)
:& (BarStyle =:: DefaultBar)
:& RNil
widgetState = WidgetState $ boundedFloatAttrs <+> progressAttrs widgetState = WidgetState $ boundedFloatAttrs <+> progressAttrs
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
[ "model_name" .= str "WidgetModel"
, "widget_class" .= str "IPython.FloatProgress"
]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,7 +12,6 @@ FloatSlider, ...@@ -12,7 +12,6 @@ FloatSlider,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -47,11 +46,9 @@ mkFloatSlider = do ...@@ -47,11 +46,9 @@ mkFloatSlider = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.FloatSlider"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -13,8 +13,6 @@ FloatRangeSlider, ...@@ -13,8 +13,6 @@ FloatRangeSlider,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Exception (throw, ArithException(LossOfPrecision))
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -50,13 +48,9 @@ mkFloatRangeSlider = do ...@@ -50,13 +48,9 @@ mkFloatRangeSlider = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
[ "model_name" .= str "WidgetModel"
, "widget_class" .= str "IPython.FloatRangeSlider"
]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,13 +12,11 @@ FloatText, ...@@ -12,13 +12,11 @@ FloatText,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import qualified Data.Scientific as Sci import qualified Data.Scientific as Sci
import Data.Text (Text) import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -41,11 +39,9 @@ mkFloatText = do ...@@ -41,11 +39,9 @@ mkFloatText = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.FloatText"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,12 +12,9 @@ ImageWidget, ...@@ -12,12 +12,9 @@ ImageWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Monoid (mempty) import Data.Monoid (mempty)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>)) import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
...@@ -38,6 +35,8 @@ mkImageWidget = do ...@@ -38,6 +35,8 @@ mkImageWidget = do
let dom = defaultDOMWidget "ImageView" let dom = defaultDOMWidget "ImageView"
img = (ImageFormat =:: PNG) img = (ImageFormat =:: PNG)
:& (Width =:+ 0)
:& (Height =:+ 0)
:& (B64Value =:: mempty) :& (B64Value =:: mempty)
:& RNil :& RNil
widgetState = WidgetState (dom <+> img) widgetState = WidgetState (dom <+> img)
...@@ -46,10 +45,8 @@ mkImageWidget = do ...@@ -46,10 +45,8 @@ mkImageWidget = do
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
let initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Image"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the image widget -- Return the image widget
return widget return widget
......
...@@ -12,13 +12,11 @@ BoundedIntText, ...@@ -12,13 +12,11 @@ BoundedIntText,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import qualified Data.Scientific as Sci import qualified Data.Scientific as Sci
import Data.Text (Text) import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -41,13 +39,9 @@ mkBoundedIntText = do ...@@ -41,13 +39,9 @@ mkBoundedIntText = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
[ "model_name" .= str "WidgetModel"
, "widget_class" .= str "IPython.BoundedIntText"
]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,13 +12,8 @@ IntProgress, ...@@ -12,13 +12,8 @@ IntProgress,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Exception (throw, ArithException(LossOfPrecision))
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>)) import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
...@@ -38,17 +33,17 @@ mkIntProgress = do ...@@ -38,17 +33,17 @@ mkIntProgress = do
uuid <- U.random uuid <- U.random
let boundedIntAttrs = defaultBoundedIntWidget "ProgressView" let boundedIntAttrs = defaultBoundedIntWidget "ProgressView"
progressAttrs = (BarStyle =:: DefaultBar) :& RNil progressAttrs = (Orientation =:: HorizontalOrientation)
:& (BarStyle =:: DefaultBar)
:& RNil
widgetState = WidgetState $ boundedIntAttrs <+> progressAttrs widgetState = WidgetState $ boundedIntAttrs <+> progressAttrs
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.IntProgress"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,7 +12,6 @@ IntSlider, ...@@ -12,7 +12,6 @@ IntSlider,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -47,11 +46,9 @@ mkIntSlider = do ...@@ -47,11 +46,9 @@ mkIntSlider = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.IntSlider"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,7 +12,6 @@ IntRangeSlider, ...@@ -12,7 +12,6 @@ IntRangeSlider,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -48,13 +47,9 @@ mkIntRangeSlider = do ...@@ -48,13 +47,9 @@ mkIntRangeSlider = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
[ "model_name" .= str "WidgetModel"
, "widget_class" .= str "IPython.IntRangeSlider"
]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,13 +12,11 @@ IntText, ...@@ -12,13 +12,11 @@ IntText,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import qualified Data.Scientific as Sci import qualified Data.Scientific as Sci
import Data.Text (Text) import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -41,10 +39,9 @@ mkIntText = do ...@@ -41,10 +39,9 @@ mkIntText = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.IntText"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE PolyKinds #-} {-# LANGUAGE PolyKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternSynonyms #-}
module IHaskell.Display.Widgets.Interactive (interactive, uncurryHList, Rec(..), Argument(..)) where module IHaskell.Display.Widgets.Interactive (interactive, uncurryHList, Rec(..), Argument(..)) where
...@@ -25,7 +22,7 @@ import IHaskell.Display ...@@ -25,7 +22,7 @@ import IHaskell.Display
import IHaskell.Display.Widgets.Types import IHaskell.Display.Widgets.Types
import IHaskell.Display.Widgets.Common import IHaskell.Display.Widgets.Common
import qualified IHaskell.Display.Widgets.Singletons as S (SField(..), Field(..)) import qualified IHaskell.Display.Widgets.Singletons as S (SField, Field(..))
import IHaskell.Display.Widgets.Box.FlexBox import IHaskell.Display.Widgets.Box.FlexBox
import IHaskell.Display.Widgets.Bool.CheckBox import IHaskell.Display.Widgets.Bool.CheckBox
...@@ -44,10 +41,6 @@ data WidgetConf a where ...@@ -44,10 +41,6 @@ data WidgetConf a where
a a
-> WidgetConf a -> WidgetConf a
newtype WrappedConstructor a =
WrappedConstructor
{ wrappedConstructor :: IO (IPythonWidget (SuitableWidget a)) }
type family WithTypes (ts :: [*]) (r :: *) :: * where type family WithTypes (ts :: [*]) (r :: *) :: * where
WithTypes '[] r = r WithTypes '[] r = r
...@@ -70,8 +63,6 @@ newtype EventSetter a = EventSetter (IPythonWidget (SuitableWidget a) -> IO () - ...@@ -70,8 +63,6 @@ newtype EventSetter a = EventSetter (IPythonWidget (SuitableWidget a) -> IO () -
newtype Initializer a = Initializer (IPythonWidget (SuitableWidget a) -> Argument a -> IO ()) newtype Initializer a = Initializer (IPythonWidget (SuitableWidget a) -> Argument a -> IO ())
newtype Trigger a = Trigger (IPythonWidget (SuitableWidget a) -> IO ())
data RequiredWidget a where data RequiredWidget a where
RequiredWidget :: RequiredWidget ::
...@@ -107,11 +98,8 @@ extractGetter (WidgetConf wr) = Getter $ getValue wr ...@@ -107,11 +98,8 @@ extractGetter (WidgetConf wr) = Getter $ getValue wr
extractEventSetter :: WidgetConf x -> EventSetter x extractEventSetter :: WidgetConf x -> EventSetter x
extractEventSetter (WidgetConf wr) = EventSetter $ setEvent wr extractEventSetter (WidgetConf wr) = EventSetter $ setEvent wr
extractTrigger :: WidgetConf x -> Trigger x
extractTrigger (WidgetConf wr) = Trigger $ trigger wr
extractInitializer :: WidgetConf x -> Initializer x extractInitializer :: WidgetConf x -> Initializer x
extractInitializer (WidgetConf wr) = Initializer initializer extractInitializer WidgetConf{} = Initializer initializer
createWidget :: Constructor a -> IO (RequiredWidget a) createWidget :: Constructor a -> IO (RequiredWidget a)
createWidget (Constructor con) = fmap RequiredWidget con createWidget (Constructor con) = fmap RequiredWidget con
...@@ -146,7 +134,6 @@ liftToWidgets func rc initvals = do ...@@ -146,7 +134,6 @@ liftToWidgets func rc initvals = do
getters = rmap extractGetter rc getters = rmap extractGetter rc
eventSetters = rmap extractEventSetter rc eventSetters = rmap extractEventSetter rc
initializers = rmap extractInitializer rc initializers = rmap extractInitializer rc
triggers = rmap extractTrigger rc
bx <- mkFlexBox bx <- mkFlexBox
out <- mkOutputWidget out <- mkOutputWidget
...@@ -188,15 +175,9 @@ construct (WrappedWidget cons _ _) = cons ...@@ -188,15 +175,9 @@ construct (WrappedWidget cons _ _) = cons
getValue :: WrappedWidget w h f a -> IPythonWidget w -> IO a getValue :: WrappedWidget w h f a -> IPythonWidget w -> IO a
getValue (WrappedWidget _ _ field) widget = getField widget field getValue (WrappedWidget _ _ field) widget = getField widget field
setValue :: WrappedWidget w h f a -> IPythonWidget w -> a -> IO ()
setValue (WrappedWidget _ _ field) widget = setField widget field
setEvent :: WrappedWidget w h f a -> IPythonWidget w -> IO () -> IO () setEvent :: WrappedWidget w h f a -> IPythonWidget w -> IO () -> IO ()
setEvent (WrappedWidget _ h _) widget = setField widget h setEvent (WrappedWidget _ h _) widget = setField widget h
trigger :: WrappedWidget w h f a -> IPythonWidget w -> IO ()
trigger (WrappedWidget _ h _) = triggerEvent h
class RecAll Attr (WidgetFields (SuitableWidget a)) ToPairs => FromWidget a where class RecAll Attr (WidgetFields (SuitableWidget a)) ToPairs => FromWidget a where
type SuitableWidget a :: WidgetType type SuitableWidget a :: WidgetType
type SuitableHandler a :: S.Field type SuitableHandler a :: S.Field
......
...@@ -18,12 +18,8 @@ module IHaskell.Display.Widgets.Output ( ...@@ -18,12 +18,8 @@ module IHaskell.Display.Widgets.Output (
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -45,10 +41,9 @@ mkOutputWidget = do ...@@ -45,10 +41,9 @@ mkOutputWidget = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the image widget -- Return the image widget
return widget return widget
......
...@@ -12,7 +12,7 @@ Dropdown, ...@@ -12,7 +12,7 @@ Dropdown,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void) import Control.Monad (void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -41,11 +41,9 @@ mkDropdown = do ...@@ -41,11 +41,9 @@ mkDropdown = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Dropdown"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,12 +12,11 @@ RadioButtons, ...@@ -12,12 +12,11 @@ RadioButtons,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void) import Control.Monad (when, void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text) import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -39,11 +38,9 @@ mkRadioButtons = do ...@@ -39,11 +38,9 @@ mkRadioButtons = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.RadioButtons"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -39,10 +39,9 @@ mkSelect = do ...@@ -39,10 +39,9 @@ mkSelect = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Select"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,13 +12,12 @@ SelectMultiple, ...@@ -12,13 +12,12 @@ SelectMultiple,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (fmap, join, sequence, void) import Control.Monad (void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Vector as V import qualified Data.Vector as V
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -40,13 +39,9 @@ mkSelectMultiple = do ...@@ -40,13 +39,9 @@ mkSelectMultiple = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
[ "model_name" .= str "WidgetModel"
, "widget_class" .= str "IPython.SelectMultiple"
]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,7 +12,7 @@ ToggleButtons, ...@@ -12,7 +12,7 @@ ToggleButtons,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join, void) import Control.Monad (void)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -44,13 +44,9 @@ mkToggleButtons = do ...@@ -44,13 +44,9 @@ mkToggleButtons = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
[ "model_name" .= str "WidgetModel"
, "widget_class" .= str "IPython.ToggleButtons"
]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE InstanceSigs #-}
module IHaskell.Display.Widgets.Singletons where module IHaskell.Display.Widgets.Singletons where
import Data.Singletons.TH import Data.Singletons.TH
import Data.Singletons.Prelude.Ord
-- Widget properties -- Widget properties
singletons singletons
...@@ -16,6 +19,8 @@ singletons ...@@ -16,6 +19,8 @@ singletons
data Field = ViewModule data Field = ViewModule
| ViewName | ViewName
| ModelModule
| ModelName
| MsgThrottle | MsgThrottle
| Version | Version
| DisplayHandler | DisplayHandler
...@@ -85,5 +90,8 @@ singletons ...@@ -85,5 +90,8 @@ singletons
| Align | Align
| Titles | Titles
| SelectedIndex | SelectedIndex
| ReadOutMsg
| Child
| Selector
deriving (Eq, Ord, Show) deriving (Eq, Ord, Show)
|] |]
...@@ -12,11 +12,8 @@ HTMLWidget, ...@@ -12,11 +12,8 @@ HTMLWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -37,10 +34,9 @@ mkHTMLWidget = do ...@@ -37,10 +34,9 @@ mkHTMLWidget = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.HTML"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,11 +12,8 @@ LatexWidget, ...@@ -12,11 +12,8 @@ LatexWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
import IHaskell.Eval.Widgets import IHaskell.Eval.Widgets
...@@ -37,10 +34,9 @@ mkLatexWidget = do ...@@ -37,10 +34,9 @@ mkLatexWidget = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Latex"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,11 +12,10 @@ TextWidget, ...@@ -12,11 +12,10 @@ TextWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join) import Control.Monad (when)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as Map import qualified Data.HashMap.Strict as Map
import Data.IORef (newIORef) import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>)) import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display import IHaskell.Display
...@@ -41,10 +40,9 @@ mkTextWidget = do ...@@ -41,10 +40,9 @@ mkTextWidget = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Text"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,7 +12,6 @@ TextArea, ...@@ -12,7 +12,6 @@ TextArea,
-- To keep `cabal repl` happy when running from the ihaskell repo -- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude import Prelude
import Control.Monad (when, join)
import Data.Aeson import Data.Aeson
import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef) import Data.IORef (newIORef)
...@@ -41,11 +40,9 @@ mkTextArea = do ...@@ -41,11 +40,9 @@ mkTextArea = do
stateIO <- newIORef widgetState stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO let widget = IPythonWidget uuid stateIO
initData = object
["model_name" .= str "WidgetModel", "widget_class" .= str "IPython.Textarea"]
-- Open a comm for this widget, and store it in the kernel state -- Open a comm for this widget, and store it in the kernel state
widgetSendOpen widget initData $ toJSON widgetState widgetSendOpen widget $ toJSON widgetState
-- Return the widget -- Return the widget
return widget return widget
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
{-# LANGUAGE BangPatterns #-} {-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE AutoDeriveTypeable #-}
module IHaskell.Display.Widgets.Types where module IHaskell.Display.Widgets.Types where
...@@ -48,8 +50,8 @@ module IHaskell.Display.Widgets.Types where ...@@ -48,8 +50,8 @@ module IHaskell.Display.Widgets.Types where
-- --
-- The IPython widgets expect state updates of the form {"property": value}, where an empty string -- The IPython widgets expect state updates of the form {"property": value}, where an empty string
-- for numeric values is ignored by the frontend and the default value is used instead. Some numbers -- for numeric values is ignored by the frontend and the default value is used instead. Some numbers
-- need to be sent as numbers (represented by @Integer@), whereas some need to be sent as Strings -- need to be sent as numbers (represented by @Integer@), whereas some (css lengths) need to be sent
-- (@StrInt@). -- as Strings (@PixCount@).
-- --
-- Child widgets are expected to be sent as strings of the form "IPY_MODEL_<uuid>", where @<uuid>@ -- Child widgets are expected to be sent as strings of the form "IPY_MODEL_<uuid>", where @<uuid>@
-- represents the uuid of the widget's comm. -- represents the uuid of the widget's comm.
...@@ -57,20 +59,20 @@ module IHaskell.Display.Widgets.Types where ...@@ -57,20 +59,20 @@ module IHaskell.Display.Widgets.Types where
-- To know more about the IPython messaging specification (as implemented in this package) take a -- To know more about the IPython messaging specification (as implemented in this package) take a
-- look at the supplied MsgSpec.md. -- look at the supplied MsgSpec.md.
-- --
-- Widgets are not able to do console input, the reason for that can also be found in the messaging -- Widgets are not able to do console input, the reason for that can be found in the messaging
-- specification -- specification.
import Control.Monad (unless, join, when, void, mapM_) import Control.Monad (unless, join, when, void)
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import qualified Control.Exception as Ex import qualified Control.Exception as Ex
import Data.Typeable (Typeable, TypeRep, typeOf)
import GHC.IO.Exception import Data.IORef (IORef, readIORef, modifyIORef)
import Data.Text (Text, pack)
import System.IO.Error import System.IO.Error
import System.Posix.IO import System.Posix.IO
import Text.Printf (printf)
import Data.Aeson import Data.Aeson
import Data.Aeson.Types (Pair) import Data.Aeson.Types (Pair)
import Data.IORef (IORef, readIORef, modifyIORef)
import Data.Text (Text, pack)
import Data.Vinyl (Rec(..), (<+>), recordToList, reifyConstraint, rmap, Dict(..)) import Data.Vinyl (Rec(..), (<+>), recordToList, reifyConstraint, rmap, Dict(..))
import Data.Vinyl.Functor (Compose(..), Const(..)) import Data.Vinyl.Functor (Compose(..), Const(..))
...@@ -80,17 +82,19 @@ import Data.Vinyl.TypeLevel (RecAll) ...@@ -80,17 +82,19 @@ import Data.Vinyl.TypeLevel (RecAll)
import Data.Singletons.Prelude ((:++)) import Data.Singletons.Prelude ((:++))
import Data.Singletons.TH import Data.Singletons.TH
import GHC.IO.Exception
import IHaskell.Eval.Widgets (widgetSendUpdate) import IHaskell.Eval.Widgets (widgetSendUpdate)
import IHaskell.Display (Base64, IHaskellWidget(..)) import IHaskell.Display (Base64, IHaskellWidget(..))
import IHaskell.IPython.Message.UUID import IHaskell.IPython.Message.UUID
import IHaskell.Display.Widgets.Singletons (Field, SField(..)) import IHaskell.Display.Widgets.Singletons (Field, SField)
import qualified IHaskell.Display.Widgets.Singletons as S import qualified IHaskell.Display.Widgets.Singletons as S
import IHaskell.Display.Widgets.Common import IHaskell.Display.Widgets.Common
-- Classes from IPython's widget hierarchy. Defined as such to reduce code duplication. -- Classes from IPython's widget hierarchy. Defined as such to reduce code duplication.
type WidgetClass = '[S.ViewModule, S.ViewName, S.MsgThrottle, S.Version, type WidgetClass = '[S.ViewModule, S.ViewName, S.ModelModule, S.ModelName,
S.DisplayHandler] S.MsgThrottle, S.Version, S.DisplayHandler]
type DOMWidgetClass = WidgetClass :++ '[S.Visible, S.CSS, S.DOMClasses, S.Width, S.Height, S.Padding, type DOMWidgetClass = WidgetClass :++ '[S.Visible, S.CSS, S.DOMClasses, S.Width, S.Height, S.Padding,
S.Margin, S.Color, S.BackgroundColor, S.BorderColor, S.BorderWidth, S.Margin, S.Color, S.BackgroundColor, S.BorderColor, S.BorderWidth,
...@@ -104,7 +108,7 @@ type BoolClass = DOMWidgetClass :++ '[S.BoolValue, S.Disabled, S.Description, S. ...@@ -104,7 +108,7 @@ type BoolClass = DOMWidgetClass :++ '[S.BoolValue, S.Disabled, S.Description, S.
type SelectionClass = DOMWidgetClass :++ '[S.Options, S.SelectedValue, S.SelectedLabel, S.Disabled, type SelectionClass = DOMWidgetClass :++ '[S.Options, S.SelectedValue, S.SelectedLabel, S.Disabled,
S.Description, S.SelectionHandler] S.Description, S.SelectionHandler]
type MultipleSelectionClass = DOMWidgetClass :++ '[S.Options, S.SelectedLabels, S.SelectedValues, S.Disabled, type MultipleSelectionClass = DOMWidgetClass :++ '[S.Options, S.SelectedValues, S.SelectedLabels, S.Disabled,
S.Description, S.SelectionHandler] S.Description, S.SelectionHandler]
type IntClass = DOMWidgetClass :++ '[S.IntValue, S.Disabled, S.Description, S.ChangeHandler] type IntClass = DOMWidgetClass :++ '[S.IntValue, S.Disabled, S.Description, S.ChangeHandler]
...@@ -128,29 +132,31 @@ type BoxClass = DOMWidgetClass :++ '[S.Children, S.OverflowX, S.OverflowY, S.Box ...@@ -128,29 +132,31 @@ type BoxClass = DOMWidgetClass :++ '[S.Children, S.OverflowX, S.OverflowY, S.Box
type SelectionContainerClass = BoxClass :++ '[S.Titles, S.SelectedIndex, S.ChangeHandler] type SelectionContainerClass = BoxClass :++ '[S.Titles, S.SelectedIndex, S.ChangeHandler]
-- Types associated with Fields. -- Types associated with Fields.
type family FieldType (f :: Field) :: * where type family FieldType (f :: Field) :: * where
FieldType S.ViewModule = Text FieldType S.ViewModule = Text
FieldType S.ViewName = Text FieldType S.ViewName = Text
FieldType S.ModelModule = Text
FieldType S.ModelName = Text
FieldType S.MsgThrottle = Integer FieldType S.MsgThrottle = Integer
FieldType S.Version = Integer FieldType S.Version = Integer
FieldType S.DisplayHandler = IO () FieldType S.DisplayHandler = IO ()
FieldType S.Visible = Bool FieldType S.Visible = Bool
FieldType S.CSS = [(Text, Text, Text)] FieldType S.CSS = [(Text, Text, Text)]
FieldType S.DOMClasses = [Text] FieldType S.DOMClasses = [Text]
FieldType S.Width = StrInt FieldType S.Width = PixCount
FieldType S.Height = StrInt FieldType S.Height = PixCount
FieldType S.Padding = StrInt FieldType S.Padding = PixCount
FieldType S.Margin = StrInt FieldType S.Margin = PixCount
FieldType S.Color = Text FieldType S.Color = Text
FieldType S.BackgroundColor = Text FieldType S.BackgroundColor = Text
FieldType S.BorderColor = Text FieldType S.BorderColor = Text
FieldType S.BorderWidth = StrInt FieldType S.BorderWidth = PixCount
FieldType S.BorderRadius = StrInt FieldType S.BorderRadius = PixCount
FieldType S.BorderStyle = BorderStyleValue FieldType S.BorderStyle = BorderStyleValue
FieldType S.FontStyle = FontStyleValue FieldType S.FontStyle = FontStyleValue
FieldType S.FontWeight = FontWeightValue FieldType S.FontWeight = FontWeightValue
FieldType S.FontSize = StrInt FieldType S.FontSize = PixCount
FieldType S.FontFamily = Text FieldType S.FontFamily = Text
FieldType S.Description = Text FieldType S.Description = Text
FieldType S.ClickHandler = IO () FieldType S.ClickHandler = IO ()
...@@ -201,6 +207,9 @@ type family FieldType (f :: Field) :: * where ...@@ -201,6 +207,9 @@ type family FieldType (f :: Field) :: * where
FieldType S.Align = LocationValue FieldType S.Align = LocationValue
FieldType S.Titles = [Text] FieldType S.Titles = [Text]
FieldType S.SelectedIndex = Integer FieldType S.SelectedIndex = Integer
FieldType S.ReadOutMsg = Text
FieldType S.Child = Maybe ChildWidget
FieldType S.Selector = Text
-- | Can be used to put different widgets in a list. Useful for dealing with children widgets. -- | Can be used to put different widgets in a list. Useful for dealing with children widgets.
data ChildWidget = forall w. RecAll Attr (WidgetFields w) ToPairs => ChildWidget (IPythonWidget w) data ChildWidget = forall w. RecAll Attr (WidgetFields w) ToPairs => ChildWidget (IPythonWidget w)
...@@ -215,7 +224,7 @@ class CustomBounded a where ...@@ -215,7 +224,7 @@ class CustomBounded a where
upperBound :: a upperBound :: a
-- Set according to what IPython widgets use -- Set according to what IPython widgets use
instance CustomBounded StrInt where instance CustomBounded PixCount where
upperBound = 10 ^ 16 - 1 upperBound = 10 ^ 16 - 1
lowerBound = -(10 ^ 16 - 1) lowerBound = -(10 ^ 16 - 1)
...@@ -237,6 +246,7 @@ data WidgetType = ButtonType ...@@ -237,6 +246,7 @@ data WidgetType = ButtonType
| TextAreaType | TextAreaType
| CheckBoxType | CheckBoxType
| ToggleButtonType | ToggleButtonType
| ValidType
| DropdownType | DropdownType
| RadioButtonsType | RadioButtonsType
| SelectType | SelectType
...@@ -253,19 +263,21 @@ data WidgetType = ButtonType ...@@ -253,19 +263,21 @@ data WidgetType = ButtonType
| FloatProgressType | FloatProgressType
| FloatRangeSliderType | FloatRangeSliderType
| BoxType | BoxType
| ProxyType
| PlaceProxyType
| FlexBoxType | FlexBoxType
| AccordionType | AccordionType
| TabType | TabType
-- Fields associated with a widget -- Fields associated with a widget
type family WidgetFields (w :: WidgetType) :: [Field] where type family WidgetFields (w :: WidgetType) :: [Field] where
WidgetFields ButtonType = WidgetFields ButtonType =
DOMWidgetClass :++ DOMWidgetClass :++
'[S.Description, S.Tooltip, S.Disabled, S.Icon, S.ButtonStyle, '[S.Description, S.Tooltip, S.Disabled, S.Icon, S.ButtonStyle,
S.ClickHandler] S.ClickHandler]
WidgetFields ImageType = WidgetFields ImageType =
DOMWidgetClass :++ '[S.ImageFormat, S.B64Value] DOMWidgetClass :++ '[S.ImageFormat, S.Width, S.Height, S.B64Value]
WidgetFields OutputType = DOMWidgetClass WidgetFields OutputType = DOMWidgetClass
WidgetFields HTMLType = StringClass WidgetFields HTMLType = StringClass
WidgetFields LatexType = StringClass WidgetFields LatexType = StringClass
...@@ -275,6 +287,7 @@ type family WidgetFields (w :: WidgetType) :: [Field] where ...@@ -275,6 +287,7 @@ type family WidgetFields (w :: WidgetType) :: [Field] where
WidgetFields CheckBoxType = BoolClass WidgetFields CheckBoxType = BoolClass
WidgetFields ToggleButtonType = WidgetFields ToggleButtonType =
BoolClass :++ '[S.Tooltip, S.Icon, S.ButtonStyle] BoolClass :++ '[S.Tooltip, S.Icon, S.ButtonStyle]
WidgetFields ValidType = BoolClass :++ '[S.ReadOutMsg]
WidgetFields DropdownType = SelectionClass :++ '[S.ButtonStyle] WidgetFields DropdownType = SelectionClass :++ '[S.ButtonStyle]
WidgetFields RadioButtonsType = SelectionClass WidgetFields RadioButtonsType = SelectionClass
WidgetFields SelectType = SelectionClass WidgetFields SelectType = SelectionClass
...@@ -286,7 +299,8 @@ type family WidgetFields (w :: WidgetType) :: [Field] where ...@@ -286,7 +299,8 @@ type family WidgetFields (w :: WidgetType) :: [Field] where
WidgetFields IntSliderType = WidgetFields IntSliderType =
BoundedIntClass :++ BoundedIntClass :++
'[S.Orientation, S.ShowRange, S.ReadOut, S.SliderColor] '[S.Orientation, S.ShowRange, S.ReadOut, S.SliderColor]
WidgetFields IntProgressType = BoundedIntClass :++ '[S.BarStyle] WidgetFields IntProgressType =
BoundedIntClass :++ '[S.Orientation, S.BarStyle]
WidgetFields IntRangeSliderType = WidgetFields IntRangeSliderType =
BoundedIntRangeClass :++ BoundedIntRangeClass :++
'[S.Orientation, S.ShowRange, S.ReadOut, S.SliderColor] '[S.Orientation, S.ShowRange, S.ReadOut, S.SliderColor]
...@@ -296,11 +310,14 @@ type family WidgetFields (w :: WidgetType) :: [Field] where ...@@ -296,11 +310,14 @@ type family WidgetFields (w :: WidgetType) :: [Field] where
BoundedFloatClass :++ BoundedFloatClass :++
'[S.Orientation, S.ShowRange, S.ReadOut, S.SliderColor] '[S.Orientation, S.ShowRange, S.ReadOut, S.SliderColor]
WidgetFields FloatProgressType = WidgetFields FloatProgressType =
BoundedFloatClass :++ '[S.BarStyle] BoundedFloatClass :++ '[S.Orientation, S.BarStyle]
WidgetFields FloatRangeSliderType = WidgetFields FloatRangeSliderType =
BoundedFloatRangeClass :++ BoundedFloatRangeClass :++
'[S.Orientation, S.ShowRange, S.ReadOut, S.SliderColor] '[S.Orientation, S.ShowRange, S.ReadOut, S.SliderColor]
WidgetFields BoxType = BoxClass WidgetFields BoxType = BoxClass
WidgetFields ProxyType = WidgetClass :++ '[S.Child]
WidgetFields PlaceProxyType =
WidgetFields ProxyType :++ '[S.Selector]
WidgetFields FlexBoxType = WidgetFields FlexBoxType =
BoxClass :++ '[S.Orientation, S.Flex, S.Pack, S.Align] BoxClass :++ '[S.Orientation, S.Flex, S.Pack, S.Align]
WidgetFields AccordionType = SelectionContainerClass WidgetFields AccordionType = SelectionContainerClass
...@@ -315,12 +332,15 @@ unwrap (Dummy x) = x ...@@ -315,12 +332,15 @@ unwrap (Dummy x) = x
unwrap (Real x) = x unwrap (Real x) = x
-- Wrapper around a field. -- Wrapper around a field.
data Attr (f :: Field) = data Attr (f :: Field) where
Attr Attr :: Typeable (FieldType f)
{ _value :: AttrVal (FieldType f) => { _value :: AttrVal (FieldType f)
, _verify :: FieldType f -> IO (FieldType f) , _verify :: FieldType f -> IO (FieldType f)
, _field :: Field , _field :: Field
} } -> Attr f
getFieldType :: Attr f -> TypeRep
getFieldType Attr { _value = attrval } = typeOf $ unwrap attrval
instance ToJSON (FieldType f) => ToJSON (Attr f) where instance ToJSON (FieldType f) => ToJSON (Attr f) where
toJSON attr = toJSON attr =
...@@ -339,6 +359,12 @@ instance ToPairs (Attr S.ViewModule) where ...@@ -339,6 +359,12 @@ instance ToPairs (Attr S.ViewModule) where
instance ToPairs (Attr S.ViewName) where instance ToPairs (Attr S.ViewName) where
toPairs x = ["_view_name" .= toJSON x] toPairs x = ["_view_name" .= toJSON x]
instance ToPairs (Attr S.ModelModule) where
toPairs x = ["_model_module" .= toJSON x]
instance ToPairs (Attr S.ModelName) where
toPairs x = ["_model_name" .= toJSON x]
instance ToPairs (Attr S.MsgThrottle) where instance ToPairs (Attr S.MsgThrottle) where
toPairs x = ["msg_throttle" .= toJSON x] toPairs x = ["msg_throttle" .= toJSON x]
...@@ -552,9 +578,18 @@ instance ToPairs (Attr S.Titles) where ...@@ -552,9 +578,18 @@ instance ToPairs (Attr S.Titles) where
instance ToPairs (Attr S.SelectedIndex) where instance ToPairs (Attr S.SelectedIndex) where
toPairs x = ["selected_index" .= toJSON x] toPairs x = ["selected_index" .= toJSON x]
instance ToPairs (Attr S.ReadOutMsg) where
toPairs x = ["readout" .= toJSON x]
instance ToPairs (Attr S.Child) where
toPairs x = ["child" .= toJSON x]
instance ToPairs (Attr S.Selector) where
toPairs x = ["selector" .= toJSON x]
-- | Store the value for a field, as an object parametrized by the Field. No verification is done -- | Store the value for a field, as an object parametrized by the Field. No verification is done
-- for these values. -- for these values.
(=::) :: SingI f => Sing f -> FieldType f -> Attr f (=::) :: (SingI f, Typeable (FieldType f)) => Sing f -> FieldType f -> Attr f
s =:: x = Attr { _value = Real x, _verify = return, _field = reflect s } s =:: x = Attr { _value = Real x, _verify = return, _field = reflect s }
-- | If the number is in the range, return it. Otherwise raise the appropriate (over/under)flow -- | If the number is in the range, return it. Otherwise raise the appropriate (over/under)flow
...@@ -567,13 +602,13 @@ rangeCheck (l, u) x ...@@ -567,13 +602,13 @@ rangeCheck (l, u) x
| otherwise = error "The impossible happened in IHaskell.Display.Widgets.Types.rangeCheck" | otherwise = error "The impossible happened in IHaskell.Display.Widgets.Types.rangeCheck"
-- | Store a numeric value, with verification mechanism for its range. -- | Store a numeric value, with verification mechanism for its range.
ranged :: (SingI f, Num (FieldType f), Ord (FieldType f)) ranged :: (SingI f, Num (FieldType f), Ord (FieldType f), Typeable (FieldType f))
=> Sing f -> (FieldType f, FieldType f) -> AttrVal (FieldType f) -> Attr f => Sing f -> (FieldType f, FieldType f) -> AttrVal (FieldType f) -> Attr f
ranged s range x = Attr x (rangeCheck range) (reflect s) ranged s range x = Attr x (rangeCheck range) (reflect s)
-- | Store a numeric value, with the invariant that it stays non-negative. The value set is set as a -- | Store a numeric value, with the invariant that it stays non-negative. The value set is set as a
-- dummy value if it's equal to zero. -- dummy value if it's equal to zero.
(=:+) :: (SingI f, Num (FieldType f), CustomBounded (FieldType f), Ord (FieldType f)) (=:+) :: (SingI f, Num (FieldType f), CustomBounded (FieldType f), Ord (FieldType f), Typeable (FieldType f))
=> Sing f -> FieldType f -> Attr f => Sing f -> FieldType f -> Attr f
s =:+ val = Attr s =:+ val = Attr
((if val == 0 ((if val == 0
...@@ -591,6 +626,8 @@ reflect = fromSing ...@@ -591,6 +626,8 @@ reflect = fromSing
defaultWidget :: FieldType S.ViewName -> Rec Attr WidgetClass defaultWidget :: FieldType S.ViewName -> Rec Attr WidgetClass
defaultWidget viewName = (ViewModule =:: "") defaultWidget viewName = (ViewModule =:: "")
:& (ViewName =:: viewName) :& (ViewName =:: viewName)
:& (ModelModule =:: "")
:& (ModelName =:: "WidgetModel")
:& (MsgThrottle =:+ 3) :& (MsgThrottle =:+ 3)
:& (Version =:: 0) :& (Version =:: 0)
:& (DisplayHandler =:: return ()) :& (DisplayHandler =:: return ())
...@@ -656,8 +693,8 @@ defaultMultipleSelectionWidget :: FieldType S.ViewName -> Rec Attr MultipleSelec ...@@ -656,8 +693,8 @@ defaultMultipleSelectionWidget :: FieldType S.ViewName -> Rec Attr MultipleSelec
defaultMultipleSelectionWidget viewName = defaultDOMWidget viewName <+> mulSelAttrs defaultMultipleSelectionWidget viewName = defaultDOMWidget viewName <+> mulSelAttrs
where where
mulSelAttrs = (Options =:: OptionLabels []) mulSelAttrs = (Options =:: OptionLabels [])
:& (SelectedLabels =:: [])
:& (SelectedValues =:: []) :& (SelectedValues =:: [])
:& (SelectedLabels =:: [])
:& (Disabled =:: False) :& (Disabled =:: False)
:& (Description =:: "") :& (Description =:: "")
:& (SelectionHandler =:: return ()) :& (SelectionHandler =:: return ())
...@@ -739,8 +776,10 @@ defaultBoundedFloatRangeWidget viewName = defaultFloatRangeWidget viewName <+> b ...@@ -739,8 +776,10 @@ defaultBoundedFloatRangeWidget viewName = defaultFloatRangeWidget viewName <+> b
-- | A record representing a widget of the _Box class from IPython -- | A record representing a widget of the _Box class from IPython
defaultBoxWidget :: FieldType S.ViewName -> Rec Attr BoxClass defaultBoxWidget :: FieldType S.ViewName -> Rec Attr BoxClass
defaultBoxWidget viewName = defaultDOMWidget viewName <+> boxAttrs defaultBoxWidget viewName = domAttrs <+> boxAttrs
where where
defaultDOM = defaultDOMWidget viewName
domAttrs = rput (ModelName =:: "BoxModel") defaultDOM
boxAttrs = (Children =:: []) boxAttrs = (Children =:: [])
:& (OverflowX =:: DefaultOverflow) :& (OverflowX =:: DefaultOverflow)
:& (OverflowY =:: DefaultOverflow) :& (OverflowY =:: DefaultOverflow)
...@@ -806,9 +845,12 @@ str = id ...@@ -806,9 +845,12 @@ str = id
properties :: IPythonWidget w -> IO () properties :: IPythonWidget w -> IO ()
properties widget = do properties widget = do
st <- readIORef $ state widget st <- readIORef $ state widget
let convert :: Attr f -> Const Field f let convert :: Attr f -> Const (Field, TypeRep) f
convert attr = Const { getConst = _field attr } convert attr = Const (_field attr, getFieldType attr)
mapM_ print $ recordToList . rmap convert . _getState $ st
renderRow (fname, ftype) = printf "%s ::: %s" (show fname) (show ftype)
rows = map renderRow . recordToList . rmap convert $ _getState st
mapM_ putStrLn rows
-- Helper function for widget to enforce their inability to fetch console input -- Helper function for widget to enforce their inability to fetch console input
noStdin :: IO a -> IO () noStdin :: IO a -> IO ()
......
...@@ -7,7 +7,7 @@ name: ihaskell ...@@ -7,7 +7,7 @@ name: ihaskell
-- PVP summary: +-+------- breaking API changes -- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions -- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change -- | | | +--- code changes with no API change
version: 0.7.0.3 version: 0.8.2.0
-- A short (one-line) description of the package. -- A short (one-line) description of the package.
synopsis: A Haskell backend kernel for the IPython project. synopsis: A Haskell backend kernel for the IPython project.
...@@ -55,7 +55,7 @@ library ...@@ -55,7 +55,7 @@ library
hs-source-dirs: src hs-source-dirs: src
default-language: Haskell2010 default-language: Haskell2010
build-depends: build-depends:
aeson >=0.7 && < 0.10, aeson >=0.7 && < 0.11,
base >=4.6 && < 4.9, base >=4.6 && < 4.9,
base64-bytestring >=1.0, base64-bytestring >=1.0,
bytestring >=0.10, bytestring >=0.10,
...@@ -143,7 +143,7 @@ executable ihaskell ...@@ -143,7 +143,7 @@ executable ihaskell
ghc >=7.6 || < 7.11, ghc >=7.6 || < 7.11,
process >=1.1, process >=1.1,
here ==1.2.*, here ==1.2.*,
aeson >=0.7 && < 0.10, aeson >=0.7 && < 0.11,
bytestring >=0.10, bytestring >=0.10,
containers >=0.5, containers >=0.5,
strict >=0.3, strict >=0.3,
...@@ -167,7 +167,7 @@ Test-Suite hspec ...@@ -167,7 +167,7 @@ Test-Suite hspec
default-language: Haskell2010 default-language: Haskell2010
build-depends: build-depends:
ihaskell, ihaskell,
aeson >=0.6 && < 0.10, aeson >=0.6 && < 0.11,
base >=4.6 && < 4.9, base >=4.6 && < 4.9,
base64-bytestring >=1.0, base64-bytestring >=1.0,
bytestring >=0.10, bytestring >=0.10,
......
...@@ -265,4 +265,5 @@ main = do ...@@ -265,4 +265,5 @@ main = do
_ -> do _ -> do
putStrLn "Usage:" putStrLn "Usage:"
putStrLn "simple-calc-example install -- set up the kernelspec" putStrLn "simple-calc-example install -- set up the kernelspec"
putStrLn "simple-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend" putStrLn
"simple-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend"
...@@ -2,13 +2,13 @@ module Main where ...@@ -2,13 +2,13 @@ module Main where
import qualified Data.Text as T import qualified Data.Text as T
import System.Environment (getArgs) import System.Environment (getArgs)
import Text.Parsec import Text.Parsec
import Text.Parsec.String import Text.Parsec.String
import IHaskell.IPython.EasyKernel (easyKernel, installKernelspec, KernelConfig(..)) import IHaskell.IPython.EasyKernel (easyKernel, installKernelspec, KernelConfig(..))
import IHaskell.IPython.Types import IHaskell.IPython.Types
-- Define the actual language! -- Define the actual language!
data Expr = Plus Expr Expr data Expr = Plus Expr Expr
...@@ -47,12 +47,13 @@ parseExpr str = ...@@ -47,12 +47,13 @@ parseExpr str =
char ',' char ','
y <- expr y <- expr
char ')' char ')'
return $ case func of return $
"plus" -> Plus x y case func of
"minus" -> Minus x y "plus" -> Plus x y
"times" -> Times x y "minus" -> Minus x y
"div" -> Div x y "times" -> Times x y
"exp" -> Exp x y "div" -> Div x y
"exp" -> Exp x y
languageConfig :: LanguageInfo languageConfig :: LanguageInfo
languageConfig = LanguageInfo languageConfig = LanguageInfo
...@@ -73,11 +74,10 @@ displayString :: String -> [DisplayData] ...@@ -73,11 +74,10 @@ displayString :: String -> [DisplayData]
displayString str = [DisplayData PlainText (T.pack str)] displayString str = [DisplayData PlainText (T.pack str)]
languageCompletion :: Monad m => T.Text -> Int -> m (T.Text, [T.Text]) languageCompletion :: Monad m => T.Text -> Int -> m (T.Text, [T.Text])
languageCompletion code pos = return $ languageCompletion code pos = return $
let (before, _) = T.splitAt pos code let (before, _) = T.splitAt pos code
word = last $ T.words $ T.map replace before word = last $ T.words $ T.map replace before
in (word, map T.pack $ matches $ T.unpack word) in (word, map T.pack $ matches $ T.unpack word)
where where
matches :: String -> [String] matches :: String -> [String]
matches word = matches word =
...@@ -92,7 +92,7 @@ languageCompletion code pos = return $ ...@@ -92,7 +92,7 @@ languageCompletion code pos = return $
replace '(' = ' ' replace '(' = ' '
replace ')' = ' ' replace ')' = ' '
replace ',' = ' ' replace ',' = ' '
replace x = x replace x = x
languageInspect :: Monad m => T.Text -> Int -> m (Maybe [DisplayData]) languageInspect :: Monad m => T.Text -> Int -> m (Maybe [DisplayData])
languageInspect _ _ = return $ languageInspect _ _ = return $
...@@ -120,7 +120,6 @@ languageRun code init intermediate = do ...@@ -120,7 +120,6 @@ languageRun code init intermediate = do
Left err -> err Left err -> err
Right expr -> show (eval expr), IHaskell.IPython.Types.Ok, "") Right expr -> show (eval expr), IHaskell.IPython.Types.Ok, "")
simpleConfig :: KernelConfig IO String String simpleConfig :: KernelConfig IO String String
simpleConfig = KernelConfig simpleConfig = KernelConfig
{ kernelLanguageInfo = languageConfig { kernelLanguageInfo = languageConfig
...@@ -145,4 +144,5 @@ main = do ...@@ -145,4 +144,5 @@ main = do
_ -> do _ -> do
putStrLn "Usage:" putStrLn "Usage:"
putStrLn "fun-calc-example install -- set up the kernelspec" putStrLn "fun-calc-example install -- set up the kernelspec"
putStrLn "fun-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend" putStrLn
"fun-calc-example kernel FILE -- run a kernel with FILE for communication with the frontend"
name: ipython-kernel name: ipython-kernel
version: 0.8.0.0 version: 0.8.2.0
synopsis: A library for creating kernels for IPython frontends synopsis: A library for creating kernels for IPython frontends
description: ipython-kernel is a library for communicating with frontends for the interactive IPython framework. It is used extensively in IHaskell, the interactive Haskell environment. description: ipython-kernel is a library for communicating with frontends for the interactive IPython framework. It is used extensively in IHaskell, the interactive Haskell environment.
...@@ -35,7 +35,7 @@ library ...@@ -35,7 +35,7 @@ library
hs-source-dirs: src hs-source-dirs: src
default-language: Haskell2010 default-language: Haskell2010
build-depends: base >=4.6 && < 4.9, build-depends: base >=4.6 && < 4.9,
aeson >=0.6 && < 0.10, aeson >=0.6 && < 0.11,
bytestring >=0.10, bytestring >=0.10,
cereal >=0.3, cereal >=0.3,
containers >=0.5, containers >=0.5,
......
...@@ -11,17 +11,16 @@ ...@@ -11,17 +11,16 @@
-- --
-- = Kernel Specs -- = Kernel Specs
-- --
-- To run your kernel, you will need to install the kernelspec into the Jupyter namespace. -- To run your kernel, you will need to install the kernelspec into the Jupyter namespace. If your
-- If your kernel name is `kernel`, you will need to run the command: -- kernel name is `kernel`, you will need to run the command:
-- --
-- > kernel install -- > kernel install
-- --
-- This will inform Jupyter of the kernel so that it may be used. -- This will inform Jupyter of the kernel so that it may be used.
-- --
-- == Further profile improvements -- == Further profile improvements Consult the IPython documentation along with the generated
-- Consult the IPython documentation along with the generated profile -- profile source code for further configuration of the frontend, including syntax highlighting,
-- source code for further configuration of the frontend, including -- logos, help text, and so forth.
-- syntax highlighting, logos, help text, and so forth.
module IHaskell.IPython.EasyKernel (easyKernel, installKernelspec, KernelConfig(..)) where module IHaskell.IPython.EasyKernel (easyKernel, installKernelspec, KernelConfig(..)) where
import Data.Aeson (decode, encode) import Data.Aeson (decode, encode)
...@@ -99,7 +98,6 @@ installKernelspec config replace installPrefixMay = ...@@ -99,7 +98,6 @@ installKernelspec config replace installPrefixMay =
installPrefixFlag = maybe ["--user"] (\prefix -> ["--prefix", prefix]) installPrefixMay installPrefixFlag = maybe ["--user"] (\prefix -> ["--prefix", prefix]) installPrefixMay
cmd = concat [["kernelspec", "install"], installPrefixFlag, [kernelDir], replaceFlag] cmd = concat [["kernelspec", "install"], installPrefixFlag, [kernelDir], replaceFlag]
void $ rawSystem "ipython" cmd void $ rawSystem "ipython" cmd
where where
withTmpDir act = do withTmpDir act = do
tmp <- getTemporaryDirectory tmp <- getTemporaryDirectory
......
...@@ -8,13 +8,15 @@ ...@@ -8,13 +8,15 @@
-- 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, Value(..)) import Control.Applicative ((<|>), (<$>), (<*>))
import Data.Aeson ((.:), (.:?), (.!=), decode, Result(..), Object, Value(..))
import Data.Aeson.Types (parse, parseEither) import Data.Aeson.Types (parse, parseEither)
import Data.ByteString hiding (unpack) import Data.ByteString hiding (unpack)
import qualified Data.ByteString.Lazy as Lazy import qualified Data.ByteString.Lazy as Lazy
import Data.HashMap.Strict as HM import Data.HashMap.Strict as HM
import Data.Map (Map) import Data.Map (Map)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Data.Text (Text, unpack) import Data.Text (Text, unpack)
import Debug.Trace import Debug.Trace
import IHaskell.IPython.Types import IHaskell.IPython.Types
...@@ -254,9 +256,10 @@ inputReplyParser = requestParser $ \obj -> do ...@@ -254,9 +256,10 @@ inputReplyParser = requestParser $ \obj -> do
commOpenParser :: LByteString -> Message commOpenParser :: LByteString -> Message
commOpenParser = requestParser $ \obj -> do commOpenParser = requestParser $ \obj -> do
uuid <- obj .: "comm_id" uuid <- obj .: "comm_id"
name <- obj .: "target_name" targetName <- obj .: "target_name"
targetModule <- obj .:? "target_module" .!= ""
value <- obj .: "data" value <- obj .: "data"
return $ CommOpen noHeader name uuid value return $ CommOpen noHeader targetName targetModule uuid value
commDataParser :: LByteString -> Message commDataParser :: LByteString -> Message
commDataParser = requestParser $ \obj -> do commDataParser = requestParser $ \obj -> do
......
...@@ -101,7 +101,12 @@ instance ToJSON Message where ...@@ -101,7 +101,12 @@ instance ToJSON Message where
object ["prompt" .= prompt] object ["prompt" .= prompt]
toJSON req@CommOpen{} = toJSON req@CommOpen{} =
object ["comm_id" .= commUuid req, "target_name" .= commTargetName req, "data" .= commData req] object
[ "comm_id" .= commUuid req
, "target_name" .= commTargetName req
, "target_module" .= commTargetModule req
, "data" .= commData req
]
toJSON req@CommData{} = toJSON req@CommData{} =
object ["comm_id" .= commUuid req, "data" .= commData req] object ["comm_id" .= commUuid req, "data" .= commData req]
......
...@@ -417,6 +417,7 @@ data Message = ...@@ -417,6 +417,7 @@ data Message =
CommOpen CommOpen
{ header :: MessageHeader { header :: MessageHeader
, commTargetName :: String , commTargetName :: String
, commTargetModule :: String
, commUuid :: UUID , commUuid :: UUID
, commData :: Value , commData :: Value
} }
...@@ -497,6 +498,7 @@ replyType CompleteRequestMessage = Just CompleteReplyMessage ...@@ -497,6 +498,7 @@ replyType CompleteRequestMessage = Just CompleteReplyMessage
replyType InspectRequestMessage = Just InspectReplyMessage replyType InspectRequestMessage = Just InspectReplyMessage
replyType ShutdownRequestMessage = Just ShutdownReplyMessage replyType ShutdownRequestMessage = Just ShutdownReplyMessage
replyType HistoryRequestMessage = Just HistoryReplyMessage replyType HistoryRequestMessage = Just HistoryReplyMessage
replyType CommOpenMessage = Just CommDataMessage
replyType _ = Nothing replyType _ = Nothing
-- | Data for display: a string with associated MIME type. -- | Data for display: a string with associated MIME type.
......
...@@ -14,6 +14,7 @@ import qualified Data.ByteString.Char8 as CBS ...@@ -14,6 +14,7 @@ import qualified Data.ByteString.Char8 as CBS
-- Standard library imports. -- Standard library imports.
import Control.Concurrent (threadDelay) import Control.Concurrent (threadDelay)
import Control.Concurrent.Chan import Control.Concurrent.Chan
import Control.Arrow (second)
import Data.Aeson import Data.Aeson
import System.Directory import System.Directory
import System.Process (readProcess, readProcessWithExitCode) import System.Process (readProcess, readProcessWithExitCode)
...@@ -102,6 +103,8 @@ parseKernelArgs = foldl' addFlag defaultKernelSpecOptions ...@@ -102,6 +103,8 @@ parseKernelArgs = foldl' addFlag defaultKernelSpecOptions
kernelSpecOpts { kernelSpecGhcLibdir = libdir } kernelSpecOpts { kernelSpecGhcLibdir = libdir }
addFlag kernelSpecOpts (KernelspecInstallPrefix prefix) = addFlag kernelSpecOpts (KernelspecInstallPrefix prefix) =
kernelSpecOpts { kernelSpecInstallPrefix = Just prefix } kernelSpecOpts { kernelSpecInstallPrefix = Just prefix }
addFlag kernelSpecOpts KernelspecUseStack =
kernelSpecOpts { kernelSpecUseStack = True }
addFlag kernelSpecOpts flag = error $ "Unknown flag" ++ show flag addFlag kernelSpecOpts flag = error $ "Unknown flag" ++ show flag
-- | Run the IHaskell language kernel. -- | Run the IHaskell language kernel.
...@@ -111,6 +114,7 @@ runKernel :: KernelSpecOptions -- ^ Various options from when the kernel was ins ...@@ -111,6 +114,7 @@ runKernel :: KernelSpecOptions -- ^ Various options from when the kernel was ins
runKernel kernelOpts profileSrc = do runKernel kernelOpts profileSrc = do
let debug = kernelSpecDebug kernelOpts let debug = kernelSpecDebug kernelOpts
libdir = kernelSpecGhcLibdir kernelOpts libdir = kernelSpecGhcLibdir kernelOpts
useStack = kernelSpecUseStack kernelOpts
-- Parse the profile file. -- Parse the profile file.
Just profile <- liftM decode $ LBS.readFile profileSrc Just profile <- liftM decode $ LBS.readFile profileSrc
...@@ -120,22 +124,23 @@ runKernel kernelOpts profileSrc = do ...@@ -120,22 +124,23 @@ runKernel kernelOpts profileSrc = do
Stdin.recordKernelProfile dir profile Stdin.recordKernelProfile dir profile
#if MIN_VERSION_ghc(7,8,0) #if MIN_VERSION_ghc(7,8,0)
-- Detect if we have stack when useStack $ do
runResult <- try $ readProcessWithExitCode "stack" [] "" -- Detect if we have stack
let stack = runResult <- try $ readProcessWithExitCode "stack" [] ""
case runResult :: Either SomeException (ExitCode, String, String) of let stack =
Left _ -> False case runResult :: Either SomeException (ExitCode, String, String) of
Right (exitCode, stackStdout, _) -> exitCode == ExitSuccess && "The Haskell Tool Stack" `isInfixOf` stackStdout Left _ -> False
Right (exitCode, stackStdout, _) -> exitCode == ExitSuccess && "The Haskell Tool Stack" `isInfixOf` stackStdout
-- If we're in a stack directory, use `stack` to set the environment
-- We can't do this with base <= 4.6 because setEnv doesn't exist. -- If we're in a stack directory, use `stack` to set the environment
when stack $ do -- We can't do this with base <= 4.6 because setEnv doesn't exist.
stackEnv <- lines <$> readProcess "stack" ["exec", "env"] "" when stack $ do
forM_ stackEnv $ \line -> stackEnv <- lines <$> readProcess "stack" ["exec", "env"] ""
let (var, val) = break (== '=') line forM_ stackEnv $ \line ->
in case tailMay val of let (var, val) = break (== '=') line
Nothing -> return () in case tailMay val of
Just val' -> setEnv var val' Nothing -> return ()
Just val' -> setEnv var val'
#endif #endif
-- Serve on all sockets and ports defined in the profile. -- Serve on all sockets and ports defined in the profile.
...@@ -333,6 +338,44 @@ replyTo _ HistoryRequest{} replyHeader state = do ...@@ -333,6 +338,44 @@ replyTo _ HistoryRequest{} replyHeader state = do
} }
return (state, reply) return (state, reply)
-- Accomodating the workaround for retrieving list of open comms from the kernel
--
-- The main idea is that the frontend opens a comm at kernel startup, whose target is a widget that
-- sends back the list of live comms and commits suicide.
--
-- The message needs to be written to the iopub channel, and not returned from here. If returned,
-- the same message also gets written to the shell channel, which causes issues due to two messages
-- having the same identifiers in their headers.
--
-- Sending the message only on the shell_reply channel doesn't work, so we send it as a comm message
-- on the iopub channel and return the SendNothing message.
replyTo interface open@CommOpen{} replyHeader state = do
let send msg = liftIO $ writeChan (iopubChannel interface) msg
incomingUuid = commUuid open
target = commTargetName open
targetMatches = target == "ipython.widget"
valueMatches = commData open == object ["widget_class" .= "ipywidgets.CommInfo"]
commMap = openComms state
uuidTargetPairs = map (second targetName) $ Map.toList commMap
pairProcessor (x, y) = T.pack (UUID.uuidToString x) .= object ["target_name" .= T.pack y]
currentComms = object $ map pairProcessor $ (incomingUuid, "comm") : uuidTargetPairs
replyValue = object [ "method" .= "custom"
, "content" .= object ["comms" .= currentComms]
]
msg = CommData replyHeader (commUuid open) replyValue
-- To the iopub channel you go
when (targetMatches && valueMatches) $ send msg
return (state, SendNothing)
-- TODO: What else can be implemented? -- TODO: What else can be implemented?
replyTo _ message _ state = do replyTo _ message _ state = do
liftIO $ hPutStrLn stderr $ "Unimplemented message: " ++ show message liftIO $ hPutStrLn stderr $ "Unimplemented message: " ++ show message
......
...@@ -52,9 +52,8 @@ widgetSend :: IHaskellWidget a ...@@ -52,9 +52,8 @@ widgetSend :: IHaskellWidget a
widgetSend msgType widget value = queue $ msgType (Widget widget) value widgetSend msgType widget value = queue $ msgType (Widget widget) value
-- | Send a message to open a comm -- | Send a message to open a comm
widgetSendOpen :: IHaskellWidget a => a -> Value -> Value -> IO () widgetSendOpen :: IHaskellWidget a => a -> Value -> IO ()
widgetSendOpen widget initVal stateVal = widgetSendOpen = widgetSend Open
queue $ Open (Widget widget) initVal stateVal
-- | Send a state update message -- | Send a state update message
widgetSendUpdate :: IHaskellWidget a => a -> Value -> IO () widgetSendUpdate :: IHaskellWidget a => a -> Value -> IO ()
...@@ -93,8 +92,9 @@ handleMessage :: (Message -> IO ()) ...@@ -93,8 +92,9 @@ handleMessage :: (Message -> IO ())
-> IO KernelState -> IO KernelState
handleMessage send replyHeader state msg = do handleMessage send replyHeader state msg = do
case msg of case msg of
Open widget initVal stateVal -> do Open widget value -> do
let target = targetName widget let target_name = targetName widget
target_module = targetModule widget
uuid = getCommUUID widget uuid = getCommUUID widget
present = isJust $ Map.lookup uuid oldComms present = isJust $ Map.lookup uuid oldComms
...@@ -109,12 +109,9 @@ handleMessage send replyHeader state msg = do ...@@ -109,12 +109,9 @@ handleMessage send replyHeader state msg = do
if present if present
then return state then return state
else do else do
-- Send the comm open -- Send the comm open, with the initial state
header <- dupHeader replyHeader CommOpenMessage header <- dupHeader replyHeader CommOpenMessage
send $ CommOpen header target uuid initVal send $ CommOpen header target_name target_module uuid value
-- Initial state update
communicate . toJSON $ UpdateState stateVal
-- Send anything else the widget requires. -- Send anything else the widget requires.
open widget communicate open widget communicate
...@@ -123,8 +120,7 @@ handleMessage send replyHeader state msg = do ...@@ -123,8 +120,7 @@ handleMessage send replyHeader state msg = do
return newState return newState
Close widget value -> do Close widget value -> do
let target = targetName widget let uuid = getCommUUID widget
uuid = getCommUUID widget
present = isJust $ Map.lookup uuid oldComms present = isJust $ Map.lookup uuid oldComms
newComms = Map.delete uuid $ openComms state newComms = Map.delete uuid $ openComms state
......
...@@ -38,6 +38,7 @@ data Argument = ConfFile String -- ^ A file with commands to load at startup ...@@ -38,6 +38,7 @@ data Argument = ConfFile String -- ^ A file with commands to load at startup
| ConvertToFormat NotebookFormat | ConvertToFormat NotebookFormat
| ConvertLhsStyle (LhsStyle String) | ConvertLhsStyle (LhsStyle String)
| KernelspecInstallPrefix String | KernelspecInstallPrefix String
| KernelspecUseStack
deriving (Eq, Show) deriving (Eq, Show)
data LhsStyle string = data LhsStyle string =
...@@ -100,6 +101,12 @@ kernelDebugFlag = flagNone ["debug"] addDebug "Print debugging output from the k ...@@ -100,6 +101,12 @@ kernelDebugFlag = flagNone ["debug"] addDebug "Print debugging output from the k
where where
addDebug (Args mode prev) = Args mode (KernelDebug : prev) addDebug (Args mode prev) = Args mode (KernelDebug : prev)
kernelStackFlag :: Flag Args
kernelStackFlag = flagNone ["stack"] addStack
"Inherit environment from `stack` when it is installed"
where
addStack (Args mode prev) = Args mode (KernelspecUseStack : prev)
confFlag :: Flag Args confFlag :: Flag Args
confFlag = flagReq ["conf", "c"] (store ConfFile) "<rc.hs>" confFlag = flagReq ["conf", "c"] (store ConfFile) "<rc.hs>"
"File with commands to execute at start; replaces ~/.ihaskell/rc.hs." "File with commands to execute at start; replaces ~/.ihaskell/rc.hs."
...@@ -118,11 +125,11 @@ store constructor str (Args mode prev) = Right $ Args mode $ constructor str : p ...@@ -118,11 +125,11 @@ store constructor str (Args mode prev) = Right $ Args mode $ constructor str : p
installKernelSpec :: Mode Args installKernelSpec :: Mode Args
installKernelSpec = installKernelSpec =
mode "install" (Args InstallKernelSpec []) "Install the Jupyter kernelspec." noArgs mode "install" (Args InstallKernelSpec []) "Install the Jupyter kernelspec." noArgs
[ghcLibFlag, kernelDebugFlag, confFlag, installPrefixFlag, helpFlag] [ghcLibFlag, kernelDebugFlag, confFlag, installPrefixFlag, helpFlag, kernelStackFlag]
kernel :: Mode Args kernel :: Mode Args
kernel = mode "kernel" (Args (Kernel Nothing) []) "Invoke the IHaskell kernel." kernelArg kernel = mode "kernel" (Args (Kernel Nothing) []) "Invoke the IHaskell kernel." kernelArg
[ghcLibFlag, kernelDebugFlag, confFlag] [ghcLibFlag, kernelDebugFlag, confFlag, kernelStackFlag]
where where
kernelArg = flagArg update "<json-kernel-file>" kernelArg = flagArg update "<json-kernel-file>"
update filename (Args _ flags) = Right $ Args (Kernel $ Just filename) flags update filename (Args _ flags) = Right $ Args (Kernel $ Just filename) flags
......
...@@ -47,6 +47,7 @@ data KernelSpecOptions = ...@@ -47,6 +47,7 @@ data KernelSpecOptions =
, kernelSpecDebug :: Bool -- ^ Spew debugging output? , kernelSpecDebug :: Bool -- ^ Spew debugging output?
, kernelSpecConfFile :: IO (Maybe String) -- ^ Filename of profile JSON file. , kernelSpecConfFile :: IO (Maybe String) -- ^ Filename of profile JSON file.
, kernelSpecInstallPrefix :: Maybe String , kernelSpecInstallPrefix :: Maybe String
, kernelSpecUseStack :: Bool -- ^ Whether to use @stack@ environments.
} }
defaultKernelSpecOptions :: KernelSpecOptions defaultKernelSpecOptions :: KernelSpecOptions
...@@ -55,6 +56,7 @@ defaultKernelSpecOptions = KernelSpecOptions ...@@ -55,6 +56,7 @@ defaultKernelSpecOptions = KernelSpecOptions
, kernelSpecDebug = False , kernelSpecDebug = False
, kernelSpecConfFile = defaultConfFile , kernelSpecConfFile = defaultConfFile
, kernelSpecInstallPrefix = Nothing , kernelSpecInstallPrefix = Nothing
, kernelSpecUseStack = False
} }
-- | The IPython kernel name. -- | The IPython kernel name.
...@@ -72,6 +74,13 @@ ipythonCommand = do ...@@ -72,6 +74,13 @@ ipythonCommand = do
Nothing -> "ipython" Nothing -> "ipython"
Just _ -> "jupyter" Just _ -> "jupyter"
locateIPython :: SH.Sh SH.FilePath
locateIPython = do
mbinary <- SH.which "ipython"
case mbinary of
Nothing -> SH.errorExit "The IPython binary could not be located"
Just ipython -> return ipython
-- | Run the IPython command with any arguments. The kernel is set to IHaskell. -- | Run the IPython command with any arguments. The kernel is set to IHaskell.
ipython :: Bool -- ^ Whether to suppress output. ipython :: Bool -- ^ Whether to suppress output.
-> [Text] -- ^ IPython command line arguments. -> [Text] -- ^ IPython command line arguments.
...@@ -181,6 +190,7 @@ installKernelspec replace opts = void $ do ...@@ -181,6 +190,7 @@ installKernelspec replace opts = void $ do
Nothing -> [] Nothing -> []
Just file -> ["--conf", file]) Just file -> ["--conf", file])
++ ["--ghclib", kernelSpecGhcLibdir opts] ++ ["--ghclib", kernelSpecGhcLibdir opts]
++ ["--stack" | kernelSpecUseStack opts]
let kernelSpec = KernelSpec let kernelSpec = KernelSpec
{ kernelDisplayName = "Haskell" { kernelDisplayName = "Haskell"
...@@ -201,15 +211,17 @@ installKernelspec replace opts = void $ do ...@@ -201,15 +211,17 @@ installKernelspec replace opts = void $ do
src <- liftIO $ Paths.getDataFileName $ "html/" ++ file src <- liftIO $ Paths.getDataFileName $ "html/" ++ file
SH.cp (SH.fromText $ T.pack src) (tmp SH.</> kernelName SH.</> file) SH.cp (SH.fromText $ T.pack src) (tmp SH.</> kernelName SH.</> file)
Just ipython <- SH.which "ipython" ipython <- locateIPython
let replaceFlag = ["--replace" | replace] let replaceFlag = ["--replace" | replace]
installPrefixFlag = maybe ["--user"] (\prefix -> ["--prefix", T.pack prefix]) (kernelSpecInstallPrefix opts) installPrefixFlag = maybe ["--user"] (\prefix -> ["--prefix", T.pack prefix]) (kernelSpecInstallPrefix opts)
cmd = concat [["kernelspec", "install"], installPrefixFlag, [SH.toTextIgnore kernelDir], replaceFlag] cmd = concat [["kernelspec", "install"], installPrefixFlag, [SH.toTextIgnore kernelDir], replaceFlag]
SH.silently $ SH.run ipython cmd SH.silently $ SH.run ipython cmd
kernelSpecCreated :: SH.Sh Bool kernelSpecCreated :: SH.Sh Bool
kernelSpecCreated = do kernelSpecCreated = do
Just ipython <- SH.which "ipython" ipython <- locateIPython
out <- SH.silently $ SH.run ipython ["kernelspec", "list"] out <- SH.silently $ SH.run ipython ["kernelspec", "list"]
let kernelspecs = map T.strip $ T.lines out let kernelspecs = map T.strip $ T.lines out
return $ T.pack kernelName `elem` kernelspecs return $ T.pack kernelName `elem` kernelspecs
......
...@@ -65,11 +65,15 @@ class IHaskellDisplay a where ...@@ -65,11 +65,15 @@ class IHaskellDisplay a where
-- | Display as an interactive widget. -- | Display as an interactive widget.
class IHaskellDisplay a => IHaskellWidget a where class IHaskellDisplay a => IHaskellWidget a where
-- | Output target name for this widget. The actual input parameter should be ignored. By default -- | Target name for this widget. The actual input parameter should be ignored. By default evaluate
-- evaluate to "ipython.widget", which is used by IPython for its backbone widgets. -- to "ipython.widget", which is used by IPython for its backbone widgets.
targetName :: a -> String targetName :: a -> String
targetName _ = "ipython.widget" targetName _ = "ipython.widget"
-- | Target module for this widget. Evaluates to an empty string by default.
targetModule :: a -> String
targetModule _ = ""
-- | Get the uuid for comm associated with this widget. The widget is responsible for storing the -- | Get the uuid for comm associated with this widget. The widget is responsible for storing the
-- UUID during initialization. -- UUID during initialization.
getCommUUID :: a -> UUID getCommUUID :: a -> UUID
...@@ -102,6 +106,7 @@ instance IHaskellDisplay Widget where ...@@ -102,6 +106,7 @@ instance IHaskellDisplay Widget where
instance IHaskellWidget Widget where instance IHaskellWidget Widget where
targetName (Widget widget) = targetName widget targetName (Widget widget) = targetName widget
targetModule (Widget widget) = targetModule widget
getCommUUID (Widget widget) = getCommUUID widget getCommUUID (Widget widget) = getCommUUID widget
open (Widget widget) = open widget open (Widget widget) = open widget
comm (Widget widget) = comm widget comm (Widget widget) = comm widget
...@@ -185,11 +190,10 @@ data LintStatus = LintOn ...@@ -185,11 +190,10 @@ data LintStatus = LintOn
deriving (Eq, Show) deriving (Eq, Show)
-- | Send JSON objects with specific formats -- | Send JSON objects with specific formats
data WidgetMsg = Open Widget Value Value data WidgetMsg = Open Widget Value
| |
-- ^ Cause the interpreter to open a new comm, and register the associated widget in -- ^ Cause the interpreter to open a new comm, and register the associated widget in
-- the kernelState. Also sends a Value with comm_open, and then sends an initial -- the kernelState. Also sends an initial state Value with comm_open.
-- state update Value.
Update Widget Value Update Widget Value
| |
-- ^ Cause the interpreter to send a comm_msg containing a state update for the -- ^ Cause the interpreter to send a comm_msg containing a state update for the
......
...@@ -8,7 +8,6 @@ packages: ...@@ -8,7 +8,6 @@ packages:
- ihaskell-display/ihaskell-juicypixels/ - ihaskell-display/ihaskell-juicypixels/
- ihaskell-display/ihaskell-magic/ - ihaskell-display/ihaskell-magic/
- ihaskell-display/ihaskell-rlangqq/ - ihaskell-display/ihaskell-rlangqq/
- ihaskell-display/ihaskell-parsec/
- ihaskell-display/ihaskell-plot/ - ihaskell-display/ihaskell-plot/
- ihaskell-display/ihaskell-blaze/ - ihaskell-display/ihaskell-blaze/
- ihaskell-display/ihaskell-widgets/ - ihaskell-display/ihaskell-widgets/
......
...@@ -11,6 +11,7 @@ cabal update ...@@ -11,6 +11,7 @@ cabal update
cabal install happy alex cabal install happy alex
cabal install cpphs cabal install cpphs
cabal install gtk2hs-buildtools cabal install gtk2hs-buildtools
cabal install HTTP
# Build ihaskell, and all the display packages # Build ihaskell, and all the display packages
./build.sh all ./build.sh all
...@@ -52,7 +52,10 @@ for source_dir in ["src", "ipython-kernel", "ihaskell-display"]: ...@@ -52,7 +52,10 @@ for source_dir in ["src", "ipython-kernel", "ihaskell-display"]:
continue continue
# Ignore IHaskellPrelude.hs, it uses CPP in weird places # Ignore IHaskellPrelude.hs, it uses CPP in weird places
ignored_files = ["IHaskellPrelude.hs"] if widget_dir in root:
ignored_files = ["Types.hs"]
else:
ignored_files = ["IHaskellPrelude.hs"]
for filename in filenames: for filename in filenames:
if filename.endswith(".hs") and filename not in ignored_files: if filename.endswith(".hs") and filename not in ignored_files:
sources.append(os.path.join(root, filename)) sources.append(os.path.join(root, filename))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment