firefox
Vimperator
VimFx

Goodbye Vimperator, Hello VimFx + e10s

More than 1 year has passed since last update.

TL;DR: これは Vimperator を捨てて VimFx をインストールし、e10s を有効化したらすこぶる快適になった話です。Firefox 万歳!VimFx 万歳!

前置きはここに至るまでの経緯なので読み飛ばしてもらって構いません。


前置き

Firefox の遅さや開発ツールの使いにくさから Google Chrome に移行して久しいですが、メモリ使用量がとんでもなく多い事やキーボードブラウジングの不完全さから昨年あたりに Firefox + Vimperator に戻ってきていました。キーボードブラウジングは cVim や Vimium 等を一通り試しましたが、Chrome の拡張の仕組み上、ウェブページがロードされないと使えなかったり、一部のタブでは動作しなかったりする点に不満と限界を感じていました。

そんな中、最近の Firefox は早くなったという記事を見かけるようになり、プロファイルを新しくして起動してみると Chrome よりも快適に使えるような気がしました。昔は KeySnail を使っていましたが、ブラウザは Emacs 風じゃなくていいかなと思い Vimperator をインストールすることにしました。こうして真のキーボードブラウジング環境を取り戻したのでした。 めでたしめでたし

Firefox 48 から高速化のための Electrolysis (e10s) が使えるようになりました。早速有効にしたかったのですが、Vimperator が対応していないじゃないですか。なんでも、かなりアグレッシブに Firefox の UI を書き換えていたり、古いコードがたくさんあって対応が困難なようで、Fork 版の Pentadactyl も状況は同じようでした。この時点で VimFx なら e10s 対応してるよ!という情報を見ていましたが、Chrome + Vimium の苦い思い出からどうせキーボードショートカットを vim 風にしただけのものでしょと思っていました。ごめんなさい。

とりあえずキーボードブラウジングの方が大事だったので、泣く泣く e10s は忘れてそのうち対応されるだろうと Vimperator を使っていました。しかし、Firefox 51 に上げたところ tabopen コマンドが使えなくなって Vimperator の未来に限界を感じ、以前より Hit-a-Hint がたまに動かないこともあって、思い切って VimFx と入れ替えてみることにしました。


Hello VimFx

VimFx は Vimium for Chrome の開発者が、その開発経験を踏まえて開発されたものです。Vimperator ほど Firefox に変更を加えず、Firefox に元から備わっているものは極力利用し、キーボードブラウジングに必要なものだけを取り入れています。

JavaScript で設定ファイルを記述することで、かなり高度な事ができるようになります。ブラウザの機能にアクセスするカスタムコマンドを追加でき、Vimium と比べると非常にパワフルです。Vimperator でお困りの方は一度試してみるのをおすすめします。

VimFx についてはこちらのサイトが参考になります。


…and e10s

e10s はざっくり言うとブラウザの UI とウェブコンテンツをレンダリングするプロセスを分離するものです。Firefox 48 から利用できますが、非対応のアドオンがあると自動的に無効になります。有効になっているかは about:support のマルチプロセスウインドウを見ればわかります。この値が 1/1 なら有効です。

非対応なアドオンがあっても、about:config を開いて browser.tabs.remote.force-enable を true にすれば強制的に有効にすることができます。1Password のアドオンが正式には対応していなかったのでこの方法で有効にしました。

e10s はデフォルトではウェブコンテンツ用のプロセスは1つですが、about:config から dom.ipc.processCount を設定することで任意の数まで増やせます。4以上で顕著なパフォーマンス向上が見込め、8以上はメモリ使用量が多くなりすぎるとのことです。今のところ4に設定し、快適に使えています。

なお、dom.ipc.processCount が1以上の時の検証は十分にされていないようなので、うまく動かなければ1に戻しましょう。


Customize VimFx

VimFx の設定ファイルは ~/.config/vimfxconfig.jsframe.js を作成します。そして about:config から extensions.VimFx.config_file_directory~/.config/vimfx に設定します。設定が済んだら gC とタイプすると設定ファイルが読み込まれ、ブラウザの右下に通知がでます。

参考までに現状の設定ファイルを貼り付けておきます。設定方法について詳しくはドキュメントを見てください。


config.js

const {classes: Cc, interfaces: Ci, utils: Cu} = Components;

const gClipboardHelper = Cc['@mozilla.org/widget/clipboardhelper;1']
.getService(Ci.nsIClipboardHelper);
const {Preferences} = Cu.import('resource://gre/modules/Preferences.jsm', {});

