Refine autocomplete to operate as user types

pull/3374/head
Andrew Watkins 2018-05-07 10:04:56 -07:00
parent ec7581e9fd
commit 1ccd4e1af8
7 changed files with 976 additions and 217 deletions

View File

@ -38,6 +38,7 @@
},
"devDependencies": {
"@types/chai": "^4.1.2",
"@types/codemirror": "^0.0.56",
"@types/dygraphs": "^1.1.6",
"@types/enzyme": "^3.1.9",
"@types/jest": "^22.1.4",
@ -49,7 +50,6 @@
"@types/react-dnd-html5-backend": "^2.1.9",
"@types/react-router": "^3.0.15",
"@types/text-encoding": "^0.0.32",
"@types/codemirror": "^0.0.56",
"autoprefixer": "^6.3.1",
"babel-core": "^6.5.1",
"babel-eslint": "6.1.2",

View File

@ -1,13 +1,13 @@
/* eslint-disable */
const CodeMirror = require('codemirror')
CodeMirror.defineSimpleMode = function(name, states) {
CodeMirror.defineMode(name, function(config) {
CodeMirror.defineSimpleMode = function (name, states) {
CodeMirror.defineMode(name, function (config) {
return CodeMirror.simpleMode(config, states)
})
}
CodeMirror.simpleMode = function(config, states) {
CodeMirror.simpleMode = function (config, states) {
ensureState(states, 'start')
const states_ = {},
meta = states.meta || {}
@ -53,10 +53,8 @@ CodeMirror.simpleMode = function(config, states) {
s.persistentStates = {
mode: pers.mode,
spec: pers.spec,
state:
pers.state === state.localState
? s.localState
: CodeMirror.copyState(pers.mode, pers.state),
state: pers.state === state.localState ?
s.localState : CodeMirror.copyState(pers.mode, pers.state),
next: s.persistentStates,
}
}
@ -64,7 +62,10 @@ CodeMirror.simpleMode = function(config, states) {
},
token: tokenFunction(states_, config),
innerMode(state) {
return state.local && {mode: state.local.mode, state: state.localState}
return state.local && {
mode: state.local.mode,
state: state.localState
}
},
indent: indentFunction(states_, meta),
}
@ -127,7 +128,7 @@ function Rule(data, states) {
}
function tokenFunction(states, config) {
return function(stream, state) {
return function (stream, state) {
if (state.pending) {
const pend = state.pending.shift()
if (state.pending.length === 0) {
@ -163,8 +164,8 @@ function tokenFunction(states, config) {
if (matches) {
if (rule.data.next) {
state.state = rule.data.next
} else if (rule.data.push) {
;(state.stack || (state.stack = [])).push(state.state)
} else if (rule.data.push) {;
(state.stack || (state.stack = [])).push(state.state)
state.state = rule.data.push
} else if (rule.data.pop && state.stack && state.stack.length) {
state.state = state.stack.pop()
@ -187,7 +188,10 @@ function tokenFunction(states, config) {
state.pending = []
for (let j = 2; j < matches.length; j++) {
if (matches[j]) {
state.pending.push({text: matches[j], token: rule.token[j - 1]})
state.pending.push({
text: matches[j],
token: rule.token[j - 1]
})
}
}
stream.backUp(
@ -238,9 +242,9 @@ function enterLocalMode(config, state, spec, token) {
}
}
}
const mode = pers
? pers.mode
: spec.mode || CodeMirror.getMode(config, spec.spec)
const mode = pers ?
pers.mode :
spec.mode || CodeMirror.getMode(config, spec.spec)
const lState = pers ? pers.state : CodeMirror.startState(mode)
if (spec.persistent && !pers) {
state.persistentStates = {
@ -269,7 +273,7 @@ function indexOf(val, arr) {
}
function indentFunction(states, meta) {
return function(state, textAfter, line) {
return function (state, textAfter, line) {
if (state.local && state.local.mode.indent) {
return state.local.mode.indent(state.localState, textAfter, line)
}
@ -309,8 +313,14 @@ CodeMirror.defineSimpleMode('tickscript', {
// The start state contains the rules that are intially used
start: [
// The regex matches the token, the token property contains the type
{regex: /"(?:[^\\]|\\.)*?(?:"|$)/, token: 'string.double'},
{regex: /'(?:[^\\]|\\.)*?(?:'|$)/, token: 'string.single'},
{
regex: /"(?:[^\\]|\\.)*?(?:"|$)/,
token: 'string.double'
},
{
regex: /'(?:[^\\]|\\.)*?(?:'|$)/,
token: 'string.single'
},
{
regex: /(function)(\s+)([a-z$][\w$]*)/,
token: ['keyword', null, 'variable-2'],
@ -321,22 +331,47 @@ CodeMirror.defineSimpleMode('tickscript', {
regex: /(?:var|return|if|for|while|else|do|this|stream|batch|influxql|lambda)/,
token: 'keyword',
},
{regex: /true|false|null|undefined|TRUE|FALSE/, token: 'atom'},
{
regex: /true|false|null|undefined|TRUE|FALSE/,
token: 'atom'
},
{
regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
token: 'number',
},
{regex: /\/\/.*/, token: 'comment'},
{regex: /\/(?:[^\\]|\\.)*?\//, token: 'variable-3'},
{
regex: /\/\/.*/,
token: 'comment'
},
{
regex: /\/(?:[^\\]|\\.)*?\//,
token: 'variable-3'
},
// A next property will cause the mode to move to a different state
{regex: /\/\*/, token: 'comment', next: 'comment'},
{regex: /[-+\/*=<>!]+/, token: 'operator'},
{regex: /[a-z$][\w$]*/, token: 'variable'},
{
regex: /\/\*/,
token: 'comment',
next: 'comment'
},
{
regex: /[-+\/*=<>!]+/,
token: 'operator'
},
{
regex: /[a-z$][\w$]*/,
token: 'variable'
},
],
// The multi-line comment state.
comment: [
{regex: /.*?\*\//, token: 'comment', next: 'start'},
{regex: /.*/, token: 'comment'},
comment: [{
regex: /.*?\*\//,
token: 'comment',
next: 'start'
},
{
regex: /.*/,
token: 'comment'
},
],
// The meta property contains global information about the mode. It
// can contain properties like lineComment, which are supported by
@ -347,3 +382,536 @@ CodeMirror.defineSimpleMode('tickscript', {
lineComment: '//',
},
})
// CodeMirror Hints
var HINT_ELEMENT_CLASS = "CodeMirror-hint";
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
// This is the old interface, kept around for now to stay backwards-compatible.
CodeMirror.showHint = function (cm, getHints, options) {
if (!getHints) return cm.showHint(options);
if (options && options.async) getHints.async = true;
var newOpts = {
hint: getHints
};
if (options)
for (var prop in options) newOpts[prop] = options[prop];
return cm.showHint(newOpts);
};
CodeMirror.defineExtension("showHint", function (options) {
options = parseOptions(this, this.getCursor("start"), options);
var selections = this.listSelections()
if (selections.length > 1) return;
// By default, don't allow completion when something is selected.
// A hint function can have a `supportsSelection` property to
// indicate that it can handle selections.
if (this.somethingSelected()) {
if (!options.hint.supportsSelection) return;
// Don't try with cross-line selections
for (var i = 0; i < selections.length; i++)
if (selections[i].head.line != selections[i].anchor.line) return;
}
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
if (!completion.options.hint) return;
CodeMirror.signal(this, "startCompletion", this);
completion.update(true);
});
function Completion(cm, options) {
this.cm = cm;
this.options = options;
this.widget = null;
this.debounce = 0;
this.tick = 0;
this.startPos = this.cm.getCursor("start");
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
var self = this;
cm.on("cursorActivity", this.activityFunc = function () {
self.cursorActivity();
});
}
var requestAnimationFrame = window.requestAnimationFrame || function (fn) {
return setTimeout(fn, 1000 / 60);
};
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
Completion.prototype = {
close: function () {
if (!this.active()) return;
this.cm.state.completionActive = null;
this.tick = null;
this.cm.off("cursorActivity", this.activityFunc);
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
if (this.widget) this.widget.close();
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
active: function () {
return this.cm.state.completionActive == this;
},
pick: function (data, i) {
var completion = data.list[i];
if (completion.hint) completion.hint(this.cm, data, completion);
else this.cm.replaceRange(getText(completion), completion.from || data.from,
completion.to || data.to, "complete");
CodeMirror.signal(data, "pick", completion);
this.close();
},
cursorActivity: function () {
if (this.debounce) {
cancelAnimationFrame(this.debounce);
this.debounce = 0;
}
var pos = this.cm.getCursor(),
line = this.cm.getLine(pos.line);
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
(pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close();
} else {
var self = this;
this.debounce = requestAnimationFrame(function () {
self.update();
});
if (this.widget) this.widget.disable();
}
},
update: function (first) {
if (this.tick == null) return
var self = this,
myTick = ++this.tick
fetchHints(this.options.hint, this.cm, this.options, function (data) {
if (self.tick == myTick) self.finishUpdate(data, first)
})
},
finishUpdate: function (data, first) {
if (this.data) CodeMirror.signal(this.data, "update");
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close();
this.data = data;
if (data && data.list.length) {
if (picked && data.list.length == 1) {
this.pick(data, 0);
} else {
this.widget = new Widget(this, data);
CodeMirror.signal(data, "shown");
}
}
}
};
function parseOptions(cm, pos, options) {
var editor = cm.options.hintOptions;
var out = {};
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
if (editor)
for (var prop in editor)
if (editor[prop] !== undefined) out[prop] = editor[prop];
if (options)
for (var prop in options)
if (options[prop] !== undefined) out[prop] = options[prop];
if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
return out;
}
function getText(completion) {
if (typeof completion == "string") return completion;
else return completion.text;
}
function buildKeyMap(completion, handle) {
var baseMap = {
Up: function () {
handle.moveFocus(-1);
},
Down: function () {
handle.moveFocus(1);
},
PageUp: function () {
handle.moveFocus(-handle.menuSize() + 1, true);
},
PageDown: function () {
handle.moveFocus(handle.menuSize() - 1, true);
},
Home: function () {
handle.setFocus(0);
},
End: function () {
handle.setFocus(handle.length - 1);
},
Enter: handle.pick,
Tab: handle.pick,
Esc: handle.close
};
var custom = completion.options.customKeys;
var ourMap = custom ? {} : baseMap;
function addBinding(key, val) {
var bound;
if (typeof val != "string")
bound = function (cm) {
return val(cm, handle);
};
// This mechanism is deprecated
else if (baseMap.hasOwnProperty(val))
bound = baseMap[val];
else
bound = val;
ourMap[key] = bound;
}
if (custom)
for (var key in custom)
if (custom.hasOwnProperty(key))
addBinding(key, custom[key]);
var extra = completion.options.extraKeys;
if (extra)
for (var key in extra)
if (extra.hasOwnProperty(key))
addBinding(key, extra[key]);
return ourMap;
}
function getHintElement(hintsElement, el) {
while (el && el != hintsElement) {
if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
el = el.parentNode;
}
}
function Widget(completion, data) {
this.completion = completion;
this.data = data;
this.picked = false;
var widget = this,
cm = completion.cm;
var hints = this.hints = document.createElement("ul");
hints.className = "CodeMirror-hints";
this.selectedHint = data.selectedHint || 0;
var completions = data.list;
for (var i = 0; i < completions.length; ++i) {
var elt = hints.appendChild(document.createElement("li")),
cur = completions[i];
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
if (cur.className != null) className = cur.className + " " + className;
elt.className = className;
if (cur.render) cur.render(elt, data, cur);
else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
elt.hintId = i;
}
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
var left = pos.left,
top = pos.bottom,
below = true;
hints.style.left = left + "px";
hints.style.top = top + "px";
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
(completion.options.container || document.body).appendChild(hints);
var box = hints.getBoundingClientRect(),
overlapY = box.bottom - winH;
var scrolls = hints.scrollHeight > hints.clientHeight + 1
var startScroll = cm.getScrollInfo();
if (overlapY > 0) {
var height = box.bottom - box.top,
curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor
hints.style.top = (top = pos.top - height) + "px";
below = false;
} else if (height > winH) {
hints.style.height = (winH - 5) + "px";
hints.style.top = (top = pos.bottom - box.top) + "px";
var cursor = cm.getCursor();
if (data.from.ch != cursor.ch) {
pos = cm.cursorCoords(cursor);
hints.style.left = (left = pos.left) + "px";
box = hints.getBoundingClientRect();
}
}
}
var overlapX = box.right - winW;
if (overlapX > 0) {
if (box.right - box.left > winW) {
hints.style.width = (winW - 5) + "px";
overlapX -= (box.right - box.left) - winW;
}
hints.style.left = (left = pos.left - overlapX) + "px";
}
if (scrolls)
for (var node = hints.firstChild; node; node = node.nextSibling)
node.style.paddingRight = cm.display.nativeBarWidth + "px"
cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function (n, avoidWrap) {
widget.changeActive(widget.selectedHint + n, avoidWrap);
},
setFocus: function (n) {
widget.changeActive(n);
},
menuSize: function () {
return widget.screenAmount();
},
length: completions.length,
close: function () {
completion.close();
},
pick: function () {
widget.pick();
},
data: data
}));
if (completion.options.closeOnUnfocus) {
var closingOnBlur;
cm.on("blur", this.onBlur = function () {
closingOnBlur = setTimeout(function () {
completion.close();
}, 100);
});
cm.on("focus", this.onFocus = function () {
clearTimeout(closingOnBlur);
});
}
cm.on("scroll", this.onScroll = function () {
var curScroll = cm.getScrollInfo(),
editor = cm.getWrapperElement().getBoundingClientRect();
var newTop = top + startScroll.top - curScroll.top;
var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
if (!below) point += hints.offsetHeight;
if (point <= editor.top || point >= editor.bottom) return completion.close();
hints.style.top = newTop + "px";
hints.style.left = (left + startScroll.left - curScroll.left) + "px";
});
CodeMirror.on(hints, "dblclick", function (e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {
widget.changeActive(t.hintId);
widget.pick();
}
});
CodeMirror.on(hints, "click", function (e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {
widget.changeActive(t.hintId);
if (completion.options.completeOnSingleClick) widget.pick();
}
});
CodeMirror.on(hints, "mousedown", function () {
setTimeout(function () {
cm.focus();
}, 20);
});
CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
return true;
}
Widget.prototype = {
close: function () {
if (this.completion.widget != this) return;
this.completion.widget = null;
this.hints.parentNode.removeChild(this.hints);
this.completion.cm.removeKeyMap(this.keyMap);
var cm = this.completion.cm;
if (this.completion.options.closeOnUnfocus) {
cm.off("blur", this.onBlur);
cm.off("focus", this.onFocus);
}
cm.off("scroll", this.onScroll);
},
disable: function () {
this.completion.cm.removeKeyMap(this.keyMap);
var widget = this;
this.keyMap = {
Enter: function () {
widget.picked = true;
}
};
this.completion.cm.addKeyMap(this.keyMap);
},
pick: function () {
this.completion.pick(this.data, this.selectedHint);
},
changeActive: function (i, avoidWrap) {
if (i >= this.data.list.length)
i = avoidWrap ? this.data.list.length - 1 : 0;
else if (i < 0)
i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint];
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node = this.hints.childNodes[this.selectedHint = i];
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
if (node.offsetTop < this.hints.scrollTop)
this.hints.scrollTop = node.offsetTop - 3;
else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
},
screenAmount: function () {
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
}
};
function applicableHelpers(cm, helpers) {
if (!cm.somethingSelected()) return helpers
var result = []
for (var i = 0; i < helpers.length; i++)
if (helpers[i].supportsSelection) result.push(helpers[i])
return result
}
function fetchHints(hint, cm, options, callback) {
if (hint.async) {
hint(cm, callback, options)
} else {
var result = hint(cm, options)
if (result && result.then) result.then(callback)
else callback(result)
}
}
function resolveAutoHints(cm, pos) {
var helpers = cm.getHelpers(pos, "hint"),
words
if (helpers.length) {
var resolved = function (cm, callback, options) {
var app = applicableHelpers(cm, helpers);
function run(i) {
if (i == app.length) return callback(null)
fetchHints(app[i], cm, options, function (result) {
if (result && result.list.length > 0) callback(result)
else run(i + 1)
})
}
run(0)
}
resolved.async = true
resolved.supportsSelection = true
return resolved
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
return function (cm) {
return CodeMirror.hint.fromList(cm, {
words: words
})
}
} else if (CodeMirror.hint.anyword) {
return function (cm, options) {
return CodeMirror.hint.anyword(cm, options)
}
} else {
return function () {}
}
}
CodeMirror.registerHelper("hint", "auto", {
resolve: resolveAutoHints
});
CodeMirror.registerHelper("hint", "fromList", function (cm, options) {
var cur = cm.getCursor(),
token = cm.getTokenAt(cur)
var term, from = CodeMirror.Pos(cur.line, token.start),
to = cur
if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
term = token.string.substr(0, cur.ch - token.start)
} else {
term = ""
from = cur
}
var found = [];
for (var i = 0; i < options.words.length; i++) {
var word = options.words[i];
if (word.slice(0, term.length) == term)
found.push(word);
}
if (found.length) return {
list: found,
from: from,
to: to
};
});
CodeMirror.commands.autocomplete = CodeMirror.showHint;
var defaultOptions = {
hint: CodeMirror.hint.auto,
completeSingle: true,
alignWithWord: true,
closeCharacters: /[\s()\[\]{};:>,]/,
closeOnUnfocus: true,
completeOnSingleClick: true,
container: null,
customKeys: null,
extraKeys: null
};
CodeMirror.defineOption("hintOptions", null);
var WORD = /[\w$]+/,
RANGE = 500;
CodeMirror.registerHelper("hint", "anyword", function (editor, options) {
var word = options && options.word || WORD;
var range = options && options.range || RANGE;
var cur = editor.getCursor(),
curLine = editor.getLine(cur.line);
var end = cur.ch,
start = end;
while (start && word.test(curLine.charAt(start - 1))) --start;
var curWord = start != end && curLine.slice(start, end);
var list = options && options.list || [],
seen = {};
var re = new RegExp(word.source, "g");
for (var dir = -1; dir <= 1; dir += 2) {
var line = cur.line,
endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
for (; line != endLine; line += dir) {
var text = editor.getLine(line),
m;
while (m = re.exec(text)) {
if (line == cur.line && m[0] === curWord) continue;
if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
seen[m[0]] = true;
list.push(m[0]);
}
}
}
}
return {
list: list,
from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end)
};
});

View File

@ -4,12 +4,17 @@ import {EditorChange} from 'codemirror'
import 'src/external/codemirror'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {OnChangeScript} from 'src/types/ifql'
import {editor} from 'src/ifql/constants'
interface Props {
script: string
onChangeScript: OnChangeScript
}
interface EditorInstance extends IInstance {
showHint: (options?: any) => void
}
@ErrorHandling
class TimeMachineEditor extends PureComponent<Props> {
constructor(props) {
@ -24,6 +29,8 @@ class TimeMachineEditor extends PureComponent<Props> {
theme: 'material',
tabIndex: 1,
readonly: false,
extraKeys: {'Ctrl-Space': 'autocomplete'},
completeSingle: false,
}
return (
@ -35,11 +42,22 @@ class TimeMachineEditor extends PureComponent<Props> {
options={options}
onBeforeChange={this.updateCode}
onTouchStart={this.onTouchStart}
onKeyUp={this.handleKeyUp}
/>
</div>
)
}
private handleKeyUp = (instance: EditorInstance, e: KeyboardEvent) => {
const {key} = e
if (editor.EXCLUDED_KEYS.includes(key)) {
return
}
instance.showHint({completeSingle: false})
}
private onTouchStart = () => {}
private updateCode = (

View File

@ -0,0 +1,155 @@
export const ast = {
type: 'File',
start: 0,
end: 22,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 22,
},
},
program: {
type: 'Program',
start: 0,
end: 22,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 22,
},
},
sourceType: 'module',
body: [
{
type: 'ExpressionStatement',
start: 0,
end: 22,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 22,
},
},
expression: {
type: 'CallExpression',
start: 0,
end: 22,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 22,
},
},
callee: {
type: 'Identifier',
start: 0,
end: 4,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 4,
},
identifierName: 'from',
},
name: 'from',
},
arguments: [
{
type: 'ObjectExpression',
start: 5,
end: 21,
loc: {
start: {
line: 1,
column: 5,
},
end: {
line: 1,
column: 21,
},
},
properties: [
{
type: 'ObjectProperty',
start: 6,
end: 20,
loc: {
start: {
line: 1,
column: 6,
},
end: {
line: 1,
column: 20,
},
},
method: false,
shorthand: false,
computed: false,
key: {
type: 'Identifier',
start: 6,
end: 8,
loc: {
start: {
line: 1,
column: 6,
},
end: {
line: 1,
column: 8,
},
identifierName: 'db',
},
name: 'db',
},
value: {
type: 'StringLiteral',
start: 10,
end: 20,
loc: {
start: {
line: 1,
column: 10,
},
end: {
line: 1,
column: 20,
},
},
extra: {
rawValue: 'telegraf',
raw: 'telegraf',
},
value: 'telegraf',
},
},
],
},
],
},
},
],
directives: [],
},
}

View File

@ -0,0 +1,55 @@
export const EXCLUDED_KEYS = [
'ArrowRight',
'ArrowLeft',
'ArrowDown',
'ArrowUp',
'Backspace',
'Tab',
'Enter',
'Shift',
'Ctrl',
'Alt',
'Pause',
'Capslock',
'Escape',
'Pageup',
'Pagedown',
'End',
'Home',
'Left',
'Up',
'Right',
'Down',
'Insert',
'Delete',
'Left window key',
'Right window key',
'Select',
'Add',
'Subtract',
'Decimal point',
'Divide',
'F1',
'F2',
'F3',
'F4',
'F5',
'F6',
'F7',
'F8',
'F9',
'F10',
'F11',
'F12',
'Numlock',
'Scrolllock',
'Semicolon',
'Equalsign',
'Comma',
'Dash',
'Slash',
'Graveaccent',
'Backslash',
'Quote',
' ',
]

View File

@ -1,160 +1,6 @@
import * as funcNames from 'src/ifql/constants/funcNames'
import * as argTypes from 'src/ifql/constants/argumentTypes'
import {ast} from 'src/ifql/constants/ast'
import * as editor from 'src/ifql/constants/editor'
const ast = {
type: 'File',
start: 0,
end: 22,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 22,
},
},
program: {
type: 'Program',
start: 0,
end: 22,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 22,
},
},
sourceType: 'module',
body: [
{
type: 'ExpressionStatement',
start: 0,
end: 22,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 22,
},
},
expression: {
type: 'CallExpression',
start: 0,
end: 22,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 22,
},
},
callee: {
type: 'Identifier',
start: 0,
end: 4,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 4,
},
identifierName: 'from',
},
name: 'from',
},
arguments: [
{
type: 'ObjectExpression',
start: 5,
end: 21,
loc: {
start: {
line: 1,
column: 5,
},
end: {
line: 1,
column: 21,
},
},
properties: [
{
type: 'ObjectProperty',
start: 6,
end: 20,
loc: {
start: {
line: 1,
column: 6,
},
end: {
line: 1,
column: 20,
},
},
method: false,
shorthand: false,
computed: false,
key: {
type: 'Identifier',
start: 6,
end: 8,
loc: {
start: {
line: 1,
column: 6,
},
end: {
line: 1,
column: 8,
},
identifierName: 'db',
},
name: 'db',
},
value: {
type: 'StringLiteral',
start: 10,
end: 20,
loc: {
start: {
line: 1,
column: 10,
},
end: {
line: 1,
column: 20,
},
},
extra: {
rawValue: 'telegraf',
raw: 'telegraf',
},
value: 'telegraf',
},
},
],
},
],
},
},
],
directives: [],
},
}
export {ast, funcNames, argTypes}
export {ast, funcNames, argTypes, editor}

