Compare commits

..

No commits in common. "master" and "v0.3.0.1" have entirely different histories.

293 changed files with 40868 additions and 42432 deletions

View File

@ -1,30 +0,0 @@
*.hi
Untitled*.ipynb
main/Main
.stack-work
notebooks/Test.ipynb
notebooks/Untitled.ipynb
notebooks/Untitled0.ipynb
*.dyn_o
*.dyn_hi
*.o
dist
IHaskell/GHC
env
.shelly
.ihaskell_capture
.ipynb_checkpoints
Hspec
todo
profile/profile.tar
.cabal-sandbox
cabal.sandbox.config
.tmp1
.tmp2
.tmp3
.stack-work
src/Hspec
notebooks
dist
**/dist
**/.stack-work

3
.ghci
View File

@ -1,4 +1,5 @@
:set -package ghc
:set -package ghc-paths
:set -optP-include -optPdist/build/autogen/cabal_macros.h
:set -i. -isrc -idist/build/autogen
:set prompt "\ESC[34mλ> \ESC[m"
:set -XDoAndIfThenElse -XOverloadedStrings

View File

@ -1,74 +0,0 @@
name: Docker
on:
push:
branches:
paths:
- '.dockerignore'
- '.github/workflows/docker.yml'
- 'Dockerfile'
- 'LICENSE'
- 'ghc-parser/**'
- 'html/**'
- 'ihaskell-display/**'
- 'ihaskell.cabal'
- 'ipython-kernel/**'
- 'jupyterlab-ihaskell/**'
- 'main/**'
- 'src/**'
- 'stack.yaml'
pull_request:
paths:
- '.dockerignore'
- '.github/workflows/docker.yml'
- 'Dockerfile'
- 'LICENSE'
- 'ghc-parser/**'
- 'html/**'
- 'ihaskell-display/**'
- 'ihaskell.cabal'
- 'ipython-kernel/**'
- 'jupyterlab-ihaskell/**'
- 'main/**'
- 'src/**'
- 'stack.yaml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
if: (github.event_name != 'pull_request' && ! github.event.pull_request.head.repo.fork) || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork)
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v3
- uses: haskell-actions/setup@v2
name: Setup Haskell Stack
with:
enable-stack: true
stack-version: "latest"
- name: Check Dockerfile GHC version matches
run: |
set -e
STACK_GHC_VERSION=$(stack exec -- ghc --version | awk '{ print $NF }')
DOCKER_GHC_VERSION=$(sed -n 's/ARG GHC_VERSION=\(.*\)/\1/p' Dockerfile)
if [[ ${STACK_GHC_VERSION} != ${DOCKER_GHC_VERSION} ]]; then
echo 'GHC_VERSION in Dockerfile does not match stack resolver'
echo "GHC_VERSION should be ${STACK_GHC_VERSION}"
exit 1
fi
- uses: elgohr/Publish-Docker-Github-Action@v5
with:
name: gibiansky/ihaskell
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
snapshot: true
no_push: ${{ github.event_name == 'pull_request' }}

View File

@ -1,74 +0,0 @@
name: Nix
on:
schedule:
- cron: '0 2 * * *'
push:
paths-ignore:
- 'demo/**'
- 'docker/**'
- 'Dockerfile'
- '.dockerignore'
- '.ghci'
- '.gitignore'
- 'images/**'
- 'notebooks/**'
- 'stack/**'
- 'README.md'
- '*.yaml'
pull_request:
paths-ignore:
- 'demo/**'
- 'docker/**'
- 'Dockerfile'
- '.dockerignore'
- '.ghci'
- '.gitignore'
- 'images/**'
- 'notebooks/**'
- 'stack/**'
- 'README.md'
- '*.yaml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
if: (github.event_name != 'pull_request' && ! github.event.pull_request.head.repo.fork) || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork)
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
env:
- ihaskell-env-ghc96
- ihaskell-env-ghc98
- ihaskell-env-ghc910
- ihaskell-env-display-ghc96
- ihaskell-env-display-ghc98
# - ihaskell-env-display-ghc910
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
install_url: https://releases.nixos.org/nix/nix-2.22.1/install
- uses: cachix/cachix-action@v14
with:
name: ihaskell
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
- name: Build environment ${{matrix.env}}
run: |
nix build .#${{matrix.env}}
- name: Check acceptance test for ${{matrix.env}}
# Don't bother running it with the display envs since we already run it
# with the basic envs, and it doesn't test any display stuff.
if: ${{ !(contains(matrix.env, fromJSON('"display"'))) }}
run: |
nix build .#checks.x86_64-linux.${{matrix.env}} -L

View File

@ -1,108 +0,0 @@
name: Stack (--nix)
on:
push:
paths-ignore:
- 'demo/**'
- 'docker/**'
- 'Dockerfile'
- '.dockerignore'
- '.ghci'
- '.gitignore'
- 'images/**'
- 'nix/**'
- 'notebooks/**'
- 'flake.nix'
- 'flake.lock'
- 'README.md'
- 'README.md'
- 'hie.yaml'
pull_request:
paths-ignore:
- 'demo/**'
- 'docker/**'
- 'Dockerfile'
- '.dockerignore'
- '.ghci'
- '.gitignore'
- 'images/**'
- 'nix/**'
- 'notebooks/**'
- 'flake.nix'
- 'flake.lock'
- 'README.md'
- 'README.md'
- 'hie.yaml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
linux:
if: (github.event_name != 'pull_request' && ! github.event.pull_request.head.repo.fork) || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork)
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
stack-yaml:
# - 'stack/stack-8.2.yaml'
# - 'stack/stack-8.4.yaml'
# - 'stack/stack-8.6.yaml'
# - 'stack/stack-8.8.yaml'
- 'stack/stack-8.10.yaml'
- 'stack/stack-9.0.yaml'
- 'stack/stack-9.2.yaml'
- 'stack/stack-9.4.yaml'
- 'stack/stack-9.6.yaml'
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
install_url: https://releases.nixos.org/nix/nix-2.13.3/install
- uses: haskell-actions/setup@v2
name: Setup Haskell Stack
with:
enable-stack: true
stack-version: "latest"
- uses: actions/cache@v3
name: Cache Haskell dependencies
with:
path: |
~/.stack/stack.sqlite3
~/.stack/snapshots
key: ${{ matrix.stack-yaml }}-nix-${{ hashFiles(format('./{0}', matrix.stack-yaml)) }}
restore-keys: |
${{ matrix.stack-yaml }}-nix-${{ hashFiles(format('./{0}', matrix.stack-yaml)) }}
${{ matrix.stack-yaml }}-nix-
- name: Build
run: |
export "NIX_PATH=nixpkgs=$(nix run .#print-nixpkgs-master)"
stack build --nix --stack-yaml ${{matrix.stack-yaml}}
- name: Test
run: |
export "NIX_PATH=nixpkgs=$(nix run .#print-nixpkgs-master)"
stack test --nix --stack-yaml ${{matrix.stack-yaml}}
- name: Run integration test
run: |
set -e
export "NIX_PATH=nixpkgs=$(nix run .#print-nixpkgs-master)"
nix build .#jupyterlab
export PATH="$(pwd)/result/bin:$(pwd)/.local/bin:$PATH"
stack install --nix --stack-yaml ${{matrix.stack-yaml}}
ihaskell install --stack --stack-flag="--nix" --stack-flag="--stack-yaml=$(realpath ${{matrix.stack-yaml}})"
# Ensure that IHaskell notebook remains unchanged.
# Run the notebook to regenerate the outputs, then compare the new notebook to the old one.
test/acceptance.nbconvert.sh jupyter nbconvert

View File

@ -1,110 +0,0 @@
name: Stack
on:
push:
paths-ignore:
- 'demo/**'
- 'docker/**'
- 'Dockerfile'
- '.dockerignore'
- '.ghci'
- '.gitignore'
- 'images/**'
- 'nix/**'
- 'notebooks/**'
- 'flake.nix'
- 'flake.lock'
- 'README.md'
- 'hie.yaml'
pull_request:
paths-ignore:
- 'demo/**'
- 'docker/**'
- 'Dockerfile'
- '.dockerignore'
- '.ghci'
- '.gitignore'
- 'images/**'
- 'nix/**'
- 'notebooks/**'
- 'flake.nix'
- 'flake.lock'
- 'README.md'
- 'hie.yaml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
linux:
if: (github.event_name != 'pull_request' && ! github.event.pull_request.head.repo.fork) || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork)
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
stack-yaml:
- 'stack/stack-8.4.yaml'
- 'stack/stack-8.6.yaml'
- 'stack/stack-8.8.yaml'
- 'stack/stack-8.10.yaml'
- 'stack/stack-9.0.yaml'
- 'stack/stack-9.2.yaml'
- 'stack/stack-9.4.yaml'
- 'stack/stack-9.6.yaml'
- 'stack.yaml'
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v22
with:
install_url: https://releases.nixos.org/nix/nix-2.13.3/install
- uses: haskell-actions/setup@v2
name: Setup Haskell Stack
with:
enable-stack: true
stack-version: "latest"
- uses: actions/cache@v3
name: Cache Haskell dependencies
with:
path: |
~/.stack/stack.sqlite3
~/.stack/snapshots
key: ${{ matrix.stack-yaml }}-${{ hashFiles(format('./{0}', matrix.stack-yaml)) }}
restore-keys: |
${{ matrix.stack-yaml }}-${{ hashFiles(format('./{0}', matrix.stack-yaml)) }}
${{ matrix.stack-yaml }}-
- name: Install system dependencies
run: |
sudo apt update
sudo apt install libmagic-dev libgmp-dev libblas-dev liblapack-dev libcairo2-dev libpango1.0-dev libzmq3-dev jq
- name: Test ipython-kernel
run: |
stack build ipython-kernel --flag ipython-kernel:examples --stack-yaml ${{matrix.stack-yaml}}
- name: Build
run: |
export "NIX_PATH=nixpkgs=$(nix run .#print-nixpkgs-master)"
stack build ihaskell --stack-yaml ${{matrix.stack-yaml}}
- name: Test
run: |
stack test --stack-yaml ${{matrix.stack-yaml}}
- name: Run integration test
run: |
nix build .#jupyterlab
export PATH="$(pwd)/result/bin:$(pwd)/.local/bin:$PATH"
stack install --stack-yaml ${{matrix.stack-yaml}}
ihaskell install --stack --stack-flag="--stack-yaml=$(realpath ${{matrix.stack-yaml}})"
# Ensure that IHaskell notebook remains unchanged.
# Run the notebook to regenerate the outputs, then compare the new notebook to the old one.
test/acceptance.nbconvert.sh jupyter nbconvert

View File

@ -1,23 +0,0 @@
name: Update flake.lock
on:
workflow_dispatch:
schedule:
- cron: '1 1 * * 0'
jobs:
lockfile:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v13
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@v23
with:
pr-title: "Update `flake.lock`"
pr-labels: |
dependencies
automated
token: ${{ secrets.GH_TOKEN_FLAKE_LOCK_UPDATE }}

18
.gitignore vendored
View File

@ -1,12 +1,4 @@
*.hi
Untitled*.ipynb
main/Main
.stack-work
notebooks/Test.ipynb
notebooks/Untitled.ipynb
notebooks/Untitled0.ipynb
*.dyn_o
*.dyn_hi
*.o
dist
IHaskell/GHC
@ -19,13 +11,3 @@ todo
profile/profile.tar
.cabal-sandbox
cabal.sandbox.config
.tmp1
.tmp2
.tmp3
stack.yaml.lock
result
default.nix
dist-*/
cabal.project.local
cabal.config
tsconfig.tsbuildinfo

View File

