Skip to content

Commit

Permalink
import loop-drop-editor/raw directly into project
Browse files Browse the repository at this point in the history
  • Loading branch information
mmckegg committed Mar 5, 2015
1 parent 7066cbd commit 01e3d6e
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 3 deletions.
104 changes: 104 additions & 0 deletions lib/jsmn.js
@@ -0,0 +1,104 @@
var safeEval = require('notevil')

module.exports.parse = function(literal){
literal = literal.replace(/\{\{([\w\W]*?)\}\}/g, function(_, exp){
return '{$: ' + JSON.stringify(fixIndent(exp)) + '}'
})
return safeEval('j = {' + literal + '}')
}

module.exports.stringify = function(object){
return getObjectContent(object).trim()
}

module.exports.eval = xval

function xval(object, context){
if (Array.isArray(object)){
return object.map(function(x){
return xval(x, context)
})
} else if (object instanceof Object) {
if (object.$){
return safeEval(object.$, context)
} else {
var res = {}
Object.keys(object).forEach(function(key){
res[key] = xval(object[key], context)
})
return res
}
} else {
return object
}
}

function getObjectContent(object){
var result = Object.keys(object).map(function(key){
return escapeKey(key) + ': ' + getLiteral(object[key])
})
return smartWrap(result)
}

var numberMatch = /^[0-9]/

function isNumeric(key){
return typeof key === 'string' && !!numberMatch.exec(key)
}

function escapeKey(key){
if (~key.indexOf(' ') || ~key.indexOf('"') || ~key.indexOf('-') || isNumeric(key)){
return JSON.stringify(String(key))
} else {
return key
}
}

function getArrayContent(array){
var result = array.map(function(obj){
return getLiteral(obj)
})
return smartWrap(result)
}

function smartWrap(array){
if (array.join(', ').length>50){
return '\n' + array.join(',\n') + '\n'
} else {
return ' ' + array.join(', ') + ' '
}
}

function indent(text){
return text.replace(/\n(.)/g, '\n $1')
}

function getLiteral(value){
if (!value || typeof value !== 'object'){
return JSON.stringify(value)
} else if (Array.isArray(value)){
return '[' + indent(getArrayContent(value)) + ']'
} else if (value && '$' in value){
return '{{' + value['$'] + '}}'
} else {
return '{' + indent(getObjectContent(value)) + '}'
}
}

var matchStartSpace = /^(\s+)/
var matchNewLineWrapper = /^\s*\n|\n\s*$/g

function fixIndent(text){
if (text && ~text.indexOf('\n')){
text = text.replace(matchNewLineWrapper, '')
var match = matchStartSpace.exec(text)
var indent = match && match[1].length
if (indent){
text = '\n' + text.replace(/(^|\n)(\s+)/g, function(_, start, spaces){
return start + spaces.slice(indent-2)
}) + '\n'
}
}

return text
}
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -13,6 +13,7 @@
"audio-rms": "^1.1.0",
"audio-slot": "^3.0.0",
"bopper": "^2.7.0",
"brace": "^0.5.0",
"browserify": "3.37.2",
"catw": "~0.2.0",
"concat-stream": "~1.4.1",
Expand All @@ -22,14 +23,14 @@
"geval": "^2.1.1",
"json-query": "^1.4.0",
"lfo": "^3.0.0",
"loop-drop-editor": "^0.1.0",
"loop-drop-project": "^3.0.0",
"loop-drop-setup": "^2.0.0",
"loop-launchpad": "^3.0.0",
"loop-qwerty": "^2.0.0",
"mercury": "^14.0.0",
"micro-css": "~0.5.0",
"next-tick": "^0.2.2",
"notevil": "^0.8.1",
"observ": "^0.2.0",
"tap-tempo": "0.0.0",
"teoria": "~0.4.0",
Expand Down
128 changes: 128 additions & 0 deletions views/editor/raw.js
@@ -0,0 +1,128 @@

var JSMN = require('../../lib/jsmn.js')
var deepEqual = require('deep-equal')
var watch = require('observ/watch')

var ace = require('brace')
require('brace/mode/javascript')
require('brace/theme/ambiance')

var NO_TRANSACTION = {}

module.exports = RawEditor

function RawEditor(fileObject){
if (!(this instanceof RawEditor)){
return new RawEditor(fileObject)
}
this.fileObject = fileObject
this.file = fileObject && fileObject.file
}

RawEditor.prototype.type = 'Widget'

RawEditor.prototype.init = function(){
var element = document.createElement('div')
element.className = 'RawEditor'

var el = document.createElement('div')

var textEditor = this.editor = ace.edit(el)

window.editors = window.editors || []
window.editors.push(textEditor)

textEditor.setTheme('ace/theme/ambiance');
textEditor.session.setMode('ace/mode/javascript')
textEditor.session.setUseWorker(false)
textEditor.session.setTabSize(2)
textEditor.renderer.setScrollMargin(20,100)
textEditor.renderer.setPadding(20)
textEditor.renderer.setShowGutter(false)

var currentFile = null
var self = this

var currentTransaction = NO_TRANSACTION
var currentSaveTransaction = NO_TRANSACTION

textEditor.setFile = function(fileObject){
clearTimeout(saveTimer)

if (self.release){
self.release()
self.release = null
}

currentFile = fileObject

if (fileObject){
self.release = watch(fileObject, update)
}
}

function save(){
var value = textEditor.session.getValue()
if (currentFile){
try {
var object = JSMN.parse(value)
currentSaveTransaction = object
currentFile.set(object)
currentSaveTransaction = NO_TRANSACTION
} catch (ex) {}
}
}

function update(){
var data = currentFile ? currentFile() : null
if (data && currentSaveTransaction !== data._diff && !deepEqual(currentSaveTransaction,data)){
var newValue = JSMN.stringify(data || {})
currentTransaction = newValue
textEditor.session.setValue(newValue, -1)
currentTransaction = NO_TRANSACTION
}
}

var blurTimer = null
textEditor.on('focus', function(){
clearTimeout(blurTimer)
})

textEditor.on('blur', function(){
clearTimeout(blurTimer)
blurTimer = setTimeout(function(){
if (!textEditor.isFocused()){
update()
}
}, 100)
})

var saveTimer = null
textEditor.on('change', function(){
if (currentTransaction === NO_TRANSACTION){
clearTimeout(saveTimer)
saveTimer = setTimeout(save, 100)
}
})

textEditor.setFile(this.fileObject)

element.appendChild(el)
return element
}

RawEditor.prototype.update = function(prev, elem){
this.editor = prev.editor
this.release = prev.release

if (prev.file !== this.file){
this.editor.setFile(this.fileObject)
}
return elem
}

RawEditor.prototype.destroy = function(elem){
this.editor.destroy()
this.release && this.release()
this.release = null
}
4 changes: 2 additions & 2 deletions views/tabbed-editor.js
Expand Up @@ -5,9 +5,9 @@ var getDirectory = require('path').dirname

var change = require('./editor/params/value-event.js')


var renderEditor = require('./editor')
var rawEditor = require('loop-drop-editor/raw')
var rawEditor = require('./editor/raw.js')

module.exports = TabbedEditor

function TabbedEditor(state, actions){
Expand Down

0 comments on commit 01e3d6e

Please sign in to comment.