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:
@@ -131,16 +131,11 @@ var g_commands = [/*{{{*/
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
["execute", "exe"],
|
["execute", "exe"],
|
||||||
"Run any javascript command through eval()",
|
"Executes a string as an Ex command",
|
||||||
"Acts as a javascript interpreter by passing the argument to <code>eval()</code>.<br>"+
|
"Usage: <code>:execute {expr1} [ ... ]</code><br>" +
|
||||||
"<code>:exec alert('Hello world')</code> would show a dialog box with the text \"Hello world\".<br>"+
|
"Executes the string that results from the evaluation of {expr1} as an Ex command.<br>"+
|
||||||
"The special version <code>:execute!</code> will open the javascript console of Firefox.",
|
"<code>:execute "echo test"</code> would show a message with the text "test".<br>",
|
||||||
function(args, special) {
|
execute,
|
||||||
if (special) // open javascript console
|
|
||||||
openURLsInNewTab("chrome://global/content/console.xul", true);
|
|
||||||
else
|
|
||||||
eval(args);
|
|
||||||
},
|
|
||||||
null
|
null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -174,6 +169,21 @@ var g_commands = [/*{{{*/
|
|||||||
hsshow,
|
hsshow,
|
||||||
function(filter) { return get_history_completions(filter); }
|
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 <<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"],
|
||||||
"Mark current location within the webpage",
|
"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>"+
|
"The .vimperatorrc file in your home directory is always sourced at start up.<br>"+
|
||||||
"~ is supported as a shortcut for the $HOME directory.",
|
"~ is supported as a shortcut for the $HOME directory.",
|
||||||
source,
|
source,
|
||||||
null
|
function (filter) { return get_file_completions(filter); }
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
["tabnext", "tn", "tnext"],
|
["tabnext", "tn", "tnext"],
|
||||||
@@ -910,6 +920,7 @@ function get_command(cmd) // {{{
|
|||||||
|
|
||||||
function execute_command(count, cmd, special, args) // {{{
|
function execute_command(count, cmd, special, args) // {{{
|
||||||
{
|
{
|
||||||
|
if (!cmd) return;
|
||||||
var command = get_command(cmd);
|
var command = get_command(cmd);
|
||||||
if (command == null)
|
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
|
// statusbar/commandbar handling ////////////////////////////////// {{{1
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1628,7 +1719,12 @@ function source(filename, silent)
|
|||||||
var s = fd.read();
|
var s = fd.read();
|
||||||
fd.close();
|
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)
|
catch(e)
|
||||||
{
|
{
|
||||||
@@ -1637,7 +1733,6 @@ function source(filename, silent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function help(section, easter)
|
function help(section, easter)
|
||||||
{
|
{
|
||||||
if (easter)
|
if (easter)
|
||||||
|
|||||||
@@ -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
|
* filter a list of urls
|
||||||
|
|||||||
@@ -129,6 +129,19 @@ function fo_write(buf)
|
|||||||
LocalFile.prototype.read =
|
LocalFile.prototype.read =
|
||||||
function fo_read(max)
|
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))
|
if (!("inputStream" in this))
|
||||||
throw "file not open for reading.";
|
throw "file not open for reading.";
|
||||||
|
|
||||||
|
|||||||
@@ -63,17 +63,6 @@ var g_settings = [/*{{{*/
|
|||||||
null,
|
null,
|
||||||
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"],
|
["extendedhinttags", "eht"],
|
||||||
"XPath string of hintable elements activated by ';'",
|
"XPath string of hintable elements activated by ';'",
|
||||||
@@ -221,6 +210,17 @@ var g_settings = [/*{{{*/
|
|||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
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
|
||||||
]
|
]
|
||||||
]/*}}}*/
|
]/*}}}*/
|
||||||
|
|
||||||
|
|||||||
@@ -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_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 multi-line commands
|
||||||
|
var prev_match = new Array(5);
|
||||||
|
var heredoc = '';
|
||||||
|
|
||||||
// handles to our gui elements
|
// handles to our gui elements
|
||||||
var preview_window = null;
|
var preview_window = null;
|
||||||
var status_line = null;
|
var status_line = null;
|
||||||
@@ -83,7 +87,7 @@ nsBrowserStatusHandler.prototype =
|
|||||||
|
|
||||||
setOverLink : function(link, b)
|
setOverLink : function(link, b)
|
||||||
{
|
{
|
||||||
echo(link);
|
updateStatusbar(link);
|
||||||
|
|
||||||
if (link == "")
|
if (link == "")
|
||||||
showMode();
|
showMode();
|
||||||
@@ -518,45 +522,24 @@ function onVimperatorKeypress(event)/*{{{*/
|
|||||||
updateStatusbar();
|
updateStatusbar();
|
||||||
return false;
|
return false;
|
||||||
}/*}}}*/
|
}/*}}}*/
|
||||||
|
|
||||||
function onCommandBarKeypress(evt)/*{{{*/
|
function onCommandBarKeypress(evt)/*{{{*/
|
||||||
{
|
{
|
||||||
|
var end = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
/* parse our command string into tokens */
|
/* parse our command string into tokens */
|
||||||
var command = command_line.value;
|
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 */
|
/* user pressed ENTER to carry out a command */
|
||||||
if (evt.keyCode == KeyEvent.DOM_VK_RETURN)
|
if (evt.keyCode == KeyEvent.DOM_VK_RETURN)
|
||||||
{
|
{
|
||||||
// unfocus command line first
|
// unfocus command line first
|
||||||
focusContent(false, true); // also sets comp_tab_index to -1
|
|
||||||
add_to_command_history(command);
|
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) ||
|
else if ((evt.keyCode == KeyEvent.DOM_VK_ESCAPE) ||
|
||||||
@@ -606,6 +589,8 @@ 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 match = tokenize_ex(command);
|
||||||
|
var [count, cmd, special, args] = match;
|
||||||
//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;
|
||||||
|
|
||||||
@@ -714,6 +699,17 @@ function onCommandBarInput(event)
|
|||||||
command_line.value = ":";
|
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
|
// focus and mode handling //////////////////////////////////////// {{{1
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -802,12 +798,12 @@ function setStatusbarColor(color)
|
|||||||
bar.setAttribute("style", "background-color: " + color);
|
bar.setAttribute("style", "background-color: " + color);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateStatusbar()
|
function updateStatusbar(message)
|
||||||
{
|
{
|
||||||
var buffers = "[" + (gBrowser.tabContainer.selectedIndex + 1).toString() + "/" +
|
var buffers = "[" + (gBrowser.tabContainer.selectedIndex + 1).toString() + "/" +
|
||||||
gBrowser.tabContainer.childNodes.length.toString() + "]";
|
gBrowser.tabContainer.childNodes.length.toString() + "]";
|
||||||
|
|
||||||
showStatusbarMessage(getCurrentLocation(), STATUSFIELD_URL);
|
showStatusbarMessage(message || getCurrentLocation(), STATUSFIELD_URL);
|
||||||
showStatusbarMessage(" " + g_inputbuffer + " ", STATUSFIELD_INPUTBUFFER);
|
showStatusbarMessage(" " + g_inputbuffer + " ", STATUSFIELD_INPUTBUFFER);
|
||||||
showStatusbarMessage("", STATUSFIELD_PROGRESS);
|
showStatusbarMessage("", STATUSFIELD_PROGRESS);
|
||||||
showStatusbarMessage(buffers, STATUSFIELD_BUFFERS);
|
showStatusbarMessage(buffers, STATUSFIELD_BUFFERS);
|
||||||
|
|||||||
@@ -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"
|
<textbox class="plain" id="vim-commandbar" flex="1" hidden="false" type="timed" timeout="100"
|
||||||
onkeypress="onCommandBarKeypress(event);" oninput="onCommandBarInput(event);"
|
onkeypress="onCommandBarKeypress(event);" oninput="onCommandBarInput(event);"
|
||||||
style="font-family: monospace"/>
|
onmousedown="onCommandBarMouseDown(event);" style="font-family: monospace"/>
|
||||||
</vbox>
|
</vbox>
|
||||||
</toolbar>
|
</toolbar>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user