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

Highlight substrings matching the filter in completions. Fix javascript completion and :hi. Run dump() arguments through objectToString and append "\n"

This commit is contained in:
Kris Maglione
2008-10-07 20:33:44 +00:00
parent 01e89bc6d8
commit 08ac946225
7 changed files with 109 additions and 38 deletions

View File

@@ -34,11 +34,11 @@ liberator.Buffer = function () //{{{
////////////////////// PRIVATE SECTION ///////////////////////////////////////// ////////////////////// PRIVATE SECTION /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{ /////////////////////////////////////////////////////////////////////////////{{{
const highlightClasses = ["Boolean", "ErrorMsg", "Function", "InfoMsg", "Keyword", const highlightClasses = ["Boolean", "ErrorMsg", "Filter", "Function", "InfoMsg", "Keyword",
"LineNr", "ModeMsg", "MoreMsg", "Normal", "Null", "Number", "Question", "LineNr", "ModeMsg", "MoreMsg", "Normal", "Null", "Number", "Question",
"StatusLine", "StatusLineBroken", "StatusLineSecure", "String", "Tag", "StatusLine", "StatusLineBroken", "StatusLineSecure", "String", "Tag",
"Title", "URL", "WarningMsg", "Title", "URL", "WarningMsg",
["Hint", ".liberator-hint", "*"] ["Hint", ".liberator-hint", "*"],
["Search", ".__liberator-search", "*"], ["Search", ".__liberator-search", "*"],
["Bell", "#liberator-visualbell"], ["Bell", "#liberator-visualbell"],
]; ];
@@ -806,7 +806,10 @@ liberator.Buffer = function () //{{{
}, },
{ {
// TODO: add this as a standard highlight completion function? // TODO: add this as a standard highlight completion function?
completer: function (filter) [0, liberator.completion.filter([[v, ""] for ([k, v] in Iterator(highlightClasses))], filter)], // I agree. It could (should) be much more sophisticated. --Kris
completer: function (filter) [0,
liberator.completion.filter([[v instanceof Array ? v[0] : v, ""] for ([k, v] in Iterator(highlightClasses))], filter)
],
hereDoc: true, hereDoc: true,
bang: true, bang: true,
}); });

View File

