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

wildmode and wildsort support

:open . and .. and .../ supported
This commit is contained in:
Martin Stubenschrott
2007-04-27 19:06:03 +00:00
parent a49ffd552b
commit c21df11e92
7 changed files with 421 additions and 204 deletions

3
TODO
View File

@@ -9,6 +9,7 @@ BUGS:
- autoupdate does not work - autoupdate does not work
- multiple windows to not work at all, so :q will close the whole browser session, even when there are other windows which has tabs - multiple windows to not work at all, so :q will close the whole browser session, even when there are other windows which has tabs
- reload/stop buttons don't update enabled state - reload/stop buttons don't update enabled state
- http://en.wikipedia.org/wiki/Portal:Current_events - 'f' shows more hints than 'F' (on left side of nav bar)
FEATURES: FEATURES:
9 marks of a Location, [m a-zA-Z] to set it, [` a-zA-Z] to go there 9 marks of a Location, [m a-zA-Z] to set it, [` a-zA-Z] to go there
@@ -31,7 +32,7 @@ FEATURES:
6 autocommands (BrowserStart, BrowserQuit, TabClose, TabOpen, TabChanged, PageLoaded, any more?) 6 autocommands (BrowserStart, BrowserQuit, TabClose, TabOpen, TabChanged, PageLoaded, any more?)
6 vim like mappings for caret mode and textboxes (i to start caret mode?) 6 vim like mappings for caret mode and textboxes (i to start caret mode?)
6 pipe selected text/link/website to an external command 6 pipe selected text/link/website to an external command
6 it would be nice to have :undo <url> w/ tab completion support 6 it would be nice to have :(undo|back|forward) <url> w/ tab completion support
6 macros (qq) 6 macros (qq)
6 support firefox search engines, or at least make our search enginges user configurable 6 support firefox search engines, or at least make our search enginges user configurable
6 gf = view source? 6 gf = view source?

View File

