Working on Formating DSL completion
This commit is contained in:
11
src/myfasthtml/assets/Readme.md
Normal file
11
src/myfasthtml/assets/Readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Commands used
|
||||
```
|
||||
cd src/myfasthtml/assets
|
||||
|
||||
# codemirror version 5 . Attenntion the version number is the url is misleading !
|
||||
wget https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.20/codemirror.min.js
|
||||
wget https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.20/codemirror.min.css
|
||||
wget https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.20/addon/hint/show-hint.min.js
|
||||
wget https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.20/addon/hint/show-hint.min.css
|
||||
wget https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.20/addon/display/placeholder.min.js
|
||||
```
|
||||
1
src/myfasthtml/assets/codemirror.min.css
vendored
Normal file
1
src/myfasthtml/assets/codemirror.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/myfasthtml/assets/codemirror.min.js
vendored
Normal file
1
src/myfasthtml/assets/codemirror.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -2114,6 +2114,175 @@ function moveColumn(table, sourceColId, targetColId) {
|
||||
}, ANIMATION_DURATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize DslEditor with CodeMirror 5
|
||||
*
|
||||
* Features:
|
||||
* - DSL-based autocompletion
|
||||
* - Line numbers
|
||||
* - Readonly support
|
||||
* - Placeholder support
|
||||
* - Textarea synchronization
|
||||
* - Debounced HTMX server update via updateCommandId
|
||||
*
|
||||
* Required CodeMirror addons:
|
||||
* - addon/hint/show-hint.js
|
||||
* - addon/hint/show-hint.css
|
||||
* - addon/display/placeholder.js
|
||||
*
|
||||
* Requires:
|
||||
* - htmx loaded globally
|
||||
*
|
||||
* @param {Object} config
|
||||
*/
|
||||
function initDslEditor(config) {
|
||||
const {
|
||||
elementId,
|
||||
textareaId,
|
||||
lineNumbers,
|
||||
autocompletion,
|
||||
placeholder,
|
||||
readonly,
|
||||
updateCommandId,
|
||||
dsl
|
||||
} = config;
|
||||
|
||||
const wrapper = document.getElementById(elementId);
|
||||
const textarea = document.getElementById(textareaId);
|
||||
const editorContainer = document.getElementById(`cm_${elementId}`);
|
||||
|
||||
if (!wrapper || !textarea || !editorContainer) {
|
||||
console.error(`DslEditor: Missing elements for ${elementId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof CodeMirror === "undefined") {
|
||||
console.error("DslEditor: CodeMirror 5 not loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------
|
||||
* Build completion list from DSL config
|
||||
* -------------------------------------------------- */
|
||||
|
||||
const completionItems = [];
|
||||
|
||||
if (dsl && dsl.completions) {
|
||||
const pushAll = (items) => {
|
||||
if (!Array.isArray(items)) return;
|
||||
items.forEach(item => completionItems.push(item));
|
||||
};
|
||||
|
||||
pushAll(dsl.completions.keywords);
|
||||
pushAll(dsl.completions.operators);
|
||||
pushAll(dsl.completions.functions);
|
||||
pushAll(dsl.completions.types);
|
||||
pushAll(dsl.completions.literals);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------
|
||||
* DSL autocompletion hint
|
||||
* -------------------------------------------------- */
|
||||
|
||||
function dslHint(cm) {
|
||||
const cursor = cm.getCursor();
|
||||
const line = cm.getLine(cursor.line);
|
||||
const ch = cursor.ch;
|
||||
|
||||
let start = ch;
|
||||
while (start > 0 && /\w/.test(line.charAt(start - 1))) {
|
||||
start--;
|
||||
}
|
||||
|
||||
const word = line.slice(start, ch);
|
||||
|
||||
const matches = completionItems.filter(item =>
|
||||
item.startsWith(word)
|
||||
);
|
||||
|
||||
return {
|
||||
list: matches,
|
||||
from: CodeMirror.Pos(cursor.line, start),
|
||||
to: CodeMirror.Pos(cursor.line, ch)
|
||||
};
|
||||
}
|
||||
|
||||
/* --------------------------------------------------
|
||||
* Create CodeMirror editor
|
||||
* -------------------------------------------------- */
|
||||
|
||||
const editor = CodeMirror(editorContainer, {
|
||||
value: textarea.value || "",
|
||||
lineNumbers: !!lineNumbers,
|
||||
readOnly: !!readonly,
|
||||
placeholder: placeholder || "",
|
||||
extraKeys: autocompletion ? {
|
||||
"Ctrl-Space": "autocomplete"
|
||||
} : {},
|
||||
hintOptions: autocompletion ? {
|
||||
hint: dslHint,
|
||||
completeSingle: false
|
||||
} : undefined
|
||||
});
|
||||
|
||||
/* --------------------------------------------------
|
||||
* Debounced update + HTMX transport
|
||||
* -------------------------------------------------- */
|
||||
|
||||
let debounceTimer = null;
|
||||
const DEBOUNCE_DELAY = 300;
|
||||
|
||||
editor.on("change", function (cm) {
|
||||
const value = cm.getValue();
|
||||
textarea.value = value;
|
||||
|
||||
if (!updateCommandId) return;
|
||||
|
||||
clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(() => {
|
||||
wrapper.dispatchEvent(
|
||||
new CustomEvent("dsl-editor-update", {
|
||||
detail: {
|
||||
commandId: updateCommandId,
|
||||
value: value
|
||||
}
|
||||
})
|
||||
);
|
||||
}, DEBOUNCE_DELAY);
|
||||
});
|
||||
|
||||
/* --------------------------------------------------
|
||||
* HTMX listener (LOCAL to wrapper)
|
||||
* -------------------------------------------------- */
|
||||
|
||||
if (updateCommandId && typeof htmx !== "undefined") {
|
||||
wrapper.addEventListener("dsl-editor-update", function (e) {
|
||||
htmx.ajax("POST", "/myfasthtml/commands", {
|
||||
target: wrapper,
|
||||
swap: "none",
|
||||
values: {
|
||||
c_id: e.detail.commandId,
|
||||
content: e.detail.value
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* --------------------------------------------------
|
||||
* Public API
|
||||
* -------------------------------------------------- */
|
||||
|
||||
wrapper._dslEditor = {
|
||||
editor: editor,
|
||||
getContent: () => editor.getValue(),
|
||||
setContent: (content) => editor.setValue(content)
|
||||
};
|
||||
|
||||
console.debug(`DslEditor initialized (CM5 + HTMX): ${elementId} with ${dsl?.name || "DSL"}`);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function updateDatagridSelection(datagridId) {
|
||||
const selectionManager = document.getElementById(`tsm_${datagridId}`);
|
||||
if (!selectionManager) return;
|
||||
|
||||
1
src/myfasthtml/assets/placeholder.min.js
vendored
Normal file
1
src/myfasthtml/assets/placeholder.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(r){function n(e){e.state.placeholder&&(e.state.placeholder.parentNode.removeChild(e.state.placeholder),e.state.placeholder=null)}function i(e){n(e);var o=e.state.placeholder=document.createElement("pre"),t=(o.style.cssText="height: 0; overflow: visible",o.style.direction=e.getOption("direction"),o.className="CodeMirror-placeholder CodeMirror-line-like",e.getOption("placeholder"));"string"==typeof t&&(t=document.createTextNode(t)),o.appendChild(t),e.display.lineSpace.insertBefore(o,e.display.lineSpace.firstChild)}function l(e){c(e)&&i(e)}function a(e){var o=e.getWrapperElement(),t=c(e);o.className=o.className.replace(" CodeMirror-empty","")+(t?" CodeMirror-empty":""),(t?i:n)(e)}function c(e){return 1===e.lineCount()&&""===e.getLine(0)}r.defineOption("placeholder","",function(e,o,t){var t=t&&t!=r.Init;o&&!t?(e.on("blur",l),e.on("change",a),e.on("swapDoc",a),r.on(e.getInputField(),"compositionupdate",e.state.placeholderCompose=function(){var t;t=e,setTimeout(function(){var e,o=!1;((o=1==t.lineCount()?"TEXTAREA"==(e=t.getInputField()).nodeName?!t.getLine(0).length:!/[^\u200b]/.test(e.querySelector(".CodeMirror-line").textContent):o)?i:n)(t)},20)}),a(e)):!o&&t&&(e.off("blur",l),e.off("change",a),e.off("swapDoc",a),r.off(e.getInputField(),"compositionupdate",e.state.placeholderCompose),n(e),(t=e.getWrapperElement()).className=t.className.replace(" CodeMirror-empty","")),o&&!e.hasFocus()&&l(e)})});
|
||||
1
src/myfasthtml/assets/show-hint.min.css
vendored
Normal file
1
src/myfasthtml/assets/show-hint.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.CodeMirror-hints{position:absolute;z-index:10;overflow:hidden;list-style:none;margin:0;padding:2px;-webkit-box-shadow:2px 3px 5px rgba(0,0,0,.2);-moz-box-shadow:2px 3px 5px rgba(0,0,0,.2);box-shadow:2px 3px 5px rgba(0,0,0,.2);border-radius:3px;border:1px solid silver;background:#fff;font-size:90%;font-family:monospace;max-height:20em;overflow-y:auto;box-sizing:border-box}.CodeMirror-hint{margin:0;padding:0 4px;border-radius:2px;white-space:pre;color:#000;cursor:pointer}li.CodeMirror-hint-active{background:#08f;color:#fff}
|
||||
1
src/myfasthtml/assets/show-hint.min.js
vendored
Normal file
1
src/myfasthtml/assets/show-hint.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user