mirror of
https://github.com/IHaskell/IHaskell.git
synced 2025-04-19 21:06:07 +00:00
Compare commits
No commits in common. "master" and "v0.3.0.1" have entirely different histories.
@ -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
3
.ghci
@ -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
|
||||
|
74
.github/workflows/docker.yml
vendored
74
.github/workflows/docker.yml
vendored
@ -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' }}
|
74
.github/workflows/nix.yml
vendored
74
.github/workflows/nix.yml
vendored
@ -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
|
108
.github/workflows/stack-nix.yml
vendored
108
.github/workflows/stack-nix.yml
vendored
@ -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
|
110
.github/workflows/stack.yml
vendored
110
.github/workflows/stack.yml
vendored
@ -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
|
23
.github/workflows/update-flake-lock.yml
vendored
23
.github/workflows/update-flake-lock.yml
vendored
@ -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
18
.gitignore
vendored
@ -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
|
||||
|
96
Dockerfile
96
Dockerfile
@ -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
363
README.md
@ -1,227 +1,186 @@
|
||||
  [](https://github.com/gibiansky/IHaskell/actions?query=workflow%3ACI) [](https://mybinder.org/v2/gh/gibiansky/IHaskell/mybinder)
|
||||

|
||||
|
||||
# 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:
|
||||
|
||||

|
||||
|
||||
As well as the IPython browser-based notebook interface:
|
||||
|
||||

|
||||
|
||||
### 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.
|
||||
|
3
Setup.hs
3
Setup.hs
@ -1,3 +1,2 @@
|
||||
import Distribution.Simple
|
||||
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
|
36
build.sh
Executable file
36
build.sh
Executable 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
|
@ -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
3345
demo/IHaskell.html
Normal file
File diff suppressed because one or more lines are too long
1421
demo/IHaskell.ipynb
Normal file
1421
demo/IHaskell.ipynb
Normal file
File diff suppressed because one or more lines are too long
BIN
demo/doc-demo.png
Normal file
BIN
demo/doc-demo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
BIN
demo/hoogle-demo.png
Normal file
BIN
demo/hoogle-demo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 105 KiB |
BIN
demo/info-demo.png
Normal file
BIN
demo/info-demo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
BIN
demo/json-demo.png
Normal file
BIN
demo/json-demo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
149
flake.lock
generated
149
flake.lock
generated
@ -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
109
flake.nix
@ -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;
|
||||
});
|
||||
}
|
2201
ghc-parser/HaskellParser.y.pp
Normal file
2201
ghc-parser/HaskellParser.y.pp
Normal file
File diff suppressed because it is too large
Load Diff
26875
ghc-parser/Language/Haskell/GHC/HappyParser.hs
Normal file
26875
ghc-parser/Language/Haskell/GHC/HappyParser.hs
Normal file
File diff suppressed because it is too large
Load Diff
130
ghc-parser/Language/Haskell/GHC/Parser.hs
Normal file
130
ghc-parser/Language/Haskell/GHC/Parser.hs
Normal 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"
|
@ -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
13
ghc-parser/build-parser.sh
Executable 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
|
@ -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 == '\''
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
36
hie.yaml
36
hie.yaml
@ -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"
|
@ -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};
|
||||
}
|
||||
);
|
@ -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 |
@ -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>|]
|
||||
|
@ -1,3 +1,2 @@
|
||||
import Distribution.Simple
|
||||
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
|
@ -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
|
||||
|
15
ihaskell-display/ihaskell-basic/IHaskell/Display/Basic.hs
Normal file
15
ihaskell-display/ihaskell-basic/IHaskell/Display/Basic.hs
Normal 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)
|
4
ihaskell-display/ihaskell-basic/README.md
Normal file
4
ihaskell-display/ihaskell-basic/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
IHaskell-Display
|
||||
================
|
||||
|
||||
Instances of IHaskellDisplay for default prelude data types.
|
2
ihaskell-display/ihaskell-basic/Setup.hs
Normal file
2
ihaskell-display/ihaskell-basic/Setup.hs
Normal file
@ -0,0 +1,2 @@
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,2 @@
|
||||
import Distribution.Simple
|
||||
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,2 @@
|
||||
import Distribution.Simple
|
||||
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
|
File diff suppressed because one or more lines are too long
@ -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
@ -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)
|
||||
|
@ -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
|
@ -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)
|
||||
|
@ -1,3 +1,2 @@
|
||||
import Distribution.Simple
|
||||
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
|
331
ihaskell-display/ihaskell-diagrams/Test.ipynb
Normal file
331
ihaskell-display/ihaskell-diagrams/Test.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -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
@ -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]
|
@ -1,3 +0,0 @@
|
||||
import Distribution.Simple
|
||||
|
||||
main = defaultMain
|
@ -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
|
@ -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
|
@ -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.
|
@ -1,3 +0,0 @@
|
||||
import Distribution.Simple
|
||||
|
||||
main = defaultMain
|
@ -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
|
@ -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
|
@ -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.
|
@ -1,4 +0,0 @@
|
||||
IHaskell-HaTeX
|
||||
================
|
||||
|
||||
Instances to work with [HaTeX](http://hackage.haskell.org/package/HaTeX)
|
@ -1,3 +0,0 @@
|
||||
import Distribution.Simple
|
||||
|
||||
main = defaultMain
|
@ -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
|
||||
|
@ -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]
|
@ -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.
|
@ -1,3 +0,0 @@
|
||||
import Distribution.Simple
|
||||
|
||||
main = defaultMain
|
@ -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
|
@ -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
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,2 @@
|
||||
import Distribution.Simple
|
||||
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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]
|
@ -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
@ -1,3 +0,0 @@
|
||||
import Distribution.Simple
|
||||
|
||||
main = defaultMain
|
@ -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
|
@ -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"
|
@ -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
@ -1,3 +0,0 @@
|
||||
import Distribution.Simple
|
||||
|
||||
main = defaultMain
|
@ -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
|
@ -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
|
@ -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.
|
@ -1,3 +0,0 @@
|
||||
import Distribution.Simple
|
||||
|
||||
main = defaultMain
|
@ -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
|
@ -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.
|
@ -1,3 +0,0 @@
|
||||
import Distribution.Simple
|
||||
|
||||
main = defaultMain
|
@ -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]
|
1
ihaskell-display/ihaskell-widgets/.gitignore
vendored
1
ihaskell-display/ihaskell-widgets/.gitignore
vendored
@ -1 +0,0 @@
|
||||
Examples/.chart
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user