Tab-completion kpn-terminaaliin: ennustava komennonsyöttö sana kerrallaan
TAB täydentää kontekstin mukaan:
- tyhjä → "kpn "
- "kpn " → "kpn help", "kpn run", "kpn pipeline" jne.
- "kpn run " → agentit ja mallit (coder, manager, qwen-coder...)
- "kpn run coder " → esimerkkiprompteja ("hello world in python")
- "kpn pi" → "kpn pipeline "
- osittainen sana → yhteinen etuliite tai ainoa vaihtoehto
Tukee myös kpn pipeline -esimerkkiprompteja.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1915,8 +1915,78 @@
|
|||||||
termLog(` kpn: tuntematon alikomento "${sub}". Kokeile: kpn help`, '#f85149');
|
termLog(` kpn: tuntematon alikomento "${sub}". Kokeile: kpn help`, '#f85149');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tab-completion: ennustava komennonsyöttö sana kerrallaan
|
||||||
|
const kpnCommands = {
|
||||||
|
'kpn': ['help', 'run', 'pipeline', 'load', 'status', 'models', 'hello', 'clear'],
|
||||||
|
'kpn run': ['coder', 'manager', 'tester', 'qa', 'data', 'observer', 'qwen-coder', 'smollm-135m', 'qwen-05b', 'phi3-mini'],
|
||||||
|
'kpn pipeline': ['"'],
|
||||||
|
};
|
||||||
|
// Esimerkkipromptit malleittain
|
||||||
|
const kpnExamples = {
|
||||||
|
'kpn run coder': ['"hello world in python"', '"fibonacci in rust"', '"quicksort in javascript"'],
|
||||||
|
'kpn run manager': ['"suunnittele REST API"', '"priorisoi tiimin tehtävät"'],
|
||||||
|
'kpn run tester': ['"testaa login-toiminto"'],
|
||||||
|
'kpn pipeline': ['"rakenna todo-sovellus"', '"tee laskin pythonilla"'],
|
||||||
|
};
|
||||||
|
|
||||||
|
function tabComplete(input) {
|
||||||
|
const val = input.value;
|
||||||
|
const words = val.trimEnd().split(/\s+/);
|
||||||
|
|
||||||
|
// Etsitään sopiva täydennystaso
|
||||||
|
// "kpn" → "kpn " alikomennot, "kpn run" → mallit, "kpn run coder" → prompti
|
||||||
|
for (let depth = words.length; depth >= 1; depth--) {
|
||||||
|
const prefix = words.slice(0, depth).join(' ');
|
||||||
|
const partial = words[depth] || '';
|
||||||
|
|
||||||
|
// Tarkistetaan esimerkkipromptit ensin
|
||||||
|
if (kpnExamples[prefix] && !partial) {
|
||||||
|
const example = kpnExamples[prefix][Math.floor(Math.random() * kpnExamples[prefix].length)];
|
||||||
|
input.value = prefix + ' ' + example;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Komentojen täydennys
|
||||||
|
const candidates = kpnCommands[prefix];
|
||||||
|
if (candidates) {
|
||||||
|
const matches = partial
|
||||||
|
? candidates.filter(c => c.startsWith(partial))
|
||||||
|
: candidates;
|
||||||
|
if (matches.length === 1) {
|
||||||
|
words[depth] = matches[0];
|
||||||
|
input.value = words.slice(0, depth + 1).join(' ') + ' ';
|
||||||
|
return true;
|
||||||
|
} else if (matches.length > 1 && !partial) {
|
||||||
|
input.value = prefix + ' ' + matches[0];
|
||||||
|
return true;
|
||||||
|
} else if (matches.length > 1) {
|
||||||
|
// Yhteinen etuliite
|
||||||
|
let common = matches[0];
|
||||||
|
for (const m of matches) {
|
||||||
|
while (!m.startsWith(common)) common = common.slice(0, -1);
|
||||||
|
}
|
||||||
|
if (common.length > partial.length) {
|
||||||
|
words[depth] = common;
|
||||||
|
input.value = words.slice(0, depth + 1).join(' ');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tyhjä input → "kpn "
|
||||||
|
if (!val.trim()) {
|
||||||
|
input.value = 'kpn ';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
termInput?.addEventListener('keydown', (e) => {
|
termInput?.addEventListener('keydown', (e) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Tab') {
|
||||||
|
e.preventDefault();
|
||||||
|
tabComplete(termInput);
|
||||||
|
} else if (e.key === 'Enter') {
|
||||||
const cmd = termInput.value.trim();
|
const cmd = termInput.value.trim();
|
||||||
if (cmd) termExec(cmd);
|
if (cmd) termExec(cmd);
|
||||||
termInput.value = '';
|
termInput.value = '';
|
||||||
|
|||||||
Reference in New Issue
Block a user