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

More completion stuff

This commit is contained in:
Kris Maglione
2008-11-22 09:14:21 +00:00
parent fcc799aa6a
commit ef0b517d3f
5 changed files with 108 additions and 101 deletions

View File

@@ -43,13 +43,18 @@ function CompletionContext(editor, name, offset)
name = parent.name + "/" + name; name = parent.name + "/" + name;
this.contexts = parent.contexts; this.contexts = parent.contexts;
if (name in this.contexts) if (name in this.contexts)
return this.contexts[name]; {
let self = this.contexts[name];
self.offset = parent.offset + (offset || 0);
return self;
}
this.contexts[name] = this; this.contexts[name] = this;
this.parent = parent; this.parent = parent;
this.editor = parent.editor; this.editor = parent.editor;
this.offset = parent.offset + (offset || 0); this.offset = parent.offset + (offset || 0);
this.__defineGetter__("tabPressed", function () this.parent.tabPressed); this.__defineGetter__("tabPressed", function () this.parent.tabPressed);
this.__defineGetter__("onUpdate", function () this.parent.onUpdate); this.__defineGetter__("onUpdate", function () this.parent.onUpdate);
this.__defineGetter__("value", function () this.parent.value);
this.incomplete = false; this.incomplete = false;
} }
else else
@@ -94,6 +99,9 @@ CompletionContext.prototype = {
get contextList() [v for ([k, v] in Iterator(this.contexts))], get contextList() [v for ([k, v] in Iterator(this.contexts))],
get createRow() this._createRow || template.completionRow, // XXX
set createRow(createRow) this._createRow = createRow,
get filter() this.value.substr(this.offset, this.caret), get filter() this.value.substr(this.offset, this.caret),
get items() this._items, get items() this._items,
@@ -104,7 +112,8 @@ CompletionContext.prototype = {
this.onUpdate.call(this); this.onUpdate.call(this);
}, },
get value() this.editor.rootElement.textContent, get title() this._title || ["Completions"], // XXX
set title(val) this._title = val,
advance: function (count) advance: function (count)
{ {
@@ -154,6 +163,7 @@ CompletionContext.prototype = {
this.selectionTypes = {}; this.selectionTypes = {};
this.tabPressed = false; this.tabPressed = false;
this.offset = 0; this.offset = 0;
this.value = this.editor.rootElement.textContent;
//for (let key in (k for ([k, v] in Iterator(self.contexts)) if (v.offset > this.caret))) //for (let key in (k for ([k, v] in Iterator(self.contexts)) if (v.offset > this.caret)))
// delete this.contexts[key]; // delete this.contexts[key];
for each (let context in this.contexts) for each (let context in this.contexts)
@@ -294,7 +304,6 @@ function Completion() //{{{
if (last != undefined) // Escaping the key (without adding quotes), so it matches the escaped completions. if (last != undefined) // Escaping the key (without adding quotes), so it matches the escaped completions.
key = util.escapeString(key.substr(offset), ""); key = util.escapeString(key.substr(offset), "");
completion.filterString = key;
let res = buildLongestStartingSubstring(compl, key); let res = buildLongestStartingSubstring(compl, key);
if (res.length == 0) if (res.length == 0)
{ {
@@ -529,7 +538,7 @@ function Completion() //{{{
cacheKey = str.substring(statement, dot); cacheKey = str.substring(statement, dot);
obj = self.eval(s, cacheKey, obj); obj = self.eval(s, cacheKey, obj);
} }
return [[obj], str.substring(statement, stop + 1)]; return [[obj, str.substring(statement, stop + 1)]];
} }
function getObjKey(frame) function getObjKey(frame)
@@ -692,7 +701,6 @@ function Completion() //{{{
// list = [ [['com1', 'com2'], 'text'], [['com3', 'com4'], 'text'] ] // list = [ [['com1', 'com2'], 'text'], [['com3', 'com4'], 'text'] ]
function buildLongestCommonSubstring(list, filter, favicon) function buildLongestCommonSubstring(list, filter, favicon)
{ {
completion.filterString = filter;
var filtered = []; var filtered = [];
var ignorecase = false; var ignorecase = false;
@@ -1027,13 +1035,13 @@ function Completion() //{{{
environment: function environment(filter) environment: function environment(filter)
{ {
let command = liberator.has("Win32") ? "set" : "export"; let command = liberator.has("Win32") ? "set" : "env";
let lines = io.system(command).split("\n"); let lines = io.system(command).split("\n");
lines.splice(lines.length - 1, 1); lines.pop();
let vars = lines.map(function (line) { let vars = lines.map(function (line) {
let matches = line.match(/([^=]+)=(.+)/); let matches = line.match(/([^=]+)=(.+)/) || [];
return [matches[1], matches[2]]; return [matches[1], matches[2]];
}); });
@@ -1044,7 +1052,6 @@ function Completion() //{{{
ex: function ex(context) ex: function ex(context)
{ {
this.filterMap = null; this.filterMap = null;
this.filterString = "";
substrings = []; substrings = [];
if (context.filter.indexOf(cacheFilter["ex"]) != 0) if (context.filter.indexOf(cacheFilter["ex"]) != 0)
{ {
@@ -1069,7 +1076,6 @@ function Completion() //{{{
{ {
[prefix] = context.filter.match(/^(?:\w*[\s!]|!)\s*/); [prefix] = context.filter.match(/^(?:\w*[\s!]|!)\s*/);
context = context.fork(cmd, prefix.length); context = context.fork(cmd, prefix.length);
this.filterString = context.filter;
args = command.parseArgs(context.filter, true); args = command.parseArgs(context.filter, true);
if (args) if (args)
{ {
@@ -1220,7 +1226,6 @@ function Completion() //{{{
// XXX: Move to bookmarks.js? // XXX: Move to bookmarks.js?
searchEngineSuggest: function (context, engineAliases) searchEngineSuggest: function (context, engineAliases)
{ {
this.filterString = context.filter;
if (!filter) if (!filter)
return [0, []]; return [0, []];
@@ -1325,7 +1330,6 @@ function Completion() //{{{
// if the 'complete' argument is passed like "h", it temporarily overrides the complete option // if the 'complete' argument is passed like "h", it temporarily overrides the complete option
url: function url(context, complete) url: function url(context, complete)
{ {
this.filterString = context.filter;
var numLocationCompletions = 0; // how many async completions did we already return to the caller? var numLocationCompletions = 0; // how many async completions did we already return to the caller?
var start = 0; var start = 0;
var skip = context.filter.match("^.*" + options["urlseparator"]); // start after the last 'urlseparator' var skip = context.filter.match("^.*" + options["urlseparator"]); // start after the last 'urlseparator'
@@ -1339,6 +1343,13 @@ function Completion() //{{{
b: function (context) b: function (context)
{ {
context.title = ["Bookmark", "Title"]; context.title = ["Bookmark", "Title"];
context.createRow = function (context, item, class)
{
// FIXME
if (class)
return template.completionRow(context, item, class);
return template.bookmarkItem(item);
}
context.items = bookmarks.get(context.filter) context.items = bookmarks.get(context.filter)
}, },
l: function (context) l: function (context)

View File

@@ -28,6 +28,7 @@ function Highlights(name, store, serial)
NonText color: blue; min-height: 16px; padding-left: 2px; NonText color: blue; min-height: 16px; padding-left: 2px;
CompTitle color: magenta; background: white; font-weight: bold;
CompItem CompItem
CompItem[selected] background: yellow; CompItem[selected] background: yellow;
CompItem>* padding: 0 .5ex; CompItem>* padding: 0 .5ex;

View File

@@ -32,6 +32,38 @@ const template = {
return <>{xml}</>; return <>{xml}</>;
}, },
completionRow: function (context, item, class)
{
let text = item.text || item[0] || "";
let description = item.description || item[1] || "";
let icon = item.icon || item[2];
/* Kludge until we have completion contexts. */
let map = completion.filterMap;
if (map)
{
text = map[0] ? map[0](text) : text;
description = map[1] ? map[1](description) : description;
}
// FIXME: Move.
let filter = context.filter;
if (filter)
{
text = template.highlightFilter(text, filter);
description = template.highlightFilter(description, filter);
}
if (typeof icon == "function")
icon = icon();
return <ul class={class || "hl-CompItem"}>
<li class="hl-CompIcon">{icon ? <img src={icon}/> : <></>}</li>
<li class="hl-CompResult">{text}</li>
<li class="hl-CompDesc">{description}</li>
</ul>;
},
// if "processStrings" is true, any passed strings will be surrounded by " and // if "processStrings" is true, any passed strings will be surrounded by " and
// any line breaks are displayed as \n // any line breaks are displayed as \n
highlight: function (arg, processStrings) highlight: function (arg, processStrings)

View File

@@ -842,7 +842,7 @@ function CommandLine() //{{{
//if (options.get("wildoptions").has("sort")) //if (options.get("wildoptions").has("sort"))
// completions.items.sort(function (a, b) String.localeCompare(a[0], b[0])); // completions.items.sort(function (a, b) String.localeCompare(a[0], b[0]));
completionList.setItems(completionContext.allItems); completionList.setItems(completionContext);
} }
if (completions.items.length == 0) if (completions.items.length == 0)
@@ -1243,7 +1243,7 @@ function CommandLine() //{{{
//if (newCompletions.incompleteResult && newCompletions.items.length == 0) //if (newCompletions.incompleteResult && newCompletions.items.length == 0)
// return; // return;
completionList.setItems(newCompletions.items); completionList.setItems(completionContext);
// try to keep the old item selected // try to keep the old item selected
if (completionIndex >= 0 && completionIndex < newCompletions.items.length && completionIndex < completions.items.length) if (completionIndex >= 0 && completionIndex < newCompletions.items.length && completionIndex < completions.items.length)
@@ -1314,7 +1314,7 @@ function ItemList(id) //{{{
doc.body.id = id + "-content"; doc.body.id = id + "-content";
doc.body.appendChild(doc.createTextNode("")); doc.body.appendChild(doc.createTextNode(""));
var items = []; var items = null;
var startIndex = -1; // The index of the first displayed item var startIndex = -1; // The index of the first displayed item
var endIndex = -1; // The index one *after* the last displayed item var endIndex = -1; // The index one *after* the last displayed item
var selIndex = -1; // The index of the currently selected element var selIndex = -1; // The index of the currently selected element
@@ -1333,40 +1333,6 @@ function ItemList(id) //{{{
commandline.updateOutputHeight(false); commandline.updateOutputHeight(false);
} }
// TODO: move to completions?
function createDefaultRow(item, dom)
{
let { text: text, description: description, icon: icon } = item;
/* Kludge until we have completion contexts. */
let map = completion.filterMap;
if (map)
{
text = map[0] ? map[0](text) : text;
description = map[1] ? map[1](description) : description;
}
/* Obviously, ItemList shouldn't know or care about this. */
let filter = completion.filterString;
if (filter)
{
text = template.highlightFilter(text, filter);
description = template.highlightFilter(description, filter);
}
if (typeof icon == "function")
icon = icon();
let row =
<ul class="hl-CompItem">
<li class="hl-CompIcon">{icon ? <img src={icon}/> : <></>}</li>
<li class="hl-CompResult">{text}</li>
<li class="hl-CompDesc">{description}</li>
</ul>;
if (dom)
return util.xmlToDom(row, doc);
return row;
}
function getCompletion(index) completionElements[index - startIndex]; function getCompletion(index) completionElements[index - startIndex];
/** /**
@@ -1378,60 +1344,56 @@ function ItemList(id) //{{{
function fill(offset) function fill(offset)
{ {
let diff = offset - startIndex; let diff = offset - startIndex;
if (offset == null || offset - startIndex == 0 || offset < 0 || items.length && offset >= items.length) if (items == null || offset == null || offset - startIndex == 0 || offset < 0)
return; return;
startIndex = offset; startIndex = offset;
endIndex = Math.min(startIndex + maxItems, items.length); endIndex = Math.min(startIndex + maxItems, items.allItems.items.length);
if (selIndex > -1 && Math.abs(diff) == 1) /* Scroll one position */ // do a full refill of the list:
XML.ignoreWhitespace = true;
let off = 0;
function range(context)
{ {
let tbody = completionBody; let len = context.items.length;
let start = off;
if (diff == 1) /* Scroll down */ off += len;
{ return util.range(Math.max(offset - start, 0), Math.min(endIndex - start, len));
let item = items[endIndex - 1];
let row = "xml" in item ? util.xmlToDom(item.xml, doc) : createDefaultRow(item, true);
tbody.removeChild(tbody.firstChild);
tbody.appendChild(row);
}
else /* Scroll up */
{
let item = items[offset];
let row = "xml" in item ? util.xmlToDom(item.xml, doc) : createDefaultRow(item, true);
tbody.removeChild(tbody.lastChild);
tbody.insertBefore(row, tbody.firstChild);
}
} }
else
{
// do a full refill of the list:
XML.ignoreWhitespace = true;
let xml = <div class="ex-command-output hl-Normal" style="white-space: nowrap">
<span class="hl-Title">Completions:</span>
<div class="hl-Completions">
{
template.map(util.range(offset, endIndex), function (i)
"xml" in items[i] ? items[i].xml : createDefaultRow(items[i]))
}
</div>
<div class="hl-Completions">
{
// Hmm. The problem with not making this a CompItem is that
// the height and padding aren't the same.
template.map(util.range(0, maxItems), function (i)
<ul><li class="hl-NonText">~</li></ul>)
}
</div>
</div>;
div = util.xmlToDom(xml, doc); let xml = <div class="ex-command-output hl-Normal" style="white-space: nowrap">
completionBody = div.getElementsByClassName("hl-Completions")[0]; {
//completionElements = completionBody.childNodes; // Kris: This is broken for things like :dia pr<tab> items.allItems.items.length == 0 &&
completionElements = div.getElementsByClassName("hl-CompItem"); <div class="hl-Completions">
doc.body.replaceChild(div, doc.body.firstChild); <span class="hl-Title">No Completions</span>
autoSize(); </div> || <></>
} }
{
template.map(items.contextList, function (context) context.hasItems &&
<div class="hl-Completions">
{ context.createRow(context, context.title || {}, "hl-CompTitle") }
{
template.map(range(context), function (i) context.createRow(context, context.items[i]))
}
</div>
|| undefined)
}
<div class="hl-Completions">
{
// Hmm. The problem with not making this a CompItem is that
// the height and padding aren't the same.
template.map(util.range(0, maxItems), function (i)
<ul><li class="hl-NonText">~</li></ul>)
}
</div>
</div>;
div = util.xmlToDom(xml, doc);
completionBody = div.getElementsByClassName("hl-Completions")[0];
//completionElements = completionBody.childNodes; // Kris: This is broken for things like :dia pr<tab>
completionElements = div.getElementsByClassName("hl-CompItem");
doc.body.replaceChild(div, doc.body.firstChild);
autoSize();
} }
/////////////////////////////////////////////////////////////////////////////}}} /////////////////////////////////////////////////////////////////////////////}}}
@@ -1460,7 +1422,7 @@ function ItemList(id) //{{{
setItems: function setItems(newItems, selectedItem) setItems: function setItems(newItems, selectedItem)
{ {
startIndex = endIndex = selIndex = -1; startIndex = endIndex = selIndex = -1;
items = newItems || []; items = newItems;
if (typeof selectedItem == "number") if (typeof selectedItem == "number")
{ {
this.selectItem(selectedItem); this.selectItem(selectedItem);
@@ -1474,7 +1436,8 @@ function ItemList(id) //{{{
//if (container.collapsed) // fixme //if (container.collapsed) // fixme
// return; // return;
if (index == -1 || index == items.length) // wrapped around let len = items.allItems.items.length;
if (index == -1 || index == len) // wrapped around
{ {
if (selIndex >= 0) if (selIndex >= 0)
getCompletion(selIndex).removeAttribute("selected"); getCompletion(selIndex).removeAttribute("selected");
@@ -1491,7 +1454,7 @@ function ItemList(id) //{{{
else if (index <= startIndex + CONTEXT_LINES) else if (index <= startIndex + CONTEXT_LINES)
newOffset = index - CONTEXT_LINES; newOffset = index - CONTEXT_LINES;
newOffset = Math.min(newOffset, items.length - maxItems); newOffset = Math.min(newOffset, len - maxItems);
newOffset = Math.max(newOffset, 0); newOffset = Math.max(newOffset, 0);
if (selIndex > -1) if (selIndex > -1)

View File

@@ -60,13 +60,13 @@ the terms of any one of the MPL, the GPL or the LGPL.
width: 100%; width: 100%;
display: table; display: table;
} }
.hl-CompItem { .hl-CompItem, .hl-CompTitle {
display: table-row; display: table-row;
} }
.hl-Completions > ul { .hl-Completions > ul {
display: table-row; display: table-row;
} }
.hl-CompItem > * { .hl-CompItem > *, .hl-CompTitle > * {
-moz-binding: url(chrome://liberator/content/bindings.xml#compitem-td); -moz-binding: url(chrome://liberator/content/bindings.xml#compitem-td);
display: table-cell; display: table-cell;
vertical-align: middle; vertical-align: middle;