View File

@ -20,73 +20,190 @@
font-weight: 600;
height: 100%;
}
.CodeMirror-vscrollbar {
@include custom-scrollbar-round($g2-kevlar,$g6-smoke);
@include custom-scrollbar-round($g2-kevlar, $g6-smoke);
}
.CodeMirror-hscrollbar {
@include custom-scrollbar-round($g0-obsidian,$g6-smoke);
@include custom-scrollbar-round($g0-obsidian, $g6-smoke);
}
.cm-s-material .CodeMirror-gutters {
@include gradient-v($g2-kevlar, $g0-obsidian)
border: none;
@include gradient-v($g2-kevlar, $g0-obsidian) border: none;
}
.cm-s-material .CodeMirror-gutters .CodeMirror-gutter {
background-color: fade-out($g4-onyx, 0.75);
height: calc(100% + 30px);
}
.CodeMirror-gutter.CodeMirror-linenumbers {
width: 60px;
}
.cm-s-material.CodeMirror .CodeMirror-sizer {
margin-left: 60px;
}
.cm-s-material.CodeMirror .CodeMirror-linenumber.CodeMirror-gutter-elt {
padding-right: 9px;
width: 46px;
color: $g8-storm;
}
.cm-s-material .CodeMirror-guttermarker, .cm-s-material .CodeMirror-guttermarker-subtle, .cm-s-material .CodeMirror-linenumber { color: rgb(83,127,126); }
.cm-s-material .CodeMirror-guttermarker,
.cm-s-material .CodeMirror-guttermarker-subtle,
.cm-s-material .CodeMirror-linenumber {
color: rgb(83, 127, 126);
}
.cm-s-material .CodeMirror-cursor {
width: 2px;
border: 0;
background-color: $g20-white;
box-shadow:
0 0 3px $c-laser,
0 0 6px $c-ocean,
0 0 11px $c-amethyst;
box-shadow: 0 0 3px $c-laser, 0 0 6px $c-ocean, 0 0 11px $c-amethyst;
}
.cm-s-material div.CodeMirror-selected,
.cm-s-material.CodeMirror-focused div.CodeMirror-selected {
background-color: fade-out($g8-storm,0.7);
background-color: fade-out($g8-storm, 0.7);
}
.cm-s-material .CodeMirror-line::selection,
.cm-s-material .CodeMirror-line>span::selection,
.cm-s-material .CodeMirror-line>span>span::selection {
background: rgba(255, 255, 255, 0.10);
}
.cm-s-material .CodeMirror-line::-moz-selection,
.cm-s-material .CodeMirror-line>span::-moz-selection,
.cm-s-material .CodeMirror-line>span>span::-moz-selection {
background: rgba(255, 255, 255, 0.10);
}
.cm-s-material .CodeMirror-activeline-background {
background: rgba(0, 0, 0, 0);
}
.cm-s-material .cm-keyword {
color: $c-comet;
}
.cm-s-material .cm-operator {
color: $c-dreamsicle;
}
.cm-s-material .cm-variable-2 {
color: #80CBC4;
}
.cm-s-material .cm-variable-3,
.cm-s-material .cm-type {
color: $c-laser;
}
.cm-s-material .cm-builtin {
color: #DECB6B;
}
.cm-s-material .cm-atom {
color: $c-viridian;
}
.cm-s-material .cm-number {
color: $c-daisy;
}
.cm-s-material .cm-def {
color: rgba(233, 237, 237, 1);
}
.cm-s-material .cm-string {
color: $c-krypton;
}
.cm-s-material .cm-string-2 {
color: #80CBC4;
}
.cm-s-material .cm-comment {
color: $g10-wolf;
}
.cm-s-material .cm-variable {
color: $c-laser;
}
.cm-s-material .cm-tag {
color: #80CBC4;
}
.cm-s-material .cm-meta {
color: #80CBC4;
}
.cm-s-material .cm-attribute {
color: #FFCB6B;
}
.cm-s-material .cm-property {
color: #80CBAE;
}
.cm-s-material .cm-qualifier {
color: #DECB6B;
}
.cm-s-material .cm-variable-3,
.cm-s-material .cm-type {
color: #DECB6B;
}
.cm-s-material .cm-tag {
color: rgba(255, 83, 112, 1);
}
.cm-s-material .CodeMirror-line::selection, .cm-s-material .CodeMirror-line > span::selection, .cm-s-material .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
.cm-s-material .CodeMirror-line::-moz-selection, .cm-s-material .CodeMirror-line > span::-moz-selection, .cm-s-material .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }
.cm-s-material .CodeMirror-activeline-background { background: rgba(0, 0, 0, 0); }
.cm-s-material .cm-keyword { color: $c-comet; }
.cm-s-material .cm-operator { color: $c-dreamsicle; }
.cm-s-material .cm-variable-2 { color: #80CBC4; }
.cm-s-material .cm-variable-3, .cm-s-material .cm-type { color: $c-laser; }
.cm-s-material .cm-builtin { color: #DECB6B; }
.cm-s-material .cm-atom { color: $c-viridian; }
.cm-s-material .cm-number { color: $c-daisy; }
.cm-s-material .cm-def { color: rgba(233, 237, 237, 1); }
.cm-s-material .cm-string { color: $c-krypton; }
.cm-s-material .cm-string-2 { color: #80CBC4; }
.cm-s-material .cm-comment { color: $g10-wolf; }
.cm-s-material .cm-variable { color: $c-laser; }
.cm-s-material .cm-tag { color: #80CBC4; }
.cm-s-material .cm-meta { color: #80CBC4; }
.cm-s-material .cm-attribute { color: #FFCB6B; }
.cm-s-material .cm-property { color: #80CBAE; }
.cm-s-material .cm-qualifier { color: #DECB6B; }
.cm-s-material .cm-variable-3, .cm-s-material .cm-type { color: #DECB6B; }
.cm-s-material .cm-tag { color: rgba(255, 83, 112, 1); }
.cm-s-material .cm-error {
color: rgba(255, 255, 255, 1.0);
background-color: #EC5F67;
}
.cm-s-material .CodeMirror-matchingbracket {
text-decoration: underline;
color: white !important;
}
// CodeMirror hints
.CodeMirror-hints {
position: absolute;
z-index: 10;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
-moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
border-radius: 3px;
border: 1px solid silver;
background: white;
font-size: 90%;
font-family: monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror-hint {
margin: 0;
padding: 0 4px;
border-radius: 2px;
white-space: pre;
color: black;
cursor: pointer;
}
li.CodeMirror-hint-active {
background: #08f;
color: white;
}