diff --git a/web-console/src/ace-modes/dsql.js b/web-console/src/ace-modes/dsql.js new file mode 100644 index 00000000000..38c936a9532 --- /dev/null +++ b/web-console/src/ace-modes/dsql.js @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This file a modified version of the file located at +// https://github.com/thlorenz/brace/blob/master/mode/sql.js +// Originally licensed under the MIT license (https://github.com/thlorenz/brace/blob/master/LICENSE) +// This file was modified to make the list of keywords more closely adhere to what is found in DruidSQL + +ace.define( + 'ace/mode/dsql_highlight_rules', + ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/text_highlight_rules'], + function(acequire, exports, module) { + 'use strict'; + + var oop = acequire('../lib/oop'); + var TextHighlightRules = acequire('./text_highlight_rules').TextHighlightRules; + + var SqlHighlightRules = function() { + var keywords = + 'select|from|where|and|or|group|by|order|limit|offset|having|as|case|' + + 'when|else|end|type|on|desc|asc|union|create|table|if|' + + 'foreign|not|references|default|null|inner|cross|drop|grant'; + + var builtinConstants = 'true|false'; + + var builtinFunctions = + 'avg|count|first|last|max|min|sum|ucase|lcase|mid|len|round|rank|now|format|' + + 'coalesce|ifnull|isnull|nvl'; + + var dataTypes = + 'int|numeric|decimal|date|varchar|char|bigint|float|double|bit|binary|text|set|timestamp|' + + 'money|real|number|integer'; + + var keywordMapper = this.createKeywordMapper( + { + 'support.function': builtinFunctions, + keyword: keywords, + 'constant.language': builtinConstants, + 'storage.type': dataTypes, + }, + 'identifier', + true, + ); + + this.$rules = { + start: [ + { + token: 'comment', + regex: '--.*$', + }, + { + token: 'comment', + start: '/\\*', + end: '\\*/', + }, + { + token: 'string', // " string + regex: '".*?"', + }, + { + token: 'string', // ' string + regex: "'.*?'", + }, + { + token: 'string', // ` string (apache drill) + regex: '`.*?`', + }, + { + token: 'constant.numeric', // float + regex: '[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b', + }, + { + token: keywordMapper, + regex: '[a-zA-Z_$][a-zA-Z0-9_$]*\\b', + }, + { + token: 'keyword.operator', + regex: '\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|=', + }, + { + token: 'paren.lparen', + regex: '[\\(]', + }, + { + token: 'paren.rparen', + regex: '[\\)]', + }, + { + token: 'text', + regex: '\\s+', + }, + ], + }; + this.normalizeRules(); + }; + + oop.inherits(SqlHighlightRules, TextHighlightRules); + + exports.SqlHighlightRules = SqlHighlightRules; + }, +); + +ace.define( + 'ace/mode/dsql', + ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/text', 'ace/mode/dsql_highlight_rules'], + function(acequire, exports, module) { + 'use strict'; + + var oop = acequire('../lib/oop'); + var TextMode = acequire('./text').Mode; + var SqlHighlightRules = acequire('./dsql_highlight_rules').SqlHighlightRules; + + var Mode = function() { + this.HighlightRules = SqlHighlightRules; + this.$behaviour = this.$defaultBehaviour; + }; + oop.inherits(Mode, TextMode); + + (function() { + this.lineCommentStart = '--'; + + this.$id = 'ace/mode/dsql'; + }.call(Mode.prototype)); + + exports.Mode = Mode; + }, +); diff --git a/web-console/src/ace-modes/hjson.js b/web-console/src/ace-modes/hjson.js new file mode 100644 index 00000000000..17142c89e59 --- /dev/null +++ b/web-console/src/ace-modes/hjson.js @@ -0,0 +1,300 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This file a modified version of the file located at +// https://github.com/thlorenz/brace/blob/master/mode/hjson.js +// Originally licensed under the MIT license (https://github.com/thlorenz/brace/blob/master/LICENSE) +// This file was modified to remove the folding functionality that did not play nice when loaded along side the +// sql mode (which does not have any folding function) + +ace.define( + 'ace/mode/hjson_highlight_rules', + ['require', 'exports', 'module', 'ace/lib/oop', 'ace/mode/text_highlight_rules'], + function(acequire, exports, module) { + 'use strict'; + + var oop = acequire('../lib/oop'); + var TextHighlightRules = acequire('./text_highlight_rules').TextHighlightRules; + + var HjsonHighlightRules = function() { + this.$rules = { + start: [ + { + include: '#comments', + }, + { + include: '#rootObject', + }, + { + include: '#value', + }, + ], + '#array': [ + { + token: 'paren.lparen', + regex: /\[/, + push: [ + { + token: 'paren.rparen', + regex: /\]/, + next: 'pop', + }, + { + include: '#value', + }, + { + include: '#comments', + }, + { + token: 'text', + regex: /,|$/, + }, + { + token: 'invalid.illegal', + regex: /[^\s\]]/, + }, + { + defaultToken: 'array', + }, + ], + }, + ], + '#comments': [ + { + token: ['comment.punctuation', 'comment.line'], + regex: /(#)(.*$)/, + }, + { + token: 'comment.punctuation', + regex: /\/\*/, + push: [ + { + token: 'comment.punctuation', + regex: /\*\//, + next: 'pop', + }, + { + defaultToken: 'comment.block', + }, + ], + }, + { + token: ['comment.punctuation', 'comment.line'], + regex: /(\/\/)(.*$)/, + }, + ], + '#constant': [ + { + token: 'constant', + regex: /\b(?:true|false|null)\b/, + }, + ], + '#keyname': [ + { + token: 'keyword', + regex: /(?:[^,\{\[\}\]\s]+|"(?:[^"\\]|\\.)*")\s*(?=:)/, + }, + ], + '#mstring': [ + { + token: 'string', + regex: /'''/, + push: [ + { + token: 'string', + regex: /'''/, + next: 'pop', + }, + { + defaultToken: 'string', + }, + ], + }, + ], + '#number': [ + { + token: 'constant.numeric', + regex: /-?(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:[eE][+-]?\d+)?)?/, + comment: 'handles integer and decimal numbers', + }, + ], + '#object': [ + { + token: 'paren.lparen', + regex: /\{/, + push: [ + { + token: 'paren.rparen', + regex: /\}/, + next: 'pop', + }, + { + include: '#keyname', + }, + { + include: '#value', + }, + { + token: 'text', + regex: /:/, + }, + { + token: 'text', + regex: /,/, + }, + { + defaultToken: 'paren', + }, + ], + }, + ], + '#rootObject': [ + { + token: 'paren', + regex: /(?=\s*(?:[^,\{\[\}\]\s]+|"(?:[^"\\]|\\.)*")\s*:)/, + push: [ + { + token: 'paren.rparen', + regex: /---none---/, + next: 'pop', + }, + { + include: '#keyname', + }, + { + include: '#value', + }, + { + token: 'text', + regex: /:/, + }, + { + token: 'text', + regex: /,/, + }, + { + defaultToken: 'paren', + }, + ], + }, + ], + '#string': [ + { + token: 'string', + regex: /"/, + push: [ + { + token: 'string', + regex: /"/, + next: 'pop', + }, + { + token: 'constant.language.escape', + regex: /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/, + }, + { + token: 'invalid.illegal', + regex: /\\./, + }, + { + defaultToken: 'string', + }, + ], + }, + ], + '#ustring': [ + { + token: 'string', + regex: /\b[^:,0-9\-\{\[\}\]\s].*$/, + }, + ], + '#value': [ + { + include: '#constant', + }, + { + include: '#number', + }, + { + include: '#string', + }, + { + include: '#array', + }, + { + include: '#object', + }, + { + include: '#comments', + }, + { + include: '#mstring', + }, + { + include: '#ustring', + }, + ], + }; + + this.normalizeRules(); + }; + + HjsonHighlightRules.metaData = { + fileTypes: ['hjson'], + keyEquivalent: '^~J', + name: 'Hjson', + scopeName: 'source.hjson', + }; + + oop.inherits(HjsonHighlightRules, TextHighlightRules); + + exports.HjsonHighlightRules = HjsonHighlightRules; + }, +); + +ace.define( + 'ace/mode/hjson', + [ + 'require', + 'exports', + 'module', + 'ace/lib/oop', + 'ace/mode/text', + 'ace/mode/hjson_highlight_rules', + ], + function(acequire, exports, module) { + 'use strict'; + + var oop = acequire('../lib/oop'); + var TextMode = acequire('./text').Mode; + var HjsonHighlightRules = acequire('./hjson_highlight_rules').HjsonHighlightRules; + + var Mode = function() { + this.HighlightRules = HjsonHighlightRules; + }; + oop.inherits(Mode, TextMode); + + (function() { + this.lineCommentStart = '//'; + this.blockComment = { start: '/*', end: '*/' }; + this.$id = 'ace/mode/hjson'; + }.call(Mode.prototype)); + + exports.Mode = Mode; + }, +); diff --git a/web-console/src/entry.ts b/web-console/src/entry.ts index 59e7fddeb16..fdbee695e72 100644 --- a/web-console/src/entry.ts +++ b/web-console/src/entry.ts @@ -18,14 +18,14 @@ import 'brace'; // Import Ace editor and all the sub components used in the app import 'brace/ext/language_tools'; -import 'brace/mode/hjson'; -import 'brace/mode/sql'; import 'brace/theme/solarized_dark'; import 'es6-shim/es6-shim'; import 'es7-shim'; // Webpack with automatically pick browser.js which does the shim() import React from 'react'; import ReactDOM from 'react-dom'; +import './ace-modes/dsql'; +import './ace-modes/hjson'; import './bootstrap/react-table-defaults'; import { ConsoleApplication } from './console-application'; diff --git a/web-console/src/views/query-view/query-input/query-input.tsx b/web-console/src/views/query-view/query-input/query-input.tsx index 6df25e82963..3d65057c1bf 100644 --- a/web-console/src/views/query-view/query-input/query-input.tsx +++ b/web-console/src/views/query-view/query-input/query-input.tsx @@ -185,8 +185,7 @@ export class QueryInput extends React.PureComponent