By setting a few CSS properties, CodeMirror can be made to
32 | automatically resize to fit its content.
33 |
34 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/theme/eclipse.css:
--------------------------------------------------------------------------------
1 | .cm-s-eclipse span.cm-meta {color: #FF1717;}
2 | .cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
3 | .cm-s-eclipse span.cm-atom {color: #219;}
4 | .cm-s-eclipse span.cm-number {color: #164;}
5 | .cm-s-eclipse span.cm-def {color: #00f;}
6 | .cm-s-eclipse span.cm-variable {color: black;}
7 | .cm-s-eclipse span.cm-variable-2 {color: #0000C0;}
8 | .cm-s-eclipse span.cm-variable-3 {color: #0000C0;}
9 | .cm-s-eclipse span.cm-property {color: black;}
10 | .cm-s-eclipse span.cm-operator {color: black;}
11 | .cm-s-eclipse span.cm-comment {color: #3F7F5F;}
12 | .cm-s-eclipse span.cm-string {color: #2A00FF;}
13 | .cm-s-eclipse span.cm-string-2 {color: #f50;}
14 | .cm-s-eclipse span.cm-error {color: #f00;}
15 | .cm-s-eclipse span.cm-qualifier {color: #555;}
16 | .cm-s-eclipse span.cm-builtin {color: #30a;}
17 | .cm-s-eclipse span.cm-bracket {color: #cc7;}
18 | .cm-s-eclipse span.cm-tag {color: #170;}
19 | .cm-s-eclipse span.cm-attribute {color: #00c;}
20 | .cm-s-eclipse span.cm-link {color: #219;}
21 |
22 | .cm-s-eclipse .CodeMirror-matchingbracket {
23 | border:1px solid grey;
24 | color:black !important;;
25 | }
26 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/python/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2010 Timothy Farrell
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/xquery/test/testQuotes.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){
2 | module("testQuoteEscape");
3 | test("testQuoteEscapeDouble", function() {
4 | expect(1);
5 |
6 | var input = 'let $rootfolder := "c:\\builds\\winnt\\HEAD\\qa\\scripts\\"\
7 | let $keysfolder := concat($rootfolder, "keys\\")\
8 | return\
9 | $keysfolder';
10 | var expected = 'let$rootfolder:="c:\\builds\\winnt\\HEAD\\qa\\scripts\\"let$keysfolder:=concat($rootfolder, "keys\\")return$keysfolder';
11 |
12 | $("#sandbox").html('');
13 | var editor = CodeMirror.fromTextArea($("#editor")[0]);
14 | var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
15 |
16 | equal(result, expected);
17 | $("#editor").html("");
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/js/events.js:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------------
2 | // Copyright (C) 2008-2011 The IPython Development Team
3 | //
4 | // Distributed under the terms of the BSD License. The full license is in
5 | // the file COPYING, distributed as part of this software.
6 | //----------------------------------------------------------------------------
7 |
8 | //============================================================================
9 | // Events
10 | //============================================================================
11 |
12 | // Give us an object to bind all events to. This object should be created
13 | // before all other objects so it exists when others register event handlers.
14 | // To trigger an event handler:
15 | // $([IPython.events]).trigger('event.Namespace);
16 | // To handle it:
17 | // $([IPython.events]).on('event.Namespace',function () {});
18 |
19 | var IPython = (function (IPython) {
20 |
21 | var utils = IPython.utils;
22 |
23 | var Events = function () {};
24 |
25 | IPython.Events = Events;
26 | IPython.events = new Events();
27 |
28 | return IPython;
29 |
30 | }(IPython));
31 |
32 |
--------------------------------------------------------------------------------
/server/src/main/resources/reference.conf:
--------------------------------------------------------------------------------
1 | notebook {
2 |
3 | ###
4 | # Uncomment to enable attachment of a remote debugger (you will likely either need to change the port on the line below, or configure your debugger to connect to the specified port)
5 | #vmArgs=["-agentlib:jdwp=transport=dt_socket,address=localhost:9000,server=y,suspend=y"]
6 |
7 | ###
8 | # Working directory for kernel VMs
9 | #kernel.dir=.
10 |
11 | ###
12 | # Server dir (containing notebook files)
13 | #notebooks.dir=.
14 |
15 | ###
16 | # List of URLs of kernel init scripts (to be run when a kernel first starts).
17 | #kernel.init=[]
18 |
19 | ###
20 | # Kernel VM memory settings
21 | #heap=4g
22 | #permGen=128m
23 |
24 | ###
25 | # Static resources to be made available on the web server
26 | # You may add your own resource directories
27 | # Paths may be relative to the server root, or absolute.
28 | #resources=["./my-resources"]
29 |
30 | ###
31 | # Classpath for kernel VMs (defaults to server VM classpath)
32 | #kernel.classpath=[]
33 |
34 | ###
35 | # REPL compiler options
36 | #compilerArgs=[]
37 |
38 | }
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/perl/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2011 by Sabaca under the MIT license.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/xquery/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2011 by MarkLogic Corporation
2 | Author: Mike Brevoort
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/vb/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2012 Codility Limited, 107 Cheapside, London EC2V 6DN, UK
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/theme/night.css:
--------------------------------------------------------------------------------
1 | /* Loosely based on the Midnight Textmate theme */
2 |
3 | .cm-s-night { background: #0a001f; color: #f8f8f8; }
4 | .cm-s-night div.CodeMirror-selected { background: #447 !important; }
5 | .cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
6 | .cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; }
7 | .cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
8 |
9 | .cm-s-night span.cm-comment { color: #6900a1; }
10 | .cm-s-night span.cm-atom { color: #845dc4; }
11 | .cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }
12 | .cm-s-night span.cm-keyword { color: #599eff; }
13 | .cm-s-night span.cm-string { color: #37f14a; }
14 | .cm-s-night span.cm-meta { color: #7678e2; }
15 | .cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }
16 | .cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }
17 | .cm-s-night span.cm-error { color: #9d1e15; }
18 | .cm-s-night span.cm-bracket { color: #8da6ce; }
19 | .cm-s-night span.cm-comment { color: #6900a1; }
20 | .cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }
21 | .cm-s-night span.cm-link { color: #845dc4; }
22 |
--------------------------------------------------------------------------------
/observable/src/main/scala/com/bwater/notebook/ObservableHandler.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook
9 |
10 | import akka.actor.{ActorRef, Actor}
11 | import org.slf4j.LoggerFactory
12 |
13 | /**
14 | * Actor that handles updates from a client and triggers the proper Scala EventStreams and
15 | * vice versa.
16 | *
17 | * Only one of these Handlers is intended to exist in a VM at a time. On construction, it will
18 | * set the JSBus publisher to itself.
19 | */
20 | class ObservableHandler(proxy: ActorRef) extends Actor {
21 |
22 | JSBusState.setPublisher((id, value) => proxy ! ObservableVMToBrowser(id, value))
23 |
24 | val log = LoggerFactory.getLogger(getClass())
25 |
26 | log.info("Obs handler is ready")
27 |
28 | def receive = {
29 | case ObservableBrowserToVM(obsId, newValue) =>
30 | try {
31 | log.info("Forwarding message to " + obsId)
32 | JSBus.forwardClientUpdateMessage(obsId, newValue)
33 | } catch {
34 | case e: Exception => e.printStackTrace()
35 | }
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/jinja2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Jinja2 mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
CodeMirror: Jinja2 mode
13 |
31 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/kernel/src/main/scala/com/bwater/notebook/kernel/completor/FileCompletor.scala:
--------------------------------------------------------------------------------
1 | package com.bwater.notebook.kernel.completor
2 |
3 | import java.io.File
4 |
5 | import com.bwater.notebook.{Match, StringCompletor}
6 | import org.apache.commons.io.FileUtils
7 |
8 | /**
9 | * Auto-completes file paths based on the current directory
10 | */
11 | class FileCompletor extends StringCompletor {
12 | def complete(stringToComplete: String): (String, Seq[Match]) = {
13 | val filesInCurrentDirectory = listFiles
14 |
15 | val matches = for {
16 | candidateFile <- filesInCurrentDirectory if normalize(candidateFile).startsWith(normalize(stringToComplete))
17 | } yield {
18 | val f = new File(candidateFile)
19 |
20 | val metadata = Map("Path" -> f.getAbsolutePath)
21 | val extraMetadata = if (f.isDirectory) { Map ("Type" -> "Directory") } else { Map("Size" -> FileUtils.byteCountToDisplaySize(f.length())) }
22 |
23 | Match(candidateFile.toString, metadata ++ extraMetadata)
24 | }
25 |
26 | (stringToComplete, matches)
27 | }
28 |
29 | private def normalize(x: String) = x.trim.toLowerCase
30 |
31 | protected def listFiles: Seq[String] = {
32 | val currentDirectory = new File(".")
33 | currentDirectory.list.toSeq
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/coffeescript/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2011 Jeff Pickhardt
4 | Modified from the Python CodeMirror mode, Copyright (c) 2010 Timothy Farrell
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/theme/monokai.css:
--------------------------------------------------------------------------------
1 | /* Based on Sublime Text's Monokai theme */
2 |
3 | .cm-s-monokai {background: #272822; color: #f8f8f2;}
4 | .cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}
5 | .cm-s-monokai .CodeMirror-gutter {background: #272822; border-right: 0px;}
6 | .cm-s-monokai .CodeMirror-gutter-text {color: #d0d0d0;}
7 | .cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
8 |
9 | .cm-s-monokai span.cm-comment {color: #75715e;}
10 | .cm-s-monokai span.cm-atom {color: #ae81ff;}
11 | .cm-s-monokai span.cm-number {color: #ae81ff;}
12 |
13 | .cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
14 | .cm-s-monokai span.cm-keyword {color: #f92672;}
15 | .cm-s-monokai span.cm-string {color: #e6db74;}
16 |
17 | .cm-s-monokai span.cm-variable {color: #a6e22e;}
18 | .cm-s-monokai span.cm-variable-2 {color: #9effff;}
19 | .cm-s-monokai span.cm-def {color: #fd971f;}
20 | .cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
21 | .cm-s-monokai span.cm-bracket {color: #f8f8f2;}
22 | .cm-s-monokai span.cm-tag {color: #f92672;}
23 | .cm-s-monokai span.cm-link {color: #ae81ff;}
24 |
25 | .cm-s-monokai .CodeMirror-matchingbracket {
26 | text-decoration: underline;
27 | color: white !important;
28 | }
29 |
--------------------------------------------------------------------------------
/observable/src/main/scala/com/bwater/notebook/Observer.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook
9 |
10 | /**
11 | * Author: Ken
12 | */
13 | trait Observer[T] extends rx.Observer[T] {
14 | def map[A](fxn: A=>T): Observer[A] = new MappingObserver[T,A]{ def innerObserver = Observer.this; def observerMapper = fxn }
15 | def <--(other: Observable[T]): Unit = {
16 | other.subscribe(this)
17 | }
18 | }
19 |
20 | /**
21 | * A no-op observer, useful for extending just the methods you want
22 | * @tparam T
23 | */
24 | trait ConcreteObserver[T] extends Observer[T] {
25 | def onCompleted() {}
26 |
27 | def onError(e: Exception) {}
28 |
29 | def onNext(args: T) {}
30 | }
31 |
32 | class NoopObserver[T] extends ConcreteObserver[T]
33 |
34 | trait MappingObserver[A,B] extends Observer[B] {
35 | protected def innerObserver: Observer[A]
36 |
37 | protected def observerMapper: B=>A
38 |
39 | def onCompleted() {innerObserver.onCompleted()}
40 |
41 | def onError(e: Exception) {innerObserver.onError(e)}
42 |
43 | def onNext(args: B) {innerObserver.onNext(observerMapper(args))}
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/rust/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Rust mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
36 |
37 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/4.+Completions.snb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata":{
3 | "name":"4. Completions",
4 | "user_save_timestamp":"2015-02-07T17:16:05.795Z",
5 | "auto_save_timestamp":"2015-02-07T17:15:53.510Z"
6 | },
7 | "worksheets":[{
8 | "cells":[{
9 | "cell_type":"markdown",
10 | "source":"## Completions\n\nScala Notebook supports help auto-complete options to make writing code less painful."
11 | },{
12 | "cell_type":"code",
13 | "input":"// Put caret at the end of the line and hit Tab. Should auto-complete to \"notebook\". Add a period and\n// hit tab again. A dropdown of possible completions will appeaar.\ncom.bwater.note",
14 | "language":"scala",
15 | "collapsed":true,
16 | "outputs":[]
17 | },{
18 | "cell_type":"code",
19 | "input":"// Type a left paren and wait. Method signature information will appear.\nsys.error",
20 | "language":"scala",
21 | "collapsed":true,
22 | "outputs":[]
23 | },{
24 | "cell_type":"code",
25 | "input":"// Type a left paren and wait. Method overloads will appear as well.\nConsole.println",
26 | "language":"scala",
27 | "collapsed":true,
28 | "outputs":[]
29 | },{
30 | "cell_type":"code",
31 | "input":"// SN can also complete String literals.\n// Hit tab -- a list of files and directory starting with the letter s in the current \n// working directory will appear.\nnew File(\"s",
32 | "language":"scala",
33 | "collapsed":true,
34 | "outputs":[]
35 | }]
36 | }],
37 | "autosaved":[],
38 | "nbformat":3
39 | }
--------------------------------------------------------------------------------
/observable/src/main/scala/com/bwater/notebook/ObsWebSocketService.scala:
--------------------------------------------------------------------------------
1 | package com.bwater.notebook
2 |
3 | import scala.concurrent._
4 | import akka.actor._
5 | import scala.concurrent.duration._
6 | import unfiltered.netty.websockets.WebSocket
7 | import akka.actor.Deploy
8 | import net.liftweb.json._, JsonDSL._
9 |
10 | /**
11 | * Author: Ken
12 | */
13 | class ObsWebSocketService(system: ActorSystem, val webSock: WebSocket, remoteDeployFuture: Future[Deploy]) {
14 |
15 | val obsActor = system.actorOf(Props(new LocalActor))
16 |
17 | class LocalActor extends Actor with ActorLogging {
18 | var remote: ActorRef = null
19 |
20 | override def preStart() {
21 | val remoteDeploy = Await.result(remoteDeployFuture, 2 minutes)
22 | remote = context.actorOf(Props[ObsServiceRemoteActor].withDeploy(remoteDeploy))
23 | }
24 |
25 | def receive = {
26 | case msg@ObservableBrowserToVM(id, newValue) =>
27 | remote ! msg
28 | case ObservableVMToBrowser(id, value) =>
29 | val respJson = ("id" -> id) ~ ("new_value" -> value)
30 | webSock.send(pretty(render(respJson)))
31 | }
32 | }
33 |
34 | }
35 |
36 |
37 |
38 | class ObsServiceRemoteActor extends Actor with ActorLogging {
39 | override def preStart() {
40 | JSBusState.setPublisher((id, value) => self ! ObservableVMToBrowser(id, value))
41 | }
42 |
43 | def receive = {
44 | case ObservableBrowserToVM(id, newValue) => JSBus.forwardClientUpdateMessage(id, newValue)
45 | case msg: ObservableVMToBrowser => context.parent ! msg
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/jinja2/jinja2.js:
--------------------------------------------------------------------------------
1 | CodeMirror.defineMode("jinja2", function(config, parserConf) {
2 | var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
3 | "loop", "none", "self", "super", "if", "as", "not", "and",
4 | "else", "import", "with", "without", "context"];
5 | keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
6 |
7 | function tokenBase (stream, state) {
8 | var ch = stream.next();
9 | if (ch == "{") {
10 | if (ch = stream.eat(/\{|%|#/)) {
11 | stream.eat("-");
12 | state.tokenize = inTag(ch);
13 | return "tag";
14 | }
15 | }
16 | }
17 | function inTag (close) {
18 | if (close == "{") {
19 | close = "}";
20 | }
21 | return function (stream, state) {
22 | var ch = stream.next();
23 | if ((ch == close || (ch == "-" && stream.eat(close)))
24 | && stream.eat("}")) {
25 | state.tokenize = tokenBase;
26 | return "tag";
27 | }
28 | if (stream.match(keywords)) {
29 | return "keyword";
30 | }
31 | return close == "#" ? "comment" : "string";
32 | };
33 | }
34 | return {
35 | startState: function () {
36 | return {tokenize: tokenBase};
37 | },
38 | token: function (stream, state) {
39 | return state.tokenize(stream, state);
40 | }
41 | };
42 | });
43 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/js/loginwidget.js:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------------
2 | // Copyright (C) 2008-2011 The IPython Development Team
3 | //
4 | // Distributed under the terms of the BSD License. The full license is in
5 | // the file COPYING, distributed as part of this software.
6 | //----------------------------------------------------------------------------
7 |
8 | //============================================================================
9 | // Login button
10 | //============================================================================
11 |
12 | var IPython = (function (IPython) {
13 |
14 | var LoginWidget = function (selector) {
15 | this.selector = selector;
16 | if (this.selector !== undefined) {
17 | this.element = $(selector);
18 | this.style();
19 | this.bind_events();
20 | }
21 | };
22 |
23 | LoginWidget.prototype.style = function () {
24 | this.element.find('button#logout').button();
25 | this.element.find('button#login').button();
26 | };
27 |
28 |
29 | LoginWidget.prototype.bind_events = function () {
30 | var that = this;
31 | this.element.find("button#logout").click(function () {
32 | window.location = "/logout";
33 | });
34 | this.element.find("button#login").click(function () {
35 | window.location = "/login";
36 | });
37 | };
38 |
39 | // Set module variables
40 | IPython.LoginWidget = LoginWidget;
41 |
42 | return IPython;
43 |
44 | }(IPython));
45 |
--------------------------------------------------------------------------------
/observable/src/main/scala/com/bwater/notebook/ObservableIntent.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook
9 |
10 | import unfiltered.netty.websockets
11 | import unfiltered.request.{Seg, Path}
12 | import akka.actor.{ActorSystem, ActorRef, ActorRefFactory}
13 | import websockets._
14 | import net.liftweb.json.JsonAST.{JString, JField}
15 | import net.liftweb.json._
16 |
17 | class ObservableIntent(system: ActorSystem) {
18 |
19 | val kernelIdToObsService = collection.mutable.Map[String, ObsWebSocketService]()
20 |
21 | val webSocketIntent: websockets.Intent = {
22 | case req @ Path(Seg("observable" :: contextId :: Nil)) => {
23 | case Open(socket) =>
24 | for (kernel <- KernelManager.get(contextId)) {
25 |
26 | val service = new ObsWebSocketService(system, socket, kernel.remoteDeployFuture)
27 | kernelIdToObsService += contextId -> service
28 | }
29 |
30 | case Message(socket, Text(msg)) =>
31 | for {
32 | json <- parseOpt(msg)
33 | service <- kernelIdToObsService.get(contextId)
34 | JField("id", JString(id)) <- json
35 | JField("new_value", value) <- json
36 | } {
37 | service.obsActor ! ObservableBrowserToVM(id, value)
38 | }
39 |
40 | case Close(_) =>
41 | kernelIdToObsService.remove(contextId)
42 |
43 | case Error(s, e) =>
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/demo/marker.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Breakpoint Demo
5 |
6 |
7 |
8 |
9 |
10 |
19 |
20 |
21 |
CodeMirror: Breakpoint demo
22 |
23 |
35 |
36 |
Click the line-number gutter to add or remove 'breakpoints'.
37 |
38 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/r/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, Ubalo, Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | * Neither the name of the Ubalo, Inc nor the names of its
12 | contributors may be used to endorse or promote products derived
13 | from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY
19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/pagedown/LICENSE.txt:
--------------------------------------------------------------------------------
1 | A javascript port of Markdown, as used on Stack Overflow
2 | and the rest of Stack Exchange network.
3 |
4 | Largely based on showdown.js by John Fraser (Attacklab).
5 |
6 | Original Markdown Copyright (c) 2004-2005 John Gruber
7 |
8 |
9 |
10 | Original Showdown code copyright (c) 2007 John Fraser
11 |
12 | Modifications and bugfixes (c) 2009 Dana Robinson
13 | Modifications and bugfixes (c) 2009-2011 Stack Exchange Inc.
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy
16 | of this software and associated documentation files (the "Software"), to deal
17 | in the Software without restriction, including without limitation the rights
18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 | copies of the Software, and to permit persons to whom the Software is
20 | furnished to do so, subject to the following conditions:
21 |
22 | The above copyright notice and this permission notice shall be included in
23 | all copies or substantial portions of the Software.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31 | THE SOFTWARE.
32 |
33 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/ruby/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, Ubalo, Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | * Neither the name of the Ubalo, Inc. nor the names of its
12 | contributors may be used to endorse or promote products derived
13 | from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY
19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/demo/changemode.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Mode-Changing Demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
CodeMirror: Mode-Changing demo
17 |
18 |
25 |
26 |
On changes to the content of the above editor, a (crude) script
27 | tries to auto-detect the language used, and switches the editor to
28 | either JavaScript or Scheme mode based on that.
29 |
30 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/js/projectdashboardmain.js:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------------
2 | // Copyright (C) 2008-2011 The IPython Development Team
3 | //
4 | // Distributed under the terms of the BSD License. The full license is in
5 | // the file COPYING, distributed as part of this software.
6 | //----------------------------------------------------------------------------
7 |
8 | //============================================================================
9 | // On document ready
10 | //============================================================================
11 |
12 |
13 | $(document).ready(function () {
14 |
15 | IPython.page = new IPython.Page();
16 |
17 | $('div#tabs').tabs();
18 | $('div#tabs').on('tabsselect', function (event, ui) {
19 | var new_url = $('body').data('baseProjectUrl') + '#' + ui.panel.id;
20 | window.history.replaceState({}, '', new_url);
21 | });
22 | $('div#main_app').addClass('border-box-sizing ui-widget');
23 | $('div#notebooks_toolbar').addClass('ui-widget ui-helper-clearfix');
24 | $('#new_notebook').button().click(function (e) {
25 | var url = $('body').data('baseProjectUrl')+'new'
26 | IPython.CSRF.postAction(url)
27 | });
28 |
29 | IPython.read_only = $('body').data('readOnly') === 'True';
30 | IPython.notebook_list = new IPython.NotebookList('div#notebook_list');
31 | IPython.cluster_list = new IPython.ClusterList('div#cluster_list');
32 | IPython.login_widget = new IPython.LoginWidget('span#login_widget');
33 |
34 | IPython.notebook_list.load_list();
35 | IPython.cluster_list.load_list();
36 |
37 | IPython.page.show();
38 |
39 | });
40 |
41 |
--------------------------------------------------------------------------------
/subprocess/src/main/scala/com/bwater/notebook/kernel/remote/AkkaConfigUtils.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook.kernel.remote
9 |
10 | import com.typesafe.config.{ConfigFactory, Config}
11 | import scala.collection.JavaConversions._
12 |
13 |
14 | /**
15 | *
16 | */
17 |
18 | object AkkaConfigUtils {
19 |
20 | private val SecureCookiePath = "akka.remote.netty.secure-cookie"
21 | private val RequireCookiePath = "akka.remote.netty.require-cookie"
22 |
23 | /** Creates a configuration that requires the specified secure requiredCookie if defined. */
24 | def requireCookie(baseConfig: Config, cookie: String) =
25 | ConfigFactory.parseMap(Map(
26 | SecureCookiePath -> cookie,
27 | RequireCookiePath -> "on"
28 | )).withFallback(baseConfig)
29 |
30 | /** If the specified configuration requires a secure requiredCookie, but does not define the requiredCookie value, this generates a new config with an appropriate value. */
31 | def optSecureCookie(baseConfig: Config, cookie: => String) =
32 | requiredCookie(baseConfig).map {
33 | req => if (req.isEmpty) {
34 | ConfigFactory.parseMap(Map(SecureCookiePath -> cookie)).withFallback(baseConfig)
35 | } else baseConfig
36 | } getOrElse baseConfig
37 |
38 | /** Returns the secure requiredCookie value if the specified Config requires their use. */
39 | def requiredCookie(config: Config) =
40 | if (config.getBoolean(RequireCookiePath)) {
41 | Some(config.getString(SecureCookiePath))
42 | } else None
43 | }
44 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/php/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: PHP mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
CodeMirror: PHP mode
17 |
18 |
29 |
30 |
41 |
42 |
Simple HTML/PHP mode based on
43 | the C-like mode. Depends on XML,
44 | JavaScript, CSS, and C-like modes.
54 |
55 |
56 |
--------------------------------------------------------------------------------
/kernel/src/main/scala/com/bwater/notebook/kernel/ConfigUtils.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook.kernel
9 |
10 | import java.io.File
11 | import com.typesafe.config.Config
12 | import collection.JavaConversions._
13 | import com.typesafe.config.ConfigException
14 |
15 |
16 | object ConfigUtils {
17 |
18 | implicit def configToRichConfig(config: Config) = new EasyConfig(config)
19 |
20 | class EasyConfig(config: Config) {
21 | def get(key: String) = if (config.hasPath(key)) Some(config.getString(key)) else None
22 |
23 | def getArray(key: String): Option[List[String]] = {
24 | if (config.hasPath(key)) {
25 | Some(configPathAsList(config, key))
26 | } else None
27 | }
28 |
29 | def getMem(key: String) = get(key) map parseMem
30 | }
31 |
32 | private def configPathAsList(c: Config, path: String) = {
33 | scala.util.control.Exception.allCatch.either(c.getStringList(path).toList) match {
34 | /* Read scalar value as list for backwards compat with config that has been converted from scalar to list. */
35 | case Left(_: ConfigException.WrongType) => List(c.getString(path))
36 | case Left(e) => throw e
37 | case Right(v) => v
38 | }
39 | }
40 |
41 | private val MemSpec = """\s*(\d+)\s*([kKmMgG]?)""".r
42 |
43 | private def parseMem(memString: String) = {
44 | val MemSpec(mem, unit) = memString
45 | mem.toLong << (unit match {
46 | case "" => 0
47 | case "k" => 10
48 | case "m" => 20
49 | case "g" => 30
50 | })
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/observable/src/main/scala/com/bwater/notebook/Connection.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook
9 |
10 | /**
11 | * Author: Ken
12 | * An observer and observable - mutable data that can be changed or subscribed to
13 | */
14 | trait Connection[T] {
15 |
16 | def observable: Observable[T]
17 | def observer: Observer[T]
18 |
19 | def biMap[A](codec: Codec[T,A]): Connection[A] = new MappingConnection[T,A](Connection.this, codec)
20 |
21 | def biMap[A](aToB: A=>T, bToA: T=>A): Connection[A] = biMap[A](new Codec[T,A] {
22 | def encode(x: T) = bToA(x)
23 | def decode(x: A) = aToB(x)
24 | })
25 |
26 | def <--(other: Connection[T]) {
27 | other.observable.subscribe(observer)
28 | }
29 |
30 | def -->(other: Connection[T]) {
31 | observable.subscribe(other.observer)
32 | }
33 |
34 | def <-->(other: Connection[T]) {
35 | this <-- other
36 | this --> other
37 | }
38 | }
39 |
40 | class ConcreteConnection[T](val observable: Observable[T], val observer: Observer[T]) extends Connection[T]
41 |
42 | object Connection {
43 | def just[T](v: T) = new ConcreteConnection[T](Observable.just(v), new NoopObserver[T]())
44 | }
45 |
46 | class MappingConnection[A,B](inner:Connection[A], codec: Codec[A,B]) extends Connection[B] {
47 | val observable = new MappingObservable[A,B] {
48 | protected def innerObservable = inner.observable
49 | protected def observableMapper = codec.encode
50 | }
51 |
52 | val observer = new MappingObserver[A,B] {
53 | protected def innerObserver = inner.observer
54 | protected def observerMapper = codec.decode
55 | }
56 | }
--------------------------------------------------------------------------------
/common/src/main/scala/com/bwater/notebook/util/Logging.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook.util
9 |
10 | import org.slf4j.LoggerFactory
11 |
12 | trait Logging {
13 |
14 | private[this] val log = LoggerFactory.getLogger(this.getClass)
15 |
16 | protected[this] def logInfo(messageGenerator: =>String) { if (log.isInfoEnabled) log.info(messageGenerator) }
17 | protected[this] def logInfo(messageGenerator: =>String, e: Throwable) { if (log.isInfoEnabled)log.info(messageGenerator, e) }
18 |
19 | protected[this] def logDebug(messageGenerator: =>String) {if (log.isDebugEnabled) log.debug(messageGenerator) }
20 | protected[this] def logDebug(messageGenerator: =>String, e: Throwable) {if (log.isDebugEnabled) log.debug(messageGenerator, e) }
21 |
22 | protected[this] def logTrace(messageGenerator: =>String) { if (log.isTraceEnabled) log.trace(messageGenerator) }
23 | protected[this] def logTrace(messageGenerator: =>String, e: Throwable) { if (log.isTraceEnabled)log.info(messageGenerator, e) }
24 |
25 | protected[this] def logError(messageGenerator: =>String) { log.error(messageGenerator) }
26 | protected[this] def logError(messageGenerator: =>String, e: Throwable) { log.error(messageGenerator, e) }
27 |
28 | protected[this] def logWarn(messageGenerator: =>String) { log.warn(messageGenerator) }
29 | protected[this] def logWarn(messageGenerator: =>String, e: Throwable) { log.warn(messageGenerator, e) }
30 |
31 |
32 | protected[this] def ifDebugEnabled(f: => Unit) = if (log.isDebugEnabled()) f
33 | protected[this] def ifTraceEnabled(f: => Unit) = if (log.isTraceEnabled()) f
34 | }
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/demo/vim.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Vim bindings demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
CodeMirror: Vim bindings demo
19 |
20 |
35 |
36 |
The vim keybindings are enabled by
37 | including keymap/vim.js and setting
38 | the keyMap option to "vim". Because
39 | CodeMirror's internal API is quite different from Vim, they are only
40 | a loose approximation of actual vim bindings, though.
The HTML mixed mode depends on the XML, JavaScript, and CSS modes.
45 |
46 |
MIME types defined:text/html
47 | (redefined, only takes effect if you load this parser after the
48 | XML parser).
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/common/src/main/scala/com/bwater/notebook/Renderer.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook
9 |
10 | import xml.{NodeBuffer, Text, NodeSeq}
11 | import runtime.BoxedUnit
12 |
13 | /**
14 | * Typeclass for rendering objects of a specific type. Implement one of these and import it
15 | * in your notebook to change how objects of the specified type get presented after evaluation.
16 | */
17 | trait Renderer[-A] {
18 | def render(value: A): NodeSeq
19 | }
20 |
21 | class WidgetRenderer[-A](toWidget: A => Widget) extends Renderer[A] {
22 | def render(value: A) = toWidget(value).toHtml
23 | }
24 |
25 | object Renderer extends LowPriorityRenderers {
26 | implicit object htmlAsItself extends Renderer[NodeSeq] {
27 | def render(value: NodeSeq) = value
28 | }
29 | implicit object nodeBufferAsItself extends Renderer[NodeBuffer] {
30 | def render(value: NodeBuffer) = value
31 | }
32 | implicit object widgetAsItself extends Renderer[Widget] {
33 | def render(value: Widget) = value.toHtml
34 | }
35 | implicit object stringAsItself extends Renderer[String] {
36 | def render(value: String) = Text(value)
37 | }
38 | implicit object anyValAsItself extends Renderer[AnyVal] {
39 | def render(value: AnyVal) = if (value == BoxedUnit.UNIT) NodeSeq.Empty else Text(value.toString)
40 | }
41 | }
42 |
43 | trait LowPriorityRenderers {
44 | implicit object seqAsColumn extends Renderer[Seq[_]] {
45 | def render(x: Seq[_]) = {
46 | val values = if (x.lengthCompare(25) < 0) x.map(_.toString) else x.take(24).map(_.toString) :+ "..."
47 | widgets.column(values.map(widgets.text(_)):_*)
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/xml/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: XML mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
CodeMirror: XML mode
13 |
25 |
31 |
The XML mode supports two configuration parameters:
32 |
33 |
htmlMode (boolean)
34 |
This switches the mode to parse HTML instead of XML. This
35 | means attributes do not have to be quoted, and some elements
36 | (such as br) do not require a closing tag.
37 |
alignCDATA (boolean)
38 |
Setting this to true will force the opening tag of CDATA
39 | blocks to not be indented.
40 |
41 |
42 |
MIME types defined:application/xml, text/html.
43 |
44 |
45 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/lib/util/runmode.js:
--------------------------------------------------------------------------------
1 | CodeMirror.runMode = function(string, modespec, callback, options) {
2 | var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
3 | var isNode = callback.nodeType == 1;
4 | var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
5 | if (isNode) {
6 | var node = callback, accum = [], col = 0;
7 | callback = function(text, style) {
8 | if (text == "\n") {
9 | accum.push(" ");
10 | col = 0;
11 | return;
12 | }
13 | var escaped = "";
14 | // HTML-escape and replace tabs
15 | for (var pos = 0;;) {
16 | var idx = text.indexOf("\t", pos);
17 | if (idx == -1) {
18 | escaped += CodeMirror.htmlEscape(text.slice(pos));
19 | col += text.length - pos;
20 | break;
21 | } else {
22 | col += idx - pos;
23 | escaped += CodeMirror.htmlEscape(text.slice(pos, idx));
24 | var size = tabSize - col % tabSize;
25 | col += size;
26 | for (var i = 0; i < size; ++i) escaped += " ";
27 | pos = idx + 1;
28 | }
29 | }
30 |
31 | if (style)
32 | accum.push("" + escaped + "");
33 | else
34 | accum.push(escaped);
35 | }
36 | }
37 | var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
38 | for (var i = 0, e = lines.length; i < e; ++i) {
39 | if (i) callback("\n");
40 | var stream = new CodeMirror.StringStream(lines[i]);
41 | while (!stream.eol()) {
42 | var style = mode.token(stream, state);
43 | callback(stream.current(), style, i, stream.start);
44 | stream.start = stream.pos;
45 | }
46 | }
47 | if (isNode)
48 | node.innerHTML = accum.join("");
49 | };
50 |
--------------------------------------------------------------------------------
/common/src/main/scala/com/bwater/notebook/Widget.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook
9 |
10 | import util.ClassUtils
11 | import xml.{Node, NodeSeq}
12 | import java.util.UUID
13 | import scalaz._
14 |
15 | trait Widget extends Iterable[Node] {
16 | def toHtml: NodeSeq
17 |
18 | def iterator = toHtml.iterator
19 |
20 | def ++(other: Widget): Widget = toHtml ++ other
21 |
22 | override def toString = "<" + ClassUtils.getSimpleName(getClass) + " widget>"
23 | }
24 |
25 | class SimpleWidget(html: NodeSeq) extends Widget {
26 | def toHtml = html
27 | override def toString = ""
28 | }
29 |
30 | object Widget {
31 | implicit def toHtml(widget: Widget): NodeSeq = widget.toHtml
32 | def fromHtml(html: NodeSeq): Widget = new SimpleWidget(html)
33 |
34 | implicit def fromRenderer[A](value: A)(implicit renderer: Renderer[A]): Widget = fromHtml(renderer.render(value))
35 |
36 | object Empty extends Widget {
37 | def toHtml = NodeSeq.Empty
38 | override def toString = ""
39 | }
40 |
41 | implicit val widgetInstances = new Monoid[Widget] {
42 | def zero = Empty
43 | def append(s1: Widget, s2: ⇒ Widget) = s1 ++ s2
44 | }
45 |
46 | // We're stripping out dashes because we want these to be valid JS identifiers.
47 | // Prepending with the "obs_" accomplishes that as well in that it forces it to
48 | // start with a letter, but it also helps make the namespace a little more
49 | // manageable.
50 | @deprecated("Avoid using IDs in widgets, to support the same widget appearing in multiple places on a page.", "1.0")
51 | def generateId = "widget_" + UUID.randomUUID().toString.replaceAll("-", "")
52 | }
53 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/plsql/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Oracle PL/SQL mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
CodeMirror: Oracle PL/SQL mode
13 |
14 |
46 |
47 |
55 |
56 |
57 | Simple mode that handles Oracle PL/SQL language (and Oracle SQL, of course).
58 |
59 |
60 |
MIME type defined:text/x-plsql
61 | (PLSQL code)
62 |
63 |
--------------------------------------------------------------------------------
/common/src/main/scala/com/bwater/notebook/widgets/DropDown.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook
9 | package widgets
10 |
11 | import com.bwater.notebook.Widget
12 | import net.liftweb.json.JsonAST.{JValue, JArray, JInt}
13 | import net.liftweb.json.JsonDSL._
14 | import net.liftweb.json.DefaultFormats
15 | import rx.Observable
16 |
17 | class DropDown[A](options: Seq[A], toString: A=>String = (a:A)=>a.toString) extends Widget {
18 |
19 | implicit val formats = DefaultFormats // JSON formats
20 |
21 | // Just implement the second function here to support option changing in JavaScript
22 | private lazy val _optionsConnection = JSBus.createConnection
23 | lazy val optionsConnection = _optionsConnection.biMap[Seq[A]](
24 | (s: Seq[A]) => JArray(s.zipWithIndex map { case (opt, i) => ("text" -> toString(opt)) ~ ("index" -> i) } toList), (_:JValue) => Seq[A]() )
25 |
26 | private lazy val _selected = JSBus.createConnection
27 | lazy val selected = _selected.biMap[A]((a:A) => JInt(options.indexOf(a)), (v:JValue) => options(v.extract[Int]))
28 |
29 | optionsConnection <-- Connection.just(options)
30 |
31 | lazy val toHtml =
32 |
38 | }
39 |
40 | object DropDown {
41 | private val defaultToString: Any => String = _.toString
42 | }
--------------------------------------------------------------------------------
/observable/src/main/scala/com/bwater/notebook/Observable.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Bridgewater Associates, LP
3 | *
4 | * Distributed under the terms of the Modified BSD License. The full license is in
5 | * the file COPYING, distributed as part of this software.
6 | */
7 |
8 | package com.bwater.notebook
9 |
10 | /**
11 | * Author: Ken
12 | * An observer trait, which is unfortunately lacking in rx.Subscription
13 | */
14 | trait Observable[T] {
15 | def subscribe(observer: Observer[T]): rx.Subscription
16 |
17 | // def subscribe(next: T=>Unit): rx.Subscription = subscribe(new ConcreteObserver[T]{ override def onNext(args:T) = next(args) })
18 |
19 | def map[A](fxn: T=>A):Observable[A] = new Observable[A] {
20 | def subscribe(observer: Observer[A]) = Observable.this.subscribe(observer map fxn)
21 | }
22 | }
23 |
24 | class WrappedObservable[T](inner: rx.Observable[T]) extends Observable[T] {
25 | def subscribe(observer: Observer[T]) = inner.subscribe(observer)
26 | }
27 |
28 | class ConcreteObservable[T] extends Observable[T] {
29 | protected val observableHandler = rx.subjects.Subject.create[T]
30 |
31 | def subscribe(observer: Observer[T]) = observableHandler.subscribe(observer)
32 | }
33 |
34 | trait MappingObservable[A,B] extends Observable[B] {
35 | protected def innerObservable: Observable[A]
36 |
37 | protected def observableMapper: A=>B
38 |
39 | def subscribe(observer: Observer[B]) = innerObservable.subscribe(observer map observableMapper)
40 | }
41 |
42 |
43 | object Observable {
44 | def just[T](x: T): Observable[T] = new WrappedObservable[T](rx.Observable.just(x))
45 |
46 | def timer[T](x: Stream[T], delay: Int) = new WrappedObservable[T](rx.Observable.toObservable(new java.lang.Iterable[T] {
47 | def iterator = {
48 | import collection.JavaConversions._
49 | x.map(x => { Thread.sleep(delay * 100); x }).toIterator
50 | }
51 | }))
52 | }
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/mode/tiki/index.html:
--------------------------------------------------------------------------------
1 |
2 |
Demonstration of a multiplexing mode, which, at certain
51 | boundary strings, switches to one or more inner modes. The out
52 | (HTML) mode does not get fed the content of the <<
53 | >> blocks. See
54 | the manual and
55 | the source for more
56 | information.
Tabs inside the editor are spans with the
45 | class cm-tab, and can be styled. This demo uses
46 | an :after pseudo-class CSS hack that will not work on old
47 | browsers. You can use a more conservative technique like a background
48 | image as an alternative.
Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on
44 | JavaScript, CSS and XML. Other dependancies include those of the scriping language chosen.
48 |
49 |
50 |
--------------------------------------------------------------------------------
/server/src/test/scala/NBSerializerTests.scala:
--------------------------------------------------------------------------------
1 | import com.bwater.notebook.NBSerializer
2 | import com.bwater.notebook.NBSerializer._
3 | import org.scalatest.exceptions.TestFailedException
4 | import org.scalatest.FlatSpec
5 | import net.liftweb.json._
6 | import net.liftweb.json.Serialization
7 |
8 | /**
9 | * Author: Ken
10 | */
11 |
12 | class NBSerializerTests extends FlatSpec {
13 | val testnb = Notebook(new Metadata("ken1"), List(Worksheet(List(CodeCell("1+2", "python", false, Some(2), List(ScalaOutput(2, None, Some("3"))))))), Nil, None)
14 |
15 | "Notebook Serializer" should "write and read back a simple notebook" in {
16 | val s = NBSerializer.write(testnb)
17 | val res = NBSerializer.read(s)
18 | assert(testnb === res)
19 | }
20 | it should "read data scraped from iPython " in {
21 | val ipData = """{"worksheets":[{"cells":[{"input":"1+2","cell_type":"code","prompt_number":1,"outputs":[{"output_type":"pyout","prompt_number":1,"text":"res0: Int = 3\n"}],"language":"python","collapsed":false},{"input":"","cell_type":"code","outputs":[],"language":"python","collapsed":true}]}],"metadata":{"name":"Untitled2"},"nbformat":3}"""
22 | println(pretty(render(parse(NBSerializer.write(testnb)))))
23 | println(pretty(render(parse(ipData))))
24 | val nb = NBSerializer.read(ipData)
25 | assert (nb.name === "Untitled2")
26 | nb.worksheets.head.cells.head match {
27 | case CodeCell("1+2", _, _, _, _) =>
28 | case x => throw new TestFailedException("Expected serialized notebook, got " + x, 0)
29 | }
30 | }
31 | it should "read notebook with HTML outputs and stream" in {
32 | val data = """{"worksheets":[{"cells":[{"input":"3 * 3","cell_type":"code","prompt_number":1,"outputs":[{"output_type":"stream","text":"res0: Int = 9\n","stream":"stdout"},{"output_type":"pyout","prompt_number":1,"html":"9"}],"language":"python","collapsed":false}]}],"metadata":{"name":"Untitled4"},"nbformat":3}"""
33 | NBSerializer.read(data)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Scala Notebook
2 | ==============
3 |
4 | A more friendly, browser-based interactive Scala prompt (REPL).
5 |
6 | Based on the IPython notebook project, this project will let you interact with Scala in a browser window, which has the following advantages over the standard REPL:
7 |
8 | * Easy to view and edit past commands
9 | * Commands can return HTML or images, allowing richer interactivity (charts, for example)
10 | * Notebooks can be saved and loaded, providing a bridge between interactive REPL and classes in a project
11 | * Supports mixing Scala expressions and markdown, letting you create rich, interactive documents similar to Mathematica
12 |
13 | While I think this tool will be helpful for everyone using Scala, I expect it to be particularly valuable for the scientific and analytics community.
14 |
15 |
16 | Using Scala Notebook
17 | ----------------------
18 |
19 | ## Building From Source
20 | * To build and run from SBT, type
21 |
22 | ```scala
23 | project server
24 | run
25 | ```
26 |
27 | 
28 |
29 | Development
30 | -----------
31 |
32 | [](http://travis-ci.org/Bridgewater/scala-notebook)
33 |
34 | ### IDE Setup
35 |
36 | * If you're using an IntelliJ project, note that by default IntelliJ will not include SSP files resources. Change settings in IntelliJ to to include '*' as resource extension.
37 |
38 | ### Overview
39 |
40 | Having the web server process separate from the process doing the evaluation is also important in Scala; we want to separate
41 | the user's actions from the web server, allowing a restart of the client process (after building new client libraries, for example).
42 |
43 | To that end, the project is organized as follows:
44 | * *server* is the web server
45 | * *common* are the classes shared by both
46 | * *observable*
47 | * *kernel*
48 | * *subprocess*
49 |
50 |
51 | ### Architecture
52 |
53 | * Server
54 | * Kernel(s)
55 | * Widgets
56 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/demo/mustache.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Overlay Parser Demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
15 |
16 |
17 |
CodeMirror: Overlay Parser Demo
18 |
19 |
30 |
31 |
49 |
50 |
Demonstration of a mode that parses HTML, highlighting
51 | the Mustache templating
52 | directives inside of it by using the code
53 | in overlay.js. View
54 | source to see the 15 lines of code needed to accomplish this.
Loosely based on Franciszek
64 | Wawrzak's CodeMirror
65 | 1 mode. One configuration parameter is
66 | supported, specials, to which you can provide an
67 | array of strings to have those identifiers highlighted with
68 | the lua-special style.
The emacs keybindings are enabled by
35 | including keymap/emacs.js and setting
36 | the keyMap option to "emacs". Because
37 | CodeMirror's internal API is quite different from Emacs, they are only
38 | a loose approximation of actual emacs bindings, though.
39 |
40 |
Also note that a lot of browsers disallow certain keys from being
41 | captured. For example, Chrome blocks both Ctrl-W and Ctrl-N, with the
42 | result that idiomatic use of Emacs keys will constantly close your tab
43 | or open a new window.
44 |
45 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/js/page.js:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------------
2 | // Copyright (C) 2008-2011 The IPython Development Team
3 | //
4 | // Distributed under the terms of the BSD License. The full license is in
5 | // the file COPYING, distributed as part of this software.
6 | //----------------------------------------------------------------------------
7 |
8 | //============================================================================
9 | // Global header/site setup.
10 | //============================================================================
11 |
12 | var IPython = (function (IPython) {
13 |
14 | var Page = function () {
15 | this.style();
16 | this.bind_events();
17 | };
18 |
19 | Page.prototype.style = function () {
20 | $('div#header').addClass('border-box-sizing').
21 | addClass('ui-widget ui-widget-content').
22 | css('border-top-style','none').
23 | css('border-left-style','none').
24 | css('border-right-style','none');
25 | $('div#site').addClass('border-box-sizing')
26 | };
27 |
28 |
29 | Page.prototype.bind_events = function () {
30 | };
31 |
32 |
33 | Page.prototype.show = function () {
34 | // The header and site divs start out hidden to prevent FLOUC.
35 | // Main scripts should call this method after styling everything.
36 | this.show_header();
37 | this.show_site();
38 | };
39 |
40 |
41 | Page.prototype.show_header = function () {
42 | // The header and site divs start out hidden to prevent FLOUC.
43 | // Main scripts should call this method after styling everything.
44 | $('div#header').css('display','block');
45 | };
46 |
47 |
48 | Page.prototype.show_site = function () {
49 | // The header and site divs start out hidden to prevent FLOUC.
50 | // Main scripts should call this method after styling everything.
51 | $('div#site').css('display','block');
52 | };
53 |
54 |
55 | IPython.Page = Page;
56 |
57 | return IPython;
58 |
59 | }(IPython));
60 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/js/layoutmanager.js:
--------------------------------------------------------------------------------
1 | //----------------------------------------------------------------------------
2 | // Copyright (C) 2008-2011 The IPython Development Team
3 | //
4 | // Distributed under the terms of the BSD License. The full license is in
5 | // the file COPYING, distributed as part of this software.
6 | //----------------------------------------------------------------------------
7 |
8 | //============================================================================
9 | // Layout
10 | //============================================================================
11 |
12 | var IPython = (function (IPython) {
13 |
14 | var LayoutManager = function () {
15 | this.bind_events();
16 | };
17 |
18 |
19 | LayoutManager.prototype.bind_events = function () {
20 | var that = this;
21 | $(window).resize($.proxy(this.do_resize,this));
22 | $('div#expand_header > a').click($.proxy(this.toggle_header, this));
23 | };
24 |
25 |
26 | LayoutManager.prototype.do_resize = function () {
27 | var win = $(window);
28 | var w = win.width();
29 | var h = win.height();
30 | var header_height;
31 | if ($('div#header').css('display') === 'none') {
32 | header_height = 0;
33 | } else {
34 | header_height = $('div#header').outerHeight(true);
35 | }
36 | var menubar_height;
37 | if ($('div#header').css('display') === 'none') {
38 | menubar_height = 0;
39 | } else {
40 | menubar_height = $('div#menubar_container').outerHeight(true);
41 | }
42 |
43 | var app_height = h-header_height-menubar_height; // content height
44 |
45 | $('div#notebook_panel').height(app_height); // content+padding+border height
46 | };
47 |
48 | LayoutManager.prototype.toggle_header = function() {
49 | $('div#expand_header').toggle();
50 | $('div#header').toggle();
51 | $('div#menubar_container').toggle();
52 | this.do_resize();
53 | }
54 |
55 | IPython.LayoutManager = LayoutManager;
56 |
57 | return IPython;
58 |
59 | }(IPython));
60 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/css/page.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Primary styles
3 | *
4 | * Author: IPython Development Team
5 | */
6 |
7 |
8 | body {
9 | background-color: white;
10 | /* This makes sure that the body covers the entire window and needs to
11 | be in a different element than the display: box in wrapper below */
12 | position: absolute;
13 | left: 0px;
14 | right: 0px;
15 | top: 0px;
16 | bottom: 0px;
17 | overflow: visible;
18 | }
19 |
20 |
21 | div#header {
22 | /* Initially hidden to prevent FLOUC */
23 | display: none;
24 | position: relative;
25 | height: 40px;
26 | padding: 5px;
27 | margin: 0px;
28 | width: 100%;
29 | }
30 |
31 | div#expand_header {
32 | display: none;
33 | padding: 0px;
34 | margin: 0px;
35 | text-align: right;
36 | width: 100%;
37 | }
38 |
39 | div#logo {
40 | float: right;
41 | height: 100%;
42 | display: table
43 | }
44 |
45 | span#ipython_notebook {
46 | position: absolute;
47 | padding: 2px 2px 2px 5px;
48 | }
49 |
50 | span#ipython_notebook h1 img {
51 | font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
52 | height: 24px;
53 | text-decoration:none;
54 | display: inline;
55 | color: black;
56 | }
57 |
58 | #site {
59 | width: 100%;
60 | display: none;
61 | min-width: 1024px;
62 | }
63 |
64 | /* We set the fonts by hand here to override the values in the theme */
65 | .ui-widget {
66 | font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
67 | }
68 |
69 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button {
70 | font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
71 | }
72 |
73 | /* Smaller buttons */
74 | .ui-button .ui-button-text {
75 | padding: 0.2em 0.8em;
76 | font-size: 77%;
77 | }
78 |
79 | input.ui-button {
80 | padding: 0.3em 0.9em;
81 | }
82 |
83 | span#login_widget {
84 | float: right;
85 | }
86 |
87 | .border-box-sizing {
88 | box-sizing: border-box;
89 | -moz-box-sizing: border-box;
90 | -webkit-box-sizing: border-box;
91 | }
92 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/demo/runmode.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Mode Runner Demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
CodeMirror: Mode Runner Demo
13 |
14 |
20 |
21 |
22 |
23 |
29 |
30 |
Running a CodeMirror mode outside of the editor.
31 | The CodeMirror.runMode function, defined
32 | in lib/runmode.js takes the following arguments:
If this is a function, it will be called for each token with
41 | two arguments, the token's text and the token's style class (may
42 | be null for unstyled tokens). If it is a DOM node,
43 | the tokens will be converted to span elements as in
44 | an editor, and inserted into the node
45 | (through innerHTML).
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/subprocess/src/main/scala/com/bwater/notebook/Kernel.scala:
--------------------------------------------------------------------------------
1 | package com.bwater.notebook
2 |
3 | import akka.actor._
4 | import akka.actor.Deploy
5 | import scala.concurrent._
6 | import kernel.remote.{RemoteActorSystem, RemoteActorProcess}
7 | import scala.concurrent.duration._
8 | import java.util.concurrent.ConcurrentHashMap
9 | import scala.collection.JavaConverters._
10 |
11 | /**
12 | * A kernel is a remote VM with a set of sub-actors, each of which interacts with local resources (for example, WebSockets).
13 | * The local resource must be fully initialized before we will let messages flow through to the remote actor. This is
14 | * accomplished by blocking on actor startup
15 | * to the remote (this is accomplished by blocking on startup waiting for
16 | */
17 |
18 | class Kernel(system: ActorSystem) {
19 | implicit val executor = system.dispatcher
20 |
21 | val router = system.actorOf(Props(new ExecutionManager))
22 |
23 | private val remoteDeployPromise = Promise[Deploy]
24 |
25 | def remoteDeployFuture = remoteDeployPromise.future
26 |
27 | case object ShutdownNow
28 |
29 | def shutdown() { router ! ShutdownNow }
30 |
31 | class ExecutionManager extends Actor with ActorLogging {
32 | // These get filled in before we ever receive messages
33 | var remoteInfo: RemoteActorSystem = null
34 |
35 | override def preStart() {
36 | remoteInfo = Await.result( RemoteActorSystem.spawn(system, "kernel"), 1 minutes)
37 | remoteDeployPromise.success(remoteInfo.deploy)
38 | }
39 |
40 | override def postStop() {
41 | if (remoteInfo != null)
42 | remoteInfo.shutdownRemote()
43 | }
44 |
45 | def receive = {
46 | case ShutdownNow =>
47 | if (remoteInfo != null) {
48 | remoteInfo.shutdownRemote()
49 | }
50 | }
51 | }
52 | }
53 |
54 | object KernelManager {
55 | def shutdown() {
56 | kernels.values foreach { _.shutdown() }
57 | }
58 |
59 | val kernels = new ConcurrentHashMap[String, Kernel]().asScala
60 |
61 | def get(id: String) = kernels.get(id)
62 | def apply(id: String) = kernels(id)
63 |
64 | def add(id:String, kernel: Kernel) {
65 | kernels += id -> kernel
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/lib/util/overlay.js:
--------------------------------------------------------------------------------
1 | // Utility function that allows modes to be combined. The mode given
2 | // as the base argument takes care of most of the normal mode
3 | // functionality, but a second (typically simple) mode is used, which
4 | // can override the style of text. Both modes get to parse all of the
5 | // text, but when both assign a non-null style to a piece of code, the
6 | // overlay wins, unless the combine argument was true, in which case
7 | // the styles are combined.
8 |
9 | // overlayParser is the old, deprecated name
10 | CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, combine) {
11 | return {
12 | startState: function() {
13 | return {
14 | base: CodeMirror.startState(base),
15 | overlay: CodeMirror.startState(overlay),
16 | basePos: 0, baseCur: null,
17 | overlayPos: 0, overlayCur: null
18 | };
19 | },
20 | copyState: function(state) {
21 | return {
22 | base: CodeMirror.copyState(base, state.base),
23 | overlay: CodeMirror.copyState(overlay, state.overlay),
24 | basePos: state.basePos, baseCur: null,
25 | overlayPos: state.overlayPos, overlayCur: null
26 | };
27 | },
28 |
29 | token: function(stream, state) {
30 | if (stream.start == state.basePos) {
31 | state.baseCur = base.token(stream, state.base);
32 | state.basePos = stream.pos;
33 | }
34 | if (stream.start == state.overlayPos) {
35 | stream.pos = stream.start;
36 | state.overlayCur = overlay.token(stream, state.overlay);
37 | state.overlayPos = stream.pos;
38 | }
39 | stream.pos = Math.min(state.basePos, state.overlayPos);
40 | if (stream.eol()) state.basePos = state.overlayPos = 0;
41 |
42 | if (state.overlayCur == null) return state.baseCur;
43 | if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;
44 | else return state.overlayCur;
45 | },
46 |
47 | indent: base.indent && function(state, textAfter) {
48 | return base.indent(state.base, textAfter);
49 | },
50 | electricChars: base.electricChars
51 | };
52 | };
53 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/theme/ipython.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | .cm-s-ipython span.cm-keyword {color: #008000; font-weight: bold;}
4 | .cm-s-ipython span.cm-number {color: #000080;}
5 | .cm-s-ipython span.cm-operator {color: #AA22FF; font-weight: bold;}
6 | .cm-s-ipython span.cm-meta {color: #AA22FF;}
7 | .cm-s-ipython span.cm-comment {color: #408080; font-style: italic;}
8 | .cm-s-ipython span.cm-string {color: #BA2121;}
9 | .cm-s-ipython span.cm-error {color: #f00;}
10 | .cm-s-ipython span.cm-builtin {color: #008000;}
11 | .cm-s-ipython span.cm-variable {color: #000000;}
12 |
13 | div.CodeMirror { font-family:"Consolas", monospace; }
14 | div.CodeMirror span.CodeMirror-matchingbracket {background-color: #99CCFF; color: inherit; }
15 | div.CodeMirror span.CodeMirror-nonmatchingbracket {background-color: #FFDCDC; color: inherit;}
16 |
17 | /* These classes are not currently used in the python.js mode */
18 |
19 | /*.cm-s-ipython span.cm-atom {color: #219;}*/
20 | /*.cm-s-ipython span.cm-def {color: #00f;}*/
21 | /*.cm-s-ipython span.cm-variable-2 {color: #05a;}*/
22 | /*.cm-s-ipython span.cm-variable-3 {color: #0a5;}*/
23 | /*.cm-s-ipython span.cm-property {color: black;}*/
24 | /*.cm-s-ipython span.cm-qualifier {color: #555;}*/
25 | /*.cm-s-ipython span.cm-bracket {color: #cc7;}*/
26 | /*.cm-s-ipython span.cm-tag {color: #170;}*/
27 | /*.cm-s-ipython span.cm-attribute {color: #00c;}*/
28 |
29 | /* These are the old styles for our pre-themed version */
30 |
31 | /*span.py-delimiter {color: #666666;}*/
32 | /*span.py-special {color: #666666;}*/
33 | /*span.py-operator {color: #AA22FF; font-weight: bold;}*/
34 | /*span.py-keyword {color: #008000; font-weight: bold;}*/
35 | /*span.py-number {color: #666666;}*/
36 | /*span.py-identifier {color: #000000;}*/
37 | /*span.py-func {color: #000000;}*/
38 | /*span.py-type {color: #008000;}*/
39 | /*span.py-decorator {color: #AA22FF;}*/
40 | /*span.py-comment {color: #408080; font-style: italic;}*/
41 | /*span.py-string {color: #BA2121;}*/
42 | /*span.py-bytes {color: #BA2121;}*/
43 | /*span.py-raw {color: #BA2121;}*/
44 | /*span.py-unicode {color: #BA2121;}*/
45 |
46 | div.CodeMirror-selected { background: #E6E6E6; }
47 | .CodeMirror-focused div.CodeMirror-selected { background: #90cfe4; }
--------------------------------------------------------------------------------
/server/src/main/scala/Scalate.scala:
--------------------------------------------------------------------------------
1 | package com.bwater.notebook
2 | package server
3 |
4 | import org.fusesource.scalate.{
5 | TemplateEngine, Binding, DefaultRenderContext, RenderContext}
6 | import unfiltered.request.{Path,HttpRequest}
7 | import unfiltered.response.{ResponseWriter}
8 | import java.io.{File,OutputStreamWriter,PrintWriter}
9 | import scala.util.control.NonFatal
10 |
11 | object Scalate {
12 | /** Constructs a ResponseWriter for Scalate templates.
13 | * Note that any parameter in the second, implicit set
14 | * can be overriden by specifying an implicit value of the
15 | * expected type in a pariticular scope. */
16 | def apply[A, B](request: HttpRequest[A],
17 | template: String,
18 | attributes:(String,Any)*)
19 | ( implicit
20 | engine: TemplateEngine = defaultEngine,
21 | contextBuilder: ToRenderContext = defaultRenderContext,
22 | bindings: List[Binding] = Nil,
23 | additionalAttributes: Seq[(String, Any)] = Nil
24 | ) = new ResponseWriter {
25 | def write(writer: OutputStreamWriter) {
26 | val printWriter = new PrintWriter(writer)
27 | try {
28 | val scalateTemplate = engine.load(template, bindings)
29 | val context = contextBuilder(Path(request), printWriter, engine)
30 | (additionalAttributes ++ attributes) foreach {
31 | case (k,v) => context.attributes(k) = v
32 | }
33 | engine.layout(scalateTemplate, context)
34 | } catch {
35 | case NonFatal(e) if engine.isDevelopmentMode =>
36 | printWriter.println("Exception: " + e.getMessage)
37 | e.getStackTrace.foreach(printWriter.println)
38 | case NonFatal(e) => throw e
39 | }
40 | }
41 | }
42 |
43 | /* Function to construct a RenderContext. */
44 | type ToRenderContext =
45 | (String, PrintWriter, TemplateEngine) => RenderContext
46 |
47 | private val defaultTemplateDirs =
48 | new File("src/main/resources/templates") :: Nil
49 | private val defaultEngine = new TemplateEngine(defaultTemplateDirs, "development")
50 | private val defaultRenderContext: ToRenderContext =
51 | (path, writer, engine) =>
52 | new DefaultRenderContext(path, engine, writer)
53 | }
54 |
--------------------------------------------------------------------------------
/server/src/main/assets/from_ipython/static/codemirror/theme/lesser-dark.css:
--------------------------------------------------------------------------------
1 | /*
2 | http://lesscss.org/ dark theme
3 | Ported to CodeMirror by Peter Kroon
4 | */
5 | .cm-s-lesser-dark {
6 | line-height: 1.3em;
7 | }
8 | .cm-s-lesser-dark {
9 | font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Monaco', Courier, monospace !important;
10 | }
11 |
12 | .cm-s-lesser-dark { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }
13 | .cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/
14 | .cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
15 | .cm-s-lesser-dark .CodeMirror-lines { margin-left:3px; margin-right:3px; }/*editable code holder*/
16 |
17 | div.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
18 |
19 | .cm-s-lesser-dark .CodeMirror-gutter { background: #262626; border-right:1px solid #aaa; padding-right:3px; min-width:2.5em; }
20 | .cm-s-lesser-dark .CodeMirror-gutter-text { color: #777; }
21 |
22 | .cm-s-lesser-dark span.cm-keyword { color: #599eff; }
23 | .cm-s-lesser-dark span.cm-atom { color: #C2B470; }
24 | .cm-s-lesser-dark span.cm-number { color: #B35E4D; }
25 | .cm-s-lesser-dark span.cm-def {color: white;}
26 | .cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }
27 | .cm-s-lesser-dark span.cm-variable-2 { color: #669199; }
28 | .cm-s-lesser-dark span.cm-variable-3 { color: white; }
29 | .cm-s-lesser-dark span.cm-property {color: #92A75C;}
30 | .cm-s-lesser-dark span.cm-operator {color: #92A75C;}
31 | .cm-s-lesser-dark span.cm-comment { color: #666; }
32 | .cm-s-lesser-dark span.cm-string { color: #BCD279; }
33 | .cm-s-lesser-dark span.cm-string-2 {color: #f50;}
34 | .cm-s-lesser-dark span.cm-meta { color: #738C73; }
35 | .cm-s-lesser-dark span.cm-error { color: #9d1e15; }
36 | .cm-s-lesser-dark span.cm-qualifier {color: #555;}
37 | .cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
38 | .cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
39 | .cm-s-lesser-dark span.cm-tag { color: #669199; }
40 | .cm-s-lesser-dark span.cm-attribute {color: #00c;}
41 | .cm-s-lesser-dark span.cm-header {color: #a0a;}
42 | .cm-s-lesser-dark span.cm-quote {color: #090;}
43 | .cm-s-lesser-dark span.cm-hr {color: #999;}
44 | .cm-s-lesser-dark span.cm-link {color: #00c;}
45 |
--------------------------------------------------------------------------------
/server/src/main/assets/templates/default.ssp:
--------------------------------------------------------------------------------
1 | <%@ var body: String %>
2 | <%@ var title: String = "Scala Notebook" %>
3 | <%@ var stylesheet: String = "" %>
4 | <%@ var meta: String = "" %>
5 | <%@ var params: String = "" %>
6 | <%@ var header: String = "" %>
7 | <%@ var site: String = "" %>
8 | <%@ var script: String = "" %>
9 | <% import com.bwater.notebook.server.LayoutTools._ %>
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | ${title}
18 |
19 |
20 |
21 |
22 |
23 | ${unescape(stylesheet)}
24 |
25 | ${unescape(meta)}
26 |
27 |
28 |
29 |
30 |
31 |