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');
|
||||
}
|
||||
|
||||
// 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) => {
|
||||
if (e.key === 'Enter') {
|
||||
if (e.key === 'Tab') {
|
||||
e.preventDefault();
|
||||
tabComplete(termInput);
|
||||
} else if (e.key === 'Enter') {
|
||||
const cmd = termInput.value.trim();
|
||||
if (cmd) termExec(cmd);
|
||||
termInput.value = '';
|
||||
|
||||
Reference in New Issue
Block a user