gethue
Version:
Hue is an Open source SQL Query Editor for Databases/Warehouses
848 lines (756 loc) • 29.5 kB
JavaScript
// Licensed to Cloudera, Inc. under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. Cloudera, Inc. 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.
import $ from 'jquery';
import * as ko from 'knockout';
import ace from '../../../ext/aceHelper';
import { format } from '@gethue/sql-formatter';
import AceLocationHandler, {
REFRESH_STATEMENT_LOCATIONS_EVENT
} from '../../../ko/bindings/ace/aceLocationHandler';
import AceGutterHandler from '../../../ko/bindings/ace/aceGutterHandler';
import { registerBinding } from '../../../ko/bindings/bindingUtils';
import huePubSub from '../../../utils/huePubSub';
import { getFromLocalStorage, setInLocalStorage } from '../../../utils/storageUtils';
export const NAME = 'aceEditor';
export const INSERT_AT_CURSOR_EVENT = 'editor.insert.at.cursor';
registerBinding(NAME, {
init: function (element, valueAccessor) {
const $el = $(element);
const options = ko.unwrap(valueAccessor());
const snippet = options.snippet;
const aceOptions = options.aceOptions || {};
const disposeFunctions = [];
const dispose = function () {
disposeFunctions.forEach(dispose => {
dispose();
});
};
ko.utils.domNodeDisposal.addDisposeCallback(element, dispose);
$el.text(snippet.statement_raw());
const editor = ace.edit(snippet.id());
const AceRange = ace.require('ace/range').Range;
const resizeAce = function () {
window.setTimeout(() => {
try {
editor.resize(true);
} catch (e) {
// Can happen when the editor hasn't been initialized
}
}, 0);
};
const assistToggleSub = huePubSub.subscribe('assist.set.manual.visibility', resizeAce);
const resizePubSub = huePubSub.subscribe('split.panel.resized', resizeAce);
disposeFunctions.push(() => {
assistToggleSub.remove();
resizePubSub.remove();
});
const aceLocationHandler = new AceLocationHandler({
editor: editor,
editorId: $el.attr('id'),
snippet: snippet,
i18n: { expandStar: options.expandStar, contextTooltip: options.contextTooltip }
});
const aceGutterHandler = new AceGutterHandler({
editor: editor,
editorId: $el.attr('id'),
executor: snippet.executor
});
disposeFunctions.push(() => {
aceLocationHandler.dispose();
aceGutterHandler.dispose();
});
editor.session.setMode(snippet.getAceMode());
editor.setOptions({
fontSize: getFromLocalStorage(
'hue.ace.fontSize',
navigator.platform && navigator.platform.toLowerCase().indexOf('linux') > -1
? '14px'
: '12px'
)
});
function processErrorsAndWarnings(type, list) {
editor.clearErrorsAndWarnings(type);
let offset = 0;
if (snippet.isSqlDialect() && editor.getSelectedText()) {
const selectionRange = editor.getSelectionRange();
offset = Math.min(selectionRange.start.row, selectionRange.end.row);
}
if (list.length > 0) {
list.forEach((item, cnt) => {
if (item.line !== null) {
if (type === 'error') {
editor.addError(item.message, item.line + offset);
} else {
editor.addWarning(item.message, item.line + offset);
}
if (cnt === 0) {
editor.scrollToLine(item.line + offset, true, true, () => {});
if (item.col !== null) {
editor.renderer.scrollCursorIntoView(
{ row: item.line + offset, column: item.col + 10 },
0.5
);
}
}
}
});
}
}
const errorsSub = snippet.errors.subscribe(newErrors => {
processErrorsAndWarnings('error', newErrors);
});
const aceWarningsSub = snippet.aceWarnings.subscribe(newWarnings => {
processErrorsAndWarnings('warning', newWarnings);
});
const aceErrorsSub = snippet.aceErrors.subscribe(newErrors => {
processErrorsAndWarnings('error', newErrors);
});
disposeFunctions.push(() => {
errorsSub.dispose();
aceWarningsSub.dispose();
aceErrorsSub.dispose();
});
let darkThemeEnabled = getFromLocalStorage('ace.dark.theme.enabled', false);
editor.setTheme(darkThemeEnabled ? 'ace/theme/hue_dark' : 'ace/theme/hue');
const editorOptions = {
enableSnippets: true,
showGutter: false,
showLineNumbers: false,
showPrintMargin: false,
scrollPastEnd: 0.1,
minLines: 1,
maxLines: 25
};
editor.enabledMenuOptions = {
setShowInvisibles: true,
setTabSize: true,
setShowGutter: true
};
editor.customMenuOptions = {
setEnableDarkTheme: function (enabled) {
darkThemeEnabled = enabled;
setInLocalStorage('ace.dark.theme.enabled', darkThemeEnabled);
editor.setTheme(darkThemeEnabled ? 'ace/theme/hue_dark' : 'ace/theme/hue');
},
getEnableDarkTheme: function () {
return darkThemeEnabled;
},
setEnableAutocompleter: function (enabled) {
editor.setOption('enableBasicAutocompletion', enabled);
setInLocalStorage('hue.ace.enableBasicAutocompletion', enabled);
const $enableLiveAutocompletionChecked = $('#setEnableLiveAutocompletion:checked');
const $setEnableLiveAutocompletion = $('#setEnableLiveAutocompletion');
if (enabled && $enableLiveAutocompletionChecked.length === 0) {
$setEnableLiveAutocompletion.trigger('click');
} else if (!enabled && $enableLiveAutocompletionChecked.length !== 0) {
$setEnableLiveAutocompletion.trigger('click');
}
},
getEnableAutocompleter: function () {
return editor.getOption('enableBasicAutocompletion');
},
setEnableLiveAutocompletion: function (enabled) {
editor.setOption('enableLiveAutocompletion', enabled);
setInLocalStorage('hue.ace.enableLiveAutocompletion', enabled);
if (enabled && $('#setEnableAutocompleter:checked').length === 0) {
$('#setEnableAutocompleter').trigger('click');
}
},
getEnableLiveAutocompletion: function () {
return editor.getOption('enableLiveAutocompletion');
},
setFontSize: function (size) {
if (size.toLowerCase().indexOf('px') === -1 && size.toLowerCase().indexOf('em') === -1) {
size += 'px';
}
editor.setOption('fontSize', size);
setInLocalStorage('hue.ace.fontSize', size);
},
getFontSize: function () {
let size = editor.getOption('fontSize');
if (size.toLowerCase().indexOf('px') === -1 && size.toLowerCase().indexOf('em') === -1) {
size += 'px';
}
return size;
}
};
if (window.ENABLE_SQL_SYNTAX_CHECK && window.Worker) {
let errorHighlightingEnabled = getFromLocalStorage('hue.ace.errorHighlightingEnabled', true);
if (errorHighlightingEnabled) {
aceLocationHandler.attachSqlSyntaxWorker();
}
editor.customMenuOptions.setErrorHighlighting = function (enabled) {
errorHighlightingEnabled = enabled;
setInLocalStorage('hue.ace.errorHighlightingEnabled', enabled);
if (enabled) {
aceLocationHandler.attachSqlSyntaxWorker();
} else {
aceLocationHandler.detachSqlSyntaxWorker();
}
};
editor.customMenuOptions.getErrorHighlighting = function () {
return errorHighlightingEnabled;
};
editor.customMenuOptions.setClearIgnoredSyntaxChecks = function () {
setInLocalStorage('hue.syntax.checker.suppressedRules', {});
$('#setClearIgnoredSyntaxChecks')
.hide()
.before('<div style="margin-top:5px;float:right;">done</div>');
};
editor.customMenuOptions.getClearIgnoredSyntaxChecks = function () {
return false;
};
}
$.extend(editorOptions, aceOptions);
editorOptions['enableBasicAutocompletion'] = getFromLocalStorage(
'hue.ace.enableBasicAutocompletion',
true
);
if (editorOptions['enableBasicAutocompletion']) {
editorOptions['enableLiveAutocompletion'] = getFromLocalStorage(
'hue.ace.enableLiveAutocompletion',
true
);
}
editorOptions['tabSize'] = 2;
editorOptions['useSoftTabs'] = true;
editor.setOptions(editorOptions);
const AceAutocomplete = ace.require('ace/autocomplete').Autocomplete;
if (!editor.completer) {
editor.completer = new AceAutocomplete();
}
editor.completer.exactMatch = !snippet.isSqlDialect();
const initAutocompleters = function () {
if (editor.completers) {
editor.completers.length = 0;
if (snippet.isSqlDialect()) {
editor.useHueAutocompleter = true;
} else {
editor.completers.push(langTools.snippetCompleter);
editor.completers.push(langTools.textCompleter);
editor.completers.push(langTools.keyWordCompleter);
editor.completers.push(snippet.autocompleter);
}
}
};
const langTools = ace.require('ace/ext/language_tools');
langTools.textCompleter.setSqlMode(snippet.isSqlDialect());
initAutocompleters();
const UNICODES_TO_REMOVE =
/[\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u200B\u202F\u205F\u3000\uFEFF]/gi; //taken from https://www.cs.tut.fi/~jkorpela/chars/spaces.html
const removeUnicodes = function (value) {
return value.replace(UNICODES_TO_REMOVE, ' ');
};
let placeHolderElement = null;
let placeHolderVisible = false;
const placeHolderText = snippet.getPlaceHolder();
if (placeHolderText) {
placeHolderElement = $('<div>')
.text(placeHolderText)
.css('margin-left', '6px')
.addClass('ace_invisible ace_emptyMessage');
if (editor.getValue().length === 0) {
placeHolderElement.appendTo(editor.renderer.scroller);
placeHolderVisible = true;
}
}
const pasteListener = editor.on('paste', e => {
e.text = removeUnicodes(e.text);
});
disposeFunctions.push(() => {
editor.off('paste', pasteListener);
});
const inputListener = editor.on('input', () => {
if (editor.getValue().length === 0) {
if (!placeHolderVisible && placeHolderElement) {
placeHolderElement.appendTo(editor.renderer.scroller);
placeHolderVisible = true;
}
} else {
placeHolderElement.remove();
placeHolderVisible = false;
}
if (options.updateOnInput) {
snippet.statement_raw(removeUnicodes(editor.getValue()));
}
});
disposeFunctions.push(() => {
editor.off('input', inputListener);
});
if (snippet.aceCursorPosition()) {
editor.moveCursorToPosition(snippet.aceCursorPosition());
window.setTimeout(() => {
editor.centerSelection();
}, 0);
}
const focusListener = editor.on('focus', () => {
initAutocompleters();
snippet.inFocus(true);
$('.ace-editor').data('last-active-editor', false);
$el.data('last-active-editor', true);
if (editor.session.$backMarkers) {
for (const marker in editor.session.$backMarkers) {
if (editor.session.$backMarkers[marker].clazz === 'highlighted') {
editor.session.removeMarker(editor.session.$backMarkers[marker].id);
}
}
}
});
disposeFunctions.push(() => {
editor.off('focus', focusListener);
});
const changeSelectionListener = editor.selection.on('changeSelection', () => {
snippet.selectedStatement(editor.getSelectedText());
});
disposeFunctions.push(() => {
editor.selection.off('changeSelection', changeSelectionListener);
});
const blurListener = editor.on('blur', () => {
snippet.inFocus(false);
snippet.statement_raw(removeUnicodes(editor.getValue()));
if (options.onBlur) {
options.onBlur($el, removeUnicodes(editor.getValue()));
}
});
disposeFunctions.push(() => {
editor.off('blur', blurListener);
});
editor.previousSize = 0;
// TODO: Get rid of this
const idInterval = window.setInterval(() => {
editor.session.getMode().$id = snippet.getAceMode(); // forces the id again because of Ace command internals
}, 100);
disposeFunctions.push(() => {
window.clearInterval(idInterval);
});
editor.middleClick = false;
const mousedownListener = editor.on('mousedown', e => {
if (e.domEvent.which === 2) {
// middle click
editor.middleClick = true;
const tempText = editor.getSelectedText();
if (e.$pos) {
editor.session.insert(e.$pos, tempText);
}
window.setTimeout(() => {
editor.middleClick = false;
if (e.$pos) {
editor.moveCursorTo(e.$pos.row, e.$pos.column + tempText.length);
}
}, 200);
}
});
disposeFunctions.push(() => {
editor.off('mousedown', mousedownListener);
});
const aceReplaceSub = huePubSub.subscribe('ace.replace', data => {
const Range = ace.require('ace/range').Range;
const range = new Range(
data.location.first_line - 1,
data.location.first_column - 1,
data.location.last_line - 1,
data.location.last_column - 1
);
editor.getSession().getDocument().replace(range, data.text);
});
disposeFunctions.push(() => {
aceReplaceSub.remove();
});
const clickListener = editor.on('click', () => {
editor.clearErrorsAndWarnings();
});
disposeFunctions.push(() => {
editor.off('click', clickListener);
});
const changeListener = editor.on('change', () => {
snippet.statement_raw(removeUnicodes(editor.getValue()));
editor.session.getMode().$id = snippet.getAceMode();
const currentSize = editor.session.getLength();
if (
currentSize !== editor.previousSize &&
currentSize >= editorOptions.minLines &&
currentSize <= editorOptions.maxLines
) {
editor.previousSize = editor.session.getLength();
$(document).trigger('editorSizeChanged');
}
// automagically change snippet type
// TODO: Remove completely, check if used in code, '% dialect'
const firstLine = editor.session.getLine(0);
if (firstLine.indexOf('%') === 0 && firstLine.charAt(firstLine.length - 1) === ' ') {
const availableSnippets = snippet.availableSnippets;
let removeFirstLine = false;
for (let i = 0; i < availableSnippets.length; i++) {
if ($.trim(firstLine.substr(1)) === availableSnippets[i].type()) {
snippet.type(availableSnippets[i].type());
removeFirstLine = true;
break;
}
}
if (removeFirstLine) {
editor.session.remove(new AceRange(0, 0, 0, 200));
}
}
});
disposeFunctions.push(() => {
editor.off('change', changeListener);
});
editor.commands.addCommand({
name: 'execute',
bindKey: { win: 'Ctrl-Enter', mac: 'Command-Enter|Ctrl-Enter' },
exec: function () {
snippet.statement_raw(removeUnicodes(editor.getValue()));
snippet.execute();
}
});
editor.commands.addCommand({
name: 'switchTheme',
bindKey: { win: 'Ctrl-Alt-t', mac: 'Command-Alt-t' },
exec: function () {
darkThemeEnabled = !darkThemeEnabled;
setInLocalStorage('ace.dark.theme.enabled', darkThemeEnabled);
editor.setTheme(darkThemeEnabled ? 'ace/theme/hue_dark' : 'ace/theme/hue');
}
});
editor.commands.addCommand({
name: 'new',
bindKey: { win: 'Ctrl-e', mac: 'Command-e' },
exec: function () {
huePubSub.publish('editor.create.new');
}
});
editor.commands.addCommand({
name: 'save',
bindKey: { win: 'Ctrl-s', mac: 'Command-s|Ctrl-s' },
exec: function () {
huePubSub.publish('editor.save');
}
});
editor.commands.addCommand({
name: 'esc',
bindKey: { win: 'Ctrl-Shift-p', mac: 'Ctrl-Shift-p|Command-Shift-p' },
exec: function () {
huePubSub.publish('editor.presentation.toggle');
}
});
editor.commands.bindKey('Ctrl-P', 'golineup');
editor.commands.addCommand({
name: 'format',
bindKey: {
win: 'Ctrl-i|Ctrl-Shift-f|Ctrl-Alt-l',
mac: 'Command-i|Ctrl-i|Ctrl-Shift-f|Command-Shift-f|Ctrl-Shift-l|Cmd-Shift-l'
},
exec: function () {
const formatted_statements = format(
editor.getSelectedText() !== '' ? editor.getSelectedText() : editor.getValue(),
{ uppercase: true, linesBetweenQueries: 2, indentQuerySeparator: true }
);
if (editor.getSelectedText() !== '') {
editor.session.replace(editor.session.selection.getRange(), formatted_statements);
} else {
editor.setValue(formatted_statements);
snippet.statement_raw(removeUnicodes(editor.getValue()));
}
}
});
editor.commands.addCommand({
name: 'gotolinealternative',
bindKey: { win: 'Ctrl-j', mac: 'Command-j|Ctrl-j' },
exec: editor.commands.commands['gotoline'].exec
});
const isNewStatement = function () {
return /^\s*$/.test(editor.getValue()) || /^.*;\s*$/.test(editor.getTextBeforeCursor());
};
const insertSqlAtCursor = function (text, cursorEndAdjust, menu) {
const before = editor.getTextBeforeCursor();
if (/\S+$/.test(before)) {
text = ' ' + text;
}
if (menu) {
menu.hide();
}
editor.session.insert(editor.getCursorPosition(), text);
if (cursorEndAdjust !== 0) {
const cursor = editor.getCursorPosition();
editor.moveCursorToPosition({ row: cursor.row, column: cursor.column + cursorEndAdjust });
}
editor.clearSelection();
editor.focus();
};
const insertTableAtCursorSub = huePubSub.subscribe('editor.insert.table.at.cursor', details => {
if ($el.data('last-active-editor')) {
const qualifiedName =
snippet.database() === details.database
? details.name
: details.database + '.' + details.name;
if (isNewStatement()) {
insertSqlAtCursor('SELECT * FROM ' + qualifiedName + ' LIMIT 100;', -1);
} else {
insertSqlAtCursor(qualifiedName + ' ', 0);
}
}
});
const insertColumnAtCursorSub = huePubSub.subscribe(
'editor.insert.column.at.cursor',
details => {
if ($el.data('last-active-editor')) {
if (isNewStatement()) {
const qualifiedFromName =
snippet.database() === details.database
? details.table
: details.database + '.' + details.table;
insertSqlAtCursor(
'SELECT ' + details.name + ' FROM ' + qualifiedFromName + ' LIMIT 100;',
-1
);
} else {
insertSqlAtCursor(details.name + ' ', 0);
}
}
}
);
const insertAtCursorSub = huePubSub.subscribe(INSERT_AT_CURSOR_EVENT, details => {
if (
(details.targetEditor && details.targetEditor === editor) ||
$el.data('last-active-editor')
) {
insertSqlAtCursor(details.text + ' ', details.cursorEndAdjust || 0);
}
});
disposeFunctions.push(() => {
insertTableAtCursorSub.remove();
insertColumnAtCursorSub.remove();
insertAtCursorSub.remove();
});
const dblClickHdfsItemSub = huePubSub.subscribe('assist.dblClickHdfsItem', assistHdfsEntry => {
if ($el.data('last-active-editor')) {
editor.session.insert(editor.getCursorPosition(), "'" + assistHdfsEntry.path + "'");
}
});
disposeFunctions.push(() => {
dblClickHdfsItemSub.remove();
});
const dblClickAdlsItemSub = huePubSub.subscribe('assist.dblClickAdlsItem', assistHdfsEntry => {
if ($el.data('last-active-editor')) {
editor.session.insert(editor.getCursorPosition(), 'adl:/' + assistHdfsEntry.path + "'");
}
});
disposeFunctions.push(() => {
dblClickAdlsItemSub.remove();
});
const dblClickAbfsItemSub = huePubSub.subscribe('assist.dblClickAbfsItem', assistHdfsEntry => {
if ($el.data('last-active-editor')) {
editor.session.insert(editor.getCursorPosition(), 'abfs://' + assistHdfsEntry.path + "'");
}
});
disposeFunctions.push(() => {
dblClickAbfsItemSub.remove();
});
const dblClickOfsItemSub = huePubSub.subscribe('assist.dblClickOfsItem', assistOfsEntry => {
if ($el.data('last-active-editor')) {
editor.session.insert(editor.getCursorPosition(), 'ofs://' + assistOfsEntry.path + "'");
}
});
disposeFunctions.push(() => {
dblClickOfsItemSub.remove();
});
const dblClickGitItemSub = huePubSub.subscribe('assist.dblClickGitItem', assistGitEntry => {
if ($el.data('last-active-editor')) {
editor.session.setValue(assistGitEntry.fileContent());
}
});
disposeFunctions.push(() => {
dblClickGitItemSub.remove();
});
const dblClickS3ItemSub = huePubSub.subscribe('assist.dblClickS3Item', assistS3Entry => {
if ($el.data('last-active-editor')) {
editor.session.insert(editor.getCursorPosition(), "'s3a://" + assistS3Entry.path + "'");
}
});
disposeFunctions.push(() => {
dblClickS3ItemSub.remove();
});
const sampleErrorInsertSub = huePubSub.subscribe('sample.error.insert.click', popoverEntry => {
const table = popoverEntry.identifierChain[popoverEntry.identifierChain.length - 1]['name'];
const text = 'SELECT * FROM ' + table + ' LIMIT 100;';
insertSqlAtCursor(text, -1);
});
disposeFunctions.push(() => {
sampleErrorInsertSub.remove();
});
let autocompleteTemporarilyDisabled = false;
let autocompleteThrottle = -1;
const afterExecListener = editor.commands.on('afterExec', e => {
if (editor.getOption('enableLiveAutocompletion') && e.command.name === 'insertstring') {
if (/\S+\(\)$/.test(e.args)) {
editor.moveCursorTo(
editor.getCursorPosition().row,
editor.getCursorPosition().column - 1
);
return;
}
window.clearTimeout(autocompleteThrottle);
autocompleteThrottle = window.setTimeout(() => {
const textBeforeCursor = editor.getTextBeforeCursor();
const questionMarkMatch = textBeforeCursor.match(/select\s+(\? from \S+[^.]\s*$)/i);
if (questionMarkMatch && $('.ace_autocomplete:visible').length === 0) {
editor.moveCursorTo(
editor.getCursorPosition().row,
editor.getCursorPosition().column - (questionMarkMatch[1].length - 1)
);
editor.removeTextBeforeCursor(1);
huePubSub.publish(REFRESH_STATEMENT_LOCATIONS_EVENT, snippet.id());
window.setTimeout(() => {
editor.execCommand('startAutocomplete');
}, 1);
} else if (/\.$/.test(textBeforeCursor)) {
huePubSub.publish(REFRESH_STATEMENT_LOCATIONS_EVENT, snippet.id());
window.setTimeout(() => {
editor.execCommand('startAutocomplete');
}, 1);
}
}, 400);
}
editor.session.getMode().$id = snippet.getAceMode(); // forces the id again because of Ace command internals
// if it's pig and before it's LOAD ' we disable the autocomplete and show a filechooser btn
if (editor.session.getMode().$id === 'ace/mode/pig' && e.args) {
const textBefore = editor.getTextBeforeCursor();
if (
(e.args === "'" &&
textBefore.toUpperCase().indexOf('LOAD ') > -1 &&
textBefore.toUpperCase().indexOf('LOAD ') === textBefore.toUpperCase().length - 5) ||
(textBefore.toUpperCase().indexOf("LOAD '") > -1 &&
textBefore.toUpperCase().indexOf("LOAD '") === textBefore.toUpperCase().length - 6)
) {
if (editor.getOption('enableBasicAutocompletion')) {
editor.disableAutocomplete();
autocompleteTemporarilyDisabled = true;
}
const btn = editor.showFileButton();
btn.on('click', ie => {
ie.preventDefault();
// TODO: Turn the ace file chooser into a component and remove css class references
const $aceFileChooseContent = $('.ace-filechooser-content');
if (!$aceFileChooseContent.data('jHueFileChooser')) {
if ($aceFileChooseContent.data('spinner') == null) {
$aceFileChooseContent.data('spinner', $aceFileChooseContent.html());
} else {
$aceFileChooseContent.html($aceFileChooseContent.data('spinner'));
}
$aceFileChooseContent.jHueFileChooser({
onFileChoose: function (filePath) {
editor.session.insert(editor.getCursorPosition(), filePath + "'");
editor.hideFileButton();
if (autocompleteTemporarilyDisabled) {
editor.enableAutocomplete();
autocompleteTemporarilyDisabled = false;
}
$('.ace-filechooser').hide();
},
selectFolder: false,
createFolder: false
});
}
$('.ace-filechooser')
.css({
top: $(ie.currentTarget).position().top,
left: $(ie.currentTarget).position().left
})
.show();
});
} else {
editor.hideFileButton();
if (autocompleteTemporarilyDisabled) {
editor.enableAutocomplete();
autocompleteTemporarilyDisabled = false;
}
}
if (
e.args !== "'" &&
textBefore.toUpperCase().indexOf("LOAD '") > -1 &&
textBefore.toUpperCase().indexOf("LOAD '") === textBefore.toUpperCase().length - 6
) {
editor.hideFileButton();
if (autocompleteTemporarilyDisabled) {
editor.enableAutocomplete();
autocompleteTemporarilyDisabled = false;
}
}
}
});
disposeFunctions.push(() => {
editor.commands.off('afterExec', afterExecListener);
});
editor.$blockScrolling = Infinity;
snippet.ace(editor);
},
update: function (element, valueAccessor) {
const options = ko.unwrap(valueAccessor());
const snippet = options.snippet;
const AceRange = ace.require('ace/range').Range;
if (snippet.ace()) {
const editor = snippet.ace();
if (typeof options.readOnly !== 'undefined') {
editor.setReadOnly(options.readOnly);
}
const range = options.highlightedRange ? options.highlightedRange() : null;
editor.session.setMode(snippet.getAceMode());
if (range && JSON.stringify(range.start) !== JSON.stringify(range.end)) {
let conflictingWithErrorMarkers = false;
if (editor.session.$backMarkers) {
for (const marker in editor.session.$backMarkers) {
if (editor.session.$backMarkers[marker].clazz === 'ace_error-line') {
const errorRange = editor.session.$backMarkers[marker].range;
if (range.start.row <= errorRange.end.row && range.end.row >= errorRange.start.row) {
conflictingWithErrorMarkers = true;
}
}
if (editor.session.$backMarkers[marker].clazz === 'highlighted') {
editor.session.removeMarker(editor.session.$backMarkers[marker].id);
}
}
}
if (!conflictingWithErrorMarkers) {
const lineOffset = snippet.lastAceSelectionRowOffset();
window.setTimeout(() => {
editor.session.addMarker(
new AceRange(
range.start.row + lineOffset,
range.start.column,
range.end.row + lineOffset,
range.end.column
),
'highlighted',
'line'
);
ace
.require('ace/lib/dom')
.importCssString(
'.highlighted {\
background-color: #E3F7FF;\
position: absolute;\
}'
);
editor.scrollToLine(range.start.row + lineOffset, true, true, () => {});
}, 0);
}
}
try {
editor._emit('change');
} catch (e) {}
}
}
});