1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-23 11:58:00 +01:00

Dont let completion <Tab> presses backlog.

This commit is contained in:
Kris Maglione
2008-11-25 02:53:01 +00:00
parent ce0542bf66
commit a0c9d445ba
2 changed files with 124 additions and 109 deletions

View File

@@ -121,6 +121,110 @@ function CommandLine() //{{{
commandline.setCompletions(completionContext.allItems); commandline.setCompletions(completionContext.allItems);
}); });
var tabTimer = new util.Timer(10, 10, function (event) {
let command = commandline.getCommand();
// always reset our completion history so up/down keys will start with new values
historyIndex = UNINITIALIZED;
// TODO: call just once, and not on each <Tab>
let wildmode = options["wildmode"].split(",");
let wildType = wildmode[Math.min(wildIndex++, wildmode.length - 1)];
let hasList = /^list(:|$)/.test(wildType);
let longest = /(^|:)longest$/.test(wildType);
let full = !longest && /(^|:)full/.test(wildType);
// we need to build our completion list first
if (completionIndex == UNINITIALIZED)
{
completionIndex = -1;
completionPrefix = command.substring(0, commandWidget.selectionStart);
completionPostfix = command.substring(commandWidget.selectionStart);
completions = liberator.triggerCallback("complete", currentExtendedMode, completionPrefix);
// sort the completion list
// TODO: might not make sense anymore with our advanced completions, we should just sort when necessary
// FIXME: CompletionContext
//if (options.get("wildoptions").has("sort"))
// completions.items.sort(function (a, b) String.localeCompare(a[0], b[0]));
completionList.setItems(completionContext);
}
if (completions.items.length == 0)
{
// Wait for items to come available
// TODO: also use that code when we DO have completions but too few
let end = Date.now() + 5000;
while (completionContext.incomplete && completions.items.length == 0 && Date.now() < end)
{
liberator.threadYield();
completions = completionContext.allItems;
}
if (completions.items.length == 0) // still not more matches
{
liberator.beep();
return;
}
}
if (full)
{
if (event.shiftKey)
{
completionIndex--;
if (completionIndex < -1)
completionIndex = completions.items.length - 1;
}
else
{
completionIndex++;
if (completionIndex > completions.items.length)
completionIndex = 0;
}
statusTimer.tell();
}
// the following line is not inside if (hasList) for list:longest,full
completionList.selectItem(completionIndex);
if (hasList)
completionList.show();
if ((completionIndex == -1 || completionIndex >= completions.items.length) && !longest) // wrapped around matches, reset command line
{
if (full)
setCommand(completionPrefix + completionPostfix);
}
else
{
var compl = null;
if (longest && completions.items.length > 1)
compl = completion.longestSubstring;
else if (full)
compl = completions.items[completionIndex].text;
else if (completions.items.length == 1)
compl = completions.items[0].text;
if (compl)
{
setCommand(command.substring(0, completions.start) + compl + completionPostfix);
commandWidget.selectionStart = commandWidget.selectionEnd = completions.start + compl.length;
if (longest)
liberator.triggerCallback("change", currentExtendedMode, this.getCommand());
// Start a new completion in the next iteration. Useful for commands like :source
// RFC: perhaps the command can indicate whether the completion should be restarted
// -> should be doable now, since the completion items are objects
// Needed for :source to grab another set of completions after a file/directory has been filled out
// if (completions.length == 1 && !full)
// completionIndex = UNINITIALIZED;
}
}
});
// the containing box for the promptWidget and commandWidget // the containing box for the promptWidget and commandWidget
var commandlineWidget = document.getElementById("liberator-commandline"); var commandlineWidget = document.getElementById("liberator-commandline");
// the prompt for the current command, for example : or /. Can be blank // the prompt for the current command, for example : or /. Can be blank
@@ -810,108 +914,7 @@ function CommandLine() //{{{
// user pressed TAB to get completions of a command // user pressed TAB to get completions of a command
else if (key == "<Tab>" || key == "<S-Tab>") else if (key == "<Tab>" || key == "<S-Tab>")
{ {
// always reset our completion history so up/down keys will start with new values tabTimer.tell(event);
historyIndex = UNINITIALIZED;
// TODO: call just once, and not on each <Tab>
let wildmode = options["wildmode"].split(",");
let wildType = wildmode[Math.min(wildIndex++, wildmode.length - 1)];
let hasList = /^list(:|$)/.test(wildType);
let longest = /(^|:)longest$/.test(wildType);
let full = !longest && /(^|:)full/.test(wildType);
// we need to build our completion list first
if (completionIndex == UNINITIALIZED)
{
completionIndex = -1;
completionPrefix = command.substring(0, commandWidget.selectionStart);
completionPostfix = command.substring(commandWidget.selectionStart);
completions = liberator.triggerCallback("complete", currentExtendedMode, completionPrefix);
// sort the completion list
// TODO: might not make sense anymore with our advanced completions, we should just sort when necessary
// FIXME: CompletionContext
//if (options.get("wildoptions").has("sort"))
// completions.items.sort(function (a, b) String.localeCompare(a[0], b[0]));
completionList.setItems(completionContext);
}
if (completions.items.length == 0)
{
// Wait for items to come available
// TODO: also use that code when we DO have completions but too few
let end = Date.now() + 5000;
while (completionContext.incomplete && completions.items.length == 0 && Date.now() < end)
{
liberator.threadYield();
completions = completionContext.allItems;
}
if (completions.items.length == 0) // still not more matches
{
liberator.beep();
// prevent tab from moving to the next field:
event.preventDefault();
event.stopPropagation();
return false;
}
}
if (full)
{
if (event.shiftKey)
{
completionIndex--;
if (completionIndex < -1)
completionIndex = completions.items.length - 1;
}
else
{
completionIndex++;
if (completionIndex > completions.items.length)
completionIndex = 0;
}
statusTimer.tell();
}
// the following line is not inside if (hasList) for list:longest,full
completionList.selectItem(completionIndex);
if (hasList)
completionList.show();
if ((completionIndex == -1 || completionIndex >= completions.items.length) && !longest) // wrapped around matches, reset command line
{
if (full)
setCommand(completionPrefix + completionPostfix);
}
else
{
var compl = null;
if (longest && completions.items.length > 1)
compl = completion.longestSubstring;
else if (full)
compl = completions.items[completionIndex].text;
else if (completions.items.length == 1)
compl = completions.items[0].text;
if (compl)
{
setCommand(command.substring(0, completions.start) + compl + completionPostfix);
commandWidget.selectionStart = commandWidget.selectionEnd = completions.start + compl.length;
if (longest)
liberator.triggerCallback("change", currentExtendedMode, this.getCommand());
// Start a new completion in the next iteration. Useful for commands like :source
// RFC: perhaps the command can indicate whether the completion should be restarted
// -> should be doable now, since the completion items are objects
// Needed for :source to grab another set of completions after a file/directory has been filled out
// if (completions.length == 1 && !full)
// completionIndex = UNINITIALIZED;
}
}
// prevent tab from moving to the next field // prevent tab from moving to the next field
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@@ -1322,12 +1325,17 @@ function ItemList(id) //{{{
} }
</div> </div>
</div>); </div>);
noCompletions = div.childNodes[0]; noCompletions = div.childNodes[1];
completionBody = div.childNodes[1]; completionBody = div.childNodes[3];
items.contextList.forEach(function (context) { items.contextList.forEach(function (context) {
if (!context.items.length) if (!context.items.length)
return; return;
context.cache.dom = dom(<div class="hl-Completions">{context.createRow(context.title || [], "hl-CompTitle")}</div>); context.cache.dom = dom(<div>
<div class="hl-Completions">
{context.createRow(context.title || [], "hl-CompTitle")}
</div>
<div/>
</div>);
completionBody.appendChild(context.cache.dom); completionBody.appendChild(context.cache.dom);
}); });
} }
@@ -1340,10 +1348,13 @@ function ItemList(id) //{{{
*/ */
function fill(offset) function fill(offset)
{ {
function dom(xml) util.xmlToDom(xml, doc);
let diff = offset - startIndex; let diff = offset - startIndex;
if (items == null || offset == null || diff == 0 || offset < 0) if (items == null || offset == null || diff == 0 || offset < 0)
return; return;
let stuff = dom(<div class="hl-Completions"/>);
startIndex = offset; startIndex = offset;
endIndex = Math.min(startIndex + maxItems, items.allItems.items.length); endIndex = Math.min(startIndex + maxItems, items.allItems.items.length);
@@ -1361,16 +1372,19 @@ function ItemList(id) //{{{
let dom = context.cache.dom; let dom = context.cache.dom;
if (!dom) if (!dom)
return; return;
while (dom.childNodes[1]) let d = stuff.cloneNode(true);
dom.removeChild(dom.childNodes[1]);
for (let [,row] in Iterator(getRows(context))) for (let [,row] in Iterator(getRows(context)))
dom.appendChild(row); d.appendChild(row);
dom.replaceChild(d, dom.childNodes[3]);
}); });
try {
noCompletions.style.display = off > 0 ? "none" : "block"; noCompletions.style.display = off > 0 ? "none" : "block";
} catch(e) {}
let dom = div.cloneNode(true); let dom = div.cloneNode(true);
completionElements = dom.getElementsByClassName("hl-CompItem"); completionElements = dom.getElementsByClassName("hl-CompItem");
completionBody = dom.childNodes[3];
doc.body.replaceChild(dom, doc.body.firstChild); doc.body.replaceChild(dom, doc.body.firstChild);
autoSize(); autoSize();

View File

@@ -89,6 +89,7 @@ const util = { //{{{
/* minInterval is the time between the completion of the command and the next firing. */ /* minInterval is the time between the completion of the command and the next firing. */
this.doneAt = Date.now() + minInterval; this.doneAt = Date.now() + minInterval;
liberator.dump({notify: "notify"});
try try
{ {
callback(this.arg); callback(this.arg);
@@ -111,7 +112,7 @@ const util = { //{{{
if (now > this.doneAt && this.doneAt > -1) if (now > this.doneAt && this.doneAt > -1)
timeout = 0; timeout = 0;
else if (this.latest) else if (this.latest)
timeout = minInterval; timeout = Math.min(timeout, this.latest - now);
else else
this.latest = now + maxInterval; this.latest = now + maxInterval;