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

ex parser for use with .vimperatorrc, the command line and other sourced files. sourced files are no longer javascript code, but can use the new :javascript ex command to execute javascript. :javascript also supports multiline with heredocs (:js <<EOF). File completion for the :source command.

This commit is contained in:
Viktor Kojouharov
2007-04-22 14:17:28 +00:00
parent 6322db0107
commit 3ddfb11add
6 changed files with 179 additions and 54 deletions

View File

@@ -131,16 +131,11 @@ var g_commands = [/*{{{*/
],
[
["execute", "exe"],
"Run any javascript command through eval()",
"Acts as a javascript interpreter by passing the argument to <code>eval()</code>.<br>"+
"<code>:exec alert('Hello world')</code> would show a dialog box with the text \"Hello world\".<br>"+
"The special version <code>:execute!</code> will open the javascript console of Firefox.",
function(args, special) {
if (special) // open javascript console
openURLsInNewTab("chrome://global/content/console.xul", true);
else
eval(args);
},
"Executes a string as an Ex command",
"Usage: <code>:execute {expr1} [ ... ]</code><br>" +
"Executes the string that results from the evaluation of {expr1} as an Ex command.<br>"+
"<code>:execute &#34;echo test&#34;</code> would show a message with the text &#34;test&#34;.<br>",
execute,
null
],
[
@@ -174,6 +169,21 @@ var g_commands = [/*{{{*/
hsshow,
function(filter) { return get_history_completions(filter); }
],
[
["javascript", "js"],
"Run any javascript command through eval()",
"Acts as a javascript interpreter by passing the argument to <code>eval()</code>.<br>" +
"<code>:javascript alert('Hello world')</code> would show a dialog box with the text \"Hello world\".<br>" +
"<code>:javascript &lt;&lt;EOF</code> would read all the lines until a line starting with 'EOF' is found, and will <code>eval()</code> them.<br>" +
"The special version <code>:javascript!</code> will open the javascript console of Firefox.",
function(args, special) {
if (special) // open javascript console
openURLsInNewTab("chrome://global/content/console.xul", true);
else
eval(args);
},
null
],
[
["mark"],
"Mark current location within the webpage",
@@ -286,7 +296,7 @@ var g_commands = [/*{{{*/
"The .vimperatorrc file in your home directory is always sourced at start up.<br>"+
"~ is supported as a shortcut for the $HOME directory.",
source,
null
function (filter) { return get_file_completions(filter); }
],
[
["tabnext", "tn", "tnext"],
@@ -910,6 +920,7 @@ function get_command(cmd) // {{{
function execute_command(count, cmd, special, args) // {{{
{
if (!cmd) return;
var command = get_command(cmd);
if (command == null)
{
@@ -929,6 +940,86 @@ function execute_command(count, cmd, special, args) // {{{
} // }}}
function tokenize_ex(string, tag)
{
// removing commends
string.replace(/\s*".*$/, '');
if (tag)
{
if (string == tag)
return [null, null, null, null, false];
else
return [null, null, null, string, tag];
}
// 0 - count, 1 - cmd, 2 - special, 3 - args, 4 - heredoc tag
var matches = string.match(/^:*(\d+)?([a-zA-Z]+)(!)?(?:\s+(.*?))?$/);
if (!matches) return [null, null, null, null, null];
matches.shift();
if (matches[0])
{
matches[0] = parseInt(matches[0]);
if (isNaN(matches[0])) matches[0] = 0;
}
else matches[0] = 0;
matches[2] = !!matches[2];
matches.push(null);
if (matches[3])
{
tag = matches[3].match(/<<\s*(\w+)/);
if (tag && tag[1])
matches[4] = tag[1];
}
else matches[3] = '';
return matches;
}
function multiliner(line, prev_match, heredoc)
{
var end = true;
var match = tokenize_ex(line, prev_match[4]);
if (prev_match[3] === undefined) prev_match[3] = '';
if (match[4] === null)
{
focusContent(false, true); // also sets comp_tab_index to -1
execute_command.apply(this, match);
}
else
{
if (match[4] === false)
{
prev_match[3] = prev_match[3].replace(new RegExp('<<\s*' + prev_match[4]), heredoc.replace(/\n$/, ''));
execute_command.apply(this, prev_match);
prev_match = new Array(5);
prev_match[3] = '';
heredoc = '';
}
else
{
end = false;
if (!prev_match[3])
{
prev_match[0] = match[0];
prev_match[1] = match[1];
prev_match[2] = match[2];
prev_match[3] = match[3];
prev_match[4] = match[4];
}
else
{
heredoc += match[3] + '\n';
}
}
}
return [prev_match, heredoc, end];
}
function execute(string)
{
return execute_command.apply(this, tokenize_ex(string.replace(/^'(.*)'$/, '$1')));
}
////////////////////////////////////////////////////////////////////////
// statusbar/commandbar handling ////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
@@ -1628,7 +1719,12 @@ function source(filename, silent)
var s = fd.read();
fd.close();
eval(s);
var prev_match = new Array(5);
var heredoc = '';
var end = false;
s.split('\n').forEach(function (line) {
[prev_match, heredoc, end] = multiliner(line, prev_match, heredoc);
});
}
catch(e)
{
@@ -1637,7 +1733,6 @@ function source(filename, silent)
}
}
function help(section, easter)
{
if (easter)

View File

@@ -180,6 +180,27 @@ function completion_select_previous_item()/*{{{*/
}/*}}}*/
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.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;
}/*}}}*/
/*
* filter a list of urls

View File

@@ -129,6 +129,19 @@ function fo_write(buf)
LocalFile.prototype.read =
function fo_read(max)
{
if (this.localFile.isDirectory())
{
var entries = this.localFile.directoryEntries;
var array = [];
while(entries.hasMoreElements())
{
var entry = entries.getNext();
entry.QueryInterface(Components.interfaces.nsIFile);
array.push(entry);
}
return array;
}
if (!("inputStream" in this))
throw "file not open for reading.";

View File

@@ -63,17 +63,6 @@ var g_settings = [/*{{{*/
null,
null
],
[
["completeopt", "cot"],
"Define how command line completion works",
"Not implemented yet.",
function(value) { set_pref("completeopt", value); },
function() { return get_pref("completeopt"); },
"stringlist",
"menu",
null,
null
],
[
["extendedhinttags", "eht"],
"XPath string of hintable elements activated by ';'",
@@ -221,6 +210,17 @@ var g_settings = [/*{{{*/
false,
null,
null
],
[
["wildmode", "wim"],
"Define how command line completion works",
"Not implemented yet.",
function(value) { set_pref("wildmode", value); },
function() { return get_pref("wildmode"); },
"stringlist",
"menu",
null,
null
]
]/*}}}*/

View File

@@ -45,6 +45,10 @@ 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_bufshow = false; // keeps track if the preview window shows current buffers ('B')
// handles multi-line commands
var prev_match = new Array(5);
var heredoc = '';
// handles to our gui elements
var preview_window = null;
var status_line = null;
@@ -83,7 +87,7 @@ nsBrowserStatusHandler.prototype =
setOverLink : function(link, b)
{
echo(link);
updateStatusbar(link);
if (link == "")
showMode();
@@ -518,45 +522,24 @@ function onVimperatorKeypress(event)/*{{{*/
updateStatusbar();
return false;
}/*}}}*/
function onCommandBarKeypress(evt)/*{{{*/
{
var end = false;
try
{
/* parse our command string into tokens */
var command = command_line.value;
var matches1 = command.match(/^:(\d+)/);
var matches2 = command.match(/^:(\d+)?([a-zA-Z!]+)/);
var matches3 = command.match(/^:(\d+)?([a-zA-Z!]+)\s*(.*?)\s*$/);
var count = 0;
var cmd = "";
var args= "";
var special = false;
if (matches1 != null && matches1.length == 2)
count = parseInt(matches1[1], 10);
if (matches2 != null && matches2.length >= 3)
cmd = matches2[2];
if (matches3 != null && matches3.length >= 4)
args = matches3[3];
/* if the user executes a command with ! at the end */
if (cmd.length - 1 == cmd.lastIndexOf("!"))
{
special = true;
cmd = cmd.replace(/!$/, "");
}
else
special = false;
/* user pressed ENTER to carry out a command */
if (evt.keyCode == KeyEvent.DOM_VK_RETURN)
{
// unfocus command line first
focusContent(false, true); // also sets comp_tab_index to -1
add_to_command_history(command);
execute_command(count, cmd, special, args);
[prev_match, heredoc, end] = multiliner(command, prev_match, heredoc);
if (!end)
command_line.value = "";
}
else if ((evt.keyCode == KeyEvent.DOM_VK_ESCAPE) ||
@@ -606,6 +589,8 @@ function onCommandBarKeypress(evt)/*{{{*/
/* user pressed TAB to get completions of a command */
else if (evt.keyCode == KeyEvent.DOM_VK_TAB)
{
var match = tokenize_ex(command);
var [count, cmd, special, args] = match;
//always reset our completion history so up/down keys will start with new values
comp_history_index = -1;
@@ -714,6 +699,17 @@ function onCommandBarInput(event)
command_line.value = ":";
}
function onCommandBarMouseDown(event)
{
if (command_line.value.indexOf(':') != 0)
{
command_line.blur();
event.preventDefault();
event.stopPropagation();
return false;
}
}
////////////////////////////////////////////////////////////////////////
// focus and mode handling //////////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
@@ -802,12 +798,12 @@ function setStatusbarColor(color)
bar.setAttribute("style", "background-color: " + color);
}
function updateStatusbar()
function updateStatusbar(message)
{
var buffers = "[" + (gBrowser.tabContainer.selectedIndex + 1).toString() + "/" +
gBrowser.tabContainer.childNodes.length.toString() + "]";
showStatusbarMessage(getCurrentLocation(), STATUSFIELD_URL);
showStatusbarMessage(message || getCurrentLocation(), STATUSFIELD_URL);
showStatusbarMessage(" " + g_inputbuffer + " ", STATUSFIELD_INPUTBUFFER);
showStatusbarMessage("", STATUSFIELD_PROGRESS);
showStatusbarMessage(buffers, STATUSFIELD_BUFFERS);

View File

@@ -79,7 +79,7 @@ the terms of any one of the MPL, the GPL or the LGPL.
<textbox class="plain" id="vim-commandbar" flex="1" hidden="false" type="timed" timeout="100"
onkeypress="onCommandBarKeypress(event);" oninput="onCommandBarInput(event);"
style="font-family: monospace"/>
onmousedown="onCommandBarMouseDown(event);" style="font-family: monospace"/>
</vbox>
</toolbar>