├── .github ├── FUNDING.yml └── workflows │ └── build-haskell.yml ├── .gitignore ├── .hlint.yaml ├── CHANGELOG.md ├── CONTRIBUTORS ├── LICENSE ├── README.md ├── app ├── main.css ├── package.json ├── preferences.css ├── preferences.html ├── src │ ├── fileformat.js │ ├── glitter.js │ ├── interpreter-worksheet.js │ ├── interpreter.js │ ├── main.js │ ├── preferences-preload.js │ ├── preferences.js │ ├── sequence.js │ ├── worksheet-preload.js │ └── worksheet.js ├── vendor │ ├── FiraCode_1.203 │ │ ├── LICENSE │ │ ├── eot │ │ │ ├── FiraCode-Bold.eot │ │ │ ├── FiraCode-Light.eot │ │ │ ├── FiraCode-Medium.eot │ │ │ └── FiraCode-Regular.eot │ │ ├── fira_code.css │ │ ├── otf │ │ │ ├── FiraCode-Bold.otf │ │ │ ├── FiraCode-Light.otf │ │ │ ├── FiraCode-Medium.otf │ │ │ ├── FiraCode-Regular.otf │ │ │ └── FiraCode-Retina.otf │ │ ├── specimen.html │ │ ├── ttf │ │ │ ├── FiraCode-Bold.ttf │ │ │ ├── FiraCode-Light.ttf │ │ │ ├── FiraCode-Medium.ttf │ │ │ ├── FiraCode-Regular.ttf │ │ │ └── FiraCode-Retina.ttf │ │ ├── woff │ │ │ ├── FiraCode-Bold.woff │ │ │ ├── FiraCode-Light.woff │ │ │ ├── FiraCode-Medium.woff │ │ │ └── FiraCode-Regular.woff │ │ └── woff2 │ │ │ ├── FiraCode-Bold.woff2 │ │ │ ├── FiraCode-Light.woff2 │ │ │ ├── FiraCode-Medium.woff2 │ │ │ └── FiraCode-Regular.woff2 │ ├── codemirror-5.6.css │ ├── codemirror-5.7.js │ ├── codemirror-hs-5.6.js │ ├── jquery-3.1.0.js │ ├── quill-1.1.0.core.css │ └── quill-1.1.0.min.js ├── worksheet.css └── worksheet.html ├── cabal.project ├── docs ├── INSTALL.md ├── TODO.md ├── hcar │ ├── hcar.sty │ ├── html │ │ └── worksheet-diagrams.png │ ├── hyperhaskell-2016-11.tex │ ├── hyperhaskell-2017-05.tex │ ├── hyperhaskell-2017-11.tex │ └── template.tex ├── misc.md └── screenshots │ ├── app-osx.png │ ├── settings-back-end-cabal.png │ ├── settings-back-end-stack.png │ └── worksheet-diagrams.png ├── flake.lock ├── flake.nix ├── haskell ├── hyper-extra │ ├── LICENSE │ ├── hyper-extra.cabal │ └── src │ │ └── Hyper │ │ └── Extra.hs ├── hyper-haskell-server.nix ├── hyper-haskell-server │ ├── LICENSE │ ├── hyper-haskell-server.cabal │ └── src │ │ ├── HyperHaskell │ │ └── Interpreter.hs │ │ └── Main.hs ├── hyper │ ├── LICENSE │ ├── hyper.cabal │ └── src │ │ ├── Hyper.hs │ │ └── Hyper │ │ └── Internal.hs └── stack.yaml ├── justfile ├── resources ├── LICENSE.electron.txt ├── hyper-haskell.desktop ├── icons │ ├── icon.graffle │ ├── icon.icns │ ├── icon.ico │ ├── icon.png │ ├── icon.svg │ └── makeicns.sh ├── macOS-Info.plist └── shared-mime-info.xml ├── runHyperHaskell.command └── worksheets ├── Csound.hhs ├── Diagrams.hhs ├── Prelude.hhs ├── Test.hhs └── Test.hs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: http://buymeacoffee.com/hapfelmus 2 | -------------------------------------------------------------------------------- /.github/workflows/build-haskell.yml: -------------------------------------------------------------------------------- 1 | name: Build cabal project 2 | on: 3 | workflow_dispatch: 4 | pull_request: 5 | types: 6 | - synchronize 7 | - opened 8 | - reopened 9 | merge_group: 10 | push: 11 | branches: 12 | - master 13 | schedule: 14 | # Run once per day (at UTC 18:00) to maintain cache: 15 | - cron: 0 18 * * * 16 | jobs: 17 | build: 18 | name: ${{ matrix.os }}-ghc-${{ matrix.ghc }} 19 | runs-on: ${{ matrix.os }} 20 | continue-on-error: ${{ matrix.allow-failure }} 21 | strategy: 22 | matrix: 23 | allow-failure: 24 | - false 25 | os: 26 | - ubuntu-latest 27 | cabal: 28 | - '3.12' 29 | ghc: 30 | - '8.10' 31 | - '9.2' 32 | - '9.4' 33 | - '9.6' 34 | - '9.8' 35 | - '9.10' 36 | include: 37 | - allow-failure: true 38 | os: ubuntu-latest 39 | cabal: '3.12' 40 | ghc: '9.12' 41 | steps: 42 | - name: Checkout 43 | uses: actions/checkout@v4 44 | 45 | - name: Environment 46 | uses: haskell-actions/setup@v2 47 | id: setup 48 | with: 49 | ghc-version: ${{ matrix.ghc }} 50 | cabal-version: ${{ matrix.cabal }} 51 | 52 | - name: Configure 53 | run: | 54 | cabal configure \ 55 | --enable-tests \ 56 | --enable-benchmarks \ 57 | --enable-documentation \ 58 | --test-show-details=direct \ 59 | --write-ghc-environment-files=always 60 | cabal build all --dry-run 61 | # The last step generates dist-newstyle/cache/plan.json for the cache key. 62 | 63 | # For a description of how the Caching works, see 64 | # https://github.com/haskell-actions/setup?tab=readme-ov-file#model-cabal-workflow-with-caching 65 | - name: Dependencies (Restore from cache) 66 | uses: actions/cache/restore@v4 67 | id: cache 68 | env: 69 | key: ${{ matrix.os }}-ghc-${{ matrix.ghc }} 70 | hash: ${{ hashFiles('**/plan.json') }} 71 | with: 72 | key: ${{ env.key }}-${{ env.hash }} 73 | restore-keys: ${{ env.key }}- 74 | path: ${{ steps.setup.outputs.cabal-store }} 75 | 76 | - name: Dependencies (Install) 77 | if: steps.cache.outputs.cache-hit != 'true' 78 | run: cabal build all --only-dependencies 79 | 80 | # Cache dependencies already here, 81 | # so that we do not have to rebuild them should the subsequent steps fail. 82 | - name: Dependencies (Save cache) 83 | uses: actions/cache/save@v4 84 | # If we had an exact cache hit, 85 | # trying to save the cache would error because of key clash. 86 | if: steps.cache.outputs.cache-hit != 'true' 87 | with: 88 | key: ${{ steps.cache.outputs.cache-primary-key }} 89 | path: ${{ steps.setup.outputs.cabal-store }} 90 | 91 | - name: Build 92 | run: > 93 | cabal build all 94 | --enable-tests 95 | --enable-benchmarks 96 | 97 | - name: Test 98 | run: > 99 | cabal test all 100 | 101 | - name: Benchmark 102 | run: > 103 | cabal bench all 104 | || true 105 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | .cabal-sandbox/ 3 | cabal.sandbox.config 4 | dist/ 5 | dist-newstyle/ 6 | .stack-work 7 | /.dist-buildwrapper 8 | /.project 9 | /.externalToolBuilders 10 | *.sublime-workspace 11 | node_modules 12 | /build 13 | /haskell/vendor/ 14 | -------------------------------------------------------------------------------- /.hlint.yaml: -------------------------------------------------------------------------------- 1 | # HLint configuration file 2 | # https://github.com/ndmitchell/hlint 3 | ########################## 4 | 5 | # This file contains a template configuration file, which is typically 6 | # placed as .hlint.yaml in the root of your project 7 | 8 | 9 | # Warnings currently triggered by your code 10 | - ignore: {name: "Avoid lambda"} # 1 hint 11 | - ignore: {name: "Avoid lambda using `infix`"} # 6 hints 12 | - ignore: {name: "Eta reduce"} # 20 hints 13 | - ignore: {name: "Evaluate"} # 7 hints 14 | - ignore: {name: "Hoist not"} # 2 hints 15 | - ignore: {name: "Missing NOINLINE pragma"} # 1 hint 16 | - ignore: {name: "Move brackets to avoid $"} # 12 hints 17 | - ignore: {name: "Redundant $"} # 5 hints 18 | - ignore: {name: "Redundant bracket"} # 10 hints 19 | - ignore: {name: "Redundant flip"} # 1 hint 20 | - ignore: {name: "Redundant lambda"} # 1 hint 21 | - ignore: {name: "Use <$>"} # 2 hints 22 | - ignore: {name: "Use const"} # 1 hint 23 | - ignore: {name: "Use fromMaybe"} # 1 hint 24 | - ignore: {name: "Use lambda-case"} # 1 hint 25 | - ignore: {name: "Use list literal"} # 13 hints 26 | - ignore: {name: "Use list literal pattern"} # 4 hints 27 | - ignore: {name: "Use map once"} # 2 hints 28 | - ignore: {name: "Use newtype instead of data"} # 1 hint 29 | - ignore: {name: "Use section"} # 8 hints 30 | - ignore: {name: "Use tuple-section"} # 7 hints 31 | 32 | 33 | # Specify additional command line arguments 34 | # 35 | # - arguments: [--color, --cpp-simple, -XQuasiQuotes] 36 | 37 | 38 | # Control which extensions/flags/modules/functions can be used 39 | # 40 | # - extensions: 41 | # - default: false # all extension are banned by default 42 | # - name: [PatternGuards, ViewPatterns] # only these listed extensions can be used 43 | # - {name: CPP, within: CrossPlatform} # CPP can only be used in a given module 44 | # 45 | # - flags: 46 | # - {name: -w, within: []} # -w is allowed nowhere 47 | # 48 | # - modules: 49 | # - {name: [Data.Set, Data.HashSet], as: Set} # if you import Data.Set qualified, it must be as 'Set' 50 | # - {name: Control.Arrow, within: []} # Certain modules are banned entirely 51 | # 52 | # - functions: 53 | # - {name: unsafePerformIO, within: []} # unsafePerformIO can only appear in no modules 54 | 55 | 56 | # Add custom hints for this project 57 | # 58 | # Will suggest replacing "wibbleMany [myvar]" with "wibbleOne myvar" 59 | # - error: {lhs: "wibbleMany [x]", rhs: wibbleOne x} 60 | 61 | # The hints are named by the string they display in warning messages. 62 | # For example, if you see a warning starting like 63 | # 64 | # Main.hs:116:51: Warning: Redundant == 65 | # 66 | # You can refer to that hint with `{name: Redundant ==}` (see below). 67 | 68 | # Turn on hints that are off by default 69 | # 70 | # Ban "module X(module X) where", to require a real export list 71 | # - warn: {name: Use explicit module export list} 72 | # 73 | # Replace a $ b $ c with a . b $ c 74 | # - group: {name: dollar, enabled: true} 75 | # 76 | # Generalise map to fmap, ++ to <> 77 | # - group: {name: generalise, enabled: true} 78 | # 79 | # Warn on use of partial functions 80 | # - group: {name: partial, enabled: true} 81 | 82 | 83 | # Ignore some builtin hints 84 | # - ignore: {name: Use let} 85 | # - ignore: {name: Use const, within: SpecialModule} # Only within certain modules 86 | 87 | 88 | # Define some custom infix operators 89 | # - fixity: infixr 3 ~^#^~ 90 | 91 | 92 | # To generate a suitable file for HLint do: 93 | # $ hlint --default > .hlint.yaml 94 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Changelog for HyperHaskell 2 | 3 | 4 | ### HyperHaskell app bundle 5 | 6 | **v2.3.0** — Snapshot release. 7 | 8 | * Add `~/.ghcup` directory to PATH by default. 9 | * Add `View` menu and zoom functionality. 10 | * Update Electron to version 10.1.5. 11 | 12 | **v2.2.0** — Snapshot release. 13 | 14 | * Implement "Search path" field properly. 15 | * Add "Open Recent…" menu item on macOS. 16 | 17 | * Update Electron to version 3.1.8. 18 | * Support for packaging binaries on Windows (by Nicholas Silvestrin). 19 | 20 | * Fix "Save As…" menu item to work correctly again. 21 | * Fix bug where no new input cell would be created when evaluating the last one. 22 | 23 | **v2.1.0** — Snapshot release. 24 | 25 | * Upgrade file format to version `0.2.1.0`. 26 | * Add input field for setting the language extensions that are used for interpreting code. 27 | 28 | **v2.0.0** — Snapshot release. 29 | 30 | * Upgrade file format to version `0.2.0.0`. Conversion of old files happens *automatically* when loading them in the application. 31 | * Support different cell types: 32 | 1. 'code' cells -- for source code to be evaluated 33 | 2. 'text' cells -- plain text format 34 | * Compatibility with the [Nix package manager][nix] (by Rodney Lorrimar). 35 | 36 | [nix]: https://nixos.org/nix/ 37 | 38 | **v1.0.0** 39 | 40 | * Initial release. 41 | 42 | ### `hyper-haskell-server` package 43 | 44 | **v0.2.3.1** — Bump dependencies 45 | 46 | **v0.2.3.0** 47 | 48 | * Compatibility with GHC 8.8. 49 | * Remove support for `hyper == 0.1.*`. 50 | 51 | **v0.2.2.0** 52 | 53 | * Add `:type` command for querying type signatures. 54 | * Add support for qualified imports with optional aliases. For example, lines in the "Module imports" field can now have the form `import qualified Data.Map as Map`. [#27][] 55 | 56 | [#27]: https://github.com/HeinrichApfelmus/hyper-haskell/issues/27 57 | 58 | **v0.2.1.0** 59 | 60 | * Add interpretation of `let` statements and generator statements with patterns, `pat <- stmt`. The same syntax as GHC is accepted. 61 | * Add `setExtensions` method to set the language extensions that are used for interpreting code. 62 | * Compatibility with GHC 8.4. 63 | 64 | **v0.2.0.0** 65 | 66 | * Add interpretation of statements of the form `name <- stmt`. This allows us to bind values and functions to names. Here, `stmt` is an IO action with a result. 67 | 68 | **v0.1.0.2** — Bump dependencies for compatibility with GHC 8.2 69 | 70 | **v0.1.0.1** — Bump dependencies. 71 | 72 | **v0.1.0.0** — Initial release. 73 | 74 | ### `hyper-extra` package 75 | 76 | **v0.2.0.1** — Bump dependencies 77 | 78 | **v0.2.0.0** 79 | 80 | * Add preliminary support for the `svg-builder` package. 81 | * Compatibility with GHC 8.8 82 | 83 | **v0.1.1.0** 84 | 85 | * Add preliminary support for the `QuickCheck` package. 86 | 87 | **v0.1.0.3** — Bump dependencies for compatibility with GHC 8.4 88 | 89 | **v0.1.0.2** — Bump dependencies for compatibility with GHC 8.2 90 | 91 | **v0.1.0.1** — Bump dependencies. 92 | 93 | **v0.1.0.0** — Initial release. 94 | 95 | ### `hyper` package 96 | 97 | **v0.2.1.1** — Bump dependencies 98 | 99 | **v0.2.1.0** 100 | 101 | * Add `addFinalizerSession` function that allows running an IO action when the worksheet is reloaded. 102 | * Compatibility with GHC 8.8. 103 | 104 | **v0.2.0.0** 105 | 106 | * Remove `displayIO` class. 107 | * Make `string` wrap its contents in a `
").text(result.errors.join('\n'))) 135 | } 136 | } 137 | 138 | /* ************************************************************* 139 | Global supply of IDs 140 | ************************************************************* */ 141 | let totalSupply = 0; 142 | 143 | const supply = {} 144 | supply.newId = () => { 145 | totalSupply = totalSupply + 1 146 | return ("id-" + totalSupply.toString()) 147 | } 148 | 149 | /* ************************************************************* 150 | Manage a list of cells 151 | ************************************************************* */ 152 | 153 | const NewCells = (parent) => { 154 | let that = {} 155 | let cells = window.newSequence() 156 | 157 | let focus = -1 158 | const currentIsLast = () => { return (focus === cells.length() - 1) } 159 | that.current = () => { return cells.at(focus) } 160 | 161 | // set focus on a particular cell 162 | const setFocus = (index) => { 163 | if (0 <= focus && focus < cells.length()) { 164 | cells.at(focus).focus(false) 165 | } 166 | focus = index 167 | cells.at(focus).focus(true) 168 | } 169 | // update focus if necessary 170 | const updateFocus = (cell) => { 171 | const index = cells.index(cell) 172 | if (focus !== index) { setFocus(index) } 173 | } 174 | 175 | // move the cursor up or down 176 | // return value: the cursor did move 177 | const move = (cell, delta, ch) => { 178 | const index = cells.index(cell) 179 | const index2 = index + delta 180 | // move cursor to a new cell if it exists 181 | if (cells.at(index2)) { 182 | setFocus(index2) 183 | if (delta >= 1) { // from below 184 | cells.at(index2).setCursor({ line: 0, ch: ch }) 185 | } else if (delta <= -1) { // from above 186 | cells.at(index2).setCursor({ line: cells.at(index2).lineCount()-1, ch: ch}) 187 | } 188 | return true 189 | } else { return false } 190 | } 191 | 192 | // Initialize from an array of expressions. 193 | that.setCells = (xs) => { 194 | cells.empty() 195 | focus = -1 196 | parent.empty() 197 | for (let i=0; i0 && xs[xs.length-1]['source'] !== '') { 202 | that.appendCell('code').setValue('') 203 | } 204 | setFocus(0) 205 | } 206 | 207 | // Retrieve the represented expressions. 208 | that.getCells = () => { 209 | let result = [''] 210 | for (let i=0; i 0 && result[i]['source'] === '') { i--; } 219 | result = result.slice(0,i+1) 220 | return result 221 | } 222 | 223 | // Create cells 224 | // Create a new evaluation cell at the end. 225 | that.appendCell = (cell_type) => { 226 | const insertDOM = (el) => { parent.append(el) } 227 | const cell = ( cell_type === 'code' ? 228 | NewEvaluationCell(insertDOM, move) : NewTextCell(insertDOM, move) ) 229 | cell.on('focus', () => { updateFocus(cell) }) 230 | cells.push(cell) 231 | return cell 232 | } 233 | // Create cell and insert before current cell 234 | that.insertBeforeCurrent = (cell_type) => { 235 | if (focus >= 0) { 236 | const insertDOM = (el) => { cells.at(focus).dom().before(el) } 237 | const cell = ( cell_type === 'code' ? 238 | NewEvaluationCell(insertDOM, move) : NewTextCell(insertDOM, move) ) 239 | cell.on('focus', () => { updateFocus(cell) }) 240 | 241 | cells.at(focus).focus(false) 242 | cells.insertBefore(cell, focus) 243 | setFocus(focus) 244 | return cell 245 | } 246 | } 247 | 248 | // Delete the current cell 249 | that.removeCurrent = () => { 250 | if (focus >= 0) { 251 | let index = focus 252 | // remove cell from DOM 253 | cells.at(index).focus(false) 254 | cells.at(index).remove() 255 | cells.remove(index) 256 | 257 | // set new focus 258 | if (index < cells.length() ) { 259 | setFocus(index) 260 | } else { 261 | setFocus(cells.length() - 1) 262 | } 263 | } 264 | } 265 | 266 | // Evaluate the current cell and move the focus to the next one. 267 | that.evaluateCurrent = () => { 268 | if (focus >= 0) { 269 | cells.at(focus).evaluate() 270 | if (currentIsLast()) { that.appendCell('code') } 271 | setFocus(focus + 1) 272 | } 273 | } 274 | 275 | return that 276 | } 277 | 278 | /* ************************************************************* 279 | Text cell 280 | ************************************************************* */ 281 | const NewTextCell = (insertDOM, move) => { 282 | let that = {} 283 | that.cell_type = 'text' 284 | 285 | // create DOM elements 286 | const div = $("") 287 | insertDOM(div) 288 | const div2 = $("") 289 | div2.appendTo(div) 290 | const quill = new Quill(div2.get(0)) 291 | 292 | that.dom = () => { return div } 293 | that.remove = () => { div.detach() } 294 | 295 | that.setValue = (s) => { quill.setText(s) } 296 | that.getValue = () => { return quill.getText() } 297 | that.lineCount = () => { return 1 } 298 | 299 | that.evaluate = () => { } // do nothing 300 | 301 | // signal that the document has been edited 302 | quill.on('text-change', () => { window.electron.setDocumentEdited(true) }) 303 | 304 | // Focus and cursor management 305 | that.on = (event, fun) => { 306 | if (event === 'focus') { 307 | quill.on('selection-change', (range) => { if (range) { fun() } }) 308 | }} 309 | that.setCursor = (cursor) => { 310 | if (cursor.line === 0) { quill.setSelection(0,0) } 311 | if (cursor.line > 0) { quill.setSelection(quill.getLength()-1,0) } 312 | } 313 | that.focus = (bool) => { 314 | // focus or unfocus the cell 315 | div.toggleClass('focus', bool) 316 | if (bool) { quill.getSelection(true) } // looks funny, but this focuses the editor 317 | } 318 | 319 | div.on('keydown', (event) => { 320 | // moving the cursor "out" of the cell will seamlessly move to the next cell 321 | if (event.keyCode === 38 && !event.shiftKey) { // if (up key) { 322 | // hack to find out whether the cursor is at the top of the editor 323 | const atTop = (quill.getBounds(0).top === quill.getBounds(quill.getSelection()).top) 324 | if (atTop) { 325 | quill.setSelection(0) // remove any selection 326 | move(that, -1, 0) 327 | event.preventDefault() 328 | } 329 | } else if (event.keyCode === 40 && !event.shiftKey) { // if (down key) { 330 | const atBottom = (quill.getBounds(quill.getLength()).top === quill.getBounds(quill.getSelection()).top) 331 | if (atBottom) { 332 | if (move(that, 1, 0)) { 333 | quill.setSelection(null) // remove any selection 334 | event.preventDefault() 335 | } 336 | } 337 | }}) 338 | 339 | return that 340 | } 341 | 342 | /* ************************************************************* 343 | Evaluation cell 344 | ************************************************************* */ 345 | const NewEvaluationCell = (insertDOM, move) => { 346 | let that = {} 347 | that.cell_type = 'code' 348 | 349 | // create DOM elements and CodeMirror editor 350 | const div = $("") 351 | insertDOM(div) 352 | const cm = CodeMirror( (el) => { $(el).appendTo(div) } ) 353 | cm.setOption('indentUnit', 4) 354 | cm.setOption('extraKeys', { Tab: betterTab }) 355 | const out = $("") 356 | out.appendTo(div) 357 | 358 | that.dom = () => { return div } // return associated DOM element 359 | that.remove = () => { div.detach() } 360 | 361 | that.setValue = (s) => { cm.getDoc().setValue(s) } 362 | that.getValue = () => { return cm.getDoc().getValue() } 363 | that.lineCount = () => { return cm.getDoc().lineCount() } 364 | 365 | that.evaluate = () => { 366 | // evaluate the cell 367 | div.addClass('evaluating') 368 | out.empty() 369 | out.show() 370 | interpreter.eval(cm.getDoc().getValue(), (result) => { 371 | div.removeClass('evaluating') 372 | formatResult(out, result) 373 | }) 374 | } 375 | 376 | // signal that the document has been edited 377 | cm.on('changes', () => { window.electron.setDocumentEdited(true) }) 378 | 379 | // Focus and cursor management 380 | that.on = (event, fun) => { 381 | if (event === 'focus') { cm.on('focus', fun) } 382 | } 383 | that.setCursor = (x) => { cm.getDoc().setCursor(x) } 384 | that.focus = (bool) => { 385 | div.toggleClass('focus', bool) 386 | if (bool) { cm.focus() } 387 | } 388 | 389 | cm.on('keydown', (instance, event) => { 390 | // moving the cursor "out" of the cell will seamlessly move to the next cell 391 | let doc = cm.getDoc() 392 | let ch = doc.getCursor().ch 393 | if (event.keyCode === 38 && !event.shiftKey) { // if(up key) { 394 | if (doc.getCursor().line <= 0) { 395 | doc.setCursor(0,0) // remove any selection 396 | move(that, -1, ch) 397 | event.preventDefault() 398 | } 399 | } else if (event.keyCode === 40 && !event.shiftKey) { // if(down key) { 400 | if (doc.getCursor().line + 1 >= doc.lineCount()) { 401 | if (move(that, 1, ch)) { 402 | doc.setCursor(0,0) // remove any selection 403 | event.preventDefault() 404 | } 405 | } 406 | }}) 407 | 408 | return that 409 | } 410 | 411 | 412 | /* ************************************************************* 413 | CodeMirror 414 | ************************************************************* */ 415 | const betterTab = (cm) => { 416 | if (cm.somethingSelected()) { 417 | cm.indentSelection('add') 418 | } else { 419 | cm.execCommand('insertSoftTab') 420 | } 421 | } 422 | -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Nikita Prokopov http://tonsky.me 2 | with Reserved Font Name Fira Code 3 | Website: https://github.com/tonsky/FiraCode 4 | 5 | Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ 6 | with Reserved Font Name Fira Sans. 7 | 8 | Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ 9 | with Reserved Font Name Fira Mono. 10 | 11 | Copyright (c) 2014, Telefonica S.A. 12 | 13 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 14 | This license is copied below, and is also available with a FAQ at: 15 | http://scripts.sil.org/OFL 16 | 17 | 18 | ----------------------------------------------------------- 19 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 20 | ----------------------------------------------------------- 21 | 22 | PREAMBLE 23 | The goals of the Open Font License (OFL) are to stimulate worldwide 24 | development of collaborative font projects, to support the font creation 25 | efforts of academic and linguistic communities, and to provide a free and 26 | open framework in which fonts may be shared and improved in partnership 27 | with others. 28 | 29 | The OFL allows the licensed fonts to be used, studied, modified and 30 | redistributed freely as long as they are not sold by themselves. The 31 | fonts, including any derivative works, can be bundled, embedded, 32 | redistributed and/or sold with any software provided that any reserved 33 | names are not used by derivative works. The fonts and derivatives, 34 | however, cannot be released under any other type of license. The 35 | requirement for fonts to remain under this license does not apply 36 | to any document created using the fonts or their derivatives. 37 | 38 | DEFINITIONS 39 | "Font Software" refers to the set of files released by the Copyright 40 | Holder(s) under this license and clearly marked as such. This may 41 | include source files, build scripts and documentation. 42 | 43 | "Reserved Font Name" refers to any names specified as such after the 44 | copyright statement(s). 45 | 46 | "Original Version" refers to the collection of Font Software components as 47 | distributed by the Copyright Holder(s). 48 | 49 | "Modified Version" refers to any derivative made by adding to, deleting, 50 | or substituting -- in part or in whole -- any of the components of the 51 | Original Version, by changing formats or by porting the Font Software to a 52 | new environment. 53 | 54 | "Author" refers to any designer, engineer, programmer, technical 55 | writer or other person who contributed to the Font Software. 56 | 57 | PERMISSION & CONDITIONS 58 | Permission is hereby granted, free of charge, to any person obtaining 59 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 60 | redistribute, and sell modified and unmodified copies of the Font 61 | Software, subject to the following conditions: 62 | 63 | 1) Neither the Font Software nor any of its individual components, 64 | in Original or Modified Versions, may be sold by itself. 65 | 66 | 2) Original or Modified Versions of the Font Software may be bundled, 67 | redistributed and/or sold with any software, provided that each copy 68 | contains the above copyright notice and this license. These can be 69 | included either as stand-alone text files, human-readable headers or 70 | in the appropriate machine-readable metadata fields within text or 71 | binary files as long as those fields can be easily viewed by the user. 72 | 73 | 3) No Modified Version of the Font Software may use the Reserved Font 74 | Name(s) unless explicit written permission is granted by the corresponding 75 | Copyright Holder. This restriction only applies to the primary font name as 76 | presented to the users. 77 | 78 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 79 | Software shall not be used to promote, endorse or advertise any 80 | Modified Version, except to acknowledge the contribution(s) of the 81 | Copyright Holder(s) and the Author(s) or with their explicit written 82 | permission. 83 | 84 | 5) The Font Software, modified or unmodified, in part or in whole, 85 | must be distributed entirely under this license, and must not be 86 | distributed under any other license. The requirement for fonts to 87 | remain under this license does not apply to any document created 88 | using the Font Software. 89 | 90 | TERMINATION 91 | This license becomes null and void if any of the above conditions are 92 | not met. 93 | 94 | DISCLAIMER 95 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 96 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 97 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 98 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 99 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 100 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 101 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 102 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 103 | OTHER DEALINGS IN THE FONT SOFTWARE. 104 | -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/eot/FiraCode-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/eot/FiraCode-Bold.eot -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/eot/FiraCode-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/eot/FiraCode-Light.eot -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/eot/FiraCode-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/eot/FiraCode-Medium.eot -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/eot/FiraCode-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/eot/FiraCode-Regular.eot -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/fira_code.css: -------------------------------------------------------------------------------- 1 | @font-face{ 2 | font-family: 'Fira Code'; 3 | src: url('eot/FiraCode-Light.eot'); 4 | src: url('eot/FiraCode-Light.eot') format('embedded-opentype'), 5 | url('woff2/FiraCode-Light.woff2') format('woff2'), 6 | url('woff/FiraCode-Light.woff') format('woff'), 7 | url('ttf/FiraCode-Light.ttf') format('truetype'); 8 | font-weight: 300; 9 | font-style: normal; 10 | } 11 | 12 | @font-face{ 13 | font-family: 'Fira Code'; 14 | src: url('eot/FiraCode-Regular.eot'); 15 | src: url('eot/FiraCode-Regular.eot') format('embedded-opentype'), 16 | url('woff2/FiraCode-Regular.woff2') format('woff2'), 17 | url('woff/FiraCode-Regular.woff') format('woff'), 18 | url('ttf/FiraCode-Regular.ttf') format('truetype'); 19 | font-weight: 400; 20 | font-style: normal; 21 | } 22 | 23 | @font-face{ 24 | font-family: 'Fira Code'; 25 | src: url('eot/FiraCode-Medium.eot'); 26 | src: url('eot/FiraCode-Medium.eot') format('embedded-opentype'), 27 | url('woff2/FiraCode-Medium.woff2') format('woff2'), 28 | url('woff/FiraCode-Medium.woff') format('woff'), 29 | url('ttf/FiraCode-Medium.ttf') format('truetype'); 30 | font-weight: 500; 31 | font-style: normal; 32 | } 33 | 34 | @font-face{ 35 | font-family: 'Fira Code'; 36 | src: url('eot/FiraCode-Bold.eot'); 37 | src: url('eot/FiraCode-Bold.eot') format('embedded-opentype'), 38 | url('woff2/FiraCode-Bold.woff2') format('woff2'), 39 | url('woff/FiraCode-Bold.woff') format('woff'), 40 | url('ttf/FiraCode-Bold.ttf') format('truetype'); 41 | font-weight: 700; 42 | font-style: normal; 43 | } -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/otf/FiraCode-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/otf/FiraCode-Bold.otf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/otf/FiraCode-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/otf/FiraCode-Light.otf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/otf/FiraCode-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/otf/FiraCode-Medium.otf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/otf/FiraCode-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/otf/FiraCode-Regular.otf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/otf/FiraCode-Retina.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/otf/FiraCode-Retina.otf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/specimen.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Fira Code Specimen 7 | 8 | 9 | 26 | 27 | 28 |# Fira Code Light 29 | 30 | take = (n, [x, ...xs]:list) --> 31 | | n <= 0 => [] 32 | | empty list => [] 33 | | otherwise => [x] ++ take n-1, xs 34 | 35 | last3 = reverse >> take 3 >> reverse36 | 37 | 38 |# Fira Code Regular 39 | 40 | take = (n, [x, ...xs]:list) --> 41 | | n <= 0 => [] 42 | | empty list => [] 43 | | otherwise => [x] ++ take n-1, xs 44 | 45 | last3 = reverse >> take 3 >> reverse46 | 47 | 48 |# Fira Code Medium 49 | 50 | take = (n, [x, ...xs]:list) --> 51 | | n <= 0 => [] 52 | | empty list => [] 53 | | otherwise => [x] ++ take n-1, xs 54 | 55 | last3 = reverse >> take 3 >> reverse56 | 57 | 58 |# Fira Code Bold 59 | 60 | take = (n, [x, ...xs]:list) --> 61 | | n <= 0 => [] 62 | | empty list => [] 63 | | otherwise => [x] ++ take n-1, xs 64 | 65 | last3 = reverse >> take 3 >> reverse66 | -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/ttf/FiraCode-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/ttf/FiraCode-Bold.ttf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/ttf/FiraCode-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/ttf/FiraCode-Light.ttf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/ttf/FiraCode-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/ttf/FiraCode-Medium.ttf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/ttf/FiraCode-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/ttf/FiraCode-Regular.ttf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/ttf/FiraCode-Retina.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/ttf/FiraCode-Retina.ttf -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/woff/FiraCode-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/woff/FiraCode-Bold.woff -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/woff/FiraCode-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/woff/FiraCode-Light.woff -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/woff/FiraCode-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/woff/FiraCode-Medium.woff -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/woff/FiraCode-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/woff/FiraCode-Regular.woff -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/woff2/FiraCode-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/woff2/FiraCode-Bold.woff2 -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/woff2/FiraCode-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/woff2/FiraCode-Light.woff2 -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/woff2/FiraCode-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/woff2/FiraCode-Medium.woff2 -------------------------------------------------------------------------------- /app/vendor/FiraCode_1.203/woff2/FiraCode-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/app/vendor/FiraCode_1.203/woff2/FiraCode-Regular.woff2 -------------------------------------------------------------------------------- /app/vendor/codemirror-5.6.css: -------------------------------------------------------------------------------- 1 | /* 2 | License: https://codemirror.net/LICENSE 3 | */ 4 | 5 | /* BASICS */ 6 | 7 | .CodeMirror { 8 | /* Set height, width, borders, and global font properties here */ 9 | font-family: monospace; 10 | height: 300px; 11 | color: black; 12 | } 13 | 14 | /* PADDING */ 15 | 16 | .CodeMirror-lines { 17 | padding: 4px 0; /* Vertical padding around content */ 18 | } 19 | .CodeMirror pre { 20 | padding: 0 4px; /* Horizontal padding of content */ 21 | } 22 | 23 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 24 | background-color: white; /* The little square between H and V scrollbars */ 25 | } 26 | 27 | /* GUTTER */ 28 | 29 | .CodeMirror-gutters { 30 | border-right: 1px solid #ddd; 31 | background-color: #f7f7f7; 32 | white-space: nowrap; 33 | } 34 | .CodeMirror-linenumbers {} 35 | .CodeMirror-linenumber { 36 | padding: 0 3px 0 5px; 37 | min-width: 20px; 38 | text-align: right; 39 | color: #999; 40 | white-space: nowrap; 41 | } 42 | 43 | .CodeMirror-guttermarker { color: black; } 44 | .CodeMirror-guttermarker-subtle { color: #999; } 45 | 46 | /* CURSOR */ 47 | 48 | .CodeMirror-cursor { 49 | border-left: 1px solid black; 50 | border-right: none; 51 | width: 0; 52 | } 53 | /* Shown when moving in bi-directional text */ 54 | .CodeMirror div.CodeMirror-secondarycursor { 55 | border-left: 1px solid silver; 56 | } 57 | .cm-fat-cursor .CodeMirror-cursor { 58 | width: auto; 59 | border: 0; 60 | background: #7e7; 61 | } 62 | .cm-fat-cursor div.CodeMirror-cursors { 63 | z-index: 1; 64 | } 65 | 66 | .cm-animate-fat-cursor { 67 | width: auto; 68 | border: 0; 69 | -webkit-animation: blink 1.06s steps(1) infinite; 70 | -moz-animation: blink 1.06s steps(1) infinite; 71 | animation: blink 1.06s steps(1) infinite; 72 | background-color: #7e7; 73 | } 74 | @-moz-keyframes blink { 75 | 0% {} 76 | 50% { background-color: transparent; } 77 | 100% {} 78 | } 79 | @-webkit-keyframes blink { 80 | 0% {} 81 | 50% { background-color: transparent; } 82 | 100% {} 83 | } 84 | @keyframes blink { 85 | 0% {} 86 | 50% { background-color: transparent; } 87 | 100% {} 88 | } 89 | 90 | /* Can style cursor different in overwrite (non-insert) mode */ 91 | .CodeMirror-overwrite .CodeMirror-cursor {} 92 | 93 | .cm-tab { display: inline-block; text-decoration: inherit; } 94 | 95 | .CodeMirror-ruler { 96 | border-left: 1px solid #ccc; 97 | position: absolute; 98 | } 99 | 100 | /* DEFAULT THEME */ 101 | 102 | .cm-s-default .cm-header {color: blue;} 103 | .cm-s-default .cm-quote {color: #090;} 104 | .cm-negative {color: #d44;} 105 | .cm-positive {color: #292;} 106 | .cm-header, .cm-strong {font-weight: bold;} 107 | .cm-em {font-style: italic;} 108 | .cm-link {text-decoration: underline;} 109 | .cm-strikethrough {text-decoration: line-through;} 110 | 111 | .cm-s-default .cm-keyword {color: #708;} 112 | .cm-s-default .cm-atom {color: #219;} 113 | .cm-s-default .cm-number {color: #164;} 114 | .cm-s-default .cm-def {color: #00f;} 115 | .cm-s-default .cm-variable, 116 | .cm-s-default .cm-punctuation, 117 | .cm-s-default .cm-property, 118 | .cm-s-default .cm-operator {} 119 | .cm-s-default .cm-variable-2 {color: #05a;} 120 | .cm-s-default .cm-variable-3 {color: #085;} 121 | .cm-s-default .cm-comment {color: #a50;} 122 | .cm-s-default .cm-string {color: #a11;} 123 | .cm-s-default .cm-string-2 {color: #f50;} 124 | .cm-s-default .cm-meta {color: #555;} 125 | .cm-s-default .cm-qualifier {color: #555;} 126 | .cm-s-default .cm-builtin {color: #30a;} 127 | .cm-s-default .cm-bracket {color: #997;} 128 | .cm-s-default .cm-tag {color: #170;} 129 | .cm-s-default .cm-attribute {color: #00c;} 130 | .cm-s-default .cm-hr {color: #999;} 131 | .cm-s-default .cm-link {color: #00c;} 132 | 133 | .cm-s-default .cm-error {color: #f00;} 134 | .cm-invalidchar {color: #f00;} 135 | 136 | .CodeMirror-composing { border-bottom: 2px solid; } 137 | 138 | /* Default styles for common addons */ 139 | 140 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} 141 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} 142 | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } 143 | .CodeMirror-activeline-background {background: #e8f2ff;} 144 | 145 | /* STOP */ 146 | 147 | /* The rest of this file contains styles related to the mechanics of 148 | the editor. You probably shouldn't touch them. */ 149 | 150 | .CodeMirror { 151 | position: relative; 152 | overflow: hidden; 153 | background: white; 154 | } 155 | 156 | .CodeMirror-scroll { 157 | overflow: scroll !important; /* Things will break if this is overridden */ 158 | /* 30px is the magic margin used to hide the element's real scrollbars */ 159 | /* See overflow: hidden in .CodeMirror */ 160 | margin-bottom: -30px; margin-right: -30px; 161 | padding-bottom: 30px; 162 | height: 100%; 163 | outline: none; /* Prevent dragging from highlighting the element */ 164 | position: relative; 165 | } 166 | .CodeMirror-sizer { 167 | position: relative; 168 | border-right: 30px solid transparent; 169 | } 170 | 171 | /* The fake, visible scrollbars. Used to force redraw during scrolling 172 | before actuall scrolling happens, thus preventing shaking and 173 | flickering artifacts. */ 174 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 175 | position: absolute; 176 | z-index: 6; 177 | display: none; 178 | } 179 | .CodeMirror-vscrollbar { 180 | right: 0; top: 0; 181 | overflow-x: hidden; 182 | overflow-y: scroll; 183 | } 184 | .CodeMirror-hscrollbar { 185 | bottom: 0; left: 0; 186 | overflow-y: hidden; 187 | overflow-x: scroll; 188 | } 189 | .CodeMirror-scrollbar-filler { 190 | right: 0; bottom: 0; 191 | } 192 | .CodeMirror-gutter-filler { 193 | left: 0; bottom: 0; 194 | } 195 | 196 | .CodeMirror-gutters { 197 | position: absolute; left: 0; top: 0; 198 | z-index: 3; 199 | } 200 | .CodeMirror-gutter { 201 | white-space: normal; 202 | height: 100%; 203 | display: inline-block; 204 | margin-bottom: -30px; 205 | /* Hack to make IE7 behave */ 206 | *zoom:1; 207 | *display:inline; 208 | } 209 | .CodeMirror-gutter-wrapper { 210 | position: absolute; 211 | z-index: 4; 212 | background: none !important; 213 | border: none !important; 214 | } 215 | .CodeMirror-gutter-background { 216 | position: absolute; 217 | top: 0; bottom: 0; 218 | z-index: 4; 219 | } 220 | .CodeMirror-gutter-elt { 221 | position: absolute; 222 | cursor: default; 223 | z-index: 4; 224 | } 225 | .CodeMirror-gutter-wrapper { 226 | -webkit-user-select: none; 227 | -moz-user-select: none; 228 | user-select: none; 229 | } 230 | 231 | .CodeMirror-lines { 232 | cursor: text; 233 | min-height: 1px; /* prevents collapsing before first draw */ 234 | } 235 | .CodeMirror pre { 236 | /* Reset some styles that the rest of the page might have set */ 237 | -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; 238 | border-width: 0; 239 | background: transparent; 240 | font-family: inherit; 241 | font-size: inherit; 242 | margin: 0; 243 | white-space: pre; 244 | word-wrap: normal; 245 | line-height: inherit; 246 | color: inherit; 247 | z-index: 2; 248 | position: relative; 249 | overflow: visible; 250 | -webkit-tap-highlight-color: transparent; 251 | } 252 | .CodeMirror-wrap pre { 253 | word-wrap: break-word; 254 | white-space: pre-wrap; 255 | word-break: normal; 256 | } 257 | 258 | .CodeMirror-linebackground { 259 | position: absolute; 260 | left: 0; right: 0; top: 0; bottom: 0; 261 | z-index: 0; 262 | } 263 | 264 | .CodeMirror-linewidget { 265 | position: relative; 266 | z-index: 2; 267 | overflow: auto; 268 | } 269 | 270 | .CodeMirror-widget {} 271 | 272 | .CodeMirror-code { 273 | outline: none; 274 | } 275 | 276 | /* Force content-box sizing for the elements where we expect it */ 277 | .CodeMirror-scroll, 278 | .CodeMirror-sizer, 279 | .CodeMirror-gutter, 280 | .CodeMirror-gutters, 281 | .CodeMirror-linenumber { 282 | -moz-box-sizing: content-box; 283 | box-sizing: content-box; 284 | } 285 | 286 | .CodeMirror-measure { 287 | position: absolute; 288 | width: 100%; 289 | height: 0; 290 | overflow: hidden; 291 | visibility: hidden; 292 | } 293 | 294 | .CodeMirror-cursor { position: absolute; } 295 | .CodeMirror-measure pre { position: static; } 296 | 297 | div.CodeMirror-cursors { 298 | visibility: hidden; 299 | position: relative; 300 | z-index: 3; 301 | } 302 | div.CodeMirror-dragcursors { 303 | visibility: visible; 304 | } 305 | 306 | .CodeMirror-focused div.CodeMirror-cursors { 307 | visibility: visible; 308 | } 309 | 310 | .CodeMirror-selected { background: #d9d9d9; } 311 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } 312 | .CodeMirror-crosshair { cursor: crosshair; } 313 | .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } 314 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } 315 | 316 | .cm-searching { 317 | background: #ffa; 318 | background: rgba(255, 255, 0, .4); 319 | } 320 | 321 | /* IE7 hack to prevent it from returning funny offsetTops on the spans */ 322 | .CodeMirror span { *vertical-align: text-bottom; } 323 | 324 | /* Used to force a border model for a node */ 325 | .cm-force-border { padding-right: .1px; } 326 | 327 | @media print { 328 | /* Hide the cursor when printing */ 329 | .CodeMirror div.CodeMirror-cursors { 330 | visibility: hidden; 331 | } 332 | } 333 | 334 | /* See issue #2901 */ 335 | .cm-tab-wrap-hack:after { content: ''; } 336 | 337 | /* Help users use markselection to safely style text background */ 338 | span.CodeMirror-selectedtext { background: none; } 339 | -------------------------------------------------------------------------------- /app/vendor/quill-1.1.0.core.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Quill Editor v1.1.0 3 | * https://quilljs.com/ 4 | * Copyright (c) 2014, Jason Chen 5 | * Copyright (c) 2013, salesforce.com 6 | 7 | * License: https://github.com/quilljs/quill/blob/v1.1.0/LICENSE 8 | 9 | */ 10 | .ql-container { 11 | box-sizing: border-box; 12 | font-family: Helvetica, Arial, sans-serif; 13 | font-size: 13px; 14 | height: 100%; 15 | margin: 0px; 16 | position: relative; 17 | } 18 | .ql-container.ql-disabled .ql-tooltip { 19 | visibility: hidden; 20 | } 21 | .ql-clipboard { 22 | left: -100000px; 23 | height: 1px; 24 | overflow-y: hidden; 25 | position: absolute; 26 | top: 50%; 27 | } 28 | .ql-clipboard p { 29 | margin: 0; 30 | padding: 0; 31 | } 32 | .ql-editor { 33 | box-sizing: border-box; 34 | cursor: text; 35 | line-height: 1.42; 36 | height: 100%; 37 | outline: none; 38 | overflow-y: auto; 39 | padding: 12px 15px; 40 | tab-size: 4; 41 | -moz-tab-size: 4; 42 | text-align: left; 43 | white-space: pre-wrap; 44 | word-wrap: break-word; 45 | } 46 | .ql-editor p, 47 | .ql-editor ol, 48 | .ql-editor ul, 49 | .ql-editor pre, 50 | .ql-editor blockquote, 51 | .ql-editor h1, 52 | .ql-editor h2, 53 | .ql-editor h3, 54 | .ql-editor h4, 55 | .ql-editor h5, 56 | .ql-editor h6 { 57 | margin: 0; 58 | padding: 0; 59 | counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 60 | } 61 | .ql-editor ol, 62 | .ql-editor ul { 63 | padding-left: 1.5em; 64 | } 65 | .ql-editor ol > li, 66 | .ql-editor ul > li { 67 | list-style-type: none; 68 | } 69 | .ql-editor ul > li::before { 70 | content: '\25CF'; 71 | } 72 | .ql-editor li::before { 73 | display: inline-block; 74 | margin-right: 0.3em; 75 | text-align: right; 76 | white-space: nowrap; 77 | width: 1.2em; 78 | } 79 | .ql-editor li:not(.ql-direction-rtl)::before { 80 | margin-left: -1.5em; 81 | } 82 | .ql-editor ol li, 83 | .ql-editor ul li { 84 | padding-left: 1.5em; 85 | } 86 | .ql-editor ol li { 87 | counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 88 | counter-increment: list-num; 89 | } 90 | .ql-editor ol li:before { 91 | content: counter(list-num, decimal) '. '; 92 | } 93 | .ql-editor ol li.ql-indent-1 { 94 | counter-increment: list-1; 95 | } 96 | .ql-editor ol li.ql-indent-1:before { 97 | content: counter(list-1, lower-alpha) '. '; 98 | } 99 | .ql-editor ol li.ql-indent-1 { 100 | counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 101 | } 102 | .ql-editor ol li.ql-indent-2 { 103 | counter-increment: list-2; 104 | } 105 | .ql-editor ol li.ql-indent-2:before { 106 | content: counter(list-2, lower-roman) '. '; 107 | } 108 | .ql-editor ol li.ql-indent-2 { 109 | counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; 110 | } 111 | .ql-editor ol li.ql-indent-3 { 112 | counter-increment: list-3; 113 | } 114 | .ql-editor ol li.ql-indent-3:before { 115 | content: counter(list-3, decimal) '. '; 116 | } 117 | .ql-editor ol li.ql-indent-3 { 118 | counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; 119 | } 120 | .ql-editor ol li.ql-indent-4 { 121 | counter-increment: list-4; 122 | } 123 | .ql-editor ol li.ql-indent-4:before { 124 | content: counter(list-4, lower-alpha) '. '; 125 | } 126 | .ql-editor ol li.ql-indent-4 { 127 | counter-reset: list-5 list-6 list-7 list-8 list-9; 128 | } 129 | .ql-editor ol li.ql-indent-5 { 130 | counter-increment: list-5; 131 | } 132 | .ql-editor ol li.ql-indent-5:before { 133 | content: counter(list-5, lower-roman) '. '; 134 | } 135 | .ql-editor ol li.ql-indent-5 { 136 | counter-reset: list-6 list-7 list-8 list-9; 137 | } 138 | .ql-editor ol li.ql-indent-6 { 139 | counter-increment: list-6; 140 | } 141 | .ql-editor ol li.ql-indent-6:before { 142 | content: counter(list-6, decimal) '. '; 143 | } 144 | .ql-editor ol li.ql-indent-6 { 145 | counter-reset: list-7 list-8 list-9; 146 | } 147 | .ql-editor ol li.ql-indent-7 { 148 | counter-increment: list-7; 149 | } 150 | .ql-editor ol li.ql-indent-7:before { 151 | content: counter(list-7, lower-alpha) '. '; 152 | } 153 | .ql-editor ol li.ql-indent-7 { 154 | counter-reset: list-8 list-9; 155 | } 156 | .ql-editor ol li.ql-indent-8 { 157 | counter-increment: list-8; 158 | } 159 | .ql-editor ol li.ql-indent-8:before { 160 | content: counter(list-8, lower-roman) '. '; 161 | } 162 | .ql-editor ol li.ql-indent-8 { 163 | counter-reset: list-9; 164 | } 165 | .ql-editor ol li.ql-indent-9 { 166 | counter-increment: list-9; 167 | } 168 | .ql-editor ol li.ql-indent-9:before { 169 | content: counter(list-9, decimal) '. '; 170 | } 171 | .ql-editor .ql-indent-1:not(.ql-direction-rtl) { 172 | padding-left: 3em; 173 | } 174 | .ql-editor li.ql-indent-1:not(.ql-direction-rtl) { 175 | padding-left: 4.5em; 176 | } 177 | .ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { 178 | padding-right: 3em; 179 | } 180 | .ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { 181 | padding-right: 4.5em; 182 | } 183 | .ql-editor .ql-indent-2:not(.ql-direction-rtl) { 184 | padding-left: 6em; 185 | } 186 | .ql-editor li.ql-indent-2:not(.ql-direction-rtl) { 187 | padding-left: 7.5em; 188 | } 189 | .ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { 190 | padding-right: 6em; 191 | } 192 | .ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { 193 | padding-right: 7.5em; 194 | } 195 | .ql-editor .ql-indent-3:not(.ql-direction-rtl) { 196 | padding-left: 9em; 197 | } 198 | .ql-editor li.ql-indent-3:not(.ql-direction-rtl) { 199 | padding-left: 10.5em; 200 | } 201 | .ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { 202 | padding-right: 9em; 203 | } 204 | .ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { 205 | padding-right: 10.5em; 206 | } 207 | .ql-editor .ql-indent-4:not(.ql-direction-rtl) { 208 | padding-left: 12em; 209 | } 210 | .ql-editor li.ql-indent-4:not(.ql-direction-rtl) { 211 | padding-left: 13.5em; 212 | } 213 | .ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { 214 | padding-right: 12em; 215 | } 216 | .ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { 217 | padding-right: 13.5em; 218 | } 219 | .ql-editor .ql-indent-5:not(.ql-direction-rtl) { 220 | padding-left: 15em; 221 | } 222 | .ql-editor li.ql-indent-5:not(.ql-direction-rtl) { 223 | padding-left: 16.5em; 224 | } 225 | .ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { 226 | padding-right: 15em; 227 | } 228 | .ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { 229 | padding-right: 16.5em; 230 | } 231 | .ql-editor .ql-indent-6:not(.ql-direction-rtl) { 232 | padding-left: 18em; 233 | } 234 | .ql-editor li.ql-indent-6:not(.ql-direction-rtl) { 235 | padding-left: 19.5em; 236 | } 237 | .ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { 238 | padding-right: 18em; 239 | } 240 | .ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { 241 | padding-right: 19.5em; 242 | } 243 | .ql-editor .ql-indent-7:not(.ql-direction-rtl) { 244 | padding-left: 21em; 245 | } 246 | .ql-editor li.ql-indent-7:not(.ql-direction-rtl) { 247 | padding-left: 22.5em; 248 | } 249 | .ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { 250 | padding-right: 21em; 251 | } 252 | .ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { 253 | padding-right: 22.5em; 254 | } 255 | .ql-editor .ql-indent-8:not(.ql-direction-rtl) { 256 | padding-left: 24em; 257 | } 258 | .ql-editor li.ql-indent-8:not(.ql-direction-rtl) { 259 | padding-left: 25.5em; 260 | } 261 | .ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { 262 | padding-right: 24em; 263 | } 264 | .ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { 265 | padding-right: 25.5em; 266 | } 267 | .ql-editor .ql-indent-9:not(.ql-direction-rtl) { 268 | padding-left: 27em; 269 | } 270 | .ql-editor li.ql-indent-9:not(.ql-direction-rtl) { 271 | padding-left: 28.5em; 272 | } 273 | .ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { 274 | padding-right: 27em; 275 | } 276 | .ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { 277 | padding-right: 28.5em; 278 | } 279 | .ql-editor .ql-video { 280 | display: block; 281 | max-width: 100%; 282 | } 283 | .ql-editor .ql-video.ql-align-center { 284 | margin: 0 auto; 285 | } 286 | .ql-editor .ql-video.ql-align-right { 287 | margin: 0 0 0 auto; 288 | } 289 | .ql-editor .ql-bg-black { 290 | background-color: #000; 291 | } 292 | .ql-editor .ql-bg-red { 293 | background-color: #e60000; 294 | } 295 | .ql-editor .ql-bg-orange { 296 | background-color: #f90; 297 | } 298 | .ql-editor .ql-bg-yellow { 299 | background-color: #ff0; 300 | } 301 | .ql-editor .ql-bg-green { 302 | background-color: #008a00; 303 | } 304 | .ql-editor .ql-bg-blue { 305 | background-color: #06c; 306 | } 307 | .ql-editor .ql-bg-purple { 308 | background-color: #93f; 309 | } 310 | .ql-editor .ql-color-white { 311 | color: #fff; 312 | } 313 | .ql-editor .ql-color-red { 314 | color: #e60000; 315 | } 316 | .ql-editor .ql-color-orange { 317 | color: #f90; 318 | } 319 | .ql-editor .ql-color-yellow { 320 | color: #ff0; 321 | } 322 | .ql-editor .ql-color-green { 323 | color: #008a00; 324 | } 325 | .ql-editor .ql-color-blue { 326 | color: #06c; 327 | } 328 | .ql-editor .ql-color-purple { 329 | color: #93f; 330 | } 331 | .ql-editor .ql-font-serif { 332 | font-family: Georgia, Times New Roman, serif; 333 | } 334 | .ql-editor .ql-font-monospace { 335 | font-family: Monaco, Courier New, monospace; 336 | } 337 | .ql-editor .ql-size-small { 338 | font-size: 0.75em; 339 | } 340 | .ql-editor .ql-size-large { 341 | font-size: 1.5em; 342 | } 343 | .ql-editor .ql-size-huge { 344 | font-size: 2.5em; 345 | } 346 | .ql-editor .ql-direction-rtl { 347 | direction: rtl; 348 | text-align: inherit; 349 | } 350 | .ql-editor .ql-align-center { 351 | text-align: center; 352 | } 353 | .ql-editor .ql-align-justify { 354 | text-align: justify; 355 | } 356 | .ql-editor .ql-align-right { 357 | text-align: right; 358 | } 359 | .ql-editor.ql-blank::before { 360 | color: rgba(0,0,0,0.6); 361 | content: attr(data-placeholder); 362 | font-style: italic; 363 | pointer-events: none; 364 | position: absolute; 365 | } 366 | -------------------------------------------------------------------------------- /app/worksheet.css: -------------------------------------------------------------------------------- 1 | /* ************************************************************* 2 | General layout 3 | ************************************************************* */ 4 | h1 { 5 | margin-left: 1em; 6 | margin-top: 2ex; 7 | } 8 | .section { 9 | position:relative; 10 | margin-left: 2em; 11 | margin-right: 1em; 12 | } 13 | 14 | h1.closed:before { content: "▸ "; } 15 | h1:before { content: "▾ "; } 16 | 17 | h1 { 18 | font-size:110%; 19 | font-weight:bold; 20 | } 21 | 22 | label { display: inline-block; } 23 | form.table label { width:10em; } 24 | input { 25 | width:20em; 26 | } 27 | 28 | /* ************************************************************* 29 | General editing 30 | ************************************************************* */ 31 | div.CodeMirror { 32 | height: auto; 33 | background: #eee; 34 | padding: 0.7ex; 35 | line-height: 1.3; 36 | } 37 | 38 | pre, div.CodeMirror { 39 | font-family: "Fira Code"; 40 | font-size: 95%; 41 | } 42 | 43 | .ql-container { 44 | font-family: "Helvetica"; 45 | font-size: 100%; 46 | min-height: 2em; 47 | } 48 | 49 | /* ************************************************************* 50 | Text and Evaluation Cells 51 | ************************************************************* */ 52 | .cell .out { 53 | display:none; 54 | margin-top: 1ex; 55 | padding: 0.7ex; 56 | } 57 | 58 | .cell { 59 | margin-bottom: 2ex; 60 | } 61 | .cell.eval { 62 | padding: 1ex 1ex 1ex; 63 | } 64 | /* Color coding for focus and evaluation */ 65 | .cell { border-left: 4px solid #ddd; } 66 | .cell.focus { border-left-color: black; } 67 | .cell.evaluating { border-left-color: #f9f; } 68 | .cell.evaluating.focus { border-left-color: #c0c; } 69 | .cell .error { 70 | color:red; 71 | } 72 | -------------------------------------------------------------------------------- /app/worksheet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |25 |73 | 74 | 75 | -------------------------------------------------------------------------------- /cabal.project: -------------------------------------------------------------------------------- 1 | packages: 2 | haskell/hyper 3 | haskell/hyper-extra 4 | haskell/hyper-haskell-server 5 | -------------------------------------------------------------------------------- /docs/INSTALL.md: -------------------------------------------------------------------------------- 1 | **work in progress** 2 | 3 |Settings
26 | 46 | 47 |Imports and Options
48 |49 |64 | 65 |50 | 51 |
52 | 53 |
54 | 55 |
56 | 57 |
58 | 59 |
60 | 61 |
62 | Status: 63 |
Worksheet
66 |67 | 68 |72 |69 | 70 |71 |4 | # Installation 5 | 6 | A HyperHaskell installation consists of two parts: 7 | 8 | 1. The graphical front-end. 9 | 10 | Download the application binary for your platform: OS X, (Linux), (Windows) 11 | 12 | 2. The interpreter back-end. 13 | 14 | HyperHaskell requires several Haskell packages to work properly. 15 | In order to not restrict you to outdated package versions, 16 | the front-end asks you choose your own package database. 17 | However, this means that you have to install the interpreter back-end separately. 18 | 19 | If you use [Cabal][]: 20 | 21 | * Install the back-end by executing the command 22 | 23 | cabal update && cabal install hyper-haskell 24 | 25 | * The front-end will, by default, look for this option first. 26 | You only need to start the application and should be ready to go. 27 | 28 | If you use [Stack][]: 29 | 30 | * Make a new `stack.yml` file somewhere 31 | * Use `stack install hyper-haskell` to install the back-end. 32 | * Start the front-end and point it to the `stack.yml` file in the settings. 33 | 34 | [cabal]: https://www.haskell.org/cabal/ 35 | [stack]: https://www.haskellstack.org 36 |37 | -------------------------------------------------------------------------------- /docs/TODO.md: -------------------------------------------------------------------------------- 1 | TODO list 2 | ========= 3 | 4 | Immediate 5 | --------- 6 | 7 | * Level β: 8 | 9 | * Implement a way to evaluate cells concurrently. 10 | We still want to be able to bind variables sequentially. 11 | Using `forkIO` explicitely would do, but then we can't stop it again. 12 | 13 | Maybe a "suspended result"? 14 | 15 | Later 16 | ----- 17 | 18 | * Integrate a viewer for Haddock documentation 19 | 20 | * Integrate a way to query type signatures 21 | 22 | * Maybe implement editor for `.hs` files? The `FiraCode` font is quite beautiful. 23 | 24 | * Switch programming of user interface to some other language / approach. 25 | * sodium.js ? 26 | * threepenny-gui ? 27 | * GHCJS + reactive-banana ? 28 | 29 | * FIXME: Maybe do *not* move the cursor after evaluating a cell? 30 | 31 | * Level γ: 32 | 33 | * Integrate some form of a JavaScript FFI 34 | * Export Haskell functions to JavaScript 35 | * Suspended computations -- display infinite list 36 | 37 | Much later 38 | ---------- 39 | 40 | * Bundle an interpreter back-end with the front-end application. #10 41 | 42 | -------------------------------------------------------------------------------- /docs/hcar/hcar.sty: -------------------------------------------------------------------------------- 1 | \ProvidesPackage{hcar} 2 | 3 | \newif\ifhcarfinal 4 | \hcarfinalfalse 5 | \DeclareOption{final}{\hcarfinaltrue} 6 | \ProcessOptions 7 | 8 | \RequirePackage{keyval} 9 | \RequirePackage{color} 10 | \RequirePackage{array} 11 | 12 | \ifhcarfinal 13 | \RequirePackage[T1]{fontenc} 14 | \RequirePackage{lmodern} 15 | \RequirePackage{tabularx} 16 | \RequirePackage{booktabs} 17 | \RequirePackage{framed} 18 | \RequirePackage[obeyspaces,T1]{url} 19 | \RequirePackage 20 | [bookmarks=true,colorlinks=true, 21 | urlcolor=urlcolor, 22 | linkcolor=linkcolor, 23 | breaklinks=true, 24 | pdftitle={Haskell Communities and Activities Report}]% 25 | {hyperref} 26 | \else 27 | \RequirePackage[obeyspaces]{url} 28 | \fi 29 | \urlstyle{sf} 30 | 31 | \definecolor{urlcolor}{rgb}{0.1,0.3,0} 32 | \definecolor{linkcolor}{rgb}{0.3,0,0} 33 | \definecolor{shadecolor}{rgb}{0.9,0.95,1}%{0.98,1.0,0.95} 34 | \definecolor{framecolor}{gray}{0.9} 35 | \definecolor{oldgray}{gray}{0.7} 36 | 37 | \newcommand{\Contact}{\subsubsection*{Contact}} 38 | \newcommand{\FurtherReading}{\subsubsection*{Further reading}} 39 | \newcommand{\FuturePlans}{\subsubsection*{Future plans}} 40 | \newcommand{\WhatsNew}{\subsubsection*{What is new?}} 41 | 42 | \newcommand{\Separate}{\smallskip\noindent} 43 | \newcommand{\FinalNote}{\smallskip\noindent} 44 | 45 | \newcommand{\urlpart}{\begingroup\urlstyle{sf}\Url} 46 | \newcommand{\email}[1]{\href{mailto:\EMailRepl{#1}{ at }}{$\langle$\urlpart{#1}$\rangle$}} 47 | \newcommand{\cref}[1]{($\rightarrow\,$\ref{#1})} 48 | 49 | \ifhcarfinal 50 | \let\hcarshaded=\shaded 51 | \let\endhcarshaded=\endshaded 52 | \else 53 | \newsavebox{\shadedbox} 54 | \newlength{\shadedboxwidth} 55 | \def\hcarshaded 56 | {\begingroup 57 | \setlength{\shadedboxwidth}{\linewidth}% 58 | \addtolength{\shadedboxwidth}{-2\fboxsep}% 59 | \begin{lrbox}{\shadedbox}% 60 | \begin{minipage}{\shadedboxwidth}\ignorespaces} 61 | \def\endhcarshaded 62 | {\end{minipage}% 63 | \end{lrbox}% 64 | \noindent 65 | \colorbox{shadecolor}{\usebox{\shadedbox}}% 66 | \endgroup} 67 | \fi 68 | 69 | \ifhcarfinal 70 | \newenvironment{hcartabularx} 71 | {\tabularx{\linewidth}{l>{\raggedleft}X}} 72 | {\endtabularx} 73 | \else 74 | \newenvironment{hcartabularx} 75 | {\begin{tabular}{@{}m{.3\linewidth}@{}>{\raggedleft}p{.7\linewidth}@{}}} 76 | {\end{tabular}} 77 | \fi 78 | 79 | \ifhcarfinal 80 | \let\hcartoprule=\toprule 81 | \let\hcarbottomrule=\bottomrule 82 | \else 83 | \let\hcartoprule=\hline 84 | \let\hcarbottomrule=\hline 85 | \fi 86 | 87 | \define@key{hcarentry}{chapter}[]{\let\level\chapter} 88 | \define@key{hcarentry}{section}[]{\let\level\section} 89 | \define@key{hcarentry}{subsection}[]{\let\level\subsection} 90 | \define@key{hcarentry}{subsubsection}[]{\let\level\subsubsection} 91 | \define@key{hcarentry}{level}{\let\level=#1} 92 | %\define@key{hcarentry}{label}{\def\entrylabel{\label{#1}}} 93 | \define@key{hcarentry}{new}[]% 94 | {\let\startnew=\hcarshaded\let\stopnew=\endhcarshaded 95 | \def\startupdated{\let\orig@addv\addvspace\let\addvspace\@gobble}% 96 | \def\stopupdated{\let\addvspace\orig@addv}} 97 | \define@key{hcarentry}{old}[]{\def\normalcolor{\color{oldgray}}\color{oldgray}}% 98 | \define@key{hcarentry}{updated}[]% 99 | {\def\startupdated 100 | {\leavevmode\let\orig@addv\addvspace\let\addvspace\@gobble\hcarshaded}% 101 | \def\stopupdated{\endhcarshaded\let\addvspace\orig@addv}} 102 | 103 | \def\@makeheadererror{\PackageError{hcar}{hcarentry without header}{}} 104 | 105 | \newenvironment{hcarentry}[2][]% 106 | {\let\level\subsection 107 | \let\startupdated=\empty\let\stopupdated=\empty 108 | \let\startnew=\empty\let\stopnew=\empty 109 | %\let\entrylabel=\empty 110 | \global\let\@makeheaderwarning\@makeheadererror 111 | \setkeys{hcarentry}{#1}% 112 | \startnew\startupdated 113 | \level{#2}% 114 | % test: 115 | \global\let\@currentlabel\@currentlabel 116 | %\stopupdated 117 | \let\report@\empty 118 | \let\groupleaders@\empty 119 | \let\members@\empty 120 | \let\contributors@\empty 121 | \let\participants@\empty 122 | \let\developers@\empty 123 | \let\maintainer@\empty 124 | \let\status@\empty 125 | \let\release@\empty 126 | \let\portability@\empty 127 | \let\entry@\empty}% 128 | {\stopnew\@makeheaderwarning}% 129 | 130 | \renewcommand{\labelitemi}{$\circ$} 131 | \settowidth{\leftmargini}{\labelitemi} 132 | \addtolength{\leftmargini}{\labelsep} 133 | 134 | \newcommand*\MakeKey[2]% 135 | {\expandafter\def\csname #1\endcsname##1% 136 | {\expandafter\def\csname #1@\endcsname{\Key@{#2}{##1}}\ignorespaces}} 137 | \MakeKey{report}{Report by:} 138 | \MakeKey{status}{Status:} 139 | \MakeKey{groupleaders}{Group leaders:} 140 | \MakeKey{members}{Members:} 141 | \MakeKey{contributors}{Contributors:} 142 | \MakeKey{participants}{Participants:} 143 | \MakeKey{developers}{Developers:} 144 | \MakeKey{maintainer}{Maintainer:} 145 | \MakeKey{release}{Current release:} 146 | \MakeKey{portability}{Portability:} 147 | \MakeKey{entry}{Entry:} 148 | 149 | \newcommand\Key@[2]{#1 & #2\tabularnewline} 150 | 151 | \newcommand\makeheader 152 | {\smallskip 153 | \begingroup 154 | \sffamily 155 | \small 156 | \noindent 157 | \let\ohrule\hrule 158 | \def\hrule{\color{framecolor}\ohrule}% 159 | \begin{hcartabularx} 160 | \hline 161 | \report@ 162 | \groupleaders@ 163 | \members@ 164 | \participants@ 165 | \developers@ 166 | \contributors@ 167 | \maintainer@ 168 | \status@ 169 | \release@ 170 | \portability@ 171 | \hcarbottomrule 172 | \end{hcartabularx} 173 | \endgroup 174 | \stopupdated 175 | \global\let\@makeheaderwarning\empty 176 | \@afterindentfalse 177 | \@xsect\smallskipamount} 178 | 179 | % columns/linebreaks, interchanged 180 | \newcommand\NCi{&\let\NX\NCii}% 181 | \newcommand\NCii{&\let\NX\NL}% 182 | \newcommand\NL{\\\let\NX\NCi}% 183 | \let\NX\NCi 184 | \newcommand\hcareditor[1]{ (ed.)&\\} 185 | \newcommand\hcarauthor[1]{#1\NX}% 186 | \newcommand\hcareditors[1]{\multicolumn{3}{c}{#1 (eds.)}\\[2ex]} 187 | -------------------------------------------------------------------------------- /docs/hcar/html/worksheet-diagrams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/docs/hcar/html/worksheet-diagrams.png -------------------------------------------------------------------------------- /docs/hcar/hyperhaskell-2016-11.tex: -------------------------------------------------------------------------------- 1 | % hyperhaskell-Hh.tex 2 | \begin{hcarentry}[new]{HyperHaskell -- The strongly hyped Haskell interpreter} 3 | \label{hyper-haskell} 4 | \report{Heinrich Apfelmus}%11/16 5 | \status{available, active development} 6 | \makeheader 7 | 8 | \emph{HyperHaskell} is a graphical Haskell interpreter, not unlike GHCi, 9 | but hopefully more awesome. You use worksheets to enter expressions and 10 | evaluate them. Results are displayed graphically using HTML. 11 | 12 | \emph{HyperHaskell} is intended to be \emph{easy to install}. It is cross-platform and should run on Linux, Mac and Windows. Internally, it uses the GHC API to interpret Haskell programs, and the graphical front-end is built on the Electron framework. \emph{HyperHaskell} is open source. 13 | 14 | \emph{HyperHaskell}'s main attraction is a \verb`Display` class that supersedes the good old \verb`Show` class. The result looks like this: 15 | %**16 | %*ignore 17 | \begin{center} 18 | \includegraphics[width=\textwidth]{html/worksheet-diagrams.png} 19 | \end{center} 20 | %*endignore 21 | 22 | \subsubsection*{Current status} 23 | 24 | The very first release, \emph{Level $\alpha$}, version \verb`0.1.0.0` has been published. Basic features are working, but there is plenty of room to grow. Please send me any feedback, suggestions, bug reports, contributions ... that you might have! 25 | 26 | \subsubsection*{Future development} 27 | 28 | Programming a computer usually involves writing a program text in a particular language, a ``verbal'' activity. But computers can also be instructed by gestures, say, a mouse click, which is a ``nonverbal'' activity. The long term goal of \emph{HyperHaskell} is to blur the lines between programming ``verbally'' and ``nonverbally'' in Haskell. This begins with an interpreter that has graphical representations for values, but also includes editing a program text while it's running (``live coding'') and interactive representations of values (e.g. ``tangible values''). This territory is still largely uncharted from a purely functional perspective, probably due to a lack of easily installed graphical facilities. It is my hope that \emph{HyperHaskell} may provide a common ground for exploration and experimentation in this direction, in particular by offering the \verb!Display! class which may, perhaps one day, replace our good old \verb!Show! class. 29 | 30 | A simple form of live coding is planned for \emph{Level $\beta$}. 31 | 32 | \FurtherReading 33 | \begin{compactitem} 34 | \item Project page and downloads: \url{https://github.com/HeinrichApfelmus/hyper-haskell} 35 | \end{compactitem} 36 | \end{hcarentry} 37 | -------------------------------------------------------------------------------- /docs/hcar/hyperhaskell-2017-05.tex: -------------------------------------------------------------------------------- 1 | % HyperHaskellThestronglyhy-HH.tex 2 | \begin{hcarentry}[updated]{HyperHaskell -- The strongly hyped Haskell interpreter} 3 | \label{hyper-haskell} 4 | \report{Heinrich Apfelmus}%05/17 5 | \release{0.1.0.0} 6 | \status{available, active development} 7 | \makeheader 8 | 9 | \emph{HyperHaskell} is a graphical Haskell interpreter, not unlike GHCi, but 10 | hopefully more awesome. You use worksheets to enter expressions and evaluate 11 | them. Results are displayed graphically using HTML. 12 | 13 | \emph{HyperHaskell} is intended to be \emph{easy to install}. It is 14 | cross-platform and should run on Linux, Mac and Windows. Internally, it uses 15 | the GHC API to interpret Haskell programs, and the graphical front-end is 16 | built on the Electron framework. \emph{HyperHaskell} is open source. 17 | 18 | \emph{HyperHaskell}'s main attraction is a \verb`Display` class that 19 | supersedes the good old \verb`Show` class. The result looks like this: 20 | 21 | %**
22 | %*ignore 23 | \begin{center} 24 | \includegraphics[width=\columnwidth]{html/worksheet-diagrams.png} 25 | \end{center} 26 | %*endignore 27 | 28 | \subsubsection*{Current status} 29 | 30 | \emph{HyperHaskell} is currently \emph{Level $\alpha$}. Compared to the previous report, no new release has been made, but basic features are working. A new cell type, the \emph{text cell}, has been implemented, but not yet released. 31 | 32 | I am looking for help in setting up binary releases on the Windows platform! 33 | 34 | \subsubsection*{Future development} 35 | 36 | Programming a computer usually involves writing a program text in a particular 37 | language, a ``verbal'' activity. But computers can also be instructed by 38 | gestures, say, a mouse click, which is a ``nonverbal'' activity. The long term 39 | goal of \emph{HyperHaskell} is to blur the lines between programming 40 | ``verbally'' and ``nonverbally'' in Haskell. This begins with an interpreter 41 | that has graphical representations for values, but also includes editing a 42 | program text while it's running (``live coding'') and interactive 43 | representations of values (e.g. ``tangible values''). This territory is still 44 | largely uncharted from a purely functional perspective, probably due to a lack 45 | of easily installed graphical facilities. It is my hope that 46 | \emph{HyperHaskell} may provide a common ground for exploration and 47 | experimentation in this direction, in particular by offering the 48 | \verb!Display! class which may, perhaps one day, replace our good old 49 | \verb!Show! class. 50 | 51 | A simple form of live coding is planned for \emph{Level $\beta$}. 52 | 53 | \FurtherReading 54 | \begin{compactitem} 55 | \item Project homepage and downloads: \url{https://github.com/HeinrichApfelmus/hyper-haskell} 56 | \end{compactitem} 57 | \end{hcarentry} 58 | -------------------------------------------------------------------------------- /docs/hcar/hyperhaskell-2017-11.tex: -------------------------------------------------------------------------------- 1 | % HyperHaskellThestronglyhy-HH.tex 2 | \begin{hcarentry}[updated]{HyperHaskell -- The strongly hyped Haskell interpreter} 3 | \label{hyper-haskell} 4 | \report{Heinrich Apfelmus}%11/17 5 | \status{available, active development} 6 | \makeheader 7 | 8 | \emph{HyperHaskell} is a graphical Haskell interpreter, not unlike GHCi, but 9 | hopefully more awesome. You use worksheets to enter expressions and evaluate 10 | them. Results are displayed graphically using HTML. 11 | 12 | \emph{HyperHaskell} is intended to be \emph{easy to install}. It is 13 | cross-platform and should run on Linux, Mac and Windows. Internally, it uses 14 | the GHC API to interpret Haskell programs, and the graphical front-end is 15 | built on the Electron framework. \emph{HyperHaskell} is open source. 16 | 17 | \emph{HyperHaskell}'s main attraction is a \verb`Display` class that 18 | supersedes the good old \verb`Show` class. The result looks like this: 19 | 20 | %**
21 | %*ignore 22 | \begin{center} 23 | \includegraphics[width=\columnwidth]{html/worksheet-diagrams.png} 24 | \end{center} 25 | %*endignore 26 | 27 | \subsubsection*{Status} 28 | 29 | \emph{HyperHaskell} is currently \emph{Level $\alpha$}. The latest stable release is \verb`0.1.0.2`. 30 | Compared to the previous report, no new release has been made, but basic features are working. 31 | It is now possible to interpret statements in the \verb`IO` monad and to bind variables, greatly enhancing the usefulness of the interpreter. 32 | 33 | Support for the Nix package manager has been implemented by Rodney Lorrimar. 34 | I am looking for help in setting up binary releases on the Windows platform! 35 | 36 | \subsubsection*{Future development} 37 | 38 | Programming a computer usually involves writing a program text in a particular 39 | language, a ``verbal'' activity. But computers can also be instructed by 40 | gestures, say, a mouse click, which is a ``nonverbal'' activity. The long term 41 | goal of \emph{HyperHaskell} is to blur the lines between programming 42 | ``verbally'' and ``nonverbally'' in Haskell. This begins with an interpreter 43 | that has graphical representations for values, but also includes editing a 44 | program text while it's running (``live coding'') and interactive 45 | representations of values (e.g. ``tangible values''). This territory is still 46 | largely uncharted from a purely functional perspective, probably due to a lack 47 | of easily installed graphical facilities. It is my hope that 48 | \emph{HyperHaskell} may provide a common ground for exploration and 49 | experimentation in this direction, in particular by offering the 50 | \verb!Display! class which may, perhaps one day, replace our good old 51 | \verb!Show! class. 52 | 53 | A simple form of live coding is planned for \emph{Level $\beta$}, and I am experimenting with interactive music programming. 54 | 55 | \FurtherReading 56 | \begin{compactitem} 57 | \item Project homepage and downloads: \url{https://github.com/HeinrichApfelmus/hyper-haskell} 58 | \end{compactitem} 59 | \end{hcarentry} 60 | -------------------------------------------------------------------------------- /docs/hcar/template.tex: -------------------------------------------------------------------------------- 1 | \documentclass{scrreprt} 2 | \usepackage{paralist} 3 | \usepackage{graphicx} 4 | \usepackage[final]{hcar} 5 | 6 | %include polycode.fmt 7 | 8 | \begin{document} 9 | \include{hyperhaskell-2017-11} 10 | \end{document} 11 | -------------------------------------------------------------------------------- /docs/misc.md: -------------------------------------------------------------------------------- 1 | Misc 2 | ==== 3 | 4 | This document records snippets of information that are useful for developing HyperHaskell. 5 | 6 | Haskell 7 | ======= 8 | 9 | How does GHCi evaluate expressions on the prompt? 10 | ------------------------------------------------- 11 | 12 | In particular, the question is how GHCi distinguishes between expressions of `IO` type, which are executed, and expressions of non-IO type, which are wrapped in a call to `show`. 13 | 14 | Let's have a look at the [GHC source code](https://github.com/ghc/ghc). Following the execution path, we find the following functions: 15 | 16 | * [GHCi.UI.runStmt](https://github.com/ghc/ghc/blob/ghc-8.0/ghc/GHCi/UI.hs#L941) 17 | 18 | "Entry point to execute some haskell code from user" 19 | 20 | The prompt analyzed and falls into 3 cases: "import", statement, declaration. 21 | 22 | * [GHCi.UI.Monad.runStmt](https://github.com/ghc/ghc/blob/ghc-8.0/ghc/GHCi/UI/Monad.hs#L310) 23 | 24 | "Run a single Haskell expression" 25 | 26 | This function essentially just calls `GHC.execStmt`. 27 | 28 | * [GHC.execStmt](https://github.com/ghc/ghc/blob/master/compiler/main/InteractiveEval.hs#L164) 29 | 30 | "Run a statement in the current interactive context." 31 | 32 | This function is part of the public GHC API. 33 | 34 | Unfortunately, this is as far as I got. I don't quite understand what a `HValue` is. 35 | 36 | Fortunately, a Google search reveals that the relevant code is actually contained in the type checker. 37 | 38 | * [compiler/typecheck/TcRnDriver.hs](https://github.com/ghc/ghc/blob/ghc-8.0/compiler/typecheck/TcRnDriver.hs#L1737) 39 | 40 | Section "Typechecking Statements in GHCi". 41 | 42 | > By 'lift' and 'environment we mean that the code is changed to 43 | execute properly in an IO monad. See Note [Interactively-bound Ids 44 | in GHCi] in HscTypes for more details. We do this lifting by trying 45 | different ways ('plans') of lifting the code into the IO monad and 46 | type checking each plan until one succeeds. 47 | 48 | Apparently, 49 | 50 | > The plans are: 51 | > 52 | > A. [it <- e; print it] but not if it::() 53 | > 54 | > B. [it <- e] 55 | > 56 | > C. [let it = e; print it] 57 | 58 | In other words, GHC tries to typecheck the expression at the prompt in different contexts, and uses the first plan that works. 59 | 60 | 61 | Haskell path information 62 | ------------------------ 63 | 64 | **Cabal** 65 | 66 | The configuration file is in 67 | 68 | ~/.cabal/config 69 | 70 | It contains several fields that are relevant: 71 | 72 | extra-prog-path: /Users/apfelmus/.cabal/bin 73 | 74 | 75 | **Stack** 76 | 77 | Once we know where a particular `stack.yml` file is, we can use 78 | 79 | stack --stack-yaml=foo/stack.yaml 80 | 81 | to use the stack utility relative to this location. We can query various paths, in particular `GHC_PACKAGE_PATH`: 82 | 83 | stack path --ghc-package-path 84 | 85 | But to execute the interpreter server, including the right `GHC_PACKAGE_PATH`, it is actually simpler to just call 86 | 87 | stack exec hyper-haskell-server # execute binary 88 | 89 | The path of the interpreter executable can be obtained from 90 | 91 | stack exec -- which hyper-haskell-server # retrieve full path of the binary 92 | 93 | For my setup, a minimal environment is given by 94 | 95 | env -i \ 96 | PATH=/usr/bin:/Applications/ghc-7.10.3.app/Contents/bin \ 97 | HOME=/Users/hgz \ 98 | stack exec -- hyper-haskell-server 99 | 100 | JavaScript 101 | ========== 102 | 103 | Node.js — External Processes 104 | ----------------------------- 105 | 106 | We can run external processes and read their `stdout`. Example: 107 | 108 | let result = process.spawnSync(ghcbindir + '/stack', 109 | ['exec', 'printenv', '--', 'GHC_PACKAGE_PATH'], { 110 | cwd : dir, 111 | encoding : 'utf8', 112 | env : newEnv(), 113 | }).stdout.trim() 114 | 115 | Note that most UNIX utilities will traditionally emit a newline at the end of the output, and we use `trim()` to get rid of it. 116 | 117 | 118 | Cabal and GHC package environments 119 | ---------------------------------- 120 | 121 | A working installation of the HyperHaskell interpreter backend consists of two things: 122 | 123 | 1. The interpreter executable `hyper-haskell-server`, linked against a compilation A of the `hyper` package. 124 | 2. A package database that contains this compilation A of the `hyper` package. This database needs to be in scope when running the interpreter excutable. 125 | 126 | How to provision these? 127 | 128 | As of December 2024, it seemed like GHC [package environments][package-env] might be useful to provision the above setup, but unfortunately, this does not work. 129 | 130 | The following command will install the package `hyper` into the package environment `PKG_ENV`: 131 | 132 | ``` 133 | cabal install --lib hyper --package-env ${PKG_ENV} 134 | ``` 135 | 136 | The following command will install `hyper-haskell-server` into the directory `DIR` while referring to packages from the package environment `PKG_ENV`: 137 | 138 | ``` 139 | cabal install hyper-haskell-server --package-env ${PKG_ENV} --installdir=${DIR} 140 | ``` 141 | 142 | By using the same package environment `PKG_ENV`, we make sure that both the interpreter exectuable and the package environment refer to the same compilation of the `hyper` package. 143 | 144 | Unfortunately, the two commands above do not produce a working setup: `cabal install --lib` does [not install dependencies][cabal-issue-6263], and the GHC API as used by `hyper-haskell-server` is unable to handle that; I get error messages of the form 145 | 146 | ``` 147 | cannot satisfy -package-id hypr-xtr-0.2.0.1-71ddd09d: 148 | hypr-xtr-0.2.0.1-71ddd09d is unusable due to missing dependencies: 149 | […] 150 | ``` 151 | 152 | (The "missing dependency" appears to be present in the package database, and `ghci` is able to handle the situation, but the use of the GHC API by `hyper-haskell-server` is not.) 153 | 154 | To summarize, as of December 2024, I can't get GHC package environments to yield a working installation of the HyperHaskell interpreter backend. 155 | 156 | [package-env]: https://ghc.gitlab.haskell.org/ghc/doc/users_guide/packages.html#package-environments 157 | [cabal-issue-6263]: https://github.com/haskell/cabal/issues/6263 158 | 159 | 160 | Tools 161 | ===== 162 | 163 | Testing POST requests 164 | --------------------- 165 | 166 | The `curl` utility is able to send POST requests and receive a response. Example: 167 | 168 | $ curl --data "query=Prelude" http://localhost:8024/setImports 169 | {"status":"ok"} 170 | $ curl --data "query=3*4::Int" http://localhost:8024/eval 171 | {"status":"ok","value":"12"} 172 | 173 | Note that `curl` will not, by default, add a newline to the end of the received request; this may screw up the terminal. However, the option `-w '\n'` will add said newline. To make it a default, use the `~/.curlrc` file [[StackOverflow]][12849584]. 174 | 175 | echo '-w "\n"' >> ~/.curlrc 176 | 177 | [12849584]: http://stackoverflow.com/questions/12849584/automatically-add-newline-at-end-of-curl-response-body 178 | 179 | How to create an .icns file on OS X? 180 | ------------------------------------ 181 | 182 | Application icons on OS X are stored in `.icns` files. There is a command line utility called `iconutil` that is supposed to be able to create such files, but unfortunately, it only creates garbled icons for me. No idea why. Online converters seem to work fine. 183 | 184 | How to remove color profiles from images on OS X? 185 | ------------------------------------------------- 186 | 187 | sips -d profile --deleteColorManagementProperties *filename* 188 | -------------------------------------------------------------------------------- /docs/screenshots/app-osx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/docs/screenshots/app-osx.png -------------------------------------------------------------------------------- /docs/screenshots/settings-back-end-cabal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/docs/screenshots/settings-back-end-cabal.png -------------------------------------------------------------------------------- /docs/screenshots/settings-back-end-stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/docs/screenshots/settings-back-end-stack.png -------------------------------------------------------------------------------- /docs/screenshots/worksheet-diagrams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HeinrichApfelmus/hyper-haskell/7b8775ff1798e33089b62d3904aa49bf8c24cd14/docs/screenshots/worksheet-diagrams.png -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1681378341, 9 | "narHash": "sha256-2qUN04W6X9cHHytEsJTM41CmusifPTC0bgTtYsHSNY8=", 10 | "owner": "hamishmack", 11 | "repo": "flake-utils", 12 | "rev": "2767bafdb189cd623354620c2dacbeca8fd58b17", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "hamishmack", 17 | "ref": "hkm/nested-hydraJobs", 18 | "repo": "flake-utils", 19 | "type": "github" 20 | } 21 | }, 22 | "nixpkgs": { 23 | "locked": { 24 | "lastModified": 1726423290, 25 | "narHash": "sha256-KjzvVbfO9MdFZJWVYh5j70uwoF/ZQB2z385jv3Q4sjs=", 26 | "owner": "NixOS", 27 | "repo": "nixpkgs", 28 | "rev": "dbfe1b17a208c5715acd6586ca0e28879aa1339c", 29 | "type": "github" 30 | }, 31 | "original": { 32 | "owner": "NixOS", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "flake-utils": "flake-utils", 40 | "nixpkgs": "nixpkgs" 41 | } 42 | }, 43 | "systems": { 44 | "locked": { 45 | "lastModified": 1681028828, 46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 47 | "owner": "nix-systems", 48 | "repo": "default", 49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "nix-systems", 54 | "repo": "default", 55 | "type": "github" 56 | } 57 | } 58 | }, 59 | "root": "root", 60 | "version": 7 61 | } 62 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = ''HyperHaskell''; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs"; 6 | flake-utils.url = "github:hamishmack/flake-utils/hkm/nested-hydraJobs"; 7 | }; 8 | 9 | outputs = inputs: 10 | let 11 | supportedSystems = [ 12 | "x86_64-linux" 13 | "x86_64-darwin" 14 | "aarch64-linux" 15 | "aarch64-darwin" 16 | ]; in 17 | inputs.flake-utils.lib.eachSystem supportedSystems (system: 18 | let 19 | # ########################################### 20 | # Imports 21 | 22 | # Packages with patches 23 | pkgs = inputs.nixpkgs.legacyPackages.${system}; 24 | 25 | # Library 26 | lib = pkgs.lib; 27 | 28 | # ########################################### 29 | # Helpers 30 | 31 | in rec { 32 | packages = { }; 33 | 34 | apps = { }; 35 | 36 | devShells.default = pkgs.mkShell { 37 | buildInputs = [ 38 | pkgs.just 39 | 40 | pkgs.ghc 41 | pkgs.pkg-config 42 | pkgs.zlib 43 | 44 | pkgs.nodejs_22 45 | pkgs.electron 46 | ] ++ lib.optionals pkgs.stdenv.isDarwin ([ 47 | pkgs.darwin.apple_sdk.frameworks.Cocoa 48 | pkgs.darwin.apple_sdk.frameworks.CoreServices 49 | pkgs.darwin.objc4.all 50 | ]); 51 | }; 52 | 53 | shellHook = '' 54 | # add shell hook here 55 | ''; 56 | } 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /haskell/hyper-extra/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2024 Heinrich Apfelmus 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Heinrich Apfelmus nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /haskell/hyper-extra/hyper-extra.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 3.0 2 | name: hyper-extra 3 | version: 0.2.0.2 4 | synopsis: Display instances for the HyperHaskell graphical Haskell interpreter 5 | description: 6 | This package is part of the /HyperHaskell/ project and provides 7 | visual representations for various data types, in particular 8 | diagrams from the @diagrams@ package. 9 | . 10 | category: Graphics, Pretty Printer 11 | homepage: https://github.com/HeinrichApfelmus/hyper-haskell 12 | license: BSD-3-Clause 13 | license-file: LICENSE 14 | 15 | author: Heinrich Apfelmus 16 | maintainer: Heinrich Apfelmus
17 | copyright: (c) Heinrich Apfelmus 2016-2024 18 | 19 | tested-with: 20 | , GHC == 8.10.7 21 | , GHC == 9.2.8 22 | , GHC == 9.4.7 23 | , GHC == 9.6.6 24 | , GHC == 9.8.4 25 | , GHC == 9.10.1 26 | 27 | source-repository head 28 | type: git 29 | location: git://github.com/HeinrichApfelmus/hyper-haskell.git 30 | subdir: haskell/hyper-extra/ 31 | 32 | library 33 | hs-source-dirs: src 34 | default-language: Haskell2010 35 | build-depends: 36 | , base >= 4.6 && < 4.22 37 | , diagrams-lib >= 1.3 && < 1.5 38 | , diagrams-svg >= 1.4 && < 1.5 39 | , hyper >= 0.2 && < 0.3 40 | , QuickCheck >= 2.3.0.2 && < 2.16 41 | , svg-builder >= 0.1 && < 0.2 42 | , text >= 0.11 && < 2.2 43 | exposed-modules: 44 | Hyper.Extra 45 | -------------------------------------------------------------------------------- /haskell/hyper-extra/src/Hyper/Extra.hs: -------------------------------------------------------------------------------- 1 | module Hyper.Extra ( 2 | -- * Synopsis 3 | -- | Visual representation for various data types. 4 | 5 | -- * SVG 6 | fromSvg, 7 | -- * Diagrams 8 | dia, 9 | 10 | -- * QuickCheck 11 | hyperCheck, 12 | ) where 13 | 14 | import Hyper 15 | 16 | import qualified Data.Text as Text 17 | import qualified Data.Text.Lazy as Text.Lazy 18 | 19 | import Diagrams.Prelude hiding (pre) 20 | import Diagrams.Backend.SVG 21 | import qualified Graphics.Svg 22 | 23 | import qualified Test.QuickCheck as Q 24 | 25 | {----------------------------------------------------------------------------- 26 | Integration of the `svg-builder` and `diagrams-svg` spackages 27 | ------------------------------------------------------------------------------} 28 | -- | Render a SVG document. 29 | -- This assumes that the argument is indeed a complete SVG document, 30 | -- i.e. an @