Thursday, December 11, 2008

Make Vimperator's "Y"ank behave like Edit-Copy

Because I'm a vim user, it's natural for me to use vimperator on top of Firefox.

Today I posted a tip on that is derived from a suggestion someone else made on the vimperator mailing list. I'm reposting that tip here.

Vimperator has no choice but to copy selected text using the functions provided to JavaScript by Firefox. Unfortunately, these functions sometimes do not provide the expected behavior for certain types of lists, PRE environments, etc.

To make sure that "Y"anking results in the same thing as using Edit->Copy, add the following to your .vimperatorrc:
js <<EOF
mappings.addUserMap([modes.NORMAL], ["Y"],
"Yank the currently selected text",
function () {
events.feedkeys("<C-v>" +
(/^Mac/.test(navigator.platform) ?
: "<C-c>"), true);
setTimeout( function () {
liberator.echo("Yanked "
+ util.readFromClipboard(),
}, 20 );
The code should work well on all platforms (even the Mac, with its "M" key). If it isn't working perfect for you, increase that final "20" until the behavior works how you'd like it.


Preston said...

This is perfect, exactly what I was looking for. The out-of-box yank functionality is vimperator doesn't work in many situations. Your method always works! The vimperator developers should pull it into the main trunk. Thanks for sharing.

Ted said...

That script probably won't be pulled into the distribution code because it's a little bit of a hack. As you can see, rather than communicating with Firefox using API, it actually issues keypresses as if the user hit them. Because of that, it requires that "timeout" to make sure the keypresses actually have enough time to get issued.

The Vimperator developers hope that the Firefox developers will someday fix the way Firefox's JavaScript does its copying. It's really a Firefox bug and not a Vimperator bug. This Vimperator code just gives a way to use Vimperator to walk around the Firefox bug.

So don't blame Vimperator, blame Firefox. :)

Preston said...

I don't blame anybody, I just want to copy :-)

The whole reason I started looking for an alternate copy solution was because I couldn't copy from Gmail. Unfortunately, the fix posted here doesn't work either. Both the native yank and the code here return the following error:

Processing keypress event: [Exception... "Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsISelection.getRangeAt]"

But... I did find that this works, so I'm going with it :-)

noremap Y <C-v><C-c>