@@ -62,6 +62,8 @@ liberator.Completion = function () //{{{
function Javascript() function Javascript()
{ {
let json = Components.classes["@mozilla.org/dom/json;1"]
.createInstance(Components.interfaces.nsIJSON);
const OFFSET = 0, CHAR = 1, STATEMENTS = 2, DOTS = 3, FULL_STATEMENTS = 4, FUNCTIONS = 5; const OFFSET = 0, CHAR = 1, STATEMENTS = 2, DOTS = 3, FULL_STATEMENTS = 4, FUNCTIONS = 5;
let stack = []; let stack = [];
let top = []; /* The element on the top of the stack. */ let top = []; /* The element on the top of the stack. */
@@ -93,6 +95,13 @@ liberator.Completion = function () //{{{
})(); })();
try try
{ {
// The point of 'for k in obj' is to get keys
// that are accessible via . or [] notation.
// Iterators quite often return values of no
// use whatsoever for this purpose, so, we try
// this rather dirty hack of getting a standard
// object iterator for any object that defines its
// own.
if ("__iterator__" in obj) if ("__iterator__" in obj)
{ {
let oldIter = obj.__iterator__; let oldIter = obj.__iterator__;
@@ -167,7 +176,7 @@ liberator.Completion = function () //{{{
{ {
try try
{ {
// liberator.dump("eval(" + liberator.util.escapeString(arg) + ")"); // liberator.dump("eval(" + liberator.util.escapeString(arg) + ")\n");
return window.eval(arg); return window.eval(arg);
} }
catch (e) catch (e)
@@ -194,9 +203,7 @@ liberator.Completion = function () //{{{
/* Push and pop the stack, maintaining references to 'top' and 'last'. */ /* Push and pop the stack, maintaining references to 'top' and 'last'. */
let push = function (arg) let push = function (arg)
{ {
top = [i, arg, [], [], [], []]; top = [i, arg, [i], [], [], []];
if (arg)
top[STATEMENTS].push(firstNonwhite());
last = top[CHAR]; last = top[CHAR];
stack.push(top); stack.push(top);
} }
@@ -204,6 +211,8 @@ liberator.Completion = function () //{{{
{ {
if (top[CHAR] != arg) if (top[CHAR] != arg)
throw new Error("Invalid JS"); throw new Error("Invalid JS");
if (top[STATEMENTS][top[STATEMENTS].length - 1] == i)
top[STATEMENTS].pop();
top = get(-2); top = get(-2);
last = top[CHAR]; last = top[CHAR];
let ret = stack.pop(); let ret = stack.pop();
@@ -225,6 +234,12 @@ liberator.Completion = function () //{{{
stack = []; stack = [];
push(""); push("");
} }
else
{
let s = top[STATEMENTS];
if (s[s.length - 1] == start)
s.pop();
}
/* Build a parse stack, discarding entries opening characters /* Build a parse stack, discarding entries opening characters
* match closing characters. The last open entry is used to * match closing characters. The last open entry is used to
@@ -246,6 +261,15 @@ liberator.Completion = function () //{{{
} }
else else
{ {
if (/[\w$]/.test(c) && !/[\w\d$]/.test(lastChar) || !/[\w\d\s]/.test(c))
top[STATEMENTS].push(i);
// A "." or a "[" dereferences the last "statement" and effectively
// joins it to this logical statement.
if ((c == "." || c == "[") && /[\w\d\])"']/.test(lastNonwhite)
|| lastNonwhite == "." && /[\w$]/.test(c))
top[STATEMENTS].pop();
switch (c) switch (c)
{ {
case "(": case "(":
@@ -259,10 +283,11 @@ liberator.Completion = function () //{{{
push(c); push(c);
break; break;
case "[": case "[":
if (/[\])"']/.test(lastNonwhite))
top[STATEMENTS].pop();
push(c); push(c);
break; break;
case ".":
top[DOTS].push(i);
break;
case ")": pop("("); break; case ")": pop("("); break;
case "]": pop("["); break; case "]": pop("["); break;
case "}": pop("{"); /* Fallthrough */ case "}": pop("{"); /* Fallthrough */
@@ -270,20 +295,16 @@ liberator.Completion = function () //{{{
case ",": case ",":
top[FULL_STATEMENTS].push(i); top[FULL_STATEMENTS].push(i);
break; break;
case ".":
top[DOTS].push(i);
if (/[\])"']/.test(lastNonwhite))
top[STATEMENTS].pop();
break;
} }
/* Could do better. */
if (!/[\w\s.([]/.test(c))
top[STATEMENTS].push(i);
if (/\S/.test(c)) if (/\S/.test(c))
lastNonwhite = c; lastNonwhite = c;
} }
} }
if (!/[\w\d$]/.test(lastChar) && lastNonwhite != ".")
top[STATEMENTS].push(i);
lastIdx = i; lastIdx = i;
} }
@@ -291,12 +312,14 @@ liberator.Completion = function () //{{{
{ {
try try
{ {
continuing = string.indexOf(str) == 0; continuing = lastIdx && string.indexOf(str) == 0;
str = string; str = string;
buildStack(continuing ? lastIdx : 0); buildStack(continuing ? lastIdx : 0);
} }
catch (e) catch (e)
{ {
liberator.dump(liberator.util.escapeString(string) + ": " + e + "\n" + e.stack + "\n");
lastIdx = 0;
return [0, []]; return [0, []];
} }
@@ -307,6 +330,7 @@ liberator.Completion = function () //{{{
let preEval = str.substring(0, end) + ";"; let preEval = str.substring(0, end) + ";";
/* In a string. */ /* In a string. */
// TODO: Make this work with unquoted integers.
if (last == "'" || last == '"') if (last == "'" || last == '"')
{ {
/* Stack: /* Stack:
@@ -316,9 +340,11 @@ liberator.Completion = function () //{{{
*/ */
/* Is this an object accessor? */ /* Is this an object accessor? */
if (get(-2)[CHAR] != "[" /* Are inside of []? */ if (get(-2)[CHAR] != "[" // Are we inside of []?
|| get(-3, 0, STATEMENTS) == get(-2)[OFFSET]) /* Okay. Is it an array literal? */ // Okay, if the [ starts at the begining of a logical
return [0, []]; /* No. Nothing to do. */ // statement, we're in an array literal, and we're done.
|| get(-3, 0, STATEMENTS) == get(-2)[OFFSET])
return [0, []];
/* /*
* str = "foo[bar + 'baz" * str = "foo[bar + 'baz"
@@ -343,12 +369,12 @@ liberator.Completion = function () //{{{
* obj = "foo.bar" * obj = "foo.bar"
* key = "baz" * key = "baz"
*/ */
let key = str.substring(dot + 1); let [, space, key] = str.substring(dot + 1).match(/^(\s*)(.*)/);
let obj = preEval + str.substring(get(-1, 0, STATEMENTS), dot); let obj = preEval + str.substring(get(-1, 0, STATEMENTS), dot);
if (!/^(?:\w[\w\d]*)?$/.test(key)) if (!/^(?:\w[\w\d]*)?$/.test(key))
return [0, []]; /* Not a word. Forget it. Can this even happen? */ return [0, []]; /* Not a word. Forget it. Can this even happen? */
return [dot + 1, objectKeys(obj, key)]; return [dot + 1 + space.length, objectKeys(obj, key)];
} }
/* Okay, assume it's an identifier and try to complete it from the window /* Okay, assume it's an identifier and try to complete it from the window
@@ -383,6 +409,7 @@ liberator.Completion = function () //{{{
// list = [ [['com1', 'com2'], 'text'], [['com3', 'com4'], 'text'] ] // list = [ [['com1', 'com2'], 'text'], [['com3', 'com4'], 'text'] ]
function buildLongestCommonSubstring(list, filter, favicon) function buildLongestCommonSubstring(list, filter, favicon)
{ {
liberator.completion.filterString = filter;
var filtered = []; var filtered = [];
var ignorecase = false; var ignorecase = false;
@@ -766,8 +793,12 @@ liberator.Completion = function () //{{{
history: function (filter) [0, liberator.history.get(filter)], history: function (filter) [0, liberator.history.get(filter)],
javascript: function (str) javascript: function (str)
{
try
{ {
return javascript.complete(str); return javascript.complete(str);
}
catch (e) {}
}, },
macro: function (filter) macro: function (filter)
@@ -789,6 +820,7 @@ liberator.Completion = function () //{{{
// XXX: Move to bookmarks.js? // XXX: Move to bookmarks.js?
searchEngineSuggest: function (filter, engineAliases) searchEngineSuggest: function (filter, engineAliases)
{ {
this.filterString = filter;
if (!filter) if (!filter)
return [0, []]; return [0, []];
@@ -875,6 +907,7 @@ liberator.Completion = function () //{{{
// 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 (filter, complete) url: function (filter, complete)
{ {
this.filterString = filter;
var completions = []; var completions = [];
var start = 0; var start = 0;
var skip = filter.match("^(.*" + liberator.options["urlseparator"] + ")(.*)"); // start after the last 'urlseparator' var skip = filter.match("^(.*" + liberator.options["urlseparator"] + ")(.*)"); // start after the last 'urlseparator'

View File

@@ -737,7 +737,6 @@ lookup:
// no need (actually forbidden) to add: js <<EOF ... EOF around those files // no need (actually forbidden) to add: js <<EOF ... EOF around those files
source: function (filename, silent) source: function (filename, silent)
{ {
liberator.dump("filename: " + filename + "\n");
try try
{ {
var file = ioManager.getFile(filename); var file = ioManager.getFile(filename);

View File

@@ -1085,8 +1085,6 @@ const liberator = (function () //{{{
loadModule("io", liberator.IO); loadModule("io", liberator.IO);
loadModule("completion", liberator.Completion); loadModule("completion", liberator.Completion);
liberator.dump(liberator.io.source.toString() + "\n");
// This adds options/mappings/commands which are only valid in this particular extension // This adds options/mappings/commands which are only valid in this particular extension
if (liberator.config.init) if (liberator.config.init)
liberator.config.init(); liberator.config.init();

View File

@@ -80,13 +80,14 @@ liberator.template = {
{ {
let lcstr = str.toLowerCase(); let lcstr = str.toLowerCase();
let lcfilter = filter.toLowerCase(); let lcfilter = filter.toLowerCase();
str = str.replace(" ", " ");
let s = <></>; let s = <></>;
let start = 0; let start = 0;
let i; let i;
while ((i = lca.indexOf(lcfilter, start)) > -1) while ((i = lcstr.indexOf(lcfilter, start)) > -1)
{ {
s += <>{str.substring(start, i)}</>; s += <>{str.substring(start, i)}</>;
s += <span style="font-weight: bold">{str.substr(i, filter.length)}</span>; s += <span class="hl-Filter">{str.substr(i, filter.length)}</span>;
start = i + filter.length; start = i + filter.length;
} }
return s + <>{str.substr(start)}</>; return s + <>{str.substr(start)}</>;

View File

@@ -1218,17 +1218,23 @@ liberator.ItemList = function (id) //{{{
// TODO: temporary, to be changed/removed // TODO: temporary, to be changed/removed
function createRow(b, c, a, dom) function createRow(b, c, a, dom)
{ {
let row = /* Obviously, ItemList shouldn't know or care about this. */
<tr class="compitem"> let filter = liberator.completion.filterString;
<td class="favicon"/> if (filter)
<td class="completion">{b}</td> {
<td class="description">{c}</td> b = liberator.template.highlightFilter(String(b), filter);
</tr> c = liberator.template.highlightFilter(String(c), filter);
}
if (typeof a == "function") if (typeof a == "function")
a = a(); a = a();
if (a)
row.td[0].* = <img src={a}/>; let row =
<tr class="compitem">
<td class="favicon">{a ? <img src={a}/> : <span/>}</td>
<td class="completion">{b}</td>
<td class="description">{c}</td>
</tr>;
if (dom) if (dom)
return liberator.util.xmlToDom(row, doc); return liberator.util.xmlToDom(row, doc);

View File

@@ -42,6 +42,35 @@ the terms of any one of the MPL, the GPL or the LGPL.
right: 0; right: 0;
} }
.__liberator-search {
display: inline;
font-size: inherit;
padding: 0;
color: black;
background-color: yellow;
padding: 0;
display: inline;
}
.liberator-hint {
z-index:5000;
font-family:monospace;
font-size:10px;
font-weight: bold;
color:white;
background-color:red;
border-color:ButtonShadow;
border-width:0px;
border-style:solid;
padding:0px 1px 0px 1px;
position:absolute;
}
#liberator-visualbell {
border: none;
background-color: black;
}
/* Applied only to completion buffer and MOW */ /* Applied only to completion buffer and MOW */
@-moz-document @-moz-document
url-prefix(chrome://vimperator/), url-prefix(chrome://vimperator/),
@@ -51,7 +80,7 @@ the terms of any one of the MPL, the GPL or the LGPL.
.compitem[selected=true] { background-color: yellow; } .compitem[selected=true] { background-color: yellow; }
.compitem > .favicon { width: 16px; } .compitem > .favicon { width: 16px; }
.compitem > .favicon > img { width: 16px; height: 16px; } .compitem > .favicon > * { width: 16px; height: 16px; display: block; }
.compitem > .completion { width: 45%; overflow: hidden; } .compitem > .completion { width: 45%; overflow: hidden; }
.compitem > .description { color: gray; } .compitem > .description { color: gray; }
@@ -70,6 +99,8 @@ the terms of any one of the MPL, the GPL or the LGPL.
.hl-Keyword { color: red; } .hl-Keyword { color: red; }
.hl-Tag { color: blue; } .hl-Tag { color: blue; }
.hl-Filter { font-weight: bold; }
} }
/* Applied to completion buffer, MOW, browser window */ /* Applied to completion buffer, MOW, browser window */