-
Notifications
You must be signed in to change notification settings - Fork 175
Custom Commands
Please share useful custom commands here!
See documentation/config-file.md for how to use this.
Tip: Here’s a way to find how many built-in Firefox commands are implemented:
-
Go to about:config and make sure that
devtools.chrome.enabled
is set totrue
. -
Open the browser console.
-
Run the following code:
Array.map(document.querySelectorAll('command'), command => `${command.id}: ${command.getAttribute('oncommand')}`).join('\n')
That prints a list of command names and the code they use.
###Copy as markdown link
vimfx.addCommand({
name: 'copy_markdown',
description: 'Copy as markdown link',
category: 'location',
}, ({vim}) => {
let url = vim.window.gBrowser.selectedBrowser.currentURI.spec
let title = vim.window.gBrowser.selectedBrowser.contentTitle
let fmt = "["+title+"]("+url+")"
gClipboardHelper.copyString(fmt)
vim.notify("Copied String: "+ fmt)
});```
### Open new tab and focus Search Bar
```js
let {commands} = vimfx.modes.normal
vimfx.addCommand({
name: 'tab_new_and_focus_search_bar',
description: 'Open new tab and focus Search Bar',
category: 'tabs',
order: commands.tab_new.order + 1,
}, args => {
commands.tab_new.run(args)
commands.focus_search_bar.run(args)
})
vimfx.addCommand({
name: 'zoom_in',
description: 'Zoom in',
}, ({vim}) => {
vim.window.FullZoom.enlarge()
})
You can also replace enlarge
with reduce
to zoom out, and with reset
to reset to 100%.
vimfx.addCommand({
name: 'bookmark_page',
description: 'Bookmark page',
}, ({vim}) => {
let {window} = vim
window.PlacesCommandHook.bookmarkCurrentPage(true, window.PlacesUtils.bookmarksMenuFolderId)
})
The above is equivalent to the Firefox default shortcut <c-d>
.
let {commands} = vimfx.modes.normal
vimfx.addCommand({
name: 'search_tabs',
description: 'Search tabs',
category: 'tabs',
order: commands.focus_location_bar.order + 1,
}, (args) => {
let {vim} = args
let {gURLBar} = vim.window
gURLBar.value = ''
commands.focus_location_bar.run(args)
// Change the `*` on the text line to a `%` to search tabs instead of bookmarks.
gURLBar.value = '* '
gURLBar.onInput(new vim.window.KeyboardEvent('input'))
})
You may also want to read more about handy location bar features.
vimfx.addCommand({
name: 'goto_downloads',
description: 'Downloads',
}, ({vim}) => {
vim.window.gBrowser.loadURI('about:downloads')
})
Replace loadURI
with loadOneTab
to open in a new tab instead.
Here are some URLs you might find interesting (they should be self-explanatory):
about:downloads
about:preferences
about:addons
Like about:
pages? Go to about:about
to list them all!
let {commands} = vimfx.modes.normal
vimfx.addCommand({
name: 'go_increment',
description: 'Increment the last number in the URL',
category: 'location',
order: commands.go_to_root.order + 1,
}, ({vim, count = 1}) => {
let url = vim.browser.currentURI.spec
let newUrl = url.replace(/(\d+)(?=\D*$)/, match =>
Math.max(0, Number(match) + count)
)
if (newUrl === url) {
vim.notify('Cannot increment/decrement URL')
} else {
vim.window.gBrowser.loadURI(newUrl)
}
})
vimfx.addCommand({
name: 'go_decrement',
description: 'Decrement last number in the URL',
category: 'location',
order: commands.go_increment.order + 1,
}, ({vim, count = 1}) => {
commands.go_increment.run({vim, count: -count})
})
vimfx.addCommand({
name: 'search_selected_text',
description: 'Search for the selected text',
}, ({vim}) => {
let {messageManager} = vim.window.gBrowser.selectedBrowser
vimfx.send(vim, 'getSelection', null, selection => {
let inTab = true // Change to `false` if you’d like to search in current tab.
vim.window.BrowserSearch.loadSearch(selection, inTab)
})
})
frame.js:
vimfx.listen('getSelection', (data, callback) => {
let selection = content.getSelection().toString()
callback(selection)
})
vimfx.addCommand({
name: 'web_console',
description: 'Web console',
}, ({vim}) => {
vim.window.gDevToolsBrowser.selectToolCommand(vim.window.gBrowser, 'webconsole')
})
The above is equivalent to the Firefox default shortcut <c-K>
. Alternatively, you can use the following to toggle the developer tools instead:
vim.window.gDevToolsBrowser.toggleToolboxCommand(vim.window.gBrowser)
This command moves the current tab before tab number count.
vimfx.addCommand({
name: 'tab_move_to_index',
description: 'Move tab to index',
category: 'tabs',
order: commands.tab_move_forward.order + 1,
}, ({vim, count}) => {
if (count === undefined) {
vim.notify('Provide a count')
return
}
let {window} = vim
window.setTimeout(() => {
let {selectedTab} = window.gBrowser
if (selectedTab.pinned) {
vim.notify('Run from a non-pinned tab')
return
}
let newPosition = window.gBrowser._numPinnedTabs + count - 1
window.gBrowser.moveTabTo(selectedTab, newPosition)
}, 0)
})
Tip: Add the following to custom styling to make it easier to work out which number to type. It turns the tab close buttons into numbers until you hover the tab:
#TabsToolbar {
counter-reset: tabs-counter;
}
.tab-close-button:not([pinned]) {
visibility: hidden;
display: block;
color: inherit;
counter-increment: tabs-counter;
&::before {
content: counter(tabs-counter);
visibility: visible;
font-weight: normal;
font-style: normal;
}
}
Known as d
and D
in Vimperator.
vimfx.addCommand({
name: 'tab_close_and_focus_previous',
description: 'Close tab and focus previous.',
category: 'tabs',
}, ({vim}) => {
let {gBrowser} = vim.window
let previousTabIndex = gBrowser.tabContainer.selectedIndex - 1
gBrowser.removeCurrentTab()
gBrowser.selectTabAtIndex(previousTabIndex)
})
vimfx.addCommand({
name: 'tab_close_and_focus_next',
description: 'Close tab and focus next.',
category: 'tabs',
}, ({vim}) => {
let {gBrowser} = vim.window
let nextTabIndex = gBrowser.tabContainer.selectedIndex
gBrowser.removeCurrentTab()
gBrowser.selectTabAtIndex(nextTabIndex)
})
let {commands} = vimfx.modes.normal
vimfx.addCommand({
name: 'tab_close_to_start',
description: 'Close tabs to the left',
category: 'tabs',
order: commands.tab_close_to_end.order + 1,
}, ({vim}) => {
let {gBrowser} = vim.window
Array.slice(gBrowser.tabs, gBrowser._numPinnedTabs, gBrowser.selectedTab._tPos)
.forEach(tab => gBrowser.removeTab(tab))
})
let {commands} = vimfx.modes.normal
vimfx.addCommand({
name: 'window_close',
description: 'Close window',
order: commands.follow_in_private_window.order + 1,
}, ({vim}) => {
let {window} = vim
if (window.gBrowser.tabs.length > 1) {
if (window.confirm('There are multiple tabs open. Close anyway?')) {
window.close()
}
} else {
window.close()
}
})
(Related: Issue #402.)
let {commands} = vimfx.modes.normal
vimfx.addCommand({
name: 'window_minimize',
description: 'Minimize window',
order: commands.follow_in_private_window.order + 1,
}, ({vim}) => {
vim.window.minimize()
})
Click the NoScript button
vimfx.addCommand({
name: 'noscript_click_toolbar_button',
description: 'NoScript',
}, ({vim}) => {
vim.window.document.getElementById('noscript-tbb').click()
})
const {classes: Cc, interfaces: Ci} = Components
const mpv_path = '/usr/bin/mpv'
const mpv_options = '--video-unscaled=yes'
vimfx.addCommand({
name: 'play_with_mpv',
description: 'Play the focused link with MPV'
}, ({vim}) => {
vimfx.send(vim, 'getCurrentHref', null, url => {
let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile)
file.initWithPath(mpv_path)
let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess)
process.init(file)
let args = mpv_options.split(' ')
if (url.includes('youtube.com')) {
// Parse url params to an object like:
// {"v":"g04s2u30NfQ","index":"3","list":"PL58H4uS5fMRzmMC_SfMelnCoHgB8COa5r"}
let qs = (function(a) {
if (a == '') return {}
let b = {}
for (let i = 0; i < a.length; ++i) {
let p = a[i].split('=', 2)
if (p.length == 1) {
b[p[0]] = ''
} else {
b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, ' '))
}
}
return b
})(url.substr(1).split('&'))
if (qs['list'] && qs['index']) {
// Example args: ['--video-unscaled=yes', '--ytdl-raw-options=format=best']
// So check for ytdl-raw-options.
let ytdlRawOptionsIndex = -1
for (let i = 0; i < args.length; i++) {
if (args[i].includes('ytdl-raw-options')) {
ytdlRawOptionsIndex = i
break
}
}
if (ytdlRawOptionsIndex > -1) {
args[ytdlRawOptionsIndex] += `,yes-playlist=,playlist-start=${qs['index']}`
} else {
args.push(`--ytdl-raw-options=yes-playlist=,playlist-start=${qs['index']}`)
}
}
}
args.push(url)
// process.run(false, args, args.length)
process.runAsync(args, args.length)
})
})
frame.js:
vimfx.listen('getCurrentHref', (data, callback) => {
let {href} = content.document.activeElement
callback(href)
})
Sorry for hairy code :)
const {classes: Cc, interfaces: Ci} = Components;
vimfx.addCommand({
name: 'restart',
description: 'Restart Firefox'
}, (args) => {
let canceled = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(canceled, "quit-application-requested", "restart");
if (canceled.data) return false; // somebody canceled our quit request
// restart
Cc['@mozilla.org/toolkit/app-startup;1'].getService(Ci.nsIAppStartup)
.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
return true;
});