Browse files

Added Prism for syntax highlighting and changed the way data is sent.

JSON is now used so additional info can be sent along with code (e.g. filename).
Fixed websocket closing issue on node.js side.
  • Loading branch information...
1 parent 421b9c3 commit 43a74b730ef7aa3203995cd5c55393bba51f6476 @mmarcon committed Aug 16, 2012
Showing with 182 additions and 28 deletions.
  1. +4 −2 livecode/livecode.py
  2. +100 −0 server/app/css/prism.css
  3. +15 −1 server/app/css/style.css
  4. +4 −5 server/app/index.html
  5. +31 −4 server/app/js/main.js
  6. +9 −0 server/app/js/prism.js
  7. +19 −16 server/server.js
View
6 livecode/livecode.py
@@ -3,6 +3,7 @@
import thread
import time
import multiprocessing
+import json
#view.run_command("livecode",{"execute":"on"})
@@ -46,12 +47,13 @@ def getbuffer(self, edit):
def get_buffer_internal(*args):
print "Getting Buffer"
view = sublime.active_window().active_view()
- self.queue.put(view.substr(sublime.Region(0, view.size())))
+ obj = {"code": view.substr(sublime.Region(0, view.size())), "file":view.file_name()}
+ self.queue.put(json.dumps(obj))
while self.running:
print "Other LOOP"
sublime.set_timeout(get_buffer_internal , 1)
- time.sleep(3)
+ time.sleep(1)
def turn_off(self, edit):
self.running = False
View
100 server/app/css/prism.css
@@ -0,0 +1,100 @@
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+ color: black;
+ text-shadow: 0 1px white;
+ font-family: Consolas, Monaco, 'Andale Mono', monospace;
+ direction: ltr;
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+ padding: 1em;
+ margin: .5em 0;
+ overflow: auto;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+ background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+ padding: .1em;
+ border-radius: .3em;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+ color: slategray;
+}
+
+.token.punctuation {
+ color: #999;
+}
+
+.namespace {
+ opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number {
+ color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string {
+ color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+ color: #a67f59;
+ background: hsla(0,0%,100%,.5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+ color: #07a;
+}
+
+
+.token.regex,
+.token.important {
+ color: #e90;
+}
+
+.token.important {
+ font-weight: bold;
+}
+
+.token.entity {
+ cursor: help;
+}
View
16 server/app/css/style.css
@@ -19,15 +19,29 @@ h1 {
color: #f08080;
}
+h2 {
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ height: 20px;
+ width: 150px;
+ background: rgba(0, 0, 0, 0.6);
+ color: white;
+ line-height: 20px;
+ padding: 3px 9px;
+ border-radius: 4px;
+}
+
#livecode {
- border: 1px dotted #ccc;
position: absolute;
top: 30px;
right: 0;
bottom: 0;
left: 0;
padding: 5px;
overflow: scroll;
+ background: #F5F2F0;
+ border-radius: 4px;
}
#livecode code {
View
9 server/app/index.html
@@ -5,20 +5,19 @@
<title>Livecode</title>
<link rel="stylesheet" type="text/css" href="css/reset.css" />
<link rel="stylesheet" type="text/css" href="css/style.css" />
+ <link rel="stylesheet" type="text/css" href="css/prism.css" />
</head>
<body id="home">
<div class="container">
<h1>Livecode</h1>
<section id="livecode">
- <pre>
- <code>
-
- </code>
- </pre>
+ <h2></h2>
+ <pre><code></code></pre>
</section>
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
+ <script type="text/javascript" src="js/prism.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
View
35 server/app/js/main.js
@@ -1,6 +1,6 @@
-(function($){
+(function($, P){
'use strict';
- var ws, onopen, onmessage, onclose, onerror, target = $('#livecode code');
+ var ws, onopen, onmessage, onclose, onerror, target = $('#livecode code'), h2 = $('h2'), setLanguage;
onopen = function(){
console.log('Connection opened!');
@@ -15,7 +15,34 @@
};
onmessage = function(e){
- target.text($.trim(e.data));
+ var obj = JSON.parse(e.data), match;
+ target.text($.trim(obj.code));
+ match = obj.file.match(/.+\/(.+\.(.+))$/);
+ h2.text(match[1]);
+ setLanguage(match[2]);
+ P.highlightAll();
+ };
+
+ setLanguage = function(ext){
+ var lang = 'none';
+ switch(ext){
+ case 'js':
+ lang = 'javascript';
+ break;
+ case 'css':
+ lang = 'css';
+ break;
+ case 'java':
+ lang = 'java';
+ break;
+ case 'html':
+ lang = 'markup';
+ break;
+ default:
+ lang = 'none';
+ }
+ target.removeClass();
+ target.addClass('language-' + lang);
};
$(function(){
@@ -25,4 +52,4 @@
ws.onclose = onclose;
ws.onerror = onerror;
});
-})(jQuery);
+})(jQuery, Prism);
View
9 server/app/js/prism.js
@@ -0,0 +1,9 @@
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
+ * @author Lea Verou http://lea.verou.me
+ */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={languages:{insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);Object.prototype.toString.call(e)==="[object Object]"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent.trim();if(!f)return;f=f.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\u00a0/g," ");var l={element:r,language:o,grammar:u,code:f};t.hooks.run("before-highlight",l);if(i&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){l.highlightedCode=n.stringify(JSON.parse(e.data));l.element.innerHTML=l.highlightedCode;s&&s.call(l.element);t.hooks.run("after-highlight",l)};c.postMessage(JSON.stringify({language:l.language,code:l.code}))}else{l.highlightedCode=t.highlight(l.code,l.grammar);l.element.innerHTML=l.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",l)}},highlight:function(e,r){return n.stringify(t.tokenize(e,r))},tokenize:function(e,n){var r=t.Token,i=[e],s=n.rest;if(s){for(var o in s)n[o]=s[o];delete n.rest}e:for(var o in n){if(!n.hasOwnProperty(o)||!n[o])continue;var u=n[o],a=u.inside,f=!!u.lookbehind||0;u=u.pattern||u;for(var l=0;l<i.length;l++){var c=i[l];if(i.length>e.length)break e;if(c instanceof r)continue;u.lastIndex=0;var h=u.exec(c);if(h){f&&(f=h[1].length);var p=h.index-1+f,h=h[0].slice(f),d=h.length,v=p+d,m=c.slice(0,p+1),g=c.slice(v+1),y=[l,1];m&&y.push(m);var b=new r(o,a?t.tokenize(h,a):h);y.push(b);g&&y.push(g);Array.prototype.splice.apply(i,y)}}}return i},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]"){for(var r=0;r<e.length;r++)e[r]=n.stringify(e[r]);return e.join("")}var i={type:e.type,content:n.stringify(e.content),tag:"span",classes:["token",e.type],attributes:{}};i.type=="comment"&&(i.attributes.spellcheck="true");t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+"</"+i.tag+">"};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();
+Prism.languages.markup={comment:/&lt;!--[\w\W]*?--(&gt;|&gt;)/g,prolog:/&lt;\?.+?\?&gt;/,doctype:/&lt;!DOCTYPE.+?&gt;/,cdata:/&lt;!\[CDATA\[[\w\W]+?]]&gt;/i,tag:{pattern:/&lt;\/?[\w:-]+\s*[\w\W]*?&gt;/gi,inside:{tag:{pattern:/^&lt;\/?[\w:-]+/i,inside:{punctuation:/^&lt;\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(('|")[\w\W]*?(\2)|[^\s>]+)/gi,inside:{punctuation:/=/g}},punctuation:/\/?&gt;/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&amp;#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&amp;/,"&"))});
+Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:/@[\w-]+?(\s+.+)?(?=\s*{|\s*;)/gi,url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\}]*(?=\s*\{)/g,property:/(\b|\B)[a-z-]+(?=\s*:)/ig,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});
+Prism.languages.javascript={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0},keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,number:/\b-?(0x)?\d*\.?\d+\b/g,operator:/[-+]{1,2}|!|=?&lt;|=?&gt;|={1,2}|(&amp;){1,2}|\|?\||\?|\*|\//g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});
+Prism.languages.java={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:true},string:/("|')(\\?.)*?\1/g,keyword:/\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/g,"boolean":/\b(true|false)\b/g,number:/\b-?(0x)?\d*\.?\d+\b/g,operator:/[-+]{1,2}|!|=?<|=?>|={1,2}|(&){1,2}|\|?\||\?|\*|\/|%|\^|(<){2}|($gt;){2,3}|:|~/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g}
View
35 server/server.js
@@ -23,10 +23,19 @@ var express = require('express'),
path = require('path'),
WS = require('ws').Server,
chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz',
- sockets = [];
+ sockets = {};
var generateId = function(){
return 'ws-' + Math.random().toFixed(3).replace(/\./, '') + '-' + Math.sqrt(Date.now()).toString().replace(/^\d+\./, '');
+},
+getAllExcept = function(object, key){
+ var result = [], k;
+ for (k in object) {
+ if (object.hasOwnProperty(k) && key !== k) {
+ result.push(object[k]);
+ }
+ }
+ return result;
};
app.use(express.bodyParser());
@@ -37,26 +46,20 @@ var wss = new WS({server: app});
wss.on('connection', function(ws) {
console.log('WS Connected');
var id = generateId();
- ws.localId = id;
- sockets.push(ws);
+ ws._id = id;
+ sockets[id] = ws;
ws.on('message', function(message) {
- var t = this;
- sockets.forEach(function(v){
- if(t.localId !== v.localId) {
+ var others = getAllExcept(sockets, this._id);
+
+ others.forEach(function(v){
+ try {
v.send(message);
+ } catch(e) {
+ console.log('Failed to send message to socket: ' + v._id);
}
});
});
ws.on('close', function() {
- console.log('WS disconnected');
- var index, t = this;
- sockets.forEach(function(v,i){
- if(t.localId === v.localId) {
- index = i;
- }
- });
- if (index) {
- sockets.splice(index,1);
- }
+ delete sockets[ws._id];
});
});

0 comments on commit 43a74b7

Please sign in to comment.