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

Merge master

parents e14d003d 346c4960
......@@ -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.
script:
- |
if [ ${GHCVER%.*} = "7.8" ]; then
if [[ ${GHCVER%.*} == "7.8" || ${GHCVER%.*} == "7.10" ]]; then
travis_retry ./build.sh all
elif [ ${GHCVER%.*} = "7.10" ]; then
travis_retry ./build.sh all no-widgets
else
travis_retry ./build.sh ihaskell
fi
......
......@@ -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).
Arch Linux has a package for IHaskell: https://aur.archlinux.org/packages/ihaskell-git/
### Install Using Installation Scripts
#### Ubuntu:
......@@ -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.
#### 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
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
```
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, 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`.
- **Other**: You can install ZeroMQ from source or use another package manager:
```bash
......@@ -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.
#### Install Haskell Tools
*(This section can be skipped when using stack)*
First, make sure that executables installed by `cabal` are on your shell `PATH`:
```bash
# If you have a ~/.cabal/bin folder:
......@@ -102,7 +113,12 @@ cabal install happy cpphs
```
#### 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
cabal install ihaskell --reorder-goals
```
......@@ -144,6 +160,14 @@ The above will install `ihaskell`, all support libraries (specified in `stack.ya
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:
- `ihaskell install` to install the IHaskell kernel into Jupyter.
......
......@@ -32,9 +32,6 @@ fi
# What to install.
INSTALLS=""
# Remove my kernelspec
rm -rf ~/.ipython/kernels/haskell
# Compile dependencies.
if [ $# -gt 0 ]; then
if [ $1 = "all" ] || [ $1 = "ihaskell" ]; then
......@@ -47,7 +44,7 @@ INSTALLS="$INSTALLS ."
# Install ihaskell-display packages.
if [ $# -gt 0 ]; then
if [ $1 = "display" ] || [ $1 = "all" ]; then
if [ $1 = "display" ] || [ $1 = "all" ]; then
# Install all the display libraries
cd ihaskell-display
for dir in `ls | grep -v ihaskell-widgets`
......@@ -58,25 +55,46 @@ if [ $# -gt 0 ]; then
fi
fi
# Clean all required directories, just in case.
TOP=`pwd`
for pkg in $INSTALLS
do
cd ./$pkg
cabal clean
cd $TOP
done
cleanup () {
# Remove old kernelspec
rm -rf ~/.ipython/kernels/haskell
# Stick a "./" before everything.
INSTALL_DIRS=`echo $INSTALLS | tr ' ' '\n' | sed 's#^#./#' | tr ' ' '\n'`
# Clean all required directories, just in case.
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
cabal install --constraint "arithmoi -llvm" -j $INSTALL_DIRS --force-reinstalls --max-backjumps=-1 --reorder-goals
install_selected () {
# Stick a "./" before everything.
INSTALL_DIRS=`echo $INSTALLS | tr ' ' '\n' | sed 's#^#./#' | tr ' ' '\n'`
if [ $2 = "no-widgets" ]; then
echo 'Not installing ihaskell-widgets'
elif [ $1 = "display" ] || [ $1 = "all" ]; then
echo CMD: cabal install --constraint "arithmoi -llvm" -j $INSTALL_DIRS --force-reinstalls --max-backjumps=-1 --reorder-goals
cabal install --constraint "arithmoi -llvm" -j $INSTALL_DIRS --force-reinstalls --max-backjumps=-1 --reorder-goals
}
install_widgets () {
echo CMD: 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
if hash ihaskell 2>/dev/null; then
......
import Distribution.Simple
import System.Cmd
import System.Process
main = defaultMainWithHooks
simpleUserHooks { preConf = \args confFlags -> do
......
......@@ -7,7 +7,7 @@ name: ihaskell-diagrams
-- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.3.0.0
version: 0.3.1.0
-- A short (one-line) description of the package.
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
build-depends: base >=4.6 && <4.9,
plot,
bytestring,
hmatrix >= 0.10,
ihaskell >= 0.6.2
-- 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 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"{-# LANGUAGE FlexibleContexts #-}\n",
"import IHaskell.Display.Widgets\n",
"import Data.Text (pack, unpack)\n",
"import Text.Printf (printf)"
......@@ -43,18 +44,20 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"-- Constructors\n",
"-- Check box\n",
"chk <- mkCheckBox\n",
"\n",
"-- Toggle button\n",
"tgb <- mkToggleButton\n",
"\n",
"-- For demonstration\n",
"o <- mkHTMLWidget"
"-- Valid widget: Displaying booleans conveniently\n",
"vld <- mkValidWidget"
]
},
{
......@@ -66,16 +69,16 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"-- Display\n",
"-- Display the widgets\n",
"chk\n",
"tgb\n",
"o"
"vld"
]
},
{
......@@ -87,38 +90,23 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField chk Description \"Bool 1: \"\n",
"setField tgb Description \"Bool 2\"\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",
"setField o Description \"Bool 1 && Bool 2\"\n",
"setField o Padding 10\n",
"setField vld Description \"Bool 1 && Bool 2\"\n",
"\n",
" -- And (&&) the two values, and send output to html widget\n",
"setHandler w = setField w ChangeHandler $ do\n",
" b1 <- getField chk BoolValue\n",
" b2 <- getField tgb BoolValue\n",
" refresh (b1 && b2)\n",
" setField vld BoolValue (b1 && b2)\n",
"\n",
"setHandler chk\n",
"setHandler tgb"
......@@ -142,7 +130,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -163,19 +151,11 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"sign <- mkCheckBox\n",
"bits <- replicateM 7 mkToggleButton\n",
......@@ -195,19 +175,11 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"box <- mkFlexBox\n",
"out <- mkHTMLWidget\n",
......@@ -248,19 +220,11 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"import Control.Arrow (first, second)\n",
"\n",
......@@ -295,6 +259,12 @@
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
}
},
"nbformat": 4,
......
......@@ -68,7 +68,7 @@
"jpg <- get \"http://imgs.xkcd.com/comics/functional.png\"\n",
"\n",
"img <- mkImageWidget\n",
"setField img SB64Value (encode64 jpg)\n",
"setField img B64Value (encode64 jpg)\n",
"img"
]
},
......@@ -104,6 +104,12 @@
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
}
},
"nbformat": 4,
......
......@@ -27,7 +27,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -46,9 +46,9 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {
"collapsed": true
"collapsed": false
},
"outputs": [],
"source": [
......@@ -58,7 +58,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -77,19 +77,11 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField bit MaxInt 20\n",
"setField bit MinInt 10\n",
......@@ -119,7 +111,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -131,7 +123,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -143,21 +135,11 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(25,75)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"getField irs IntPairValue"
]
......@@ -178,7 +160,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -190,19 +172,11 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField inp IntValue 42"
]
......@@ -213,6 +187,12 @@
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
}
},
"nbformat": 4,
......
......@@ -13,13 +13,14 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"{-# LANGUAGE FlexibleContexts #-}\n",
"import IHaskell.Display.Widgets"
]
},
......@@ -32,7 +33,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -83,19 +84,11 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"import Data.IORef\n",
"import Graphics.Rendering.Chart.Easy hiding (tan)\n",
......@@ -164,19 +157,11 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"divBox <- mkFlexBox\n",
"setField divBox Orientation HorizontalOrientation\n",
......@@ -204,20 +189,12 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"slBox <- mkFlexBox\n",
"\n",
......@@ -244,19 +221,11 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"-- The four FlexBox widgets.\n",
"import Control.Monad (replicateM, forM_)\n",
......@@ -302,19 +271,11 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"-- A FlexBox with ToggleButtons\n",
"buttonBox <- mkFlexBox\n",
......@@ -339,19 +300,11 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"import Control.Arrow (first, second)\n",
"\n",
......@@ -384,19 +337,11 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField tlBox Children $ map ChildWidget $ boxes ++ [buttonBox] ++ rangeBoxes"
]
......@@ -410,19 +355,11 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField tlBox Titles [\"Plot title\", \"X-Label\", \"Y-Label\", \"Grid\", \"X-range\", \"Y-range\"]"
]
......@@ -436,19 +373,11 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"let syncVal widget value fieldGetter = readIORef plotState >>= setField widget value . fieldGetter\n",
" in do\n",
......@@ -478,7 +407,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -500,22 +429,11 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"-- Spurious update to display empty plot instead of empty image initially\n",
"update return\n",
......@@ -532,7 +450,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -543,7 +461,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -554,7 +472,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -569,6 +487,12 @@
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
}
},
"nbformat": 4,
......
......@@ -22,7 +22,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -34,7 +34,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -49,19 +49,11 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField msel Description \"Functions to show (One or more)\"\n",
"setField msel Options (OptionLabels [\"sin\", \"cos\"])\n",
......@@ -79,20 +71,12 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"import Graphics.Rendering.Chart.Easy hiding (tan)\n",
"import Graphics.Rendering.Chart.Backend.Cairo\n",
......@@ -140,92 +124,11 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {
"collapsed": false
},
"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"
}
],
"outputs": [],
"source": [
"-- Display the widgets\n",
"msel\n",
......@@ -246,6 +149,12 @@
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
}
},
"nbformat": 4,
......
......@@ -21,19 +21,20 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"{-# LANGUAGE FlexibleContexts #-}\n",
"import IHaskell.Display.Widgets"
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -69,7 +70,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -82,7 +83,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -94,7 +95,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -116,7 +117,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -142,7 +143,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"metadata": {
"collapsed": false
},
......@@ -154,20 +155,12 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"-- Some padding\n",
"setField text Padding 5"
......@@ -182,19 +175,11 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField text Placeholder \"Enter your text here...\"\n",
"setField area Placeholder \"Parsed output will appear here...\""
......@@ -216,7 +201,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -239,7 +224,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -300,19 +285,11 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField text ChangeHandler $ do\n",
" input <- unpack <$> getField text StringValue\n",
......@@ -338,7 +315,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"metadata": {
"collapsed": true
},
......@@ -354,6 +331,12 @@
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.2"
}
},
"nbformat": 4,
......
......@@ -8,26 +8,17 @@
## Creating widgets
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
notify the frontend about the creation of a widget, an initial state update is sent on the widget's
comm.
The kernel will open a comm for the widget, and store a reference to that comm. The comm_open message
also holds the initial state of the widget in it, which is used by the frontend to create a model for
the 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
frontend. Some numbers need to be sent as actual numbers (when non-null), whereas some (especially
those used by sliders) need to be sent as strings.
frontend. Some numbers need to be sent as actual numbers (when non-null), whereas the ones representing
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
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:
- Rest of the properties as required initially.
This state update is also used with fragments of the overall state to sync changes between the
frontend and the kernel.
This state is also used with fragments of the overall state to sync changes between the frontend and
the kernel.
## Displaying widgets
......@@ -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.
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
-- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.1.0.0
version: 0.2.2.1
-- A short (one-line) description of the package.
synopsis: IPython standard widgets for IHaskell.
......@@ -57,11 +57,14 @@ library
-- Modules included in this library but not exported.
other-modules: IHaskell.Display.Widgets.Button
IHaskell.Display.Widgets.Box.Box
IHaskell.Display.Widgets.Box.Proxy
IHaskell.Display.Widgets.Box.PlaceProxy
IHaskell.Display.Widgets.Box.FlexBox
IHaskell.Display.Widgets.Box.SelectionContainer.Accordion
IHaskell.Display.Widgets.Box.SelectionContainer.Tab
IHaskell.Display.Widgets.Bool.CheckBox
IHaskell.Display.Widgets.Bool.ToggleButton
IHaskell.Display.Widgets.Bool.Valid
IHaskell.Display.Widgets.Int.IntText
IHaskell.Display.Widgets.Int.BoundedInt.BoundedIntText
IHaskell.Display.Widgets.Int.BoundedInt.IntProgress
......@@ -92,20 +95,35 @@ library
-- other-extensions:
-- Other library packages from which modules are imported.
build-depends: aeson >=0.7 && < 0.10
, 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
, scientific -any
, unix -any
, ihaskell >= 0.6.4.1
-- singletons 2.* require ghc 7.10.2
if impl(ghc >= 7.10.2)
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
, scientific -any
, 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.
hs-source-dirs: src
......@@ -120,3 +138,8 @@ library
-- ghc-7.10.* = 100
if impl(ghc == 7.8.*)
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
import IHaskell.Display.Widgets.Button 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.SelectionContainer.Accordion as X
import IHaskell.Display.Widgets.Box.SelectionContainer.Tab as X
import IHaskell.Display.Widgets.Bool.CheckBox 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.BoundedInt.BoundedIntText 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.Common as X
import IHaskell.Display.Widgets.Types as X (setField, getField, properties)
import IHaskell.Display.Widgets.Types as X (triggerDisplay, triggerChange, triggerClick,
triggerSelection, triggerSubmit,
ChildWidget(..))
import IHaskell.Display.Widgets.Types as X (setField, getField, properties, triggerDisplay,
triggerChange, triggerClick, triggerSelection,
triggerSubmit, ChildWidget(..))
......@@ -12,12 +12,10 @@ CheckBox,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -40,11 +38,9 @@ mkCheckBox = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the image widget
return widget
......
......@@ -12,7 +12,6 @@ ToggleButton,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -45,11 +44,9 @@ mkToggleButton = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the image 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,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import Data.Text (Text)
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 'Box' represents a Box widget from IPython.html.widgets.
type Box = IPythonWidget BoxType
......@@ -40,10 +35,9 @@ mkBox = do
stateIO <- newIORef widgetState
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
widgetSendOpen box initData $ toJSON widgetState
widgetSendOpen box $ toJSON widgetState
-- Return the widget
return box
......
......@@ -12,11 +12,8 @@ FlexBox,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
......@@ -46,10 +43,9 @@ mkFlexBox = do
stateIO <- newIORef widgetState
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
widgetSendOpen box initData $ toJSON widgetState
widgetSendOpen box $ toJSON widgetState
-- Return the widget
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,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -41,11 +39,9 @@ mkAccordion = do
stateIO <- newIORef widgetState
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
widgetSendOpen box initData $ toJSON widgetState
widgetSendOpen box $ toJSON widgetState
-- Return the widget
return box
......
......@@ -12,13 +12,11 @@ TabWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -41,10 +39,9 @@ mkTabWidget = do
stateIO <- newIORef widgetState
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
widgetSendOpen box initData $ toJSON widgetState
widgetSendOpen box $ toJSON widgetState
-- Return the widget
return box
......
......@@ -12,7 +12,7 @@ Button,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Control.Monad (when)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -49,10 +49,8 @@ mkButton = do
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
widgetSendOpen button initData $ toJSON buttonState
widgetSendOpen button $ toJSON buttonState
-- Return the button widget
return button
......
......@@ -4,12 +4,15 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE AutoDeriveTypeable #-}
{-# LANGUAGE DeriveDataTypeable #-}
module IHaskell.Display.Widgets.Common where
import Data.Aeson
import Data.Aeson.Types (emptyObject)
import Data.Text (pack, Text)
import Data.Typeable (Typeable)
import IHaskell.Display (IHaskellWidget)
import IHaskell.Eval.Widgets (widgetSendClose)
......@@ -18,6 +21,8 @@ import qualified IHaskell.Display.Widgets.Singletons as S
pattern ViewModule = S.SViewModule
pattern ViewName = S.SViewName
pattern ModelModule = S.SModelModule
pattern ModelName = S.SModelName
pattern MsgThrottle = S.SMsgThrottle
pattern Version = S.SVersion
pattern DisplayHandler = S.SDisplayHandler
......@@ -87,16 +92,19 @@ pattern Pack = S.SPack
pattern Align = S.SAlign
pattern Titles = S.STitles
pattern SelectedIndex = S.SSelectedIndex
pattern ReadOutMsg = S.SReadOutMsg
pattern Child = S.SChild
pattern Selector = S.SSelector
-- | Close a widget's comm
closeWidget :: IHaskellWidget w => w -> IO ()
closeWidget w = widgetSendClose w emptyObject
newtype StrInt = StrInt Integer
deriving (Num, Ord, Eq, Enum)
newtype PixCount = PixCount Integer
deriving (Num, Ord, Eq, Enum, Typeable)
instance ToJSON StrInt where
toJSON (StrInt x) = toJSON . pack $ show x
instance ToJSON PixCount where
toJSON (PixCount x) = toJSON . pack $ show x ++ "px"
-- | Pre-defined border styles
data BorderStyleValue = NoBorder
......@@ -196,7 +204,7 @@ instance ToJSON BarStyleValue where
data ImageFormatValue = PNG
| SVG
| JPG
deriving Eq
deriving (Eq, Typeable)
instance Show ImageFormatValue where
show PNG = "png"
......
......@@ -13,13 +13,11 @@ BoundedFloatText,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -42,13 +40,9 @@ mkBoundedFloatText = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,13 +12,8 @@ FloatProgress,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Exception (throw, ArithException(LossOfPrecision))
import Control.Monad (when, join)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
......@@ -38,19 +33,17 @@ mkFloatProgress = do
uuid <- U.random
let boundedFloatAttrs = defaultBoundedFloatWidget "ProgressView"
progressAttrs = (BarStyle =:: DefaultBar) :& RNil
progressAttrs = (Orientation =:: HorizontalOrientation)
:& (BarStyle =:: DefaultBar)
:& RNil
widgetState = WidgetState $ boundedFloatAttrs <+> progressAttrs
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,7 +12,6 @@ FloatSlider,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -47,11 +46,9 @@ mkFloatSlider = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -13,8 +13,6 @@ FloatRangeSlider,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Exception (throw, ArithException(LossOfPrecision))
import Control.Monad (when, join, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -50,13 +48,9 @@ mkFloatRangeSlider = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,13 +12,11 @@ FloatText,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -41,11 +39,9 @@ mkFloatText = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,12 +12,9 @@ ImageWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import Data.Monoid (mempty)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
......@@ -38,6 +35,8 @@ mkImageWidget = do
let dom = defaultDOMWidget "ImageView"
img = (ImageFormat =:: PNG)
:& (Width =:+ 0)
:& (Height =:+ 0)
:& (B64Value =:: mempty)
:& RNil
widgetState = WidgetState (dom <+> img)
......@@ -46,10 +45,8 @@ mkImageWidget = do
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the image widget
return widget
......
......@@ -12,13 +12,11 @@ BoundedIntText,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -41,13 +39,9 @@ mkBoundedIntText = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,13 +12,8 @@ IntProgress,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Exception (throw, ArithException(LossOfPrecision))
import Control.Monad (when, join)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
......@@ -38,17 +33,17 @@ mkIntProgress = do
uuid <- U.random
let boundedIntAttrs = defaultBoundedIntWidget "ProgressView"
progressAttrs = (BarStyle =:: DefaultBar) :& RNil
progressAttrs = (Orientation =:: HorizontalOrientation)
:& (BarStyle =:: DefaultBar)
:& RNil
widgetState = WidgetState $ boundedIntAttrs <+> progressAttrs
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,7 +12,6 @@ IntSlider,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -47,11 +46,9 @@ mkIntSlider = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,7 +12,6 @@ IntRangeSlider,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -48,13 +47,9 @@ mkIntRangeSlider = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,13 +12,11 @@ IntText,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import qualified Data.Scientific as Sci
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -41,10 +39,9 @@ mkIntText = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternSynonyms #-}
module IHaskell.Display.Widgets.Interactive (interactive, uncurryHList, Rec(..), Argument(..)) where
......@@ -25,7 +22,7 @@ import IHaskell.Display
import IHaskell.Display.Widgets.Types
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.Bool.CheckBox
......@@ -44,10 +41,6 @@ data WidgetConf a where
a
-> WidgetConf a
newtype WrappedConstructor a =
WrappedConstructor
{ wrappedConstructor :: IO (IPythonWidget (SuitableWidget a)) }
type family WithTypes (ts :: [*]) (r :: *) :: * where
WithTypes '[] r = r
......@@ -70,8 +63,6 @@ newtype EventSetter a = EventSetter (IPythonWidget (SuitableWidget a) -> IO () -
newtype Initializer a = Initializer (IPythonWidget (SuitableWidget a) -> Argument a -> IO ())
newtype Trigger a = Trigger (IPythonWidget (SuitableWidget a) -> IO ())
data RequiredWidget a where
RequiredWidget ::
......@@ -107,11 +98,8 @@ extractGetter (WidgetConf wr) = Getter $ getValue wr
extractEventSetter :: WidgetConf x -> EventSetter x
extractEventSetter (WidgetConf wr) = EventSetter $ setEvent wr
extractTrigger :: WidgetConf x -> Trigger x
extractTrigger (WidgetConf wr) = Trigger $ trigger wr
extractInitializer :: WidgetConf x -> Initializer x
extractInitializer (WidgetConf wr) = Initializer initializer
extractInitializer WidgetConf{} = Initializer initializer
createWidget :: Constructor a -> IO (RequiredWidget a)
createWidget (Constructor con) = fmap RequiredWidget con
......@@ -146,7 +134,6 @@ liftToWidgets func rc initvals = do
getters = rmap extractGetter rc
eventSetters = rmap extractEventSetter rc
initializers = rmap extractInitializer rc
triggers = rmap extractTrigger rc
bx <- mkFlexBox
out <- mkOutputWidget
......@@ -188,15 +175,9 @@ construct (WrappedWidget cons _ _) = cons
getValue :: WrappedWidget w h f a -> IPythonWidget w -> IO a
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 _ 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
type SuitableWidget a :: WidgetType
type SuitableHandler a :: S.Field
......
......@@ -18,12 +18,8 @@ module IHaskell.Display.Widgets.Output (
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -45,10 +41,9 @@ mkOutputWidget = do
stateIO <- newIORef widgetState
let widget = IPythonWidget uuid stateIO
initData = object ["model_name" .= str "WidgetModel"]
-- 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 widget
......
......@@ -12,7 +12,7 @@ Dropdown,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Control.Monad (void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -41,11 +41,9 @@ mkDropdown = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,12 +12,11 @@ RadioButtons,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Control.Monad (when, void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -39,11 +38,9 @@ mkRadioButtons = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -39,10 +39,9 @@ mkSelect = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,13 +12,12 @@ SelectMultiple,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (fmap, join, sequence, void)
import Control.Monad (void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
import Data.Text (Text)
import qualified Data.Vector as V
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -40,13 +39,9 @@ mkSelectMultiple = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,7 +12,7 @@ ToggleButtons,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join, void)
import Control.Monad (void)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -44,13 +44,9 @@ mkToggleButtons = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -5,10 +5,13 @@
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE InstanceSigs #-}
module IHaskell.Display.Widgets.Singletons where
import Data.Singletons.TH
import Data.Singletons.Prelude.Ord
-- Widget properties
singletons
......@@ -16,6 +19,8 @@ singletons
data Field = ViewModule
| ViewName
| ModelModule
| ModelName
| MsgThrottle
| Version
| DisplayHandler
......@@ -85,5 +90,8 @@ singletons
| Align
| Titles
| SelectedIndex
| ReadOutMsg
| Child
| Selector
deriving (Eq, Ord, Show)
|]
......@@ -12,11 +12,8 @@ HTMLWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -37,10 +34,9 @@ mkHTMLWidget = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,11 +12,8 @@ LatexWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
import IHaskell.Eval.Widgets
......@@ -37,10 +34,9 @@ mkLatexWidget = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,11 +12,10 @@ TextWidget,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Control.Monad (when)
import Data.Aeson
import qualified Data.HashMap.Strict as Map
import Data.IORef (newIORef)
import Data.Text (Text)
import Data.Vinyl (Rec(..), (<+>))
import IHaskell.Display
......@@ -41,10 +40,9 @@ mkTextWidget = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -12,7 +12,6 @@ TextArea,
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (when, join)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import Data.IORef (newIORef)
......@@ -41,11 +40,9 @@ mkTextArea = do
stateIO <- newIORef widgetState
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
widgetSendOpen widget initData $ toJSON widgetState
widgetSendOpen widget $ toJSON widgetState
-- Return the widget
return widget
......
......@@ -7,7 +7,7 @@ name: ihaskell
-- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.7.0.3
version: 0.8.2.0
-- A short (one-line) description of the package.
synopsis: A Haskell backend kernel for the IPython project.
......@@ -55,7 +55,7 @@ library
hs-source-dirs: src
default-language: Haskell2010
build-depends:
aeson >=0.7 && < 0.10,
aeson >=0.7 && < 0.11,
base >=4.6 && < 4.9,
base64-bytestring >=1.0,
bytestring >=0.10,
......@@ -143,7 +143,7 @@ executable ihaskell
ghc >=7.6 || < 7.11,
process >=1.1,
here ==1.2.*,
aeson >=0.7 && < 0.10,
aeson >=0.7 && < 0.11,
bytestring >=0.10,
containers >=0.5,
strict >=0.3,
......@@ -167,7 +167,7 @@ Test-Suite hspec
default-language: Haskell2010
build-depends:
ihaskell,
aeson >=0.6 && < 0.10,
aeson >=0.6 && < 0.11,
base >=4.6 && < 4.9,
base64-bytestring >=1.0,
bytestring >=0.10,
......
......@@ -265,4 +265,5 @@ main = do
_ -> do
putStrLn "Usage:"
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"
This diff is collapsed.
name: ipython-kernel
version: 0.8.0.0
version: 0.8.2.0
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.
......@@ -35,7 +35,7 @@ library
hs-source-dirs: src
default-language: Haskell2010
build-depends: base >=4.6 && < 4.9,
aeson >=0.6 && < 0.10,
aeson >=0.6 && < 0.11,
bytestring >=0.10,
cereal >=0.3,
containers >=0.5,
......
......@@ -11,17 +11,16 @@
--
-- = Kernel Specs
--
-- To run your kernel, you will need to install the kernelspec into the Jupyter namespace.
-- If your kernel name is `kernel`, you will need to run the command:
-- To run your kernel, you will need to install the kernelspec into the Jupyter namespace. If your
-- kernel name is `kernel`, you will need to run the command:
--
-- > kernel install
--
-- This will inform Jupyter of the kernel so that it may be used.
--
-- == Further profile improvements
-- Consult the IPython documentation along with the generated profile
-- source code for further configuration of the frontend, including
-- syntax highlighting, logos, help text, and so forth.
-- == Further profile improvements Consult the IPython documentation along with the generated
-- profile source code for further configuration of the frontend, including syntax highlighting,
-- logos, help text, and so forth.
module IHaskell.IPython.EasyKernel (easyKernel, installKernelspec, KernelConfig(..)) where
import Data.Aeson (decode, encode)
......@@ -99,7 +98,6 @@ installKernelspec config replace installPrefixMay =
installPrefixFlag = maybe ["--user"] (\prefix -> ["--prefix", prefix]) installPrefixMay
cmd = concat [["kernelspec", "install"], installPrefixFlag, [kernelDir], replaceFlag]
void $ rawSystem "ipython" cmd
where
withTmpDir act = do
tmp <- getTemporaryDirectory
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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