in Composer/packages/tools/language-servers/language-generation/src/LGServer.ts [534:597]
private matchState(
params: TextDocumentPositionParams,
curLineState: LGCursorState | undefined
): LGCursorState | undefined {
const state: LGCursorState[] = [];
const document = this.documents.get(params.textDocument.uri);
if (!document) return;
const position = params.position;
const range = Range.create(position.line, 0, position.line, position.character);
const lineContent = document.getText(range);
//initialize the root state to plaintext
state.push(ROOT);
if (lineContent.trim().startsWith('#')) {
return TEMPLATENAME;
} else if (lineContent.trim().startsWith('>')) {
return COMMENTS;
} else if (lineContent.trim().startsWith('-') || curLineState === STRUCTURELG) {
state.push(TEMPLATEBODY);
} else {
return ROOT;
}
// find out the context state of current cursor, offer precise suggestion and completion etc.
/**
* > To learn more about the LG file format... --- COMMENTS
* # Greeting --- TEMPLATENAME
* - Hello --- TEMPLATEBODY
* - Hi, @{name}, what's the meaning of 'state'
* |
* +------------------------------------------- EXPRESSION
*/
let i = 0;
while (i < lineContent.length) {
const char = lineContent.charAt(i);
if (char === `'`) {
if (state[state.length - 1] === EXPRESSION || state[state.length - 1] === DOUBLE) {
state.push(SINGLE);
} else {
state.pop();
}
}
if (char === `"`) {
if (state[state.length - 1] === EXPRESSION || state[state.length - 1] === SINGLE) {
state.push(DOUBLE);
} else {
state.pop();
}
}
if (char === '{' && i >= 1 && state[state.length - 1] !== SINGLE && state[state.length - 1] !== DOUBLE) {
if (lineContent.charAt(i - 1) === '$') {
state.push(EXPRESSION);
}
}
if (char === '}' && state[state.length - 1] === EXPRESSION) {
state.pop();
}
i++;
}
return state.pop();
}