@@ -107,7 +107,7 @@ var g_commands = [/*{{{*/
["buffer", "b"], ["buffer", "b"],
["b[uffer]"], ["b[uffer]"],
"Go to buffer number n. Full completion works.", "Go to buffer number n. Full completion works.",
function (args) { tab_go(args.split(":")[0]); }, buffer_switch,
function (filter) {return get_buffer_completions(filter);} function (filter) {return get_buffer_completions(filter);}
], ],
[ [
@@ -1250,6 +1250,35 @@ function stringToURLs(str)
} }
} }
// check for ./ and ../ (or even .../) to go to a file in the upper directory
if (urls[url].match(/^(\.$|\.\/\S*)/))
{
var newLocation = getCurrentLocation();
newLocation = newLocation.replace(/([\s\S]+)\/[^\/]*/, "$1");
if(urls[url].match(/^\.(\/\S+)/))
newLocation += urls[url].replace(/^\.(\/\S+)/, "$1");
urls[url] = newLocation;
}
else if (urls[url].match(/^(\.\.$|\.\.\/[\S]*)/))
{
var newLocation = getCurrentLocation();
newLocation = newLocation.replace(/([\s\S]+)\/[^\/]*/, "$1/../");
if(urls[url].match(/^\.\.(\/\S+)/))
newLocation += urls[url].replace(/^\.\.\/(\S+)/, "$1");
urls[url] = newLocation;
}
else if (urls[url].match(/^(\.\.\.$|\.\.\.\/[\S]*)/))
{
var newLocation = getCurrentLocation();
newLocation = newLocation.replace(/([\s\S]+):\/\/\/?(\S+?)\/\S*/, "$1://$2/");
if(urls[url].match(/^\.\.\.(\/\S+)/))
newLocation += urls[url].replace(/^\.\.\.\/(\S+)/, "$1");
urls[url] = newLocation;
}
/* if the string contains a space or does not contain any of: .:/ /* if the string contains a space or does not contain any of: .:/
* open it with default searchengine */ * open it with default searchengine */
if (urls[url].match(/\s+/) || urls[url].match(/\.|:|\//) == null) if (urls[url].match(/\s+/) || urls[url].match(/\.|:|\//) == null)
@@ -1519,6 +1548,19 @@ function bufshow(filter, in_comp_window)
} }
} }
function buffer_switch(string)
{
var match;
if (match = string.match(/^(\d+):?/))
return tab_go(match[1]);
for (var i = 0; i < getBrowser().browsers.length; i++)
{
var url = getBrowser().getBrowserAtIndex(i).contentDocument.location.href;
if (url == string)
return tab_go(i);
}
}
//toggles the buffer preview window //toggles the buffer preview window
function buffer_preview_toggle() function buffer_preview_toggle()
{ {

View File

@@ -24,6 +24,9 @@ const COMMAND_LINE_HISTORY_SIZE = 500;
// 2nd element: help description // 2nd element: help description
var g_completions = new Array(); var g_completions = new Array();
// The completion substrings, used for showing the longest common match
var g_substrings = [];
var comp_tab_index = COMPLETION_UNINITIALIZED; // the index in the internal g_completions array var comp_tab_index = COMPLETION_UNINITIALIZED; // the index in the internal g_completions array
var comp_tab_list_offset = 0; // how many items is the displayed list shifted from the internal tab index var comp_tab_list_offset = 0; // how many items is the displayed list shifted from the internal tab index
var comp_tab_startstring = ""; var comp_tab_startstring = "";
@@ -107,17 +110,24 @@ function completion_add_to_list(completion_item, at_beginning)/*{{{*/
/* select the next index, refill list if necessary /* select the next index, refill list if necessary
* *
* changes 'comp_tab_index' */ * changes 'comp_tab_index' */
function completion_select_next_item()/*{{{*/ function completion_select_next_item(has_list, has_full, has_longest)/*{{{*/
{ {
comp_tab_index++; if (has_full)
comp_tab_index++;
has_list = has_list || (!completion_list.hidden && (has_full || has_longest));
if (comp_tab_index >= g_completions.length) /* wrap around */ if (comp_tab_index >= g_completions.length) /* wrap around */
{ {
comp_tab_index = -1; comp_tab_index = -1;
completion_list.selectedIndex = -1; if (has_list && has_full)
completion_list.selectedIndex = -1;
return; return;
} }
if (comp_tab_index == 0) // at the top of the list if (has_full)
showStatusbarMessage(" match " + (comp_tab_index + 1).toString() + " of " + g_completions.length.toString() + " ", STATUSFIELD_PROGRESS);
if (!has_list) return;
if (comp_tab_index < 1) // at the top of the list
{ {
completion_fill_list(0); completion_fill_list(0);
comp_tab_list_offset = 0; comp_tab_list_offset = 0;
@@ -135,50 +145,143 @@ function completion_select_next_item()/*{{{*/
comp_tab_list_offset++; comp_tab_list_offset++;
} }
listindex = comp_tab_index - comp_tab_list_offset; if (has_full)
completion_list.selectedIndex = listindex; {
listindex = comp_tab_index - comp_tab_list_offset;
showStatusbarMessage(" match " + (comp_tab_index+1).toString() + " of " + g_completions.length.toString() + " ", STATUSFIELD_PROGRESS); completion_list.selectedIndex = listindex;
}
}/*}}}*/ }/*}}}*/
/* select the previous index, refill list if necessary /* select the previous index, refill list if necessary
* *
* changes 'comp_tab_index' */ * changes 'comp_tab_index' */
function completion_select_previous_item()/*{{{*/ function completion_select_previous_item(has_list, has_full, has_longest)/*{{{*/
{ {
comp_tab_index--; if (has_full)
comp_tab_index--;
has_list = has_list || (!completion_list.hidden && (has_full || has_longest));
if (comp_tab_index == -1) if (comp_tab_index == -1)
{ {
completion_list.selectedIndex = -1; if (has_list && has_full)
completion_list.selectedIndex = -1;
return; return;
} }
if (has_full)
showStatusbarMessage("match " + (comp_tab_index+1).toString() + " of " + g_completions.length.toString(), STATUSFIELD_PROGRESS);
if (comp_tab_index < -1) // go to the end of the list if (comp_tab_index < -1) // go to the end of the list
{ {
comp_tab_index = g_completions.length -1; comp_tab_index = g_completions.length -1;
if (!has_list) return;
completion_fill_list(g_completions.length - COMPLETION_MAXITEMS); completion_fill_list(g_completions.length - COMPLETION_MAXITEMS);
comp_tab_list_offset = g_completions.length - COMPLETION_MAXITEMS;//COMPLETION_MAXITEMS - 1; comp_tab_list_offset = g_completions.length - COMPLETION_MAXITEMS;//COMPLETION_MAXITEMS - 1;
if (comp_tab_list_offset < 0) if (comp_tab_list_offset < 0)
comp_tab_list_offset = 0; comp_tab_list_offset = 0;
} }
if (!has_list) return;
var listindex = comp_tab_index - comp_tab_list_offset; var listindex = comp_tab_index - comp_tab_list_offset;
// only move the list, if there are still items we can move // only move the list, if there are still items we can move
if (listindex < COMPLETION_CONTEXTLINES && comp_tab_list_offset > 0) if (listindex < COMPLETION_CONTEXTLINES && comp_tab_list_offset > 0)
{ {
// for speed reason: just remove old item, and add new at the end of the list // for speed reason: just remove old item, and add new at the end of the list
var items = completion_list.getElementsByTagName("listitem"); if (has_list)
completion_list.removeChild(items[items.length-1]); {
completion_add_to_list(g_completions[comp_tab_index - COMPLETION_CONTEXTLINES], true); var items = completion_list.getElementsByTagName("listitem");
completion_list.removeChild(items[items.length-1]);
completion_add_to_list(g_completions[comp_tab_index - COMPLETION_CONTEXTLINES], true);
}
comp_tab_list_offset--; comp_tab_list_offset--;
} }
listindex = comp_tab_index - comp_tab_list_offset; if (has_full)
completion_list.selectedIndex = listindex; {
listindex = comp_tab_index - comp_tab_list_offset;
showStatusbarMessage("item " + (comp_tab_index+1).toString() + " of " + g_completions.length.toString(), STATUSFIELD_PROGRESS); completion_list.selectedIndex = listindex;
}
}/*}}}*/ }/*}}}*/
/*
* returns the longest common substring
* used for the 'longest' setting for wildmode
*
*/
function get_longest_substring()/*{{{*/
{
if (g_substrings.length == 0)
return '';
var longest = g_substrings[0];
for (var i = 1; i < g_substrings.length; i++)
{
if (g_substrings[i].length > longest.length)
longest = g_substrings[i];
}
return longest;
}/*}}}*/
// list = [ [['com1', 'com2'], 'text'], [['com3', 'com4'], 'text'] ]
function build_longest_common_substring(list, filter)/*{{{*/
{
var filtered = [];
var filter_length = filter.length;
for (var i = 0; i < list.length; i++)
{
for (var j = 0; j < list[i][0].length; j++)
{
if (list[i][0][j].indexOf(filter) == -1)
continue;
if (g_substrings.length == 0)
{
var last_index = list[i][0][j].lastIndexOf(filter);
var length = list[i][0][j].length;
for (var k = list[i][0][j].indexOf(filter); k != -1 && k <= last_index; k = list[i][0][j].indexOf(filter, k + 1))
{
for (var l = k + filter_length; l <= length; l++)
g_substrings.push(list[i][0][j].substring(k, l));
}
}
else
{
g_substrings = g_substrings.filter(function($_) {
return list[i][0][j].indexOf($_) >= 0;
});
}
filtered.push([list[i][0][j], list[i][1]]);
break;
}
}
return filtered;
}/*}}}*/
function build_longest_starting_substring(list, filter)/*{{{*/
{
var filtered = [];
var filter_length = filter.length;
for (var i = 0; i < list.length; i++)
{
for (var j = 0; j < list[i][0].length; j++)
{
if (list[i][0][j].indexOf(filter) != 0)
continue;
if (g_substrings.length == 0)
{
var length = list[i][0][j].length;
for (var k = filter_length; k <= length; k++)
g_substrings.push(list[i][0][j].substring(0, k));
}
else
{
g_substrings = g_substrings.filter(function($_) {
return list[i][0][j].indexOf($_) == 0;
});
}
filtered.push([list[i][0][j], list[i][1]]);
break;
}
}
return filtered;
}/*}}}*/
/* /*
@@ -190,6 +293,7 @@ function completion_select_previous_item()/*{{{*/
function get_url_completions(filter)/*{{{*/ function get_url_completions(filter)/*{{{*/
{ {
g_completions = []; g_completions = [];
g_substrings = [];
var cpt = get_pref("complete"); var cpt = get_pref("complete");
// join all completion arrays together // join all completion arrays together
@@ -207,147 +311,63 @@ function get_url_completions(filter)/*{{{*/
}/*}}}*/ }/*}}}*/
/* discard all entries in the 'urls' array, which don't match 'filter */ /* discard all entries in the 'urls' array, which don't match 'filter */
function filter_url_array(urls, filter, use_regex)/*{{{*/ function filter_url_array(urls, filter)/*{{{*/
{ {
var filtered = []; var filtered = [];
// completions which don't match the url but just the description // completions which don't match the url but just the description
// list them add the end of the array // list them add the end of the array
var additional_completions = []; var additional_completions = [];
var reg, reg2; if (!filter) return urls.map(function($_) {
if (use_regex) return [$_[0], $_[1]]
});
var filter_length = filter.length;
/*
* Longest Common Subsequence
* This shouldn't use build_longest_common_substring
* for performance reasons, so as not to cycle through the urls twice
*/
for (var i = 0; i < urls.length; i++)
{ {
reg = new RegExp("^" + filter, "i"); if (urls[i][0].indexOf(filter) == -1)
reg2 = new RegExp(filter, "i");
}
outer:
for (var i = 0; i < urls.length; ++i)
{
if (filter != null && filter.length > 0)
{ {
// first check if the filter matches in the main part of the URL if (urls[i][1].indexOf(filter) != -1)
var bm = urls[i][0].replace(/^.*:\/\/(www)?/, ""); additional_completions.push([urls[i][0], urls[i][1] ]);
bm = bm.replace(/\/.*$/, ""); continue;
var tokens = bm.split("."); }
for (var k = 0; k < tokens.length-1; k++) // -1 because we don't search the domain (like .com) if (g_substrings.length == 0) // Build the substrings
{
var last_index = urls[i][0].lastIndexOf(filter);
var url_length = urls[i][0].length;
for (var k = urls[i][0].indexOf(filter); k != -1 && k <= last_index; k = urls[i][0].indexOf(filter, k + 1))
{ {
if (use_regex) for (var l = k + filter_length; l <= url_length; l++)
{ g_substrings.push(urls[i][0].substring(k, l));
if(tokens[k].search(reg) != -1)
{
filtered.push([urls[i][0], urls[i][1] ]);
continue outer;
}
}
else
{
if (tokens[k].indexOf(filter) == 0)
{
filtered.push([urls[i][0], urls[i][1] ]);
continue outer;
}
}
}
// otherwise check if the filter matches in the description of the bookmark
if (use_regex)
{
if(urls[i][0].search(reg2) == -1 && urls[i][1].search(reg2) == -1)
continue;
}
else
{
if (urls[i][0].indexOf(filter) == -1 && urls[i][1].indexOf(filter) == -1)
continue;
} }
} }
additional_completions.push([urls[i][0], urls[i][1] ]); else
{
g_substrings = g_substrings.filter(function($_) {
return urls[i][0].indexOf($_) >= 0;
});
}
filtered.push([urls[i][0], urls[i][1]]);
} }
return filtered.concat(additional_completions); return filtered.concat(additional_completions);
}/*}}}*/ }/*}}}*/
function get_file_completions(filter)/*{{{*/
{
g_completions = [];
var match = filter.match(/^(.*[\/\\])(.*?)$/);
var dir;
if (!match || !(dir = match[1]))
return [];
var compl = match[2] || '';
var fd = fopen(dir, "<");
if (!fd)
return [];
var entries = fd.read();
var delim = fd.path.length == 1 ? '' : (fd.path.search(/\\/) != -1) ? "\\" : "/";
var reg = new RegExp("^" + fd.path + delim + compl);
entries.forEach(function(file)
{
if (file.path.search(reg) != -1)
g_completions.push([file.path, '']);
});
return g_completions;
}/*}}}*/
function get_search_completions(filter)/*{{{*/ function get_search_completions(filter)/*{{{*/
{ {
var search_completions = []; if (!filter) return g_searchengines.map(function($_) {
return [$_[0], $_[1]];
var reg = new RegExp("^" + filter, "i"); });
for (var i = 0; i < g_searchengines.length; i++) var mapped = g_searchengines.map(function($_) {
{ return [[$_[0]], $_[1]];
if (g_searchengines[i][0].search(reg) != -1) });
search_completions.push([g_searchengines[i][0] + " ", g_searchengines[i][1] ]); return build_longest_common_substring(mapped, filter);
}
return search_completions;
}/*}}}*/ }/*}}}*/
function get_bookmark_completions(filter)/*{{{*/
{
if (!bookmarks_loaded)
{
// update our bookmark cache
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService( Components.interfaces.nsIRDFService );
var root = RDF.GetResource( "NC:BookmarksRoot" );
bookmarks = []; // here getAllChildren will store the bookmarks
g_bookmarks = []; // also clear our bookmark cache
BookmarksUtils.getAllChildren(root, bookmarks);
for(var i = 0; i < bookmarks.length; i++)
{
if (bookmarks[i][0] && bookmarks[i][1])
g_bookmarks.push([bookmarks[i][1].Value, bookmarks[i][0].Value ]);
}
bookmarks_loaded = true;
}
return filter_url_array(g_bookmarks, filter, true);
}/*}}}*/
function get_help_completions(filter)
{
var help_completions = [];
help_completions = help_completions.concat(get_command_completions(filter));
help_completions = help_completions.concat(get_settings_completions(filter));
for(var i = 0; i < g_mappings.length; i++)
{
for(var j = 0; j < g_mappings[i][0].length; j++)
{
//var re = new RegExp("^" + filter);
if (g_mappings[i][0][j].indexOf(filter) == 0)
{
help_completions.push([g_mappings[i][0][j], g_mappings[i][1]]);
break; // only add a command once
}
}
}
return help_completions;
}
function get_history_completions(filter)/*{{{*/ function get_history_completions(filter)/*{{{*/
{ {
var history = document.getElementById("hiddenHistoryTree"); var history = document.getElementById("hiddenHistoryTree");
@@ -398,39 +418,109 @@ function get_history_completions(filter)/*{{{*/
history_loaded = true; history_loaded = true;
} }
return filter_url_array(g_history, filter, true); return filter_url_array(g_history, filter);
}/*}}}*/
function get_bookmark_completions(filter)/*{{{*/
{
if (!bookmarks_loaded)
{
// update our bookmark cache
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService( Components.interfaces.nsIRDFService );
var root = RDF.GetResource( "NC:BookmarksRoot" );
bookmarks = []; // here getAllChildren will store the bookmarks
g_bookmarks = []; // also clear our bookmark cache
BookmarksUtils.getAllChildren(root, bookmarks);
for(var i = 0; i < bookmarks.length; i++)
{
if (bookmarks[i][0] && bookmarks[i][1])
g_bookmarks.push([bookmarks[i][1].Value, bookmarks[i][0].Value ]);
}
bookmarks_loaded = true;
}
return filter_url_array(g_bookmarks, filter);
}/*}}}*/
function get_file_completions(filter)/*{{{*/
{
g_completions = [];
g_substrings = [];
var match = filter.match(/^(.*[\/\\])(.*?)$/);
var dir;
if (!match || !(dir = match[1]))
return [];
var compl = match[2] || '';
var fd = fopen(dir, "<");
if (!fd)
return [];
var entries = fd.read();
var delim = fd.path.length == 1 ? '' : (fd.path.search(/\\/) != -1) ? "\\" : "/";
var new_filter = fd.path + delim + compl;
if (!filter) return entries.map(function($_) {
var path = $_.path;
if ($_.isDirectory()) path += '/';
return [path, ''];
});
var mapped = entries.map(function($_) {
var path = $_.path;
if ($_.isDirectory()) path += '/';
return [[path], ''];
});
return g_completions = build_longest_starting_substring(mapped, filter);
}/*}}}*/
function get_help_completions(filter)/*{{{*/
{
var help_array = [];
g_substrings = [];
help_array = help_array.concat(g_commands);
help_array = help_array.concat(get_settings_completions(filter, true));
help_array = help_array.concat(g_mappings);
if (!filter) return help_array.map(function($_) {
return [$_[0][0], $_[1]];
});
return build_longest_common_substring(help_array, filter);
}/*}}}*/ }/*}}}*/
function get_command_completions(filter)/*{{{*/ function get_command_completions(filter)/*{{{*/
{ {
g_completions = []; g_completions = [];
for(var i=0; i<g_commands.length; i++) g_substrings = [];
{ if (!filter) return g_completions = g_commands.map(function($_) {
for(var j=0; j<g_commands[i][0].length; j++) return [$_[0][0], $_[1]];
{ });
//var re = new RegExp("^" + filter); return g_completions = build_longest_starting_substring(g_commands, filter);
if (g_commands[i][0][j].indexOf(filter) == 0)
{
g_completions.push([g_commands[i][0][j], g_commands[i][1]]);
break; // only add a command once
}
}
}
// commands should be sorted anyway, but it doesn't really hurt -> it DOES hurt :(
//g_completions.sort();
return g_completions;
}/*}}}*/ }/*}}}*/
function get_settings_completions(filter)/*{{{*/ function get_settings_completions(filter, unfiltered)/*{{{*/
{ {
settings_completions = []; g_substrings = [];
var settings_completions = [];
var no_mode = false; var no_mode = false;
if (filter.indexOf("no") == 0) // boolean option if (filter.indexOf("no") == 0) // boolean option
{ {
no_mode = true; no_mode = true;
filter = filter.substr(2); filter = filter.substr(2);
} }
if (unfiltered) return g_settings.filter(function($_) {
if (no_mode && $_[5] != "boolean") return false;
else return true;
}).map(function($_) {
return [$_[0], $_[1]];
});
if (!filter) return g_settings.filter(function($_) {
if (no_mode && $_[5] != "boolean") return false;
else return true;
}).map(function($_) {
return [$_[0][0], $_[1]];
});
// check if filter ends with =, then complete current value // check if filter ends with =, then complete current value
else if(filter.length > 0 && filter.lastIndexOf("=") == filter.length -1) else if(filter.length > 0 && filter.lastIndexOf("=") == filter.length -1)
{ {
@@ -449,32 +539,45 @@ function get_settings_completions(filter)/*{{{*/
return settings_completions; return settings_completions;
} }
for(var i=0; i<g_settings.length; i++) // can't use b_l_s_s, since this has special requirements (the prefix)
var filter_length = filter.length;
for (var i = 0; i < g_settings.length; i++)
{ {
if (filter == "" || g_settings[i][0][0].indexOf(filter) > -1) if (no_mode && g_settings[i][5] != "boolean")
continue;
var prefix = no_mode ? 'no' : '';
for (var j = 0; j < g_settings[i][0].length; j++)
{ {
// for 'no'-mode only return bool options if (g_settings[i][0][j].indexOf(filter) != 0) continue;
if (no_mode) if (g_substrings.length == 0)
{ {
if (g_settings[i][5] == "bool") var length = g_settings[i][0][j].length;
settings_completions.push(["no" + g_settings[i][0][0], g_settings[i][1]]); for (var k = filter_length; k <= length; k++)
g_substrings.push(prefix + g_settings[i][0][j].substring(0, k));
} }
else else
settings_completions.push([g_settings[i][0][0], g_settings[i][1]]); {
g_substrings = g_substrings.filter(function($_) {
return g_settings[i][0][j].indexOf($_) == 0;
});
}
settings_completions.push([prefix + g_settings[i][0][j], g_settings[i][1]]);
break;
} }
} }
return settings_completions; return settings_completions;
}/*}}}*/ }/*}}}*/
function get_buffer_completions(filter) function get_buffer_completions(filter)/*{{{*/
{ {
var reg = new RegExp(filter,"i"); g_substrings = [];
items = new Array(); var items = [];
var num = getBrowser().browsers.length; var num = getBrowser().browsers.length;
var title, url; var title, url;
for(var i=0; i<num;i++) for (var i = 0; i < num; i++)
{ {
try try
{ {
@@ -484,18 +587,25 @@ function get_buffer_completions(filter)
{ {
title = ""; title = "";
} }
if (title == "")
title = "(Untitled)";
url = getBrowser().getBrowserAtIndex(i).contentDocument.location.href; url = getBrowser().getBrowserAtIndex(i).contentDocument.location.href;
if(title.search(reg) != -1 || url.search(reg) != -1) if (title.indexOf(filter) == -1 && url.indexOf(filter) == -1)
continue;
if (title.indexOf(filter) != -1 || url.indexOf(filter) != -1)
{ {
items.push([(i+1)+": "+title, url]); if (title == "")
title = "(Untitled)";
items.push([[(i + 1) + ": " + title, (i + 1) + ": " + url], url]);
} }
} }
return items; if (!filter) return items.map(function($_) {
} return [$_[0][0], $_[1]];
});
return build_longest_common_substring(items, filter);
}/*}}}*/
////////// COMMAND HISTORY HANDLING //////////// ////////// COMMAND HISTORY HANDLING ////////////
@@ -521,7 +631,7 @@ function load_history()
///////// PREVIEW WINDOW ////////////////////// ///////// PREVIEW WINDOW //////////////////////
/* uses the entries in completions to fill the listbox */ /* uses the entries in completions to fill the listbox */
function preview_window_fill(completions) function preview_window_fill(completions)/*{{{*/
{ {
// remove all old items first // remove all old items first
var items = preview_window.getElementsByTagName("listitem"); var items = preview_window.getElementsByTagName("listitem");
@@ -542,9 +652,9 @@ function preview_window_fill(completions)
item.appendChild(cell2); item.appendChild(cell2);
preview_window.appendChild(item); preview_window.appendChild(item);
} }
} }/*}}}*/
function preview_window_select(event) function preview_window_select(event)/*{{{*/
{ {
var listcell = document.getElementsByTagName("listcell"); var listcell = document.getElementsByTagName("listcell");
// 2 columns for now, use the first column // 2 columns for now, use the first column
@@ -556,7 +666,7 @@ function preview_window_select(event)
openURLsInNewTab(val); openURLsInNewTab(val);
else else
return false; return false;
} }/*}}}*/
function preview_window_show()/*{{{*/ function preview_window_show()/*{{{*/
{ {

View File

@@ -39,7 +39,7 @@ var g_settings = [/*{{{*/
null null
], ],
[ [
["beep"], ["beep", "nobeep"],
["beep"], ["beep"],
"Emit a pc speaker beep on certain errors", "Emit a pc speaker beep on certain errors",
function(value) { set_pref("beep", value); }, function(value) { set_pref("beep", value); },
@@ -89,7 +89,7 @@ var g_settings = [/*{{{*/
null null
], ],
[ [
["fullscreen", "fs"], ["fullscreen", "fs", "nofullscreen", "nofs"],
["fullscreen", "fs"], ["fullscreen", "fs"],
"Shows the current window fullscreen", "Shows the current window fullscreen",
function(value) { opt_fullscreen = value; BrowserFullScreen(); }, function(value) { opt_fullscreen = value; BrowserFullScreen(); },
@@ -157,7 +157,7 @@ var g_settings = [/*{{{*/
null null
], ],
[ [
["preload"], ["preload", "nopreload"],
["preload"], ["preload"],
"Speed up first time history/bookmark completion<br/>" + "Speed up first time history/bookmark completion<br/>" +
"History access can be quite slow for a large history. Vimperator maintains a cache to speed it up significantly on subsequent access.<br>"+ "History access can be quite slow for a large history. Vimperator maintains a cache to speed it up significantly on subsequent access.<br>"+
@@ -182,7 +182,7 @@ var g_settings = [/*{{{*/
null null
], ],
[ [
["showmode", "smd"], ["showmode", "smd", "noshowmode", "nosmd"],
["showmode", "smd"], ["showmode", "smd"],
"Show the current mode in the command line", "Show the current mode in the command line",
function(value) { set_pref("showmode", value); }, function(value) { set_pref("showmode", value); },
@@ -209,7 +209,7 @@ var g_settings = [/*{{{*/
null null
], ],
[ [
["usermode", "um"], ["usermode", "um", "nousermode", "noum"],
["usermode", "um"], ["usermode", "um"],
"Show current website with a minimal stylesheet to make it easily accessible<br/>" + "Show current website with a minimal stylesheet to make it easily accessible<br/>" +
"Note that this is a local setting for now, later it may be split into a global and <code style=command>:setlocal</code> part", "Note that this is a local setting for now, later it may be split into a global and <code style=command>:setlocal</code> part",
@@ -223,12 +223,37 @@ var g_settings = [/*{{{*/
[ [
["wildmode", "wim"], ["wildmode", "wim"],
["wildmode", "wim"], ["wildmode", "wim"],
"Define how command line completion works<br/>" + "Defines how command line completion works<br/>" +
"Not implemented yet.", "It is a comma-separated list of parts, where each part specifies" +
"what to do for each consecutive use of the completion key. The first part" +
"specifies the behavior for the first use of the completion key, the second part" +
"for the second use, etc.<br/>" +
"These are the possible values for each part:<br/>" +
"<table><tbody>" +
"<tr><td><b>''</b></td><td>Complete only the first match</td></tr>" +
"<tr><td><b>'full'</b></td><td>Complete the next full match. After the last, the original string is used.</td></tr>" +
"<tr><td><b>'longest'</b></td><td>Complete till the longest common string.</td></tr>" +
"<tr><td><b>'list'</b></td><td>When more than one match, list all matches.</td></tr>" +
"<tr><td><b>'list:full'</b></td><td>When more than one match, list all matches and complete first match.</td></tr>" +
"<tr><td><b>'list:longest'</b></td><td>When more than one match, list all matches and complete till the longest common string.</td></tr>" +
"</tbody></table>" +
"When there is only a single match, it is fully completed regardless of the case.",
function(value) { set_pref("wildmode", value); }, function(value) { set_pref("wildmode", value); },
function() { return get_pref("wildmode"); }, function() { return get_pref("wildmode"); },
"stringlist", "stringlist",
"full", "list:full",
null,
null
],
[
["wildsort", "wis", "nowildsort", "nowis"],
["wildsort", "wis"],
"Defines whether command line completion is sorted<br/>" +
"If you don't want a sorted completion list, set this to false.",
function(value) { set_pref("wildsort", value); },
function() { return get_pref("wildsort"); },
"boolean",
false,
null, null,
null null
] ]

View File

@@ -5,6 +5,7 @@
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.6 // !_TAG_PROGRAM_VERSION 5.6 //
addBookmark bookmarks.js /^function addBookmark(title, uri)$/;" f addBookmark bookmarks.js /^function addBookmark(title, uri)$/;" f
addEventListeners vimperator.js /^function addEventListeners()$/;" f
addMode commands.js /^function addMode(mode)$/;" f addMode commands.js /^function addMode(mode)$/;" f
add_to_command_history completion.js /^function add_to_command_history(str)$/;" f add_to_command_history completion.js /^function add_to_command_history(str)$/;" f
beep commands.js /^function beep()$/;" f beep commands.js /^function beep()$/;" f
@@ -24,7 +25,7 @@ copyToClipboard commands.js /^function copyToClipboard(str)$/;" f
createCursorPositionString vimperator.js /^function createCursorPositionString()$/;" f createCursorPositionString vimperator.js /^function createCursorPositionString()$/;" f
createHints hints.js /^ function createHints(win)$/;" f createHints hints.js /^ function createHints(win)$/;" f
createProgressBar vimperator.js /^function createProgressBar(aProgress)$/;" f createProgressBar vimperator.js /^function createProgressBar(aProgress)$/;" f
cumulativeOffset commands.js /^function cumulativeOffset(element)$/;" f cumulativeOffset help.js /^ function cumulativeOffset(element)$/;" f
deleteBookmark bookmarks.js /^function deleteBookmark(url)$/;" f deleteBookmark bookmarks.js /^function deleteBookmark(url)$/;" f
del_url_mark commands.js /^function del_url_mark(mark)$/;" f del_url_mark commands.js /^function del_url_mark(mark)$/;" f
echo commands.js /^function echo(msg)$/;" f echo commands.js /^function echo(msg)$/;" f
@@ -62,7 +63,7 @@ get_settings_completions completion.js /^function get_settings_completions(filte
get_url_completions completion.js /^function get_url_completions(filter)\/*{{{*\/$/;" f get_url_completions completion.js /^function get_url_completions(filter)\/*{{{*\/$/;" f
get_url_mark commands.js /^function get_url_mark(mark)$/;" f get_url_mark commands.js /^function get_url_mark(mark)$/;" f
hasMode commands.js /^function hasMode(mode)$/;" f hasMode commands.js /^function hasMode(mode)$/;" f
help commands.js /^function help(section, easter)$/;" f help help.js /^function help(section, easter)$/;" f
historyGoToBeginning commands.js /^function historyGoToBeginning()$/;" f historyGoToBeginning commands.js /^function historyGoToBeginning()$/;" f
historyGoToEnd commands.js /^function historyGoToEnd()$/;" f historyGoToEnd commands.js /^function historyGoToEnd()$/;" f
hit_a_hint hints.js /^function hit_a_hint()$/;" f hit_a_hint hints.js /^function hit_a_hint()$/;" f
@@ -75,8 +76,8 @@ keyToString vimperator.js /^function keyToString(event)$/;" f
load_history completion.js /^function load_history()$/;" f load_history completion.js /^function load_history()$/;" f
LocalFile file.js /^function LocalFile(file, mode, perms, tmp)$/;" f LocalFile file.js /^function LocalFile(file, mode, perms, tmp)$/;" f
logMessage vimperator.js /^function logMessage(msg)$/;" f logMessage vimperator.js /^function logMessage(msg)$/;" f
makeHelpString commands.js /^ function makeHelpString(commands, color, beg, end, func)$/;" f makeHelpString help.js /^ function makeHelpString(commands, color, beg, end, func)$/;" f
makeSettingsHelpString commands.js /^ function makeSettingsHelpString(command)$/;" f makeSettingsHelpString help.js /^ function makeSettingsHelpString(command)$/;" f
multiliner commands.js /^function multiliner(line, prev_match, heredoc)$/;" f multiliner commands.js /^function multiliner(line, prev_match, heredoc)$/;" f
nsBrowserStatusHandler vimperator.js /^function nsBrowserStatusHandler() \/*{{{*\/$/;" f nsBrowserStatusHandler vimperator.js /^function nsBrowserStatusHandler() \/*{{{*\/$/;" f
onCommandBarInput vimperator.js /^function onCommandBarInput(event)$/;" f onCommandBarInput vimperator.js /^function onCommandBarInput(event)$/;" f

View File

@@ -45,6 +45,9 @@ var g_inputbuffer = ""; // here we store partial commands (e.g. 'g' if you want
var g_count = -1; // the parsed integer of g_inputbuffer, or -1 if no count was given var g_count = -1; // the parsed integer of g_inputbuffer, or -1 if no count was given
var g_bufshow = false; // keeps track if the preview window shows current buffers ('B') var g_bufshow = false; // keeps track if the preview window shows current buffers ('B')
// handles wildmode tab index
var wild_tab_index = 0;
// handles multi-line commands // handles multi-line commands
var prev_match = new Array(5); var prev_match = new Array(5);
var heredoc = ''; var heredoc = '';
@@ -548,8 +551,10 @@ function onCommandBarKeypress(evt)/*{{{*/
/* user pressed TAB to get completions of a command */ /* user pressed TAB to get completions of a command */
else if (evt.keyCode == KeyEvent.DOM_VK_TAB) else if (evt.keyCode == KeyEvent.DOM_VK_TAB)
{ {
var start_cmd = command;
var match = tokenize_ex(command); var match = tokenize_ex(command);
var [count, cmd, special, args] = match; var [count, cmd, special, args] = match;
var command = get_command(cmd);
//always reset our completion history so up/down keys will start with new values //always reset our completion history so up/down keys will start with new values
comp_history_index = -1; comp_history_index = -1;
@@ -559,7 +564,8 @@ function onCommandBarKeypress(evt)/*{{{*/
g_completions = []; g_completions = [];
comp_tab_index = -1; comp_tab_index = -1;
comp_tab_list_offset = 0; comp_tab_list_offset = 0;
comp_tab_startstring = command; comp_tab_startstring = start_cmd;
wild_tab_index = 0;
/* if there is no space between the command name and the cursor /* if there is no space between the command name and the cursor
* then get completions of the command name * then get completions of the command name
@@ -570,10 +576,18 @@ function onCommandBarKeypress(evt)/*{{{*/
} }
else // dynamically get completions as specified in the g_commands array else // dynamically get completions as specified in the g_commands array
{ {
var command = get_command(cmd);
if (command && command[4]) if (command && command[4])
{ {
g_completions = command[4].call(this, args); g_completions = command[4].call(this, args);
// Sort the completion list
if (get_pref('wildsort'))
g_completions.sort(function(a, b) {
if (a[0] < b[0])
return -1;
else if (a[0] > b[0])
return 1;
else return 0;
});
} }
} }
} }
@@ -586,24 +600,45 @@ function onCommandBarKeypress(evt)/*{{{*/
if (g_completions.length == 0) if (g_completions.length == 0)
beep(); beep();
var wim = get_pref('wildmode').split(/,/);
var has_list = false;
var longest = false;
var full = false;
var wildtype = wim[wild_tab_index++] || wim[wim.length - 1];
if (wildtype == 'list' || wildtype == 'list:full' || wildtype == 'list:longest')
has_list = true;
if (wildtype == 'longest' || wildtype == 'list:longest')
longest = true;
if (wildtype == 'full' || wildtype == 'list:full')
full = true;
// show the list // show the list
completion_show_list(); if (has_list)
completion_show_list();
if (evt.shiftKey) if (evt.shiftKey)
completion_select_previous_item(); completion_select_previous_item(has_list, full, longest);
else else
completion_select_next_item(); completion_select_next_item(has_list, full, longest);
//command_line.focus(); // workaraound only need for RICHlistbox //command_line.focus(); // workaraound only need for RICHlistbox
if (comp_tab_index == -1) // wrapped around matches, reset command line if (comp_tab_index == -1 && !longest) // wrapped around matches, reset command line
{ {
command_line.value = comp_tab_startstring; if (full && g_completions.length > 1)
completion_list.selectedIndex = -1; {
command_line.value = comp_tab_startstring;
completion_list.selectedIndex = -1;
}
} }
else else
{ {
var compl = g_completions[comp_tab_index][0]; if (longest && g_completions.length > 1)
var compl = get_longest_substring();
if (full)
var compl = g_completions[comp_tab_index][0];
if (g_completions.length == 1)
var compl = g_completions[0][0];
if (compl) if (compl)
{ {
/* if there is no space between the command name and the cursor /* if there is no space between the command name and the cursor
@@ -617,6 +652,9 @@ function onCommandBarKeypress(evt)/*{{{*/
{ {
command_line.value = ":" + (count ? count.toString() : "") + command_line.value = ":" + (count ? count.toString() : "") +
cmd + (special ? "!" : "") + " " + compl; cmd + (special ? "!" : "") + " " + compl;
// Start a new completion in the next iteration. Useful for commands like :source
if (g_completions.length == 1 && !full) // RFC: perhaps the command can indicate whether the completion should be restarted
comp_tab_index = COMPLETION_UNINITIALIZED;
} }
} }
} }

View File

@@ -5,7 +5,7 @@
<Description about="urn:mozilla:install-manifest"> <Description about="urn:mozilla:install-manifest">
<em:id>vimperator@mozdev.org</em:id> <em:id>vimperator@mozdev.org</em:id>
<em:name>Vimperator</em:name> <em:name>Vimperator</em:name>
<em:version>0.3</em:version> <em:version>0.4</em:version>
<em:description>Make Firefox work like Vim</em:description> <em:description>Make Firefox work like Vim</em:description>
<em:creator>Martin Stubenschrott</em:creator> <em:creator>Martin Stubenschrott</em:creator>
<em:homepageURL>http://vimperator.mozdev.org</em:homepageURL> <em:homepageURL>http://vimperator.mozdev.org</em:homepageURL>