From f6a7ac82083a5ae8d4750493b39b17353f6a28a1 Mon Sep 17 00:00:00 2001 From: Martin Stubenschrott Date: Sun, 30 Sep 2007 00:55:20 +0000 Subject: [PATCH] simple tab-completion for :javascript and :echo, really just a quick time saver, but prone to errors --- Donators | 1 + NEWS | 1 + chrome/content/vimperator/commands.js | 14 ++-- chrome/content/vimperator/completion.js | 95 +++++++++++++++++++++++-- 4 files changed, 100 insertions(+), 11 deletions(-) diff --git a/Donators b/Donators index 74148a7a..b519261a 100644 --- a/Donators +++ b/Donators @@ -15,6 +15,7 @@ * Nathan Saper * Albert Menkveld * Ian Taylor +* Thomas Svensen I want to say a big THANK YOU for all people which supported this project in this way. diff --git a/NEWS b/NEWS index b77d186e..17a7dc62 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ 2007-xx-xx: * version 0.6 * THIS VERSION ONLY WORKS WITH FIREFOX 3.0 + * Tab-completion improvments for :javascript and :open * IMPORTANT: changed semantics of :echo and :echoerr: Strings must be quoted with " or ' now, but you can do things like :echo 3+2 or :echo window.document now * statusline is now white on black with bold font by default (like in (g)vim) diff --git a/chrome/content/vimperator/commands.js b/chrome/content/vimperator/commands.js index ae3d1ac6..ca42fef4 100644 --- a/chrome/content/vimperator/commands.js +++ b/chrome/content/vimperator/commands.js @@ -523,7 +523,8 @@ function Commands() //{{{ short_help: "Display a string at the bottom of the window", help: "Useful for showing informational messages. Multiple lines can be separated by \\n.
" + "{expr} can either be a quoted string, or any expression which can be fed to eval() like 4+5. " + - "You can also view the source code of objects and functions if the return value of {expr} is an object or function." + "You can also view the source code of objects and functions if the return value of {expr} is an object or function.", + completer: function(filter) { return vimperator.completion.javascript(filter); } } )); addDefaultCommand(new Command(["echoe[rr]"], @@ -536,7 +537,8 @@ function Commands() //{{{ { usage: ["echoe[rr] {expr}"], short_help: "Display an error string at the bottom of the window", - help: "Just like :ec[ho], but echoes the result highlighted in red. Useful for showing important messages." + help: "Just like :ec[ho], but echoes the result highlighted in red. Useful for showing important messages.", + completer: function(filter) { return vimperator.completion.javascript(filter); } } )); addDefaultCommand(new Command(["exe[cute]"], @@ -643,7 +645,11 @@ function Commands() //{{{ help: "Acts as a JavaScript interpreter by passing the argument to eval().
" + ":javascript alert('Hello world') would show a dialog box with the text \"Hello world\".
" + ":javascript <<EOF would read all the lines until a line starting with 'EOF' is found, and will eval() them.
" + - "The special version :javascript! will open the JavaScript console of Firefox." + "The special version :javascript! will open the JavaScript console of Firefox.
" + + "Rudimentary <Tab> completion is available for :javascript {cmd} (but not yet for the " + + ":js <<EOF multiline widget). Be aware that Vimperator needs to run {cmd} through eval() " + + "to get the completions, which could have unwanted side effects.", + completer: function(filter) { return vimperator.completion.javascript(filter); } } )); addDefaultCommand(new Command(["let"], @@ -957,7 +963,7 @@ function Commands() //{{{ "" + "You WILL be able to use :open [-T \"linux\"] torvalds<Tab> to complete bookmarks " + "with tag \"linux\" and which contain \"torvalds\". Note that -T support is only available for tab completion, not for the actual command.
" + - "The items which are completed on <Tab> are specified in the 'complete' option.
" + + "The items which are completed on <Tab> are specified in the 'complete' option.
" + "Without argument, reloads the current page.
" + "Without argument but with !, reloads the current page skipping the cache.", completer: function(filter) { return vimperator.completion.get_url_completions(filter); } diff --git a/chrome/content/vimperator/completion.js b/chrome/content/vimperator/completion.js index 0c02f520..d8188411 100644 --- a/chrome/content/vimperator/completion.js +++ b/chrome/content/vimperator/completion.js @@ -479,6 +479,74 @@ vimperator.completion = (function() // {{{ return build_longest_common_substring(mapped, filter); }, //}}} + javascript: function(str) + { + g_substrings = []; + var matches = str.match(/^(.*?)(\s*\.\s*)?(\w*)$/); + var object = "window"; + var filter = matches[3] || ""; + var start = matches[1].length-1; + if (matches[2]) + { + var brackets = 0, parentheses = 0; + outer: + for (; start >= 0; start--) + { + dump(matches[1].substr(start) + ": " + start + "\n"); + switch (matches[1][start]) + { + case ";": + case "{": + break outer; + + case "]": + brackets--; + break; + case "[": + brackets++; + break; + case ")": + parentheses--; + break; + case "(": + parentheses++; + break; + } + if (brackets > 0 || parentheses > 0) + break outer; + } + } + object = matches[1].substr(start+1) || "window"; + + var completions = []; + try + { + completions = eval( + "var comp = [];" + + "var type = '';" + + "var value = '';" + + "var obj = eval(" + object + ");" + + "for (var i in obj) {" + + " try { type = typeof(obj[i]); } catch (e) { type = 'unknown type'; };" + + " if (type == 'number' || type == 'string' || type == 'boolean') {" + + " value = obj[i];" + + " comp.push([[i], type + ': ' + value]); }" + + // The problem with that is that you complete vimperator. + // but can't press to complete sub items + // so it's better to complete vimperator and the user can do + // . to get the sub items + //" else if (type == 'function') {" + + //" comp.push([[i+'('], type]); }" + + //" else if (type == 'object') {" + + //" comp.push([[i+'.'], type]); }" + + " else {" + + " comp.push([[i], type]); }" + + "} comp;"); + } catch (e) { completions = []; }; + + return build_longest_starting_substring(completions, filter); + }, + exTabCompletion: function(str) //{{{ { var [count, cmd, special, args] = vimperator.commands.parseCommand(str); @@ -498,14 +566,27 @@ vimperator.completion = (function() // {{{ var command = vimperator.commands.get(cmd); if (command && command.completer) { + matches = str.match(/^:*\d*\w+\s+/); + start = matches ? matches[0].length : 0; + + // TODO: maybe we should move these checks to the complete functions + if (command.hasName("open") || command.hasName("tabopen") || command.hasName("winopen")) + { + var skip = args.match(/^(.*,\s+)(.*)/); // start after the last ", " + if (skip) + { + start += skip[1].length; + args = skip[2]; + } + } + else if (command.hasName("echo") || command.hasName("echoerr") || command.hasName("javascript")) + { + var skip = args.match(/^(.*?)(\w*)$/); // start after the last ", " + if (skip) + start += skip[1].length; + } + completions = command.completer.call(this, args); - // if (command[0][0] == "open" || - // command[0][0] == "tabopen" || - // command[0][0] == "winopen") - // start = str.search(/^:*\d*\w+(\s+|.*\|)/); // up to the last | or the first space - // else - matches = str.match(/^:*\d*\w+\s+/); // up to the first spaces only - start = matches[0].length; } } return [start, completions];