@ -1,96 +0,0 @@
# should match the GHC version of the stack.yaml resolver
# checked in CI
ARG GHC_VERSION=9.6.4
FROM haskell:${GHC_VERSION} AS ihaskell_base
# Install Ubuntu packages needed for IHaskell runtime
RUN apt-get update && \
apt-get install -y libzmq5 \
&& \
rm -rf /var/lib/apt/lists/*
FROM ihaskell_base AS builder
# Install Ubuntu packages needed for IHaskell build
RUN apt-get update && \
apt-get install -y libzmq3-dev pkg-config \
&& \
rm -rf /var/lib/apt/lists/*
WORKDIR /build
# Build snapshot
COPY stack.yaml stack.yaml
COPY ihaskell.cabal ihaskell.cabal
COPY ipython-kernel ipython-kernel
COPY ghc-parser ghc-parser
COPY ihaskell-display ihaskell-display
RUN stack setup
RUN stack build ihaskell --only-snapshot
# Build IHaskell itself.
# Don't just `COPY .` so that changes in e.g. README.md don't trigger rebuild.
COPY src src
COPY html html
COPY main main
COPY jupyterlab-ihaskell jupyterlab-ihaskell
COPY LICENSE LICENSE
RUN stack install ihaskell --local-bin-path ./bin/
# Save resolver used to build IHaskell
RUN sed -n 's/resolver: \(.*\)#.*/\1/p' stack.yaml | tee resolver.txt
# Save third-party data files
RUN mkdir /data && \
snapshot_install_root=$(stack path --snapshot-install-root) && \
cp $(find ${snapshot_install_root} -name hlint.yaml) /data
FROM ihaskell_base AS ihaskell
# Install JupyterLab
RUN apt-get update && \
apt-get install -y python3-pip && \
rm -rf /var/lib/apt/lists/*
RUN pip3 install -U pip
RUN pip3 install -U jupyterlab notebook
# Create runtime user
ENV NB_USER jovyan
ENV NB_UID 1000
RUN adduser --disabled-password \
--gecos "Default user" \
--uid ${NB_UID} \
${NB_USER}
# Create directory for storing ihaskell files
ENV IHASKELL_DATA_DIR /usr/local/lib/ihaskell
RUN mkdir -p ${IHASKELL_DATA_DIR} && chown ${NB_UID} ${IHASKELL_DATA_DIR}
# Set up + set hlint data directory
ENV HLINT_DATA_DIR /usr/local/lib/hlint
COPY --from=builder --chown=${NB_UID} /data/hlint.yaml ${HLINT_DATA_DIR}/
ENV hlint_datadir ${HLINT_DATA_DIR}
# Set current user + directory
WORKDIR /home/${NB_USER}/src
RUN chown -R ${NB_UID} /home/${NB_USER}/src
USER ${NB_UID}
# Set up global project
COPY --from=builder --chown=${NB_UID} /build/resolver.txt /tmp/
RUN stack setup --resolver=$(cat /tmp/resolver.txt) --system-ghc
RUN stack config set system-ghc --global true
# Set up env file
RUN stack exec env --system-ghc > ${IHASKELL_DATA_DIR}/env
# Install + setup IHaskell
COPY --from=builder --chown=${NB_UID} /build/bin/ihaskell /usr/local/bin/
COPY --from=builder --chown=${NB_UID} /build/html ${IHASKELL_DATA_DIR}/html
COPY --from=builder --chown=${NB_UID} /build/jupyterlab-ihaskell ${IHASKELL_DATA_DIR}/jupyterlab-ihaskell
RUN export ihaskell_datadir=${IHASKELL_DATA_DIR} && \
ihaskell install --env-file ${IHASKELL_DATA_DIR}/env
RUN jupyter notebook --generate-config
CMD ["jupyter", "notebook", "--ip", "0.0.0.0"]

363
README.md
View File

@ -1,227 +1,186 @@
![jupyter](https://i.imgur.com/S16l2Hw.png) ![IHaskell](https://i.imgur.com/qhXXFbA.png) [![Build Status](https://github.com/gibiansky/IHaskell/workflows/CI/badge.svg)](https://github.com/gibiansky/IHaskell/actions?query=workflow%3ACI) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/gibiansky/IHaskell/mybinder)
![IHaskell](https://raw.github.com/gibiansky/IHaskell/master/images/ihaskell-logo.png)
# IHaskell
IHaskell
===
IHaskell is an implementation of the [IPython](http://ipython.org) kernel protocol which allows you to use Haskell inside IPython frontends such as `qtconsole` and `notebook`.
> You can now try IHaskell directly in your browser at [CoCalc](https://cocalc.com) or [mybinder.org](https://mybinder.org/v2/gh/gibiansky/IHaskell/mybinder).
>
> Alternatively, watch a [talk and demo](http://begriffs.com/posts/2016-01-20-ihaskell-notebook.html) showing off IHaskell features.
[Demo Notebook](http://gibiansky.github.io/IHaskell/demo.html)
---
IHaskell is a kernel for the [Jupyter project](https://jupyter.org), which allows you to use Haskell inside Jupyter frontends (including the console and notebook). It currently supports GHC 8.4 through 9.10.
For a tour of some IHaskell features, check out the [demo Notebook](http://nbviewer.org/github/gibiansky/IHaskell/blob/master/notebooks/IHaskell.ipynb). More example notebooks are available on the [wiki](https://github.com/gibiansky/IHaskell/wiki).
The [wiki](https://github.com/gibiansky/IHaskell/wiki) also has more extensive documentation of IHaskell features.
The project works with the IPython shell:
![IPython Console](https://raw.github.com/gibiansky/IHaskell/master/images/ihaskell-console.png)
As well as the IPython browser-based notebook interface:
![IPython Notebook](https://raw.github.com/gibiansky/IHaskell/master/images/ihaskell-notebook.png)
### Interactive In-Browser Notebook
*More usage information on the [wiki](https://github.com/gibiansky/IHaskell/wiki).*
# Installation
Installation
===
## Linux
If you have any trouble with installation or have other questions about IHaskell, feel free to open an issue [on Github](https://github.com/gibiansky/IHaskell/issues?direction=desc&sort=updated&state=open) or join our IRC at #ihaskell on chat.freenode.net.
Some prerequisites; adapt to your distribution.
ZeroMQ
---
IHaskell uses a library known as ZeroMQ for asynchronous communication. Make sure that ZeroMQ 4 is installed - it is a relatively recent library and thus you may have older versions installed.
For Macs, you can easily install it with [Homebrew](http://brew.sh/):
```bash
# For Macs with Homebrew:
brew update
brew install zeromq
```
On other platforms, you can easily install from source:
```bash
# Compiling from source:
git clone git@github.com:zeromq/zeromq4-x.git libzmq
cd libzmq
./autogen.sh && ./configure && make
sudo make install
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.
Haskell and Cabal
---
You should also have GHC and modern Cabal:
```bash
ghc --numeric-version # Should be 7.6.3
cabal --version # Should be 1.18.*
```
Since IHaskell uses the GHC API for evaluation and parsing, other versions of GHC may not work.
If you do not have GHC or Cabal, you should be able to install both via the
[Haskell Platform](http://www.haskell.org/platform/). On Macs with Homebrew, you can do this via
```bash
# Macs with Homebrew only, if you don't have GHC or Cabal
brew install haskell-platform
cabal update && cabal install cabal-install
```
Use `cabal install cabal-install` to update Cabal if you still have version 1.16 instead of 1.18.
Also, in order to use executables which `cabal` installs, they must be in your path. Execute this in your shell or add it to your `~/.bashrc`:
```bash
# If you have a ~/.cabal/bin folder:
export PATH=~/.cabal/bin:$PATH
# If you have a ~/Library/Haskell/bin folder on OS X:
export PATH=~/Library/Haskell/bin:$PATH
```
If you are using Mac OS X 10.9 (Mavericks) you will need to compile
cairo with gcc, not clang. This can be done as follows:
```bash
sudo apt-get install -y python3-pip git libtinfo-dev libzmq3-dev libcairo2-dev libpango1.0-dev libmagic-dev libblas-dev liblapack-dev
brew install gcc48
cabal install cairo --with-gcc=gcc-4.8
```
Install `stack`, clone this repository, install Python requirements, install
`ihaskell`, and install the Jupyter kernelspec with `ihaskell`.
Compilation Tools
---
Install the `happy` parser generator tool and `cpphs` preprocessor:
```bash
cabal install happy cpphs
```
These instructions assume you don't already have Stack or a Jupyter
installation, please skip the relevant steps if this is not the case.
IHaskell Installation
---
Install the IHaskell package from Hackage:
```bash
cabal install ihaskell
```
Running IHaskell
---
Finally, run the notebook or console interface:
```bash
IHaskell notebook # Should open a browser window!
IHaskell console
```
There is a test notebook in the `IHaskell` directory. To try it, run IHaskell with `IHaskell notebook --serve=IHaskell`.
If you get a pip error while IHaskell is installing Python
dependencies on the first run (it will look like
`EOFError: EOF when reading a line`), then you can do the following
after ensuring that pip >= 1.5 is installed:
```bash
env PIP_EXISTS_ACTION=w IHaskell notebook
```
If it *still* doesn't work and you are using Mac OS X then
`brew upgrade python`. Some older versions of Homebrew's Python have a
broken version of distutils. Homebrew's version of Python 2.7.6 *does* work.
**Note**: You may have some trouble due to browser caches with the notebook interface if you also use IPython's notebook interface or have used it in the past. If something doesn't work or IPython says it can't connect to the notebook server, make sure to clear the browser cache in whatever browser you're using, or try another browser.
Contributing
===
IHaskell is a young project, and I'd love your help getting it to a stable and useful point. There's a lot to do, and if you'd like to contribute, feel free to get in touch with me via my email at andrew period gibiansky at gmail - although browsing the code should be enough to get you started, I'm more than happy to answer any questions myself.
**For package maintainers:** IHaskell has an ability to display data types it knows about with a rich format based on images or HTML. In order to do so, an external package `ihaskell-something` must be created and installed. Writing these packages is simple - they must just contain instance of the `IHaskellDisplay` typeclass, defined in `IHaskell.Display`, and for a package `ihaskell-something` should have a single module `IHaskell.Display.Something`. If you have a package with interesting data types that would benefit from a rich display format, please get in contact with me (andrew dot gibiansky at gmail) to write one of these packages! A sample package is available [here](https://github.com/gibiansky/IHaskell-Display).
Developer Notes
---
Before diving in, you should read the [brief description of IPython kernel architectures](http://andrew.gibiansky.com/blog/ipython/ipython-kernels/)
and read the [complete messaging protocol specification](http://ipython.org/ipython-doc/dev/development/messaging.html).
Skim the rather-lacking [Haddock documentation](http://gibiansky.github.io/IHaskell/IHaskell/).
First steps:
- Fork the repository on Github and clone your fork for editing.
**option 1**
```bash
cd /path/to/IHaskell
./build.sh
```
**option 2**
```bash
cd /path/to/IHaskell
cabal sandbox init
cabal sandbox add-source ipython-kernel ihaskell-display/* ghc-parser
cabal install IHaskell $(basename ihaskell-display/*)
```
**Loading IHaskell into GHCi for testing:**
Use one of the methods below to access IHaskell files in GHCi. Once inside GHCi, you can load an IHaskell file; for example, `:load IHaskell/Config.hs`.
**Using cabal repl**
If you have the latest version of cabal (>v1.18.0), the simplest thing to do is
```bash
curl -sSL https://get.haskellstack.org/ | sh
git clone https://github.com/gibiansky/IHaskell
cd IHaskell
pip3 install -r requirements.txt
stack install --fast
ihaskell install --stack
cd <path-to-IHaskell>
cabal repl
```
Run Jupyter.
This will hide all packages not listed in `IHaskell.cabal`
**Using GHCi directly**
If you don't want to use `cabal repl`, you can just call ghci which can read the `.ghci` file included in the repository for the options.
```bash
stack exec jupyter -- notebook
cd <path-to-IHaskell>
chmod 600 .ghci # trust the .ghci file
ghci
```
## Mac
You need to have [Homebrew](https://brew.sh) installed.
If you do not have it yet run `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"` in your terminal.
You also need the Xcode command line tools.
You can install them by running `xcode-select --install` in the terminal and following the prompts.
These instructions assume you don't already have Stack or a Jupyter
installation, please skip the relevant steps if this is not the case.
```bash
brew install python3 zeromq libmagic cairo pkg-config haskell-stack pango
git clone https://github.com/gibiansky/IHaskell
cd IHaskell
pip3 install -r requirements.txt
stack install --fast
ihaskell install --stack
```
If you have Homebrew installed to a location that `stack` does not expect (e.g. `/opt/homebrew`), you'd need to specify `--extra-include-dirs ${HOMEBREW_PREFIX}/include --extra-lib-dirs ${HOMEBREW_PREFIX}/lib` to the `stack` command.
Run Jupyter.
```bash
stack exec jupyter -- notebook
```
_Tested on macOS Sierra (10.12.6)_
## Windows
IHaskell does not support Windows, however it can be used on Windows 10 via
Windows Subsystem for Linux (WSL). If WSL is not installed, follow the
[Installation Guide for Windows 10](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
The following assumes that Ubuntu is picked as the Linux distribution.
In the Ubuntu app, follow the steps above for Linux.
Jupyter Notebook is now ready to use. In the Ubuntu app, launch a Notebook
Server, without opening the notebook in a browser:
```bash
jupyter notebook --no-browser
```
Returning to Windows 10, open a browser and copy and paste the URL output in the
step above (the token will differ).
```bash
Or copy and paste one of these URLs:
http://localhost:8888/?token=9ca8a725ddb1fdded176d9e0e675ba557ebb5fbef6c65fdf
```
_Tested on Windows 10 (build 18362.175) with Ubuntu 18.04 on WSL_
Alternatively, install Virtualbox, install Ubuntu or another Linux distribution,
and proceed with the install instructions.
## Docker
To quickly run a Jupyter notebook with the IHaskell kernel, try the `Dockerfile`
in the top directory.
```bash
docker build -t ihaskell:latest .
docker run --rm -p 8888:8888 ihaskell:latest
```
Or use the continuously updated Docker image
[on Docker Hub](https://hub.docker.com/r/gibiansky/ihaskell).
```sh
docker run --rm -p 8888:8888 gibiansky/ihaskell
```
In order to mount your own local files into the Docker container
use following command:
```sh
docker run --rm -p 8888:8888 -v "$PWD":/home/jovyan/src gibiansky/ihaskell
```
Be aware that the directory you're mounting must contain
a `stack.yaml` file.
A simple version would be:
```yaml
resolver: lts-16.23
packages: []
```
It's recommended to use the same LTS version as the IHaskell image is using itself
(as can be seen in [its stack.yaml](./stack.yaml)).
This guarantees that stack doesn't have to first perform
a lengthy installation of GHC before running your notebook.
You can also use the following script to run IHaskell in Docker: https://gist.github.com/brandonchinn178/928d6137bfd17961b9584a8f96c18827
## Nix
If you have the `nix` package manager installed, you can create an IHaskell
notebook environment with one command. For example:
```bash
$ nix-build -I nixpkgs=https://github.com/NixOS/nixpkgs/tarball/nixos-23.05 release.nix --argstr compiler ghc928 --arg packages "haskellPackages: [ haskellPackages.lens ]"
<result path>
$ <result path>/bin/jupyter notebook
```
It might take a while the first time, but subsequent builds will be much
faster. You can use the
[https://ihaskell.cachix.org](https://app.cachix.org/cache/ihaskell) cache for
prebuilt artifacts.
The IHaskell display modules are not loaded by default and have to be specified as additional packages:
```bash
$ nix-build -I nixpkgs=https://github.com/NixOS/nixpkgs/tarball/nixos-23.05 release.nix --argstr compiler ghc928 --arg packages "haskellPackages: [ haskellPackages.ihaskell-blaze haskellPackages.ihaskell-charts ]"
```
For more examples of using IHaskell with Nix, see https://github.com/vaibhavsagar/notebooks.
# Developing
IHaskell is regularly updated to work with the latest version of GHC. To read how this is done, and how the development environment is set up, please see [this blog post](https://vaibhavsagar.com/blog/2021/05/02/updating-ihaskell-newer-ghc).
## Nix flake
There is also a Nix flake that provides a developer environment. For details on Nix flakes, please see the documentation at https://wiki.nixos.org/wiki/Flakes.
After this, IHaskell can be compiled as follows:
```bash
nix develop # This opens a new shell with all dependencies installed
cabal update # Make sure Cabal's package index is up-to-date
cabal build # Builds IHaskell
```
Note that this shell also provides `haskell-language-server`, which can be used in your editor if it supports it. Opening your editor from within the `nix develop` shell should allow it to see `haskell-language-server`.
# Troubleshooting
## Where are my packages? (IHaskell + Stack)
Stack manages separate environments for every package. By default your notebooks
will only have access to a few packages that happen to be required for
IHaskell. To make packages available add them to the stack.yaml in the IHaskell
directory and run `stack install --fast`.
Packages should be added to the `packages:` section and can take the following
form
([reproduced here from the stack documentation](https://github.com/commercialhaskell/stack/blob/master/doc/yaml_configuration.md#packages)). If
you've already installed a package by `stack install` you can simply list its
name even if it's local.
Then in the ghci session you can type things like:
```
- package-name
- location: .
- location: dir1/dir2
- location: https://example.com/foo/bar/baz-0.0.2.tar.gz
- location: http://github.com/yesodweb/wai/archive/2f8a8e1b771829f4a8a77c0111352ce45a14c30f.zip
- location:
git: git@github.com:commercialhaskell/stack.git
commit: 6a86ee32e5b869a877151f74064572225e1a0398
- location:
hg: https://example.com/hg/repo
commit: da39a3ee5e6b4b0d3255bfef95601890afd80709
:set -package setenv
:load src/Hspec.hs
hspec parserTests
:browse IHaskell.Types
```
## The kernel keeps dying (IHaskell + Stack)
The default instructions globally install IHaskell with support for only one
version of GHC. If you've e.g. installed an `lts-10` IHaskell and are using it
with an `lts-9` project the mismatch between GHC 8.2 and GHC 8.0 will cause
this error. Stack also has the notion of a 'global project' located at
`~/.stack/global-project/` and the `stack.yaml` for that project should be on
the same LTS as the version of IHaskell installed to avoid this issue.

View File

@ -1,3 +1,2 @@
import Distribution.Simple
import Distribution.Simple
main = defaultMain

36
build.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/bash
set -e
# Recompile ipython-kernel
cd ipython-kernel
cabal clean
cabal install --force-reinstalls
cd ..
# Make the profile
cd profile
rm -f profile.tar
tar -cvf profile.tar *
cd ..
# Make ihaskell itself
cabal clean
cabal install --force-reinstalls
# Remove my profile
rm -rf ~/.ipython/profile_haskell
if [ $# -gt 0 ]; then
if [ $1 = "all" ]; then
# Install all the display libraries
cd ihaskell-display
for dir in `ls`
do
cd $dir
cabal clean
cabal install
cd ..
done
fi
fi

View File

@ -1,20 +0,0 @@
packages: .
./ipython-kernel
./ghc-parser
./ihaskell-display/ihaskell-aeson
./ihaskell-display/ihaskell-blaze
./ihaskell-display/ihaskell-charts
./ihaskell-display/ihaskell-diagrams
./ihaskell-display/ihaskell-gnuplot
./ihaskell-display/ihaskell-graphviz
./ihaskell-display/ihaskell-hatex
./ihaskell-display/ihaskell-juicypixels
./ihaskell-display/ihaskell-magic
./ihaskell-display/ihaskell-plot
./ihaskell-display/ihaskell-static-canvas
./ihaskell-display/ihaskell-widgets
source-repository-package
type: git
location: https://github.com/jeffreyrosenbluth/static-canvas.git
tag: 1aad0f192828ded72dced14e42ac4e6baa6dab6f

3345
demo/IHaskell.html Normal file

File diff suppressed because one or more lines are too long

1421
demo/IHaskell.ipynb Normal file

File diff suppressed because one or more lines are too long

BIN
demo/doc-demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
demo/hoogle-demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
demo/info-demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
demo/json-demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

149
flake.lock generated
View File

@ -1,149 +0,0 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1733328505,
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"hls": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": [
"flake-utils"
],
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1744298016,
"narHash": "sha256-8zoVia97o0Fo1ADis9FLXdvkSbRN69o5fPgemqlfKdQ=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "c5c3ca4a992cc79e742bbfe9ee013467732d3aa4",
"type": "github"
},
"original": {
"owner": "haskell",
"repo": "haskell-language-server",
"type": "github"
}
},
"nix-filter": {
"locked": {
"lastModified": 1731533336,
"narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=",
"owner": "numtide",
"repo": "nix-filter",
"rev": "f7653272fd234696ae94229839a99b73c9ab7de0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "nix-filter",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1739019272,
"narHash": "sha256-7Fu7oazPoYCbDzb9k8D/DdbKrC3aU1zlnc39Y8jy/s8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fa35a3c8e17a3de613240fea68f876e5b4896aec",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs24_11": {
"locked": {
"lastModified": 1744492897,
"narHash": "sha256-qqKO4FOo/vPmNIaRPcLqwfudUlQ29iNdI1IbCZfjmxs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "86484f6076aac9141df2bfcddbf7dcfce5e0c6bb",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgsMaster": {
"locked": {
"lastModified": 1744514369,
"narHash": "sha256-N9uWy2Ti5H5gYDoAPEcJ0i4dAbdQD9auJ2YjskbMqOc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ae29fc75d2d3ee07f88ce1a252d76964eb1efb24",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"hls": "hls",
"nix-filter": "nix-filter",
"nixpkgs24_11": "nixpkgs24_11",
"nixpkgsMaster": "nixpkgsMaster"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

109
flake.nix
View File

@ -1,109 +0,0 @@
{
description = "A Haskell kernel for IPython.";
inputs.nixpkgs24_11.url = "github:NixOS/nixpkgs/release-24.11";
inputs.nixpkgsMaster.url = "github:NixOS/nixpkgs/master";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.hls = {
url = "github:haskell/haskell-language-server";
inputs.flake-utils.follows = "flake-utils";
};
inputs.nix-filter.url = "github:numtide/nix-filter";
nixConfig = {
extra-substituters = [ "https://ihaskell.cachix.org" ];
extra-trusted-public-keys = [ "ihaskell.cachix.org-1:WoIvex/Ft/++sjYW3ntqPUL3jDGXIKDpX60pC8d5VLM="];
};
outputs = { self, nixpkgs24_11, nixpkgsMaster, flake-utils, hls, nix-filter, ... }:
flake-utils.lib.eachDefaultSystem (system: let
baseOverlay = _self: _super: { inherit nix-filter; };
pkgsMaster = import nixpkgsMaster { inherit system; overlays = [baseOverlay]; };
jupyterlab = pkgsMaster.python3.withPackages (ps: [ ps.jupyterlab ps.notebook ]);
# Map from GHC version to release function
versions = let
mkVersion = pkgsSrc: compiler: overlays: extraArgs: {
name = compiler;
value = (import pkgsSrc { inherit system; overlays = [baseOverlay] ++ overlays; }).callPackage ./nix/release.nix ({
inherit compiler;
} // extraArgs);
};
in
pkgsMaster.lib.listToAttrs [
(mkVersion nixpkgs24_11 "ghc96" [(import ./nix/overlay-9.6.nix)] {})
(mkVersion nixpkgs24_11 "ghc98" [(import ./nix/overlay-9.8.nix)] {})
(mkVersion nixpkgsMaster "ghc910" [(import ./nix/overlay-9.10.nix)] {})
];
# Helper function for building environments with a given set of packages
mkEnvs = prefix: packages: pkgsMaster.lib.mapAttrs' (version: releaseFn: {
name = prefix + version;
value = (releaseFn {
# Note: this can be changed to other Jupyter systems like jupyter-console
extraEnvironmentBinaries = [ jupyterlab ];
systemPackages = p: with p; [
gnuplot # for the ihaskell-gnuplot runtime
];
inherit packages;
});
}) versions;
# Basic envs with Jupyterlab and IHaskell
envs = mkEnvs "ihaskell-env-" (_: []);
# Envs with Jupyterlab, IHaskell, and all display packages
displayEnvs = mkEnvs "ihaskell-env-display-" (p: with p; map (n: builtins.getAttr n p) (import ./nix/displays.nix));
# Executables only, pulled from passthru on the envs
exes = pkgsMaster.lib.mapAttrs' (envName: env: {
name = builtins.replaceStrings ["-env"] [""] envName;
value = env.ihaskellExe;
}) envs;
devShells = pkgsMaster.lib.mapAttrs' (version: releaseFn: {
name = "ihaskell-dev-" + version;
value = pkgsMaster.callPackage ./nix/mkDevShell.nix {
inherit hls system version;
haskellPackages = (releaseFn {}).haskellPackages;
ihaskellOverlay = (releaseFn {}).ihaskellOverlay;
};
}) versions;
in {
packages = envs // displayEnvs // exes // devShells // rec {
# For easily testing that everything builds
allEnvs = pkgsMaster.linkFarm "ihaskell-envs" envs;
allDisplayEnvs = pkgsMaster.linkFarm "ihaskell-display-envs" displayEnvs;
allExes = pkgsMaster.linkFarm "ihaskell-exes" exes;
allDevShells = pkgsMaster.linkFarm "ihaskell-dev-shells" devShells;
# To use in CI
inherit jupyterlab;
print-nixpkgs-master = pkgsMaster.writeShellScriptBin "print-nixpkgs-master.sh" "echo ${pkgsMaster.path}";
};
# Run the acceptance tests on each env
checks = pkgsMaster.lib.mapAttrs (envName: env:
pkgsMaster.stdenv.mkDerivation {
name = envName + "-check";
src = pkgsMaster.callPackage ./nix/ihaskell-src.nix {};
nativeBuildInputs = with pkgsMaster; [jq bash];
doCheck = true;
checkPhase = ''
mkdir -p home
export HOME=$(pwd)/home
bash ./test/acceptance.nbconvert.sh ${env}/bin/jupyter nbconvert
'';
installPhase = ''
touch $out
'';
}
) envs;
defaultPackage = self.packages.${system}.ihaskell-env-ghc96;
devShell = self.packages.${system}.ihaskell-dev-ghc96;
});
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
module Language.Haskell.GHC.Parser (
-- Parser handling
runParser,
LineNumber,
ColumnNumber,
ErrMsg,
StringLoc(..),
ParseOutput(..),
Parser,
-- Different parsers
parserStatement,
parserImport,
parserDeclaration,
parserTypeSignature,
parserModule,
parserExpression,
partialStatement,
partialImport,
partialDeclaration,
partialTypeSignature,
partialModule,
partialExpression,
) where
import Data.List (intercalate)
import Bag
import ErrUtils hiding (ErrMsg)
import FastString
import GHC
import Lexer
import OrdList
import Outputable hiding ((<>))
import SrcLoc
import StringBuffer
import qualified Language.Haskell.GHC.HappyParser as Parse
-- | A line number in an input string.
type LineNumber = Int
-- | A column number in an input string.
type ColumnNumber = Int
-- | An error message string.
type ErrMsg = String
-- | A location in an input string.
data StringLoc = Loc LineNumber ColumnNumber deriving (Show, Eq)
-- | Output from running a parser.
data ParseOutput a
= Failure ErrMsg StringLoc -- ^ Parser failed with given error message and location.
| Parsed a -- ^ Parser succeeded with an output.
| Partial a (String, String) -- ^ Partial parser succeeded with an output.
deriving (Eq, Show) -- Auxiliary strings say what part of the
-- input string was used and what
-- part is remaining.
data ParserType = FullParser | PartialParser
data Parser a = Parser ParserType (P a)
-- Our parsers.
parserStatement = Parser FullParser Parse.fullStatement
parserImport = Parser FullParser Parse.fullImport
parserDeclaration = Parser FullParser Parse.fullDeclaration
parserExpression = Parser FullParser Parse.fullExpression
parserTypeSignature = Parser FullParser Parse.fullTypeSignature
parserModule = Parser FullParser Parse.fullModule
partialStatement = Parser PartialParser Parse.partialStatement
partialImport = Parser PartialParser Parse.partialImport
partialDeclaration = Parser PartialParser Parse.partialDeclaration
partialExpression = Parser PartialParser Parse.partialExpression
partialTypeSignature = Parser PartialParser Parse.partialTypeSignature
partialModule = Parser PartialParser Parse.partialModule
-- | Run a GHC parser on a string. Return success or failure with
-- associated information for both.
runParser :: DynFlags -> Parser a -> String -> ParseOutput a
runParser flags (Parser parserType parser) str =
-- Create an initial parser state.
let filename = "<interactive>"
location = mkRealSrcLoc (mkFastString filename) 1 1
buffer = stringToStringBuffer str
parseState = mkPState flags buffer location in
-- Convert a GHC parser output into our own.
toParseOut $ unP parser parseState
where
toParseOut :: ParseResult a -> ParseOutput a
toParseOut (PFailed span@(RealSrcSpan realSpan) err) =
let errMsg = printErrorBag $ unitBag $ mkPlainErrMsg flags span err
line = srcLocLine $ realSrcSpanStart realSpan
col = srcLocCol $ realSrcSpanStart realSpan
in Failure errMsg $ Loc line col
toParseOut (PFailed span err) =
let errMsg = printErrorBag $ unitBag $ mkPlainErrMsg flags span err
in Failure errMsg $ Loc 0 0
toParseOut (POk parseState result) =
let parseEnd = realSrcSpanStart $ last_loc parseState
endLine = srcLocLine parseEnd
endCol = srcLocCol parseEnd
(before, after) = splitAtLoc endLine endCol str in
case parserType of
PartialParser -> Partial result (before, after)
FullParser -> Parsed result
-- Convert the bag of errors into an error string.
printErrorBag bag = joinLines . map show $ bagToList bag
-- | Split a string at a given line and column. The column is included in
-- the second part of the split.
splitAtLoc :: LineNumber -> ColumnNumber -> String -> (String, String)
splitAtLoc line col string =
if line > length (lines string)
then (string, "")
else (before, after)
where
(beforeLines, afterLines) = splitAt line $ lines string
theLine = last beforeLines
(beforeChars, afterChars) = splitAt (col - 1) theLine
before = joinLines (init beforeLines) ++ '\n' : beforeChars
after = joinLines $ afterChars : afterLines
-- Not the same as 'unlines', due to trailing \n
joinLines :: [String] -> String
joinLines = intercalate "\n"

View File

@ -1,3 +1,8 @@
import Distribution.Simple
import Distribution.Simple
import System.Cmd
main = defaultMain
main = defaultMainWithHooks simpleUserHooks{
preConf = \args confFlags -> do
system "./build-parser.sh"
preConf simpleUserHooks args confFlags
}

13
ghc-parser/build-parser.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/sh
# Called from Setup.hs.
# Preprocess the GHC parser we're using to CPP subs.
cpphs --linepragma --text HaskellParser.y.pp -OParser.y
# Compile the parser and remove intermediate file.
happy Parser.y
rm Parser.y
# Move output Haskell to source directory.
mkdir -p Language/Haskell/GHC
mv Parser.hs Language/Haskell/GHC/HappyParser.hs

View File

@ -1,390 +0,0 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE TypeApplications #-}
module Language.Haskell.GHC.Parser (
-- Parser handling
runParser,
LineNumber,
ColumnNumber,
ErrMsg,
StringLoc(..),
ParseOutput(..),
Parser,
Located(..),
-- Different parsers
parserStatement,
parserImport,
parserDeclaration,
parserTypeSignature,
parserModule,
parserExpression,
parsePragmasIntoDynFlags,
-- Haskell string preprocessing.
removeComments,
layoutChunks,
) where
import Data.List (intercalate, findIndex, isInfixOf)
import Data.Char (isAlphaNum)
#if MIN_VERSION_ghc(9,8,0)
import GHC.Driver.Config.Parser (initParserOpts)
import GHC.Parser.Errors.Types (PsMessage(..))
import GHC.Types.Error (defaultDiagnosticOpts, getMessages, MsgEnvelope(..))
import GHC.Utils.Error (diagnosticMessage, formatBulleted)
import GHC.Utils.Outputable (defaultSDocContext, renderWithContext)
#elif MIN_VERSION_ghc(9,6,0)
import GHC.Driver.Config.Parser (initParserOpts)
import GHC.Parser.Errors.Types (PsMessage(..))
import GHC.Types.Error (getMessages, MsgEnvelope(..))
import GHC.Utils.Error (diagnosticMessage, defaultDiagnosticOpts, formatBulleted)
import GHC.Utils.Outputable (defaultSDocContext, renderWithContext)
#elif MIN_VERSION_ghc(9,4,0)
import GHC.Driver.Config.Parser (initParserOpts)
import GHC.Types.Error (diagnosticMessage, getMessages, MsgEnvelope(..))
import GHC.Utils.Error (formatBulleted)
import GHC.Utils.Outputable (defaultSDocContext)
#elif MIN_VERSION_ghc(9,2,0)
import GHC.Driver.Config (initParserOpts)
import GHC.Parser.Errors.Ppr (pprError)
#endif
#if MIN_VERSION_ghc(9,0,0)
import GHC.Data.Bag
import GHC.Driver.Session (parseDynamicFilePragma)
import GHC.Data.FastString
import GHC.Parser.Header (getOptions)
import GHC.Parser.Lexer hiding (buffer)
import GHC.Data.OrdList
import GHC.Utils.Panic (handleGhcException)
import qualified GHC.Types.SrcLoc as SrcLoc
import GHC.Data.StringBuffer hiding (len)
#else
import Bag
import DynFlags (parseDynamicFilePragma)
import FastString
import HeaderInfo (getOptions)
import Lexer hiding (buffer)
import OrdList
import Panic (handleGhcException)
import qualified SrcLoc as SrcLoc
import StringBuffer hiding (len)
#endif
#if MIN_VERSION_ghc(8,10,0)
#else
import ErrUtils hiding (ErrMsg)
#endif
import GHC hiding (Located, Parsed, parser)
import qualified Language.Haskell.GHC.HappyParser as Parse
-- | A line number in an input string.
type LineNumber = Int
-- | A column number in an input string.
type ColumnNumber = Int
-- | An error message string.
type ErrMsg = String
-- | A location in an input string.
data StringLoc = Loc LineNumber ColumnNumber deriving (Show, Eq)
-- | Output from running a parser.
data ParseOutput a
= Failure ErrMsg StringLoc -- ^ Parser failed with given error message and location.
| Parsed a -- ^ Parser succeeded with an output.
| Partial a (String, String) -- ^ Partial parser succeeded with an output.
deriving (Eq, Show) -- Auxiliary strings say what part of the
-- input string was used and what
-- part is remaining.
--
-- | Store locations along with a value.
data Located a = Located {
line :: LineNumber, -- Where this element is located.
unloc :: a -- Located element.
} deriving (Eq, Show, Functor)
data Parser a = Parser (P a)
-- Our parsers.
parserStatement :: Parser (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
parserStatement = Parser Parse.fullStatement
parserImport :: Parser (LImportDecl GhcPs)
parserImport = Parser Parse.fullImport
parserDeclaration :: Parser (OrdList (LHsDecl GhcPs))
parserDeclaration = Parser Parse.fullDeclaration
parserExpression :: Parser (LHsExpr GhcPs)
parserExpression = Parser Parse.fullExpression
parserTypeSignature :: Parser (SrcLoc.Located (OrdList (LHsDecl GhcPs)))
parserTypeSignature = Parser Parse.fullTypeSignature
#if MIN_VERSION_ghc(9,6,0)
parserModule :: Parser (SrcLoc.Located (HsModule GhcPs))
#elif MIN_VERSION_ghc(9,0,0)
parserModule :: Parser (SrcLoc.Located HsModule)
#else
parserModule :: Parser (SrcLoc.Located (HsModule GhcPs))
#endif
parserModule = Parser Parse.fullModule
-- | Run a GHC parser on a string. Return success or failure with
-- associated information for both.
runParser :: DynFlags -> Parser a -> String -> ParseOutput a
runParser flags (Parser parser) str =
-- Create an initial parser state.
let filename = "<interactive>"
location = SrcLoc.mkRealSrcLoc (mkFastString filename) 1 1
buffer = stringToStringBuffer str
#if MIN_VERSION_ghc(9,2,0)
parseState = initParserState (initParserOpts flags) buffer location in
#else
parseState = mkPState flags buffer location in
#endif
-- Convert a GHC parser output into our own.
toParseOut (unP parser parseState)
where
toParseOut :: ParseResult a -> ParseOutput a
#if MIN_VERSION_ghc(9,4,0)
toParseOut (PFailed pstate) =
let realSpan = SrcLoc.psRealSpan $ last_loc pstate
errMsg = printErrorBag (getMessages $ errors pstate)
ln = srcLocLine $ SrcLoc.realSrcSpanStart realSpan
col = srcLocCol $ SrcLoc.realSrcSpanStart realSpan
in Failure errMsg $ Loc ln col
#elif MIN_VERSION_ghc(9,2,0)
toParseOut (PFailed pstate) =
let realSpan = SrcLoc.psRealSpan $ last_loc pstate
errMsg = printErrorBag (errors pstate)
ln = srcLocLine $ SrcLoc.realSrcSpanStart realSpan
col = srcLocCol $ SrcLoc.realSrcSpanStart realSpan
in Failure errMsg $ Loc ln col
#elif MIN_VERSION_ghc(9,0,0)
toParseOut (PFailed pstate) =
let realSpan = SrcLoc.psRealSpan $ last_loc pstate
errMsg = printErrorBag $ snd $ (messages pstate) flags
ln = srcLocLine $ SrcLoc.realSrcSpanStart realSpan
col = srcLocCol $ SrcLoc.realSrcSpanStart realSpan
in Failure errMsg $ Loc ln col
#elif MIN_VERSION_ghc(8,10,0)
toParseOut (PFailed pstate) =
let realSpan = last_loc pstate
errMsg = printErrorBag $ snd $ (messages pstate) flags
ln = srcLocLine $ SrcLoc.realSrcSpanStart realSpan
col = srcLocCol $ SrcLoc.realSrcSpanStart realSpan
in Failure errMsg $ Loc ln col
#else
toParseOut (PFailed _ spn@(RealSrcSpan realSpan) err) =
let errMsg = printErrorBag $ unitBag $ mkPlainErrMsg flags spn err
ln = srcLocLine $ SrcLoc.realSrcSpanStart realSpan
col = srcLocCol $ SrcLoc.realSrcSpanStart realSpan
in Failure errMsg $ Loc ln col
#endif
#if MIN_VERSION_ghc(8,10,0)
#else
toParseOut (PFailed _ spn err) =
let errMsg = printErrorBag $ unitBag $ mkPlainErrMsg flags spn err
in Failure errMsg $ Loc 0 0
#endif
toParseOut (POk _parseState result) =
Parsed result
-- Convert the bag of errors into an error string.
#if MIN_VERSION_ghc(9,8,0)
printErrorBag bag = joinLines . map (renderWithContext defaultSDocContext . formatBulleted . diagnosticMessage (defaultDiagnosticOpts @PsMessage) . errMsgDiagnostic) $ bagToList bag
#elif MIN_VERSION_ghc(9,6,0)
printErrorBag bag = joinLines . map (renderWithContext defaultSDocContext . formatBulleted defaultSDocContext . diagnosticMessage (defaultDiagnosticOpts @PsMessage) . errMsgDiagnostic) $ bagToList bag
#elif MIN_VERSION_ghc(9,4,0)
printErrorBag bag = joinLines . map (show . formatBulleted defaultSDocContext . diagnosticMessage . errMsgDiagnostic) $ bagToList bag
#elif MIN_VERSION_ghc(9,2,0)
printErrorBag bag = joinLines . map (show . pprError) $ bagToList bag
#else
printErrorBag bag = joinLines . map show $ bagToList bag
#endif
-- Taken from http://blog.shaynefletcher.org/2019/06/have-ghc-parsing-respect-dynamic-pragmas.html
parsePragmasIntoDynFlags :: DynFlags -> FilePath -> String -> IO (Maybe DynFlags)
parsePragmasIntoDynFlags flags filepath str =
catchErrors $ do
#if MIN_VERSION_ghc(9,4,0)
let opts = snd $ getOptions (initParserOpts flags) (stringToStringBuffer str) filepath
#else
let opts = getOptions flags (stringToStringBuffer str) filepath
#endif
(flags', _, _) <- parseDynamicFilePragma flags opts
return $ Just flags'
where
catchErrors :: IO (Maybe DynFlags) -> IO (Maybe DynFlags)
catchErrors act =
handleGhcException reportErr (handleSourceError reportErr act)
reportErr e = do
putStrLn $ "error : " ++ show e
return Nothing
-- Not the same as 'unlines', due to trailing \n
joinLines :: [String] -> String
joinLines = intercalate "\n"
-- | Split an input string into chunks based on indentation.
-- A chunk is a line and all lines immediately following that are indented
-- beyond the indentation of the first line. This parses Haskell layout
-- rules properly, and allows using multiline expressions via indentation.
--
-- Quasiquotes are allowed via a post-processing step.
layoutChunks :: String -> [Located String]
layoutChunks = joinQuasiquotes . go 1
where
go :: LineNumber -> String -> [Located String]
go ln = filter (not . null . unloc) . map (fmap strip) . layoutLines ln . lines
-- drop spaces on left and right
strip = dropRight . dropLeft
where
dropLeft = dropWhile (`elem` whitespace)
dropRight = reverse . dropWhile (`elem` whitespace) . reverse
whitespace = " \t\n"
layoutLines :: LineNumber -> [String] -> [Located String]
-- Empty string case. If there's no input, output is empty.
layoutLines _ [] = []
-- Use the indent of the first line to find the end of the first block.
layoutLines lineIdx xs@(firstLine:rest) =
let firstIndent = indentLevel firstLine
blockEnded ln = indentLevel ln <= firstIndent in
case findIndex blockEnded rest of
-- If the first block doesn't end, return the whole string, since
-- that just means the block takes up the entire string.
Nothing -> [Located lineIdx $ intercalate "\n" xs]
-- We found the end of the block. Split this bit out and recurse.
Just idx ->
let (before, after) = splitAt idx rest in
Located lineIdx (joinLines $ firstLine:before) : go (lineIdx + idx + 1) (joinLines after)
-- Compute indent level of a string as number of leading spaces.
indentLevel :: String -> Int
indentLevel (' ':str) = 1 + indentLevel str
-- Count a tab as two spaces.
indentLevel ('\t':str) = 2 + indentLevel str
-- Count empty lines as a large indent level, so they're always with the previous expression.
indentLevel "" = 100000
indentLevel _ = 0
-- | Drop comments from Haskell source.
-- Simply gets rid of them, does not replace them in any way.
removeComments :: String -> String
removeComments = removeOneLineComments . removeMultilineComments 0 0
where
removeOneLineComments str =
case str of
-- Don't remove comments after cmd directives
':':'!':remaining ->":!" ++ takeLine remaining ++ dropLine remaining
-- Handle strings.
'"':remaining ->
let quoted = takeString remaining
len = length quoted in
'"':quoted ++ removeOneLineComments (drop len remaining)
'-':'-':remaining -> dropLine remaining
x:xs -> x:removeOneLineComments xs
[] -> []
where
dropLine = removeOneLineComments . dropWhile (/= '\n')
removeMultilineComments :: Int -> Int -> String -> String
removeMultilineComments nesting pragmaNesting str =
case str of
-- Don't remove comments after cmd directives
':':'!':remaining ->":!" ++ takeLine remaining ++
removeMultilineComments nesting pragmaNesting (dropWhile (/= '\n') remaining)
-- Handle strings.
'"':remaining ->
if nesting == 0
then
let quoted = takeString remaining
len = length quoted in
'"':quoted ++ removeMultilineComments nesting pragmaNesting (drop len remaining)
else
removeMultilineComments nesting pragmaNesting remaining
'{':'-':'#':remaining ->
if nesting == 0
then "{-#" ++ removeMultilineComments nesting (pragmaNesting + 1) remaining
else removeMultilineComments nesting pragmaNesting remaining
'#':'-':'}':remaining ->
if nesting == 0
then if pragmaNesting > 0
then '#':'-':'}':removeMultilineComments nesting (pragmaNesting - 1) remaining
else '#':'-':'}':removeMultilineComments nesting pragmaNesting remaining
else removeMultilineComments nesting pragmaNesting remaining
'{':'-':remaining -> removeMultilineComments (nesting + 1) pragmaNesting remaining
'-':'}':remaining ->
if nesting > 0
then removeMultilineComments (nesting - 1) pragmaNesting remaining
else '-':'}':removeMultilineComments nesting pragmaNesting remaining
x:xs ->
if nesting > 0
then removeMultilineComments nesting pragmaNesting xs
else x:removeMultilineComments nesting pragmaNesting xs
[] -> []
takeLine = takeWhile (/= '\n')
-- Take a part of a string that ends in an unescaped quote.
takeString str = case str of
escaped@('\\':'"':_) -> escaped
'"':_ -> "\""
x:xs -> x:takeString xs
[] -> []
-- | Post processing step to combine quasiquoted blocks into single blocks.
-- This is necessary because quasiquoted blocks don't follow normal indentation rules.
joinQuasiquotes :: [Located String] -> [Located String]
joinQuasiquotes = reverse . joinQuasiquotes' . reverse
where
-- This operates by finding |] and then joining blocks until a line
-- that has some corresponding [...|. This is still a hack, but close to
-- good enough.
joinQuasiquotes' [] = []
joinQuasiquotes' (block:blocks) =
if "|]" `isInfixOf` unloc block
then
let (pieces, rest) = break (hasQuasiquoteStart . unloc) blocks
in case rest of
[] -> block : joinQuasiquotes' blocks
startBlock:blocks' ->
concatBlocks (block : pieces ++ [startBlock]) : joinQuasiquotes blocks'
else block : joinQuasiquotes' blocks
-- Combine a lit of reversed blocks into a single, non-reversed block.
concatBlocks :: [Located String] -> Located String
concatBlocks blocks = Located (line $ last blocks) $ joinLines $ map unloc $ reverse blocks
-- Does this string have a [...| in it?
hasQuasiquoteStart :: String -> Bool
hasQuasiquoteStart str =
case break (== '[') str of
(_, "") -> False
(_, _:rest) ->
case break (== '|') rest of
(_, "") -> False
(chars, _) -> all isIdentChar chars
isIdentChar :: Char -> Bool
isIdentChar c = isAlphaNum c || c == '_' || c == '\''

View File

@ -1,44 +1,32 @@
-- Initial ghc-parser.cabal generated by cabal init. For further
-- Initial ghc-parser.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
name: ghc-parser
version: 0.2.7.0
version: 0.1.0.0
synopsis: Haskell source parser from GHC.
-- description:
homepage: https://github.com/IHaskell/IHaskell
-- description:
homepage: https://github.com/gibiansky/IHaskell
license: MIT
license-file: LICENSE
author: Andrew Gibiansky
maintainer: andrew.gibiansky@gmail.com
-- copyright:
-- copyright:
category: Language
build-type: Simple
-- extra-source-files:
cabal-version: 1.16
build-type: Custom
-- extra-source-files:
cabal-version: >=1.16
extra-source-files:
build-parser.sh
HaskellParser.y.pp
library
ghc-options: -Wall
exposed-modules: Language.Haskell.GHC.Parser,
Language.Haskell.GHC.HappyParser
-- other-modules:
-- other-extensions:
build-depends: base >=4.9 && < 5,
ghc >=8.4 && <9.11
if impl(ghc >= 8.4) && impl(ghc < 8.10)
hs-source-dirs: generic-src src-8.4
if impl(ghc >= 8.10) && impl(ghc < 9.0)
hs-source-dirs: generic-src src-8.10
if impl(ghc >= 9.0) && impl(ghc < 9.2)
hs-source-dirs: generic-src src-9.0
if impl(ghc >= 9.2) && impl(ghc < 9.4)
hs-source-dirs: generic-src src-9.2
if impl(ghc >= 9.4) && impl(ghc < 9.6)
hs-source-dirs: generic-src src-9.4
if impl(ghc >= 9.6) && impl(ghc < 9.8)
hs-source-dirs: generic-src src-9.6
if impl(ghc >= 9.8) && impl(ghc < 9.12)
hs-source-dirs: generic-src src-9.8
-- other-modules:
-- other-extensions:
build-depends: base >=4.6 && <4.7,
ghc ==7.6.*
-- hs-source-dirs:
default-language: Haskell2010

View File

@ -1,40 +0,0 @@
module Language.Haskell.GHC.HappyParser
( fullStatement
, fullImport
, fullDeclaration
, fullExpression
, fullTypeSignature
, fullModule
) where
import Parser
import SrcLoc
-- compiler/hsSyn
import GHC.Hs
-- compiler/utils
import OrdList
-- compiler/parser
import Lexer
import RdrHsSyn (runECP_P)
fullStatement :: P (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
fullStatement = parseStmt
fullImport :: P (LImportDecl GhcPs)
fullImport = parseImport
fullDeclaration :: P (OrdList (LHsDecl GhcPs))
fullDeclaration = fmap unitOL parseDeclaration
fullExpression :: P (LHsExpr GhcPs)
fullExpression = runECP_P =<< parseExpression
fullTypeSignature :: P (Located (OrdList (LHsDecl GhcPs)))
fullTypeSignature = fmap (noLoc . unitOL) parseTypeSignature
fullModule :: P (Located (HsModule GhcPs))
fullModule = parseModule

View File

@ -1,38 +0,0 @@
module Language.Haskell.GHC.HappyParser
( fullStatement
, fullImport
, fullDeclaration
, fullExpression
, fullTypeSignature
, fullModule
) where
import Parser
import SrcLoc
-- compiler/hsSyn
import HsSyn
-- compiler/utils
import OrdList
-- compiler/parser
import Lexer
fullStatement :: P (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
fullStatement = parseStmt
fullImport :: P (LImportDecl GhcPs)
fullImport = parseImport
fullDeclaration :: P (OrdList (LHsDecl GhcPs))
fullDeclaration = fmap unitOL parseDeclaration
fullExpression :: P (LHsExpr GhcPs)
fullExpression = parseExpression
fullTypeSignature :: P (Located (OrdList (LHsDecl GhcPs)))
fullTypeSignature = fmap (noLoc . unitOL) parseTypeSignature
fullModule :: P (Located (HsModule GhcPs))
fullModule = parseModule

View File

@ -1,40 +0,0 @@
module Language.Haskell.GHC.HappyParser
( fullStatement
, fullImport
, fullDeclaration
, fullExpression
, fullTypeSignature
, fullModule
) where
import GHC.Parser
import GHC.Types.SrcLoc
-- compiler/hsSyn
import GHC.Hs
-- compiler/utils
import GHC.Data.OrdList
-- compiler/parser
import GHC.Parser.Lexer
import GHC.Parser.PostProcess (runECP_P)
fullStatement :: P (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
fullStatement = parseStmt
fullImport :: P (LImportDecl GhcPs)
fullImport = parseImport
fullDeclaration :: P (OrdList (LHsDecl GhcPs))
fullDeclaration = fmap unitOL parseDeclaration
fullExpression :: P (LHsExpr GhcPs)
fullExpression = runECP_P =<< parseExpression
fullTypeSignature :: P (Located (OrdList (LHsDecl GhcPs)))
fullTypeSignature = fmap (noLoc . unitOL) parseTypeSignature
fullModule :: P (Located HsModule)
fullModule = parseModule

View File

@ -1,40 +0,0 @@
module Language.Haskell.GHC.HappyParser
( fullStatement
, fullImport
, fullDeclaration
, fullExpression
, fullTypeSignature
, fullModule
) where
import GHC.Parser
import GHC.Types.SrcLoc
-- compiler/hsSyn
import GHC.Hs
-- compiler/utils
import GHC.Data.OrdList
-- compiler/parser
import GHC.Parser.Lexer
import GHC.Parser.PostProcess (ECP(..), runPV)
fullStatement :: P (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
fullStatement = parseStmt
fullImport :: P (LImportDecl GhcPs)
fullImport = parseImport
fullDeclaration :: P (OrdList (LHsDecl GhcPs))
fullDeclaration = fmap unitOL parseDeclaration
fullExpression :: P (LHsExpr GhcPs)
fullExpression = parseExpression >>= \p -> runPV $ unECP p
fullTypeSignature :: P (Located (OrdList (LHsDecl GhcPs)))
fullTypeSignature = fmap (noLoc . unitOL) parseTypeSignature
fullModule :: P (Located HsModule)
fullModule = parseModule

View File

@ -1,40 +0,0 @@
module Language.Haskell.GHC.HappyParser
( fullStatement
, fullImport
, fullDeclaration
, fullExpression
, fullTypeSignature
, fullModule
) where
import GHC.Parser
import GHC.Types.SrcLoc
-- compiler/hsSyn
import GHC.Hs
-- compiler/utils
import GHC.Data.OrdList
-- compiler/parser
import GHC.Parser.Lexer
import GHC.Parser.PostProcess (ECP(..), runPV)
fullStatement :: P (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
fullStatement = parseStmt
fullImport :: P (LImportDecl GhcPs)
fullImport = parseImport
fullDeclaration :: P (OrdList (LHsDecl GhcPs))
fullDeclaration = fmap unitOL parseDeclaration
fullExpression :: P (LHsExpr GhcPs)
fullExpression = parseExpression >>= \p -> runPV $ unECP p
fullTypeSignature :: P (Located (OrdList (LHsDecl GhcPs)))
fullTypeSignature = fmap (noLoc . unitOL) parseTypeSignature
fullModule :: P (Located HsModule)
fullModule = parseModule

View File

@ -1,40 +0,0 @@
module Language.Haskell.GHC.HappyParser
( fullStatement
, fullImport
, fullDeclaration
, fullExpression
, fullTypeSignature
, fullModule
) where
import GHC.Parser
import GHC.Types.SrcLoc
-- compiler/hsSyn
import GHC.Hs
-- compiler/utils
import GHC.Data.OrdList
-- compiler/parser
import GHC.Parser.Lexer
import GHC.Parser.PostProcess (ECP(..), runPV)
fullStatement :: P (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
fullStatement = parseStmt
fullImport :: P (LImportDecl GhcPs)
fullImport = parseImport
fullDeclaration :: P (OrdList (LHsDecl GhcPs))
fullDeclaration = fmap unitOL parseDeclaration
fullExpression :: P (LHsExpr GhcPs)
fullExpression = parseExpression >>= \p -> runPV $ unECP p
fullTypeSignature :: P (Located (OrdList (LHsDecl GhcPs)))
fullTypeSignature = fmap (noLoc . unitOL) parseTypeSignature
fullModule :: P (Located (HsModule GhcPs))
fullModule = parseModule

View File

@ -1,40 +0,0 @@
module Language.Haskell.GHC.HappyParser
( fullStatement
, fullImport
, fullDeclaration
, fullExpression
, fullTypeSignature
, fullModule
) where
import GHC.Parser
import GHC.Types.SrcLoc
-- compiler/hsSyn
import GHC.Hs
-- compiler/utils
import GHC.Data.OrdList
-- compiler/parser
import GHC.Parser.Lexer
import GHC.Parser.PostProcess (ECP(..), runPV)
fullStatement :: P (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
fullStatement = parseStmt
fullImport :: P (LImportDecl GhcPs)
fullImport = parseImport
fullDeclaration :: P (OrdList (LHsDecl GhcPs))
fullDeclaration = fmap unitOL parseDeclaration
fullExpression :: P (LHsExpr GhcPs)
fullExpression = parseExpression >>= \p -> runPV $ unECP p
fullTypeSignature :: P (Located (OrdList (LHsDecl GhcPs)))
fullTypeSignature = fmap (noLoc . unitOL) parseTypeSignature
fullModule :: P (Located (HsModule GhcPs))
fullModule = parseModule

View File

@ -1,36 +0,0 @@
cradle:
cabal:
- path: "./ghc-parser"
component: "ghc-parser:lib:ghc-parser"
- path: "./ipython-kernel"
component: "ipython-kernel:lib:ipython-kernel"
- path: "./src"
component: "ihaskell:lib:ihaskell"
- path: "./main"
component: "ihaskell:exe:ihaskell"
- path: "./test"
component: "ihaskell:hspec"
- path: "./ihaskell-display/ihaskell-aeson"
component: "ihaskell-aeson:lib:ihaskell-aeson"
- path: "./ihaskell-display/ihaskell-blaze"
component: "ihaskell-blaze:lib:ihaskell-blaze"
- path: "./ihaskell-display/ihaskell-charts"
component: "ihaskell-charts:lib:ihaskell-charts"
- path: "./ihaskell-display/ihaskell-diagrams"
component: "ihaskell-diagrams:lib:ihaskell-diagrams"
- path: "./ihaskell-display/ihaskell-gnuplot"
component: "ihaskell-gnuplot:lib:ihaskell-gnuplot"
- path: "./ihaskell-display/ihaskell-hatex"
component: "ihaskell-hatex:lib:ihaskell-hatex"
- path: "./ihaskell-display/ihaskell-juicypixels"
component: "ihaskell-juicypixels:lib:ihaskell-juicypixels"
- path: "./ihaskell-display/ihaskell-magic"
component: "ihaskell-magic:lib:ihaskell-magic"
- path: "./ihaskell-display/ihaskell-plot"
component: "ihaskell-plot:lib:ihaskell-plot"
- path: "./ihaskell-display/ihaskell-static-canvas"
component: "ihaskell-static-canvas:lib:ihaskell-static-canvas"
- path: "./ihaskell-display/ihaskell-widgets"
component: "ihaskell-widgets:lib:ihaskell-widgets"
- path: "./ihaskell-display/ihaskell-graphviz"
component: "ihaskell-graphviz:lib:ihaskell-graphviz"

View File

@ -1,90 +0,0 @@
define(['require',
'codemirror/lib/codemirror',
'codemirror/addon/mode/loadmode',
'base/js/namespace',
'base/js/events',
'base/js/utils'],
function(require, CodeMirror, CodemirrorLoadmode, IPython, events, utils){
var onload = function(){
console.log('Kernel haskell kernel.js is loading.');
// add here logic that should be run once per **page load**
// like adding specific UI, or changing the default value
// of codecell highlight.
// Set tooltips to be triggered after 800ms
IPython.tooltip.time_before_tooltip = 800;
// IPython keycodes.
var space = 32;
var downArrow = 40;
IPython.keyboard.keycodes.down = downArrow; // space
IPython.CodeCell.options_default['cm_config']['mode'] = 'ihaskell';
utils.requireCodeMirrorMode('haskell', function(){
// Create a multiplexing mode that uses Haskell highlighting by default but
// doesn't highlight command-line directives.
CodeMirror.defineMode("ihaskell", function(config) {
return CodeMirror.multiplexingMode(
CodeMirror.getMode(config, "haskell"),
{
open: /:(?=!)/, // Matches : followed by !, but doesn't consume !
close: /^(?!!)/, // Matches start of line not followed by !, doesn't consume character
mode: CodeMirror.getMode(config, "text/plain"),
delimStyle: "delimit"
}
);
});
cells = IPython.notebook.get_cells();
for(var i in cells){
c = cells[i];
if (c.cell_type === 'code') {
// Force the mode to be Haskell
// This is necessary, otherwise sometimes highlighting just doesn't happen.
// This may be an IPython bug.
c.code_mirror.setOption('mode', 'ihaskell');
c.force_highlight('ihaskell');
}
}
});
if(IPython.notebook.set_codemirror_mode){
IPython.notebook.set_codemirror_mode('ihaskell')
}
// Prevent the pager from surrounding everything with a <pre>
IPython.Pager.prototype.append_text = function (text) {
this.pager_element.find(".container").append($('<div/>').html(IPython.utils.autoLinkUrls(text)));
};
events.on('shell_reply.Kernel', function() {
// Add logic here that should be run once per reply.
// Highlight things with a .highlight-code class
// The id is the mode with with to highlight
$('.highlight-code').each(function() {
var $this = $(this),
$code = $this.html(),
$unescaped = $('<div/>').html($code).text();
$this.empty();
// Never highlight this block again.
this.className = "";
CodeMirror(this, {
value: $unescaped,
mode: this.id,
lineNumbers: false,
readOnly: true
});
});
});
console.log('IHaskell kernel.js should have been loaded.')
} // end def of onload
return {onload:onload};
}
);

View File

@ -1,89 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
viewBox="0 0 48.000001 47.999999"
version="1.1"
id="svg18"
sodipodi:docname="haskell_logo.svg"
inkscape:version="0.92.3 (unknown)">
<metadata
id="metadata22">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2495"
inkscape:window-height="1416"
id="namedview20"
showgrid="false"
units="px"
inkscape:zoom="4.9870803"
inkscape:cx="87.017073"
inkscape:cy="4.4960944"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg18" />
<defs
id="defs5">
<clipPath
id="clip1">
<path
d="M 0,340.15625 H 481.89062 V 0 H 0 Z m 0,0"
id="path2"
inkscape:connector-curvature="0" />
</clipPath>
</defs>
<g
id="surface0"
transform="matrix(0.09960767,0,0,0.09960767,-0.1503886,5.8491832)">
<g
clip-path="url(#clip1)"
id="g15"
style="clip-rule:nonzero">
<path
style="fill:#453b61;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 0,340.15625 113.38672,170.07812 0,0 H 85.039062 L 198.42578,170.07812 85.039062,340.15625 Z m 0,0"
id="path7"
inkscape:connector-curvature="0" />
<path
style="fill:#5f5286;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 113.38672,340.15625 226.77344,170.07812 113.38672,0 h 85.03906 L 425.19531,340.15625 H 340.15625 L 269.29297,233.85937 198.42578,340.15625 Z m 0,0"
id="path9"
inkscape:connector-curvature="0" />
<path
style="fill:#8e508a;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 387.40234,240.94531 -37.79297,-56.6914 132.28125,-0.004 v 56.69531 z m 0,0"
id="path11"
inkscape:connector-curvature="0" />
<path
style="fill:#8e508a;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 330.71094,155.90625 -37.79688,-56.691406 188.97656,-0.0039 v 56.695316 z m 0,0"
id="path13"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,17 +1,16 @@
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, QuasiQuotes #-}
module IHaskell.Display.Aeson () where
import Data.Text as T
import Data.ByteString.Lazy as LBS
import Data.Text.Encoding as E
import ClassyPrelude
import Data.Textual.Encoding
import Data.Aeson
import Data.Aeson.Encode.Pretty
import Data.String.Here
import Data.Aeson
import Data.Aeson.Encode.Pretty
import IHaskell.Display
import IHaskell.Display
instance IHaskellDisplay Value where
display renderable = return $ Display [plain json]
where
json = T.unpack $ E.decodeUtf8 $ LBS.toStrict $ encodePretty renderable
display renderable = return $ Display [plain json, html dom]
where
json = unpack $ decodeUtf8 $ encodePretty renderable
dom = [i|<div class="highlight-code" id="javascript">${json}</div>|]

View File

@ -1,3 +1,2 @@
import Distribution.Simple
import Distribution.Simple
main = defaultMain

View File

@ -1,19 +1,19 @@
-- The name of the package.
name: ihaskell-aeson
-- The package version. See the Haskell package versioning policy (PVP)
-- 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.1
version: 0.1.0.0
-- A short (one-line) description of the package.
synopsis: IHaskell display instances for Aeson
-- A longer description of the package.
-- description:
-- description:
-- URL for the project homepage or repository.
homepage: http://www.github.com/gibiansky/ihaskell
@ -27,41 +27,45 @@ license-file: LICENSE
-- The package author(s).
author: Andrew Gibiansky
-- An email address to which users can send suggestions, bug reports, and
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: andrew.gibiansky@gmail.com
-- A copyright notice.
-- copyright:
-- copyright:
category: Development
build-type: Simple
-- Extra files to be distributed with the package, such as examples or a
-- Extra files to be distributed with the package, such as examples or a
-- README.
-- extra-source-files:
-- extra-source-files:
-- Constraint on the version of Cabal needed to build this package.
cabal-version: 1.16
cabal-version: >=1.16
library
-- Modules exported by the library.
exposed-modules: IHaskell.Display.Aeson
-- Modules included in this library but not exported.
-- other-modules:
-- other-modules:
-- Language extensions.
default-extensions: DoAndIfThenElse
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
text,
bytestring,
aeson >= 0.7,
aeson-pretty >= 0.7,
ihaskell >= 0.5
build-depends: base ==4.6.*,
here,
classy-prelude >=0.7,
aeson,
aeson-pretty,
ihaskell >= 0.3
-- Directories containing source files.
-- hs-source-dirs:
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -0,0 +1,15 @@
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module IHaskell.Display.Basic () where
import IHaskell.Display
import Text.Printf
instance Show a => IHaskellDisplay (Maybe a) where
display just = return $ Display [stringDisplay, htmlDisplay]
where
stringDisplay = plain (show just)
htmlDisplay = html str
str = case just of
Nothing -> "<span style='color: red; font-weight: bold;'>Nothing</span>"
Just x -> printf "<span style='color: green; font-weight: bold;'>Just</span><span style='font-family: monospace;'>%s</span>" (show x)

View File

@ -0,0 +1,4 @@
IHaskell-Display
================
Instances of IHaskellDisplay for default prelude data types.

View File

@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,10 +1,10 @@
-- Initial ihaskell-static-canvas.cabal generated by cabal init. For
-- further documentation, see http://haskell.org/cabal/users-guide/
-- Initial ihaskell-display.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
-- The name of the package.
name: ihaskell-static-canvas
name: ihaskell-basic
-- The package version. See the Haskell package versioning policy (PVP)
-- 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
@ -13,10 +13,10 @@ name: ihaskell-static-canvas
version: 0.1.0.0
-- A short (one-line) description of the package.
synopsis: IHaskell display for static-canvas
synopsis: IHaskell display instances for basic types
-- A longer description of the package.
-- description:
-- description:
-- URL for the project homepage or repository.
homepage: http://www.github.com/gibiansky/IHaskell
@ -30,44 +30,44 @@ license-file: LICENSE
-- The package author(s).
author: Andrew Gibiansky
-- An email address to which users can send suggestions, bug reports, and
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: andrew.gibiansky@gmail.com
-- A copyright notice.
-- copyright:
-- copyright:
-- category:
category: Development
build-type: Simple
-- Extra files to be distributed with the package, such as examples or a
-- Extra files to be distributed with the package, such as examples or a
-- README.
-- extra-source-files:
-- extra-source-files:
-- Constraint on the version of Cabal needed to build this package.
cabal-version: 1.16
cabal-version: >=1.16
library
-- Modules exported by the library.
exposed-modules: IHaskell.Display.StaticCanvas
exposed-modules: IHaskell.Display.Basic
-- Modules included in this library but not exported.
-- other-modules:
-- LANGUAGE extensions used by modules in this package.
-- other-extensions:
-- other-modules:
-- Language extensions.
default-extensions: DoAndIfThenElse
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.9,
ihaskell,
static-canvas,
text
build-depends: base ==4.6.*,
classy-prelude >=0.6,
ihaskell >= 0.3
-- Directories containing source files.
hs-source-dirs: src
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -1,19 +1,17 @@
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module IHaskell.Display.Blaze () where
import IHaskell.CSS (ihaskellCSS)
import IHaskell.Display
import IHaskell.Display
import Text.Printf
import Text.Blaze.Html
import Text.Blaze.Renderer.Pretty
import Text.Blaze.Internal
import Control.Monad
import Text.Printf
import Text.Blaze.Html
import Text.Blaze.Renderer.Pretty
import Text.Blaze.Internal
import Control.Monad
instance IHaskellDisplay (MarkupM a) where
display val = return $ Display [stringDisplay, htmlDisplay]
where
where
str = renderMarkup (void val)
stringDisplay = plain str
htmlDisplay = html' (Just ihaskellCSS) str
htmlDisplay = html str

View File

@ -1,3 +1,2 @@
import Distribution.Simple
import Distribution.Simple
main = defaultMain

View File

@ -1,22 +1,22 @@
-- Initial ihaskell-display.cabal generated by cabal init. For further
-- Initial ihaskell-display.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
-- The name of the package.
name: ihaskell-blaze
-- The package version. See the Haskell package versioning policy (PVP)
-- 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.1
version: 0.1.0.0
-- A short (one-line) description of the package.
synopsis: IHaskell display instances for blaze-html types
-- A longer description of the package.
-- description:
-- description:
-- URL for the project homepage or repository.
homepage: http://www.github.com/gibiansky/ihaskell
@ -30,40 +30,45 @@ license-file: LICENSE
-- The package author(s).
author: Andrew Gibiansky
-- An email address to which users can send suggestions, bug reports, and
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: andrew.gibiansky@gmail.com
-- A copyright notice.
-- copyright:
-- copyright:
category: Development
build-type: Simple
-- Extra files to be distributed with the package, such as examples or a
-- Extra files to be distributed with the package, such as examples or a
-- README.
-- extra-source-files:
-- extra-source-files:
-- Constraint on the version of Cabal needed to build this package.
cabal-version: 1.16
cabal-version: >=1.16
library
-- Modules exported by the library.
exposed-modules: IHaskell.Display.Blaze
-- Modules included in this library but not exported.
-- other-modules:
-- other-modules:
-- Language extensions.
default-extensions: DoAndIfThenElse
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
build-depends: base ==4.6.*,
classy-prelude >=0.6,
blaze-html >= 0.6,
blaze-markup >= 0.5,
ihaskell >= 0.5
ihaskell >= 0.3
-- Directories containing source files.
-- hs-source-dirs:
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -1,17 +1,16 @@
{-# LANGUAGE NoImplicitPrelude #-}
module IHaskell.Display.Charts () where
import System.Directory
import Data.Default.Class
import Graphics.Rendering.Chart.Renderable
import Graphics.Rendering.Chart.Backend.Cairo
import qualified Data.ByteString.Char8 as Char
import qualified Data.ByteString as BS
import qualified Data.Text.Encoding as T.Encoding
import System.IO.Temp
import System.IO.Unsafe
import System.FilePath ((</>))
import ClassyPrelude
import IHaskell.Display
import System.Directory
import Data.Default.Class
import Graphics.Rendering.Chart.Renderable
import Graphics.Rendering.Chart.Backend.Cairo
import qualified Data.ByteString.Char8 as Char
import System.IO.Unsafe
import IHaskell.Display
width :: Width
width = 450
@ -23,30 +22,25 @@ instance IHaskellDisplay (Renderable a) where
display renderable = do
pngDisp <- chartData renderable PNG
-- We can add `svg svgDisplay` to the output of `display`, but SVGs are not resizable in the IPython
-- notebook.
-- We can add `svg svgDisplay` to the output of `display`,
-- but SVGs are not resizable in the IPython notebook.
svgDisp <- chartData renderable SVG
return $ Display [pngDisp, svgDisp]
chartData :: Renderable a -> FileFormat -> IO DisplayData
chartData renderable format = do
-- We should not have to round-trip this ByteString to a temp file.
-- https://github.com/IHaskell/IHaskell/issues/1248
withSystemTempDirectory "ihaskell-charts" $ \tmpdir -> do
-- Switch to a temporary directory so that any files we create aren't
-- visible. On Unix, this is usually /tmp.
try (getTemporaryDirectory >>= setCurrentDirectory) :: IO (Either SomeException ())
-- Write the PNG image.
let
filename = tmpdir </> "ihaskell-chart.png"
opts = def { _fo_format = format, _fo_size = (width, height) }
renderableToFile opts filename renderable
let filename = ".ihaskell-chart.png"
opts = def{_fo_format = format, _fo_size = (width, height)}
renderableToFile opts renderable filename
case format of
PNG -> do
-- Convert to base64.
imgData <- Char.readFile filename
pure $ png width height $ base64 imgData
SVG -> do
imgData <- BS.readFile filename
pure $ svg $ T.Encoding.decodeUtf8 imgData
_ -> error "Unreachable case, not PNG or SVG"
-- Convert to base64.
imgData <- readFile $ fpFromString filename
return $ case format of
PNG -> png width height $ base64 imgData
SVG -> svg $ Char.unpack imgData

View File

@ -1,3 +1,2 @@
import Distribution.Simple
import Distribution.Simple
main = defaultMain

File diff suppressed because one or more lines are too long

View File

@ -1,19 +1,19 @@
-- The name of the package.
name: ihaskell-charts
-- The package version. See the Haskell package versioning policy (PVP)
-- 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.1
version: 0.1.0.0
-- A short (one-line) description of the package.
synopsis: IHaskell display instances for charts types
-- A longer description of the package.
-- description:
-- description:
-- URL for the project homepage or repository.
homepage: http://www.github.com/gibiansky/ihaskell
@ -27,46 +27,48 @@ license-file: LICENSE
-- The package author(s).
author: Andrew Gibiansky
-- An email address to which users can send suggestions, bug reports, and
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: andrew.gibiansky@gmail.com
-- A copyright notice.
-- copyright:
-- copyright:
category: Development
build-type: Simple
-- Extra files to be distributed with the package, such as examples or a
-- Extra files to be distributed with the package, such as examples or a
-- README.
-- extra-source-files:
-- extra-source-files:
-- Constraint on the version of Cabal needed to build this package.
cabal-version: 1.16
cabal-version: >=1.16
library
-- Modules exported by the library.
exposed-modules: IHaskell.Display.Charts
-- Modules included in this library but not exported.
-- other-modules:
-- other-modules:
-- Language extensions.
default-extensions: DoAndIfThenElse
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
build-depends: base ==4.6.*,
classy-prelude >=0.6,
bytestring,
text,
data-default-class,
directory,
filepath,
temporary,
Chart,
Chart-cairo >=1.2,
ihaskell >= 0.6.2
Chart-cairo,
ihaskell >= 0.3
-- Directories containing source files.
-- hs-source-dirs:
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

File diff suppressed because one or more lines are too long

View File

@ -1,74 +1,51 @@
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoImplicitPrelude, TypeSynonymInstances, FlexibleInstances #-}
module IHaskell.Display.Diagrams (diagram) where
module IHaskell.Display.Diagrams
( diagram, animation
, ManuallySized, withSizeSpec, withImgWidth, withImgHeight
, ManuallySampled, withAnimFps
) where
import ClassyPrelude
import qualified Data.ByteString as BS
import System.Directory
import qualified Data.ByteString.Char8 as Char
import qualified Data.Text.Encoding as T.Encoding
import System.Directory
import System.IO.Temp
import System.FilePath ((</>))
import Diagrams.Backend.Cairo
import Diagrams.Prelude
import IHaskell.Display
import IHaskell.Display.Diagrams.Animation
import IHaskell.Display.Diagrams.ImgSize
import System.IO.Unsafe
instance IHaskellDisplay (ManuallySized (QDiagram Cairo V2 Double Any)) where
import Diagrams.Prelude
import Diagrams.Backend.Cairo
import IHaskell.Display
instance IHaskellDisplay (Diagram Cairo R2) where
display renderable = do
png <- diagramData renderable PNG
svg <- diagramData renderable SVG
return $ Display [png, svg]
diagramData :: ManuallySized (Diagram Cairo) -> OutputType -> IO DisplayData
diagramData (ManuallySized renderable imgWidth imgHeight) format = do
-- We should not have to round-trip this ByteString to a temp file.
-- https://github.com/IHaskell/IHaskell/issues/1248
withSystemTempDirectory "ihaskell-diagram" $ \tmpdir -> do
let path = case format of
SVG -> tmpdir </> "ihaskell-diagram.svg"
PNG -> tmpdir </> "ihaskell-diagram.png"
_ -> error "Unreachable case"
diagramData :: Diagram Cairo R2 -> OutputType -> IO DisplayData
diagramData renderable format = do
-- Switch to a temporary directory so that any files we create aren't
-- visible. On Unix, this is usually /tmp.
try (getTemporaryDirectory >>= setCurrentDirectory) :: IO (Either SomeException ())
-- Write the image.
renderCairo path (mkSizeSpec2D (Just imgWidth)
(Just imgHeight)) renderable
-- Compute width and height.
let w = width renderable
h = height renderable
aspect = w / h
imgHeight = 300
imgWidth = aspect * imgHeight
case format of
PNG -> do
-- Convert to base64.
imgData <- Char.readFile path
pure $ png (floor imgWidth) (floor imgHeight) $ base64 imgData
SVG -> do
imgData <- BS.readFile path
pure $ svg (T.Encoding.decodeUtf8 imgData)
_ -> error "Unreachable case"
-- Write the image.
let filename = ".ihaskell-diagram." ++ extension format
renderCairo filename (Height imgHeight) renderable
-- Convert to base64.
imgData <- readFile $ fpFromString filename
let value = case format of
PNG -> png (floor imgWidth) (floor imgHeight) $ base64 imgData
SVG -> svg $ Char.unpack imgData
return value
where
extension SVG = "svg"
extension PNG = "png"
-- Rendering hint.
diagram :: Diagram Cairo -> Diagram Cairo
diagram :: Diagram Cairo R2 -> Diagram Cairo R2
diagram = id
instance (b ~ Cairo, v ~ V2, s ~ Double, m ~ Any)
=> ManuallySizeable (QDiagram a v s m) where
withSizeSpec spec renderable = ManuallySized renderable imgWidth imgHeight
where
aspect = width renderable / height renderable
V2 imgWidth imgHeight = case getSpec spec of
V2 (Just w) (Just h) -> V2 w h
V2 (Just w) Nothing -> V2 w (w/aspect)
V2 Nothing (Just h) -> V2 (aspect*h) h
V2 Nothing Nothing -> (defaultDiagonal / sqrt (1 + aspect^2))
*^ V2 aspect 1
-- w^2 + h^2 = defaultDiagonal^2 / (1+aspect^2)
-- * (aspect^2 + 1)
-- = defaultDiagonal^2
-- w/h = aspect/1 = aspect
defaultDiagonal = 500
instance IHaskellDisplay (QDiagram Cairo V2 Double Any) where
display = display . withSizeSpec (mkSizeSpec2D Nothing Nothing)

View File

@ -1,141 +0,0 @@
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DeriveFunctor, DeriveGeneric #-}
module IHaskell.Display.Diagrams.Animation
( animation
, ManuallySampled, withAnimFps
) where
import qualified Data.ByteString.Char8 as CBS
import qualified Data.Text as T
import GHC.Generics (Generic)
import Data.Maybe (fromMaybe)
import Diagrams.Prelude
import Diagrams.Backend.Cairo
import Diagrams.Backend.Cairo.CmdLine (GifOpts(..))
import Diagrams.Backend.CmdLine (DiagramOpts(..), mainRender)
import System.IO.Temp
import System.FilePath ((</>))
import IHaskell.Display
import IHaskell.Display.Diagrams.ImgSize
data ManuallySampled a = ManuallySampled
{ contentToSample :: a
, signalManualSampleRate :: Maybe Rational
} deriving (Show, Functor, Generic)
class ManuallySamplable a where
withSamplingSpec :: Maybe Rational -> a -> ManuallySampled a
defaultFps = 30
withAnimFps :: ManuallySamplable a => Rational -> a -> ManuallySampled a
withAnimFps fps = withSamplingSpec (Just fps)
instance IHaskellDisplay (ManuallySized (ManuallySampled (QAnimation Cairo V2 Double Any))) where
display renderable = do
gif <- animationData renderable
return $ Display [html' Nothing $ "<img src=\"data:image/gif;base64," ++ gif ++ "\" />"]
animationData :: ManuallySized (ManuallySampled (Animation Cairo V2 Double)) -> IO String
animationData (ManuallySized (ManuallySampled renderable fps) imgWidth imgHeight) = do
-- We should not have to round-trip this ByteString to a temp file.
-- https://github.com/IHaskell/IHaskell/issues/1248
withSystemTempDirectory "ihaskell-diagram" $ \tmpdir -> do
let path = tmpdir </> "ihaskell-diagram.gif"
-- Generate the frames
let actualFps = fromMaybe defaultFps fps
animAdjusted = animEnvelope' actualFps renderable
frames = simulate actualFps animAdjusted
timediff = 100 `div` ceiling actualFps :: Int
frameSet = map (\x -> (x # bg white, timediff)) frames
-- Write the image.
let diagOpts = DiagramOpts
{ _width = Just . ceiling $ imgWidth
, _height = Just . ceiling $ imgHeight
, _output = path
}
gifOpts = GifOpts { _dither = True, _noLooping = False, _loopRepeat = Nothing }
mainRender (diagOpts, gifOpts) frameSet
-- Convert to ascii represented base64 encoding
imgData <- CBS.readFile path
return . T.unpack . base64 $ imgData
-- Rendering hint.
animation :: Animation Cairo V2 Double -> Animation Cairo V2 Double
animation = id
getImgSize renderable sizeSpec fps = out
where
actualFps = fromMaybe defaultFps fps
shape = activeStart $ animEnvelope' actualFps renderable
aspect = width shape / height shape
out = case getSpec sizeSpec of
V2 (Just w) (Just h) -> V2 w h
V2 (Just w) Nothing -> V2 w (w/aspect)
V2 Nothing (Just h) -> V2 (aspect*h) h
V2 Nothing Nothing -> (defaultDiagonal / sqrt (1 + aspect^2))
*^ V2 aspect 1
-- w^2 + h^2 = defaultDiagonal^2 / (1+aspect^2)
-- * (aspect^2 + 1)
-- = defaultDiagonal^2
-- w/h = aspect/1 = aspect
defaultDiagonal = 500
instance (b ~ Cairo, v ~ V2, s ~ Double, m ~ Any)
=> ManuallySamplable (QAnimation b v s m) where
withSamplingSpec fps renderable = ManuallySampled renderable fps
instance (b ~ Cairo, v ~ V2, s ~ Double, m ~ Any)
=> ManuallySamplable (ManuallySized (QAnimation b v s m)) where
withSamplingSpec fps sizedRenderable = ManuallySampled sizedRenderable fps
instance (b ~ Cairo, v ~ V2, s ~ Double, m ~ Any)
=> ManuallySizeable (QAnimation b v s m) where
withSizeSpec spec renderable = ManuallySized renderable imgWidth imgHeight
where
fps = Nothing
V2 imgWidth imgHeight = getImgSize renderable spec fps
instance (b ~ Cairo, v ~ V2, s ~ Double, m ~ Any)
=> ManuallySizeable (ManuallySampled (QAnimation b v s m)) where
withSizeSpec spec (ManuallySampled renderable fps) = out
where
out = ManuallySized (ManuallySampled renderable fps) w h
V2 w h = getImgSize renderable spec fps
instance IHaskellDisplay (QAnimation Cairo V2 Double Any) where
display = display . withSizeSpec (mkSizeSpec2D Nothing Nothing) . withSamplingSpec fps
where
fps = Nothing
instance IHaskellDisplay (ManuallySized (QAnimation Cairo V2 Double Any)) where
display (ManuallySized renderable w h) = out
where
fps = Nothing
sizeSpec = mkSizeSpec2D (Just w) (Just h)
out = display . withSizeSpec sizeSpec $ withSamplingSpec fps renderable
instance IHaskellDisplay (ManuallySampled (QAnimation Cairo V2 Double Any)) where
display = display . withSizeSpec (mkSizeSpec2D Nothing Nothing)
instance IHaskellDisplay (ManuallySampled (ManuallySized (QAnimation Cairo V2 Double Any))) where
display (ManuallySampled (ManuallySized renderable w h) fps) = out
where
sizeSpec = mkSizeSpec2D (Just w) (Just h)
out = display . withSizeSpec sizeSpec $ withSamplingSpec fps renderable

View File

@ -1,24 +0,0 @@
{-# LANGUAGE DeriveFunctor, DeriveGeneric #-}
module IHaskell.Display.Diagrams.ImgSize where
import GHC.Generics (Generic)
import Diagrams.Prelude (SizeSpec, mkSizeSpec2D, V2)
data ManuallySized a = ManuallySized
{ contentToDisplay :: a
, imgManualWidth :: Double
, imgManualHeight :: Double
} deriving (Show, Functor, Generic)
class ManuallySizeable a where
withSizeSpec :: SizeSpec V2 Double -> a -> ManuallySized a
withImgWidth :: ManuallySizeable a => Int -> a -> ManuallySized a
withImgWidth imgWidth = withSizeSpec $ mkSizeSpec2D (Just $ fromIntegral imgWidth)
Nothing
withImgHeight :: ManuallySizeable a => Int -> a -> ManuallySized a
withImgHeight imgHeight = withSizeSpec $ mkSizeSpec2D Nothing
(Just $ fromIntegral imgHeight)

View File

@ -1,3 +1,2 @@
import Distribution.Simple
import Distribution.Simple
main = defaultMain

File diff suppressed because one or more lines are too long

View File

@ -1,19 +1,19 @@
-- The name of the package.
name: ihaskell-diagrams
-- The package version. See the Haskell package versioning policy (PVP)
-- 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.4.0.0
version: 0.1.0.0
-- A short (one-line) description of the package.
synopsis: IHaskell display instances for diagram types
-- A longer description of the package.
-- description:
-- description:
-- URL for the project homepage or repository.
homepage: http://www.github.com/gibiansky/ihaskell
@ -27,51 +27,48 @@ license-file: LICENSE
-- The package author(s).
author: Andrew Gibiansky
-- An email address to which users can send suggestions, bug reports, and
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: andrew.gibiansky@gmail.com
-- A copyright notice.
-- copyright:
-- copyright:
category: Development
build-type: Simple
-- Extra files to be distributed with the package, such as examples or a
-- Extra files to be distributed with the package, such as examples or a
-- README.
-- extra-source-files:
-- extra-source-files:
-- Constraint on the version of Cabal needed to build this package.
cabal-version: 1.16
cabal-version: >=1.16
library
-- Modules exported by the library.
exposed-modules: IHaskell.Display.Diagrams
-- Modules included in this library but not exported.
other-modules: IHaskell.Display.Diagrams.Animation
IHaskell.Display.Diagrams.ImgSize
-- other-modules:
-- Language extensions.
default-extensions: DoAndIfThenElse
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
text,
build-depends: base ==4.6.*,
classy-prelude >=0.6,
bytestring,
directory,
temporary,
filepath,
-- Use diagrams wrapper package to ensure all same versions of subpackages
diagrams >= 1.3,
diagrams-lib,
diagrams,
diagrams-lib,
diagrams-cairo,
ihaskell >= 0.11,
-- The active package, used to represent animations
active >= 0.2
ihaskell >= 0.3
-- Directories containing source files.
-- hs-source-dirs:
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

File diff suppressed because one or more lines are too long

View File

@ -1,79 +0,0 @@
{-
(This paragraph was made obsolete by PR #1362 which unified the 3 types
of plot. But it's still useful commentary.)
There are 3 types of plots to consider in haskell-gnuplot: Plot, Frame and Multiplot.
Plot types are the actual plots, whereas Frame types are plots with additional options
e.g. custom axes tics, graph title etc.. Multiplots are collections of 2D and/or 3D plots.
We have to create instances of IHaskellDisplay for all of these types.
Note: To stop gnuplot from printing the filepath ontop of the canvas, you have to set
the gnuplot option "key" to "noautotitle".
Code: Graphics.Gnuplot.Frame.cons (Graphics.Gnuplot.Frame.OptionSet.add
(Graphics.Gnuplot.Frame.Option.key "")
["noautotitle"] $ ...)
-}
module IHaskell.Display.Gnuplot where
import qualified Graphics.Gnuplot.Plot as P
import qualified Graphics.Gnuplot.Frame as F
import qualified Graphics.Gnuplot.MultiPlot as M
import qualified Graphics.Gnuplot.Terminal.PNG as Pn
import qualified Graphics.Gnuplot.Terminal.SVG as Sv
import qualified Graphics.Gnuplot.Display as D
import qualified Graphics.Gnuplot.Graph as G
import qualified Data.ByteString.Char8 as Char
import qualified Data.ByteString as BS
import qualified Data.Text.Encoding as T.Encoding
import System.IO.Temp
import System.FilePath ((</>))
import Graphics.Gnuplot.Advanced (plot)
import IHaskell.Display
-- Plot-types
instance G.C graph => IHaskellDisplay (P.T graph) where
display = graphDataDisplayBoth
-- Frame-types
instance G.C graph => IHaskellDisplay (F.T graph) where
display = graphDataDisplayBoth
-- Type: Multiplot
instance IHaskellDisplay M.T where
display = graphDataDisplayBoth
-- Width and height
w = 300
h = 300
graphDataPNG :: D.C gfx => gfx -> IO DisplayData
graphDataPNG graph = do
-- We should not have to round-trip this ByteString to a temp file.
-- https://github.com/IHaskell/IHaskell/issues/1248
withSystemTempDirectory "ihaskell-gnuplot" $ \tmpdir -> do
let path = tmpdir </> "ihaskell-gnuplot.png"
-- Write the image.
plot (Pn.cons path) graph
-- Read back, and convert to base64.
imgData <- Char.readFile path
return $ png w h $ base64 imgData
graphDataSVG :: D.C gfx => gfx -> IO DisplayData
graphDataSVG graph = do
withSystemTempDirectory "ihaskell-gnuplot" $ \tmpdir -> do
let path = tmpdir </> "ihaskell-gnuplot.svg"
-- Write the image.
plot (Sv.cons path) graph
-- Read back
imgData <- BS.readFile path
return $ svg $ T.Encoding.decodeUtf8 imgData
graphDataDisplayBoth :: D.C gfx => gfx -> IO Display
graphDataDisplayBoth fig = do
pngDisp <- graphDataPNG fig
svgDisp <- graphDataSVG fig
return $ Display [pngDisp, svgDisp]

View File

@ -1,3 +0,0 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,69 +0,0 @@
-- The name of the package.
name: ihaskell-gnuplot
-- 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.1.0.1
-- A short (one-line) description of the package.
synopsis: IHaskell display instance for Gnuplot (from gnuplot package)
-- 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: Doro Rose <dororose@hotmail.com>
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: Doro Rose <dororose@hotmail.com>,
Andrew Gibiansky <andrew.gibiansky@gmail.com>
-- A copyright notice.
-- copyright:
category: Development
build-type: Simple
-- 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.Gnuplot
-- Modules included in this library but not exported.
-- other-modules:
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
bytestring,
text,
temporary,
filepath,
gnuplot >= 0.5.4,
ihaskell >= 0.6.2
-- Directories containing source files.
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -1,118 +0,0 @@
-- | A module to help displaying information using the amazing Graphviz
-- (https://www.graphviz.org/) graph layouts.
--
-- You need to install and have graphviz tools available in your environment.
--
-- Currently only 'dot' is provided as a proof-of-concept. This module may be
-- split in two (a package as an helper to Graphviz command line and this
-- package to provide 'IHaskellDisplay' instances.
--
-- Minimal notebook example:
--
-- @ import IHaskell.Display.Graphviz @
-- @ dot "digraph { l -> o; o -> v; v -> e; h -> a ; a -> s; s -> k ; k -> e ; e -> l ; l -> l}" @
module IHaskell.Display.Graphviz (
dot
, neato
, fdp
, sfdp
, circo
, twopi
, nop
, nop2
, osage
, patchwork
, Graphviz(..)
) where
import System.Process (readProcess)
import qualified Data.Text as T
import IHaskell.Display
-- | The body of a Graphviz program.
--
-- e.g. @ graph { a -- b } @
type GraphvizProgramBody = String
-- | Main Graphviz object.
data Graphviz
= Dot !GraphvizProgramBody
-- ^ A Graphviz plotted using [Dot](https://graphviz.org/docs/layouts/dot/)
| Neato !GraphvizProgramBody
-- ^ A Graphviz plotted using [Neato](https://graphviz.org/docs/layouts/neato/)
| Fdp !GraphvizProgramBody
-- ^ A Graphviz plotted using [Fdp](https://graphviz.org/docs/layouts/fdp/)
| Sfdp !GraphvizProgramBody
-- ^ A Graphviz plotted using [Sfdp](https://graphviz.org/docs/layouts/sfdp/)
| Circo !GraphvizProgramBody
-- ^ A Graphviz plotted using [Circo](https://graphviz.org/docs/layouts/circo/)
| Twopi !GraphvizProgramBody
-- ^ A Graphviz plotted using [Twopi](https://graphviz.org/docs/layouts/twopi/)
| Nop !GraphvizProgramBody
-- ^ A Graphviz plotted using [Nop](https://graphviz.org/docs/layouts/nop/)
| Nop2 !GraphvizProgramBody
-- ^ A Graphviz plotted using [Nop2](https://graphviz.org/docs/layouts/nop2/)
| Osage !GraphvizProgramBody
-- ^ A Graphviz plotted using [Osage](https://graphviz.org/docs/layouts/osage/)
| Patchwork !GraphvizProgramBody
-- ^ A Graphviz plotted using [Patchwork](https://graphviz.org/docs/layouts/patchwork/)
-- | Create a 'Graphviz' using 'dot'.
dot :: GraphvizProgramBody -> Graphviz
dot = Dot
-- | Create a 'Graphviz' using 'neato'.
neato :: GraphvizProgramBody -> Graphviz
neato = Neato
-- | Create a 'Graphviz' using 'fdp'.
fdp :: GraphvizProgramBody -> Graphviz
fdp = Fdp
-- | Create a 'Graphviz' using 'sfdp'.
sfdp :: GraphvizProgramBody -> Graphviz
sfdp = Sfdp
-- | Create a 'Graphviz' using 'circo'.
circo :: GraphvizProgramBody -> Graphviz
circo = Circo
-- | Create a 'Graphviz' using 'twopi'.
twopi :: GraphvizProgramBody -> Graphviz
twopi = Twopi
-- | Create a 'Graphviz' using 'nop'.
nop :: GraphvizProgramBody -> Graphviz
nop = Nop
-- | Create a 'Graphviz' using 'nop2'.
nop2 :: GraphvizProgramBody -> Graphviz
nop2 = Nop2
-- | Create a 'Graphviz' using 'osage'.
osage :: GraphvizProgramBody -> Graphviz
osage = Osage
-- | Create a 'Graphviz' using 'patchwork'.
patchwork :: GraphvizProgramBody -> Graphviz
patchwork = Patchwork
instance IHaskellDisplay Graphviz where
display fig = do
svgDisp <- graphDataSVG fig
return $ Display [svgDisp]
graphDataSVG :: Graphviz -> IO DisplayData
graphDataSVG prog = svg . T.pack <$> case prog of
Dot dotBody -> readProcess "dot" ["-Tsvg"] dotBody
Neato dotBody -> readProcess "neato" ["-Tsvg"] dotBody
Fdp dotBody -> readProcess "fdp" ["-Tsvg"] dotBody
Sfdp dotBody -> readProcess "sfdp" ["-Tsvg"] dotBody
Circo dotBody -> readProcess "circo" ["-Tsvg"] dotBody
Twopi dotBody -> readProcess "twopi" ["-Tsvg"] dotBody
Nop dotBody -> readProcess "nop" ["-Tsvg"] dotBody
Nop2 dotBody -> readProcess "nop2" ["-Tsvg"] dotBody
Osage dotBody -> readProcess "osage" ["-Tsvg"] dotBody
Patchwork dotBody -> readProcess "patchwork" ["-Tsvg"] dotBody

View File

@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013 Lucas DiCioccio
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.

View File

@ -1,3 +0,0 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,68 +0,0 @@
-- The name of the package.
name: ihaskell-graphviz
-- 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.1.0.0
-- A short (one-line) description of the package.
synopsis: IHaskell display instance for GraphViz (external binary)
-- 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: Lucas DiCioccio <lucas@dicioccio.fr>
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: Lucas DiCioccio <lucas@dicioccio.fr>,
Vaibhav Sagar <vaibhavsagar@gmail.com>,
Andrew Gibiansky <andrew.gibiansky@gmail.com>
-- A copyright notice.
-- copyright:
category: Development
build-type: Simple
-- 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.Graphviz
-- Modules included in this library but not exported.
-- other-modules:
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
bytestring,
text,
process,
ihaskell >= 0.6.2
-- Directories containing source files.
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -1,15 +0,0 @@
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
-- | Provides 'IHaskellDisplay' instances for 'LaTeX' and 'LaTeXT'.
module IHaskell.Display.Hatex () where
import IHaskell.Display
import Text.LaTeX
import qualified Data.Text as T
instance IHaskellDisplay LaTeX where
display = display . IHaskell.Display.latex . T.unpack . render
instance (a ~ (), IO ~ io) => IHaskellDisplay (LaTeXT io a) where
display ma = display =<< execLaTeXT ma

View File

@ -1,20 +0,0 @@
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.

View File

@ -1,4 +0,0 @@
IHaskell-HaTeX
================
Instances to work with [HaTeX](http://hackage.haskell.org/package/HaTeX)

View File

@ -1,3 +0,0 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,22 +0,0 @@
name: ihaskell-hatex
version: 0.2.1.1
synopsis: IHaskell display instances for hatex
-- description:
homepage: http://www.github.com/gibiansky/IHaskell
license: MIT
license-file: LICENSE
author: Adam Vogt
maintainer: andrew.gibiansky@gmail.com
category: Development
build-type: Simple
cabal-version: 1.16
library
exposed-modules: IHaskell.Display.Hatex
build-depends: base >=4.9 && <5,
text,
HaTeX >= 3.9,
ihaskell >= 0.5
default-language: Haskell2010

View File

@ -1,36 +0,0 @@
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module IHaskell.Display.Juicypixels (module IHaskell.Display, module Codec.Picture) where
import qualified Codec.Picture as P
import Codec.Picture (Image(..))
import Codec.Picture.Png (PngSavable, encodePng)
import IHaskell.Display (IHaskellDisplay, Display(..), display, png, base64)
import Data.ByteString.Lazy (ByteString, toStrict)
instance IHaskellDisplay (Image P.Pixel8) where
display = return . format
instance IHaskellDisplay (Image P.Pixel16) where
display = return . format
instance IHaskellDisplay (Image P.PixelYA8) where
display = return . format
instance IHaskellDisplay (Image P.PixelYA16) where
display = return . format
instance IHaskellDisplay (Image P.PixelRGB8) where
display = return . format
instance IHaskellDisplay (Image P.PixelRGB16) where
display = return . format
instance IHaskellDisplay (Image P.PixelRGBA8) where
display = return . format
instance IHaskellDisplay (Image P.PixelRGBA16) where
display = return . format
format :: PngSavable a => Image a -> Display
format im@(Image w h _) = Display [png w h . base64 . toStrict . encodePng $ im]

View File

@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013 Roland Senn
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.

View File

@ -1,3 +0,0 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,73 +0,0 @@
-- The name of the package.
name: ihaskell-juicypixels
-- 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: 1.1.0.1
-- A short (one-line) description of the package.
synopsis: IHaskell - IHaskellDisplay instances of the image types of the JuicyPixels package.
-- A longer description of the package.
description: IHaskellDisplay instances of the image types of the JuicyPixels package. They are displayed as .JPG images.
DynamicImages and Images of types PixelRGBA16, PixelRGBA8, PixelRGB16, PixelRGB8,
PixelYA16, PixelYA8, Pixel16, Pixel8, PixelCMYK16, PixelCMYK8, PixelF, Pixel32
are supported.
The module IHaskell.Juicypixels re-exports the modules IHaskell.Display and Codec.Picture.
-- 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: Roland Senn,
Will Yager
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: rsx@bluewin.ch,
will.yager@gmail.com
-- A copyright notice.
-- copyright:
category: Development
build-type: Simple
-- 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.Juicypixels
-- Modules included in this library but not exported.
-- other-modules:
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
bytestring,
directory,
JuicyPixels >= 3.1.3,
ihaskell >= 0.6.2
-- Directories containing source files.
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -1,57 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"# Notebook test\n",
"\n",
"This IHaskell noteook should just test, whether IHaskell and JuicyPixels are properly installed and working.\n",
"\n",
"Just click in the box below and click on the \"Run\" command in the above menu. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"hidden": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}\n",
"\n",
"import IHaskell.Display.Juicypixels\n",
"import Codec.Picture\n",
" \n",
"myImage = generateImage pixelRenderer 250 300\n",
" where pixelRenderer x y = PixelRGB8 (fromIntegral x) (fromIntegral y) 128\n",
" \n",
"myImage "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"mimetype": "text/x-haskell",
"name": "haskell",
"pygments_lexer": "Haskell",
"version": "8.10.4"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -1,43 +1,39 @@
{-# LANGUAGE ViewPatterns, TypeSynonymInstances, FlexibleInstances #-}
module IHaskell.Display.Magic () where
import IHaskell.Display
import Magic
import qualified Data.ByteString as B
import qualified Data.ByteString.Unsafe as B
import qualified Data.ByteString.Base64 as Base64
import qualified Data.ByteString.Char8 as Char
import Data.ByteString.UTF8
import qualified Data.ByteString.UTF8 as B
import qualified Data.ByteString.Unsafe as B
import Data.Char
import Text.Read
import Data.Char
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Text.Read
import Magic
import IHaskell.CSS (ihaskellCSS)
import IHaskell.Display
import IHaskell.IPython.Types (MimeType(MimeSvg))
import Data.ByteString.UTF8
instance IHaskellDisplay T.Text where
display = display . T.encodeUtf8
display = display . T.encodeUtf8
instance IHaskellDisplay B.ByteString where
display x = do
m <- magicOpen []
magicLoadDefault m
f <- B.unsafeUseAsCStringLen x (magicCString m)
return $ Display [withClass (parseMagic f) x]
display x = do
m <- magicOpen []
magicLoadDefault m
f <- B.unsafeUseAsCStringLen x (magicCString m)
return $ Display [withClass (parseMagic f) x]
b64 :: B.ByteString -> String
b64 = Char.unpack . Base64.encode
withClass :: MagicClass -> B.ByteString -> DisplayData
withClass SVG = DisplayData MimeSvg . T.decodeUtf8
withClass (PNG w h) = png w h . T.decodeUtf8 . Base64.encode
withClass JPG = jpg 400 300 . T.decodeUtf8 . Base64.encode
withClass HTML = html' (Just ihaskellCSS) . B.toString
withClass SVG = svg . B.toString
withClass (PNG w h) = png w h . Base64.encode
withClass JPG = jpg 400 300 . Base64.encode
withClass HTML = html . B.toString
withClass LaTeX = latex . B.toString
withClass _ = plain . B.toString
@ -57,20 +53,17 @@ JPG
-}
parseMagic :: String -> MagicClass
parseMagic f =
case words f of
"SVG":_ -> SVG
"PNG":_image:_data:(readMaybe -> Just w):_x:(readMaybe . takeWhile isDigit -> Just h):_ -> PNG w
h
"LaTeX":_ -> LaTeX
"HTML":_ -> HTML
"JPEG":_ -> JPG
_ -> Unknown
parseMagic f = case words f of
"SVG" : _ -> SVG
"PNG" : _image : _data :
(readMaybe -> Just w) : _x :
(readMaybe . takeWhile isDigit -> Just h) : _ -> PNG w h
"LaTeX" : _ -> LaTeX
"HTML" : _ -> HTML
"JPEG" : _ -> JPG
_ -> Unknown
data MagicClass = SVG
| PNG Int Int
| JPG
| HTML
| LaTeX
| Unknown
deriving Show
data MagicClass =
SVG | PNG Int Int | JPG | HTML | LaTeX | Unknown
deriving Show

View File

@ -10,14 +10,6 @@ cd ihaskell-magic
cabal install
```
On OSX:
```bash
brew install libmagic
brew link libmagic
stack install ihaskell-magic --extra-lib-dirs=/usr/local/lib --extra-include-dirs=/usr/local/include
```
The instances provided allow displaying images and text with markup using just one line:
```haskell
import qualified Data.ByteString as B

View File

@ -1,3 +1,2 @@
import Distribution.Simple
import Distribution.Simple
main = defaultMain

View File

@ -1,22 +1,22 @@
-- Initial ihaskell-display.cabal generated by cabal init. For further
-- Initial ihaskell-display.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
-- The name of the package.
name: ihaskell-magic
-- The package version. See the Haskell package versioning policy (PVP)
-- 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.1
version: 0.1.0.0
-- A short (one-line) description of the package.
synopsis: IHaskell display instances for bytestrings
-- A longer description of the package.
-- description:
-- description:
-- URL for the project homepage or repository.
homepage: http://www.github.com/gibiansky/IHaskell
@ -30,45 +30,49 @@ license-file: LICENSE
-- The package author(s).
author: Adam Vogt
-- An email address to which users can send suggestions, bug reports, and
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: andrew.gibiansky@gmail.com
-- A copyright notice.
-- copyright:
-- copyright:
category: Development
build-type: Simple
-- Extra files to be distributed with the package, such as examples or a
-- Extra files to be distributed with the package, such as examples or a
-- README.
-- extra-source-files:
-- extra-source-files:
-- Constraint on the version of Cabal needed to build this package.
cabal-version: 1.16
cabal-version: >=1.16
library
-- Modules exported by the library.
exposed-modules: IHaskell.Display.Magic
-- Modules included in this library but not exported.
-- other-modules:
-- other-modules:
-- Language extensions.
default-extensions: DoAndIfThenElse
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
build-depends: base ==4.6.*,
classy-prelude >=0.6,
magic >= 1.0.8,
text,
bytestring,
utf8-string,
base64-bytestring,
ipython-kernel,
ihaskell >= 0.5
ihaskell >= 0.3
-- Directories containing source files.
-- hs-source-dirs:
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -1,44 +0,0 @@
module IHaskell.Display.Matplotlib where
import qualified Data.ByteString.Char8 as Char
import qualified Data.ByteString.UTF8 as BSU
import qualified Data.Text.Encoding as T.Encoding
import System.IO.Temp
import System.FilePath ((</>))
import Graphics.Matplotlib
import IHaskell.Display
instance IHaskellDisplay Matplotlib where
display = graphDataDisplayBoth
-- Width and height
w, h :: Int
w = 300
h = 300
graphDataPNG :: Matplotlib -> IO DisplayData
graphDataPNG m = do
withSystemTempDirectory "ihaskell-matplotlib" $ \tmpdir -> do
let path = tmpdir </> "ihaskell-matplotlib.png"
-- Write the image.
res <- file path m
case res of
Left _ -> error "Matplotlib could not generate an immage"
Right _ -> do
-- Read back, and convert to base64.
imgData <- Char.readFile path
return $ png w h $ base64 imgData
graphDataSVG :: Matplotlib -> IO DisplayData
graphDataSVG m = do
res <- toSvg m
case res of
Left s -> error s
Right f -> return $ svg $ T.Encoding.decodeUtf8 $ BSU.fromString f
graphDataDisplayBoth :: Matplotlib -> IO Display
graphDataDisplayBoth fig = do
pngDisp <- graphDataPNG fig
svgDisp <- graphDataSVG fig
return $ Display [pngDisp, svgDisp]

View File

@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2025 Andrea Rossato andrea.rossato@unitn.it
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.

File diff suppressed because one or more lines are too long

View File

@ -1,3 +0,0 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,69 +0,0 @@
-- The name of the package.
name: ihaskell-matplotlib
-- 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.1.0.1
-- A short (one-line) description of the package.
synopsis: IHaskell display instance for matplotlib (from matplotlib package)
-- 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: Andrea Rossatoe <andrea.rossato@unitn.it>
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: Andrea Rossato <andrea.rossato@unitn.it>,
Andrew Gibiansky <andrew.gibiansky@gmail.com>
-- A copyright notice.
-- copyright:
category: Development
build-type: Simple
-- 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.Matplotlib
ghc-options: -O -Wall -Wno-orphans
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
bytestring,
utf8-string,
text,
temporary,
filepath,
matplotlib,
ihaskell >= 0.6.2
-- Directories containing source files.
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -1,46 +0,0 @@
module IHaskell.Display.Plot where
import qualified Data.ByteString.Char8 as Char
import qualified Data.ByteString as BS
import qualified Data.Text.Encoding as T.Encoding
import Graphics.Rendering.Plot
import Control.Monad (void)
import Control.Applicative ((<$>))
import System.IO.Temp
import System.FilePath ((</>))
import IHaskell.Display
instance IHaskellDisplay (Figure a) where
display fig = do
let figure = void fig
pngDisp <- figureData figure PNG
svgDisp <- figureData figure SVG
return $ Display [pngDisp, svgDisp]
figureData :: Figure () -> OutputType -> IO DisplayData
figureData figure format = do
withSystemTempDirectory "ihaskell-plot" $ \tmpdir -> do
-- Width and height
let size = 300
w = size
h = size
let path = case format of
PNG -> tmpdir </> "ihaskell-plot.png"
SVG -> tmpdir </> "ihaslell-plot.svg"
_ -> error "Unreachable case"
-- Write the image.
writeFigure format path (w, h) figure
case format of
PNG -> do
-- Read back, and convert to base64.
imgData <- Char.readFile path
pure $ png w h $ base64 imgData
SVG -> do
imgData <- BS.readFile path
pure $ svg $ T.Encoding.decodeUtf8 imgData
_ -> error "Unreachable case"

View File

@ -1,20 +0,0 @@
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.

File diff suppressed because one or more lines are too long

View File

@ -1,3 +0,0 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,70 +0,0 @@
-- The name of the package.
name: ihaskell-plot
-- 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.1
-- A short (one-line) description of the package.
synopsis: IHaskell display instance for Plot (from plot package)
-- 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: Sumit Sahrawat <sumit.sahrawat.apm13@itbhu.ac.in>
-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer: Sumit Sahrawat <sumit.sahrawat.apm13@itbhu.ac.in>,
Andrew Gibiansky <andrew.gibiansky@gmail.com>
-- A copyright notice.
-- copyright:
category: Development
build-type: Simple
-- 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.Plot
-- Modules included in this library but not exported.
-- other-modules:
-- Other library packages from which modules are imported.
build-depends: base >=4.9 && <5,
plot,
bytestring,
text,
temporary,
filepath,
hmatrix >= 0.10,
ihaskell >= 0.6.2
-- Directories containing source files.
-- hs-source-dirs:
-- Base language which the package is written in.
default-language: Haskell2010

View File

@ -1,106 +0,0 @@
{-# OPTIONS_GHC -fno-warn-missing-fields #-}
{-# LANGUAGE TupleSections, TemplateHaskell #-}
module IHaskell.Display.Rlangqq (
module RlangQQ,
rDisp,
rDisplayAll,
rOutputParsed,
rOutput,
getPlotNames,
getCaptions,
) where
import RlangQQ
import RlangQQ.ParseKnitted
import System.Directory
import System.FilePath
import Data.Maybe
import Data.List
import Text.Read
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as Char
import qualified Data.ByteString.Base64 as Base64
import IHaskell.Display
import IHaskell.Display.Blaze () -- to confirm it's installed
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as H
import Data.Char
import Control.Monad
import Data.Ord
import Data.List.Split
import Text.XFormat.Show hiding ((<>))
import Control.Applicative
import Control.Concurrent
import Data.Monoid
import Data.Typeable
import Control.Concurrent.STM
import Language.Haskell.TH.Quote
-- | same as 'RlangQQ.r', but displays plots at the end too
rDisp = QuasiQuoter { quoteExp = \s -> [|do
result <- $(quoteExp r s)
p <- rDisplayAll
printDisplay p
return result|] }
rOutput :: IO [Int]
rOutput = do
fs <- mapMaybe (readMaybe <=< stripPrefix "raw" <=< stripSuffix ".md")
<$> getDirectoryContents "Rtmp"
fs' <- forM fs $ \f -> (,f) <$> getModificationTime (showf ("Rtmp/raw" % Int % ".md") f)
return $ map snd $ sortBy (flip (comparing fst)) fs'
-- | like 'stripPrefix' except on the end
stripSuffix :: String -> String -> Maybe String
stripSuffix s x = fmap reverse $ stripPrefix (reverse s) $ reverse x
rOutputParsed :: IO [KnitInteraction]
rOutputParsed = do
ns <- rOutput
case ns of
[] -> return []
n:_ -> parseKnitted <$> readFile (showf ("Rtmp/raw" % Int % ".md") n)
getPlotNames :: IO [String]
getPlotNames = do
interactions <- rOutputParsed
return [p | KnitInteraction _ is <- interactions
, KnitImage _ p <- is]
getCaptions :: IO [String]
getCaptions = do
interactions <- rOutputParsed
return
[c | KnitInteraction _ is <- interactions
, KnitImage c _ <- is
, not (isBoringCaption c)]
-- | true when the caption name looks like one knitr will automatically generate
isBoringCaption :: String -> Bool
isBoringCaption s = maybe False (all isDigit) (stripPrefix "plot of chunk unnamed-chunk-" s)
rDisplayAll :: IO Display
rDisplayAll = do
ns <- rOutputParsed
imgs <- sequence [displayInteraction o | KnitInteraction _ os <- ns
, o <- os]
display (mconcat imgs)
displayInteraction :: KnitOutput -> IO Display
displayInteraction (KnitPrint c) = display (plain c)
displayInteraction (KnitWarning c) = display (plain c)
displayInteraction (KnitError c) = display (plain c)
displayInteraction (KnitAsIs c) = display (plain c)
displayInteraction (KnitImage cap img) = do
let caption
| isBoringCaption cap = mempty
| otherwise = H.p (H.toMarkup cap)
encoded <- Base64.encode <$> B.readFile img
display $ H.img H.! H.src
(H.unsafeByteStringValue
-- assumes you use the default device which is png
(Char.pack "data:image/png;base64," <> encoded))
<> caption

View File

@ -1,30 +0,0 @@
Copyright (c) 2013, Adam Vogt <vogt.adam@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Adam Vogt <vogt.adam@gmail.com> nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,3 +0,0 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,28 +0,0 @@
name: ihaskell-rlangqq
version: 0.3.0.0
synopsis: a rDisp quasiquote to show plots from Rlang-QQ in IHaskell
license: BSD3
license-file: LICENSE
author: Adam Vogt <vogt.adam@gmail.com>
maintainer: Adam Vogt <vogt.adam@gmail.com>
category: Development
build-type: Simple
cabal-version: 1.16
library
exposed-modules: IHaskell.Display.Rlangqq
other-extensions: TupleSections, TemplateHaskell
build-depends: base <5,
Rlang-QQ >= 0.3,
directory >=1.2,
filepath >=1.3,
bytestring >=0.10,
base64-bytestring >=1.0,
ihaskell >= 0.6.2,
ihaskell-blaze >=0.3,
blaze-html >=0.6,
split >=0.2,
stm -any,
xformat >=0.1,
template-haskell >= 2.8
default-language: Haskell2010

View File

@ -1,20 +0,0 @@
Copyright (c) 2015 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.

View File

@ -1,3 +0,0 @@
import Distribution.Simple
main = defaultMain

View File

@ -1,32 +0,0 @@
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module IHaskell.Display.StaticCanvas (Canvas(..)) where
import Data.Text.Lazy.Builder (toLazyText)
import Data.Text.Lazy (unpack)
import Data.Text (pack, Text)
import System.IO.Unsafe
import Control.Concurrent.MVar
import Graphics.Static
import IHaskell.Display
{-# NOINLINE uniqueCounter #-}
uniqueCounter :: MVar Int
uniqueCounter = unsafePerformIO $ newMVar 0
getUniqueName :: IO Text
getUniqueName = do
val <- takeMVar uniqueCounter
let val' = val + 1
putMVar uniqueCounter val'
return $ pack $ "ihaskellStaticCanvasUniqueID" ++ show val
data Canvas = Canvas { canvasWidth :: Int, canvasHeight :: Int, canvas :: CanvasFree () }
instance IHaskellDisplay Canvas where
display cnv = do
name <- getUniqueName
let script = buildScript' (canvasWidth cnv) (canvasHeight cnv) name (canvas cnv)
return $ Display [html $ unpack $ toLazyText script]

View File

@ -1 +0,0 @@
Examples/.chart

Some files were not shown because too many files have changed in this diff Show More