mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Add a function getQueryAt to get the SQL query at given cursor position from a CodeMirror input
This commit is contained in:
parent
e612140473
commit
ee0687ecd3
@ -2,6 +2,7 @@ import {
|
||||
EditorView
|
||||
} from '@codemirror/view';
|
||||
import { StateEffect, EditorState, EditorSelection } from '@codemirror/state';
|
||||
import { syntaxTree } from '@codemirror/language';
|
||||
import { autocompletion } from '@codemirror/autocomplete';
|
||||
import {undo, indentMore, indentLess, toggleComment} from '@codemirror/commands';
|
||||
import { errorMarkerEffect } from './extensions/errorMarker';
|
||||
@ -33,7 +34,145 @@ export default class CustomEditorView extends EditorView {
|
||||
}
|
||||
return this.state.doc.toString();
|
||||
}
|
||||
|
||||
|
||||
/* Function to extract query based on position passed */
|
||||
getQueryAt(currPos) {
|
||||
try {
|
||||
if(typeof currPos == 'undefined') {
|
||||
currPos = this.state.selection.main.head;
|
||||
}
|
||||
const tree = syntaxTree(this.state);
|
||||
|
||||
let origLine = this.state.doc.lineAt(currPos);
|
||||
let startPos = currPos;
|
||||
|
||||
// Move the startPos a known node type or a space.
|
||||
// We don't want to be in an unknown teritory
|
||||
for(;startPos<origLine.to; startPos++) {
|
||||
let node = tree.resolve(startPos);
|
||||
if(node.type.name != 'Script') {
|
||||
break;
|
||||
}
|
||||
const currChar = this.state.sliceDoc(startPos, startPos+1);
|
||||
if(currChar == ' ' || currChar == '\t') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let maxEndPos = this.state.doc.length;
|
||||
let statementStartPos = -1;
|
||||
let validTextFound = false;
|
||||
|
||||
// we'll go in reverse direction to get the start position.
|
||||
while(startPos >= 0) {
|
||||
const currLine = this.state.doc.lineAt(startPos);
|
||||
|
||||
// If empty line then start with prev line
|
||||
// If empty line in between then that's it
|
||||
if(currLine.text.trim() == '') {
|
||||
if(origLine.number != currLine.number) {
|
||||
startPos = currLine.to + 1;
|
||||
break;
|
||||
}
|
||||
startPos = currLine.from - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Script type doesn't give any info, better skip it.
|
||||
const currChar = this.state.sliceDoc(startPos, startPos+1);
|
||||
let node = tree.resolve(startPos);
|
||||
if(node.type.name == 'Script' || (currChar == '\n')) {
|
||||
startPos -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip the comments
|
||||
if(node.type.name == 'LineComment' || node.type.name == 'BlockComment') {
|
||||
startPos = node.from - 1;
|
||||
// comments are valid text
|
||||
validTextFound = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// sometimes, node type is child of statement.
|
||||
while(node.type.name != 'Statement' && node.parent) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
// We already had found valid text
|
||||
if(validTextFound) {
|
||||
// continue till it reaches start so we can check for empty lines, etc.
|
||||
if(statementStartPos > 0 && statementStartPos < startPos) {
|
||||
startPos -= 1;
|
||||
continue;
|
||||
}
|
||||
// don't go beyond this
|
||||
startPos = node.to;
|
||||
break;
|
||||
}
|
||||
|
||||
// statement found for the first time
|
||||
if(node.type.name == 'Statement') {
|
||||
statementStartPos = node.from;
|
||||
maxEndPos = node.to;
|
||||
|
||||
// if the statement is on the same line, jump to stmt start
|
||||
if(node.from >= currLine.from) {
|
||||
startPos = node.from;
|
||||
}
|
||||
}
|
||||
|
||||
validTextFound = true;
|
||||
startPos -= 1;
|
||||
}
|
||||
|
||||
// move forward from start position
|
||||
let endPos = startPos+1;
|
||||
maxEndPos = maxEndPos == -1 ? this.state.doc.length : maxEndPos;
|
||||
while(endPos < maxEndPos) {
|
||||
const currLine = this.state.doc.lineAt(endPos);
|
||||
|
||||
// If empty line in between then that's it
|
||||
if(currLine.text.trim() == '') {
|
||||
break;
|
||||
}
|
||||
|
||||
let node = tree.resolve(endPos);
|
||||
// Skip the comments
|
||||
if(node.type.name == 'LineComment' || node.type.name == 'BlockComment') {
|
||||
endPos = node.to + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip any other types
|
||||
if(node.type.name != 'Statement') {
|
||||
endPos += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// can't go beyond a statement
|
||||
if(node.type.name == 'Statement') {
|
||||
maxEndPos = node.to;
|
||||
}
|
||||
|
||||
if(currLine.to < maxEndPos) {
|
||||
endPos = currLine.to + 1;
|
||||
} else {
|
||||
endPos +=1;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure start and end are valid values;
|
||||
if(startPos < 0) startPos = 0;
|
||||
if(endPos > this.state.doc.length) endPos = this.state.doc.length;
|
||||
|
||||
return this.state.sliceDoc(startPos, endPos).trim();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return this.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
setValue(newValue, markClean=false) {
|
||||
newValue = newValue || '';
|
||||
if(markClean) {
|
||||
@ -46,7 +185,7 @@ export default class CustomEditorView extends EditorView {
|
||||
changes: { from: 0, to: this.getValue().length, insert: newValue }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
getSelection() {
|
||||
return this.state.sliceDoc(this.state.selection.main.from, this.state.selection.main.to) ?? '';
|
||||
}
|
||||
@ -63,7 +202,7 @@ export default class CustomEditorView extends EditorView {
|
||||
let line = this.state.doc.lineAt(offset);
|
||||
return {line: line.number, ch: offset - line.from};
|
||||
}
|
||||
|
||||
|
||||
setCursor(lineNo, ch) {
|
||||
// line is 1-based;
|
||||
// ch is 0-based;
|
||||
@ -79,15 +218,15 @@ export default class CustomEditorView extends EditorView {
|
||||
}
|
||||
this.dispatch({ selection: { anchor: pos, head: pos } });
|
||||
}
|
||||
|
||||
|
||||
getCurrentLineNo() {
|
||||
return this.state.doc.lineAt(this.state.selection.main.head).number;
|
||||
}
|
||||
|
||||
|
||||
lineCount() {
|
||||
return this.state.doc.lines;
|
||||
}
|
||||
|
||||
|
||||
getLine(lineNo) {
|
||||
// line is 1-based;
|
||||
return this.state.doc.line(lineNo).text;
|
||||
@ -141,7 +280,7 @@ export default class CustomEditorView extends EditorView {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
registerAutocomplete(completionFunc) {
|
||||
this.dispatch({
|
||||
effects: StateEffect.appendConfig.of(
|
||||
@ -160,13 +299,13 @@ export default class CustomEditorView extends EditorView {
|
||||
))
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
setErrorMark(fromCursor, toCursor) {
|
||||
const from = this.state.doc.line(fromCursor.line).from + fromCursor.pos;
|
||||
const to = this.state.doc.line(toCursor.line).from + toCursor.pos;
|
||||
this.dispatch({ effects: errorMarkerEffect.of({ from, to }) });
|
||||
}
|
||||
|
||||
|
||||
removeErrorMark() {
|
||||
this.dispatch({ effects: errorMarkerEffect.of({ clear: true }) });
|
||||
}
|
||||
@ -175,4 +314,3 @@ export default class CustomEditorView extends EditorView {
|
||||
this.dispatch({ effects: activeLineEffect.of({ from: line, to: line }) });
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user