const FIREFOX_PREFS = {
'browser.startup.page': 3,
'browser.tabs.animate': false,
'browser.search.suggest.enabled': true,
'browser.urlbar.suggest.searches': true,
'browser.urlbar.maxRichResults': 20,
'browser.tabs.remote.force-enable': true,
'dom.ipc.processCount': 4
};

const VIMFX_PREFS = {
'prevent_autofocus': true
};

const MAPPINGS = {
'copy_current_url': '',
'go_home': '',
'stop': '<c-escape>',
'stop_all': 'a<c-escape>',

'history_back': 'h',
'history_forward': 'l',

'scroll_left': 'H',
'scroll_right': 'L',
'scroll_half_page_down': '<c-f>',
'scroll_half_page_up': '<c-b>',
'mark_scroll_position': 'mm',
'scroll_to_mark': 'gm',

'tab_new': 'T',
'tab_new_after_current': 't',
'tab_close': 'd x',
'tab_restore': 'u',
'tab_restore_list': 'U',
'tab_select_previous': ',',
'tab_select_next': '.',
'tab_select_first_non_pinned': '^',
'tab_select_last': '$',

'enter_mode_ignore': 'I',
'quote': 'i',

'custom.mode.normal.search_selected_text': 's',
'custom.mode.normal.copy_selection_or_url': 'yy',
'custom.mode.normal.copy_as_markdown': 'ym',
'custom.mode.normal.click_toolbar_pocket': 'mp'
};

const {commands} = vimfx.modes.normal;

const CUSTOM_COMMANDS = [
[
{
name: 'search_selected_text',
description: 'Search for the selected text'
}, ({vim}) => {
vimfx.send(vim, 'getSelection', true, selection => {
if (selection != '') {
vim.window.switchToTabHavingURI(`https://www.google.co.jp/search?q=${selection}`, true);
}
});
}
],
[
{
name: 'copy_as_markdown',
description: 'Copy title and url as Markdown',
category: 'location',
order: commands.copy_current_url.order + 2
}, ({vim}) => {
let url = vim.window.gBrowser.selectedBrowser.currentURI.spec;
let title = vim.window.gBrowser.selectedBrowser.contentTitle;
let s = `[${title}](${url})`;
gClipboardHelper.copyString(s);
vim.notify(`Copied to clipboard: ${s}`);
}
],
[
{
name: 'copy_selection_or_url',
description: 'Copy the selection or current url',
category: 'location',
order: commands.copy_current_url.order + 1
}, ({vim}) => {
vimfx.send(vim, 'getSelection', true, selection => {
if (selection == '') {
selection = vim.window.gBrowser.selectedBrowser.currentURI.spec;
}
gClipboardHelper.copyString(selection);
vim.notify(`Copied to clipboard: ${selection}`);
});
}
],
[
{
name: 'click_toolbar_pocket',
description: 'Click toolbar button [Pocket]'
}, ({vim}) => {
vim.window.document.getElementById('pocket-button').click();
}
]
];

Object.entries(VIMFX_PREFS).forEach(([name, value]) => {
vimfx.set(name, value);
});

CUSTOM_COMMANDS.forEach(([options, fn]) => {
vimfx.addCommand(options, fn);
});

Object.entries(MAPPINGS).forEach(([cmd, key]) => {
if (!cmd.includes('.')) {
cmd = `mode.normal.${cmd}`;
}
vimfx.set(cmd, key);
});

Preferences.set(FIREFOX_PREFS);


frame.js

vimfx.listen('getSelection', (willRemove, callback) => {

let selection = content.getSelection();
let s = selection.toString();
if (willRemove) {
selection.removeAllRanges();
}
callback(s);
});


Stylish

Hint のスタイリングなどは userChrome.css か Stylish で行います。Stylish だと再起動せずに適用できるので微調整などはやりやすいです。

次の設定を入れています。

@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);

#VimFxMarkersContainer .marker {
font-size: 14px !important;
}

/* Make location bar red while in ignore mode */
#main-window[vimfx-mode="ignore"] #urlbar {
background: red !important;
}

statuspanel label.statuspanel-label {
background: linear-gradient(45deg, rgba(22, 22, 22, 0.9), rgba(99, 99, 99, 0.9)) !important;
color: whitesmoke !important;
font-size: 14px !important;
}