autocomplete

This commit is contained in:
Jan Prochazka
2020-05-28 13:55:02 +02:00
parent 3a2926976c
commit eea2c00df3

View File

@@ -2,9 +2,8 @@ import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import AceEditor from 'react-ace'; import AceEditor from 'react-ace';
import useDimensions from '../utility/useDimensions'; import useDimensions from '../utility/useDimensions';
import { addCompleter } from 'ace-builds/src-noconflict/ext-language_tools'; import { addCompleter, setCompleters } from 'ace-builds/src-noconflict/ext-language_tools';
import { useDatabaseInfo, getDatabaseInfo } from '../utility/metadataLoaders'; import { getDatabaseInfo } from '../utility/metadataLoaders';
// import { Autocomplete } from 'ace-builds';
const Wrapper = styled.div` const Wrapper = styled.div`
position: absolute; position: absolute;
@@ -20,6 +19,24 @@ const engineToMode = {
postgre: 'pgsql', postgre: 'pgsql',
}; };
const COMMON_KEYWORDS = [
'select',
'where',
'update',
'delete',
'group',
'order',
'from',
'by',
'create',
'table',
'drop',
'alter',
'view',
'execute',
'procedure',
];
export default function SqlEditor({ export default function SqlEditor({
value = undefined, value = undefined,
engine = undefined, engine = undefined,
@@ -38,29 +55,27 @@ export default function SqlEditor({
const currentEditorRef = editorRef || ownEditorRef; const currentEditorRef = editorRef || ownEditorRef;
React.useEffect(() => { React.useEffect(() => {
if ((tabVisible || focusOnCreate) && currentEditorRef.current && currentEditorRef.current.editor) if (!tabVisible) return;
currentEditorRef.current.editor.focus();
}, [tabVisible, focusOnCreate]);
React.useEffect(() => { setCompleters([]);
if (onKeyDown && currentEditorRef.current) {
currentEditorRef.current.editor.keyBinding.addKeyboardHandler(onKeyDown);
}
return () => {
currentEditorRef.current.editor.keyBinding.removeKeyboardHandler(onKeyDown);
};
}, [onKeyDown]);
React.useEffect(() => {
addCompleter({ addCompleter({
getCompletions: async function (editor, session, pos, prefix, callback) { getCompletions: async function (editor, session, pos, prefix, callback) {
const cursor = session.selection.cursor; const cursor = session.selection.cursor;
const line = session.getLine(cursor.row).slice(0, cursor.column); const line = session.getLine(cursor.row).slice(0, cursor.column);
const dbinfo = await getDatabaseInfo({ conid, database }); const dbinfo = await getDatabaseInfo({ conid, database });
if (/from\s*$/i.test(line)) { let list = COMMON_KEYWORDS.map((word) => ({
name: word,
value: word,
caption: word,
meta: 'keyword',
score: 800,
}));
if (/from\s*([a-zA-Z0-9_]*)?$/i.test(line)) {
if (dbinfo) { if (dbinfo) {
const list = [ list = [
...list,
...dbinfo.tables.map((x) => ({ ...dbinfo.tables.map((x) => ({
name: x.pureName, name: x.pureName,
value: x.pureName, value: x.pureName,
@@ -76,15 +91,16 @@ export default function SqlEditor({
score: 1000, score: 1000,
})), })),
]; ];
callback(null, list);
} }
} }
callback(null, list);
}, },
}); });
const doLiveAutocomplete = function (e) { const doLiveAutocomplete = function (e) {
const editor = e.editor; const editor = e.editor;
// var hasCompleter = editor.completer && editor.completer.activated; var hasCompleter = editor.completer && editor.completer.activated;
const session = editor.session; const session = editor.session;
const cursor = session.selection.cursor; const cursor = session.selection.cursor;
const line = session.getLine(cursor.row).slice(0, cursor.column); const line = session.getLine(cursor.row).slice(0, cursor.column);
@@ -93,29 +109,38 @@ export default function SqlEditor({
if (e.command.name === 'backspace') { if (e.command.name === 'backspace') {
// do not hide after backspace // do not hide after backspace
} else if (e.command.name === 'insertstring') { } else if (e.command.name === 'insertstring') {
if (!hasCompleter) {
if (e.args == ' ' || e.args == '.') { editor.execCommand('startAutocomplete');
if (/from\s*$/i.test(line)) {
console.log('FROM', line);
currentEditorRef.current.editor.execCommand('startAutocomplete');
}
} }
// console.log('e.command', e.command);
// console.log('e.args', e.args);
// if (!hasCompleter) { // if (e.args == ' ' || e.args == '.') {
// startAutocomplete // if (/from\s*$/i.test(line)) {
// // // always start completer // currentEditorRef.current.editor.execCommand('startAutocomplete');
// // var completer = Autocomplete.for(editor); // }
// // // Disable autoInsert
// // completer.autoInsert = false;
// // completer.showPopup(editor);
// } // }
} }
}; };
currentEditorRef.current.editor.commands.on('afterExec', doLiveAutocomplete); currentEditorRef.current.editor.commands.on('afterExec', doLiveAutocomplete);
}, []);
return () => {
currentEditorRef.current.editor.commands.removeListener('afterExec', doLiveAutocomplete);
};
}, [tabVisible, conid, database, currentEditorRef.current]);
React.useEffect(() => {
if ((tabVisible || focusOnCreate) && currentEditorRef.current && currentEditorRef.current.editor)
currentEditorRef.current.editor.focus();
}, [tabVisible, focusOnCreate]);
React.useEffect(() => {
if (onKeyDown && currentEditorRef.current) {
currentEditorRef.current.editor.keyBinding.addKeyboardHandler(onKeyDown);
}
return () => {
currentEditorRef.current.editor.keyBinding.removeKeyboardHandler(onKeyDown);
};
}, [onKeyDown]);
return ( return (
<Wrapper ref={containerRef}> <Wrapper ref={containerRef}>