2017-10-12 04:02:01 +01:00
|
|
|
// '//#' is a start point for a simple text-replacement-type macro. See excmds_macros.py
|
|
|
|
|
|
|
|
// {{{ setup
|
|
|
|
|
2017-10-23 09:42:50 +01:00
|
|
|
import * as Messaging from "./messaging"
|
2017-11-15 00:41:53 +00:00
|
|
|
import {l} from './lib/webext'
|
2017-10-23 09:42:50 +01:00
|
|
|
|
2017-10-12 04:02:01 +01:00
|
|
|
//#content_omit_line
|
|
|
|
import * as CommandLineContent from "./commandline_content"
|
|
|
|
//#content_omit_line
|
|
|
|
import "./number.clamp"
|
|
|
|
//#content_helper
|
|
|
|
import * as SELF from "./excmds_content"
|
2017-10-23 09:42:50 +01:00
|
|
|
//#content_helper
|
|
|
|
Messaging.addListener('excmd_content', Messaging.attributeCaller(SELF))
|
2017-10-28 05:11:10 +01:00
|
|
|
/** Message excmds_content.ts in the active tab of the currentWindow */
|
|
|
|
//#background_helper
|
|
|
|
import {messageActiveTab} from './messaging'
|
2017-10-12 04:02:01 +01:00
|
|
|
|
|
|
|
//#background_helper
|
|
|
|
import "./number.mod"
|
|
|
|
//#background_helper
|
|
|
|
import state from "./state"
|
2017-10-23 09:42:50 +01:00
|
|
|
//#background_helper
|
2017-11-09 00:41:07 +00:00
|
|
|
import {ModeName} from './state'
|
|
|
|
//#background_helper
|
2017-10-23 09:42:50 +01:00
|
|
|
import * as keydown from "./keydown_background"
|
2017-11-09 00:41:07 +00:00
|
|
|
//#background_helper
|
|
|
|
import {activeTab, activeTabId} from './lib/webext'
|
2017-10-12 04:02:01 +01:00
|
|
|
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#background_helper
|
2017-10-23 09:42:50 +01:00
|
|
|
export const cmd_params = new Map<string, Map<string, string>>()
|
2017-10-12 04:02:01 +01:00
|
|
|
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-11-14 23:31:08 +00:00
|
|
|
const SEARCH_URLS = new Map<string, string>([
|
|
|
|
["google","https://www.google.com/search?q="],
|
|
|
|
["googleuk","https://www.google.co.uk/search?q="],
|
|
|
|
["bing","https://www.bing.com/search?q="],
|
|
|
|
["duckduckgo","https://duckduckgo.com/?q="],
|
|
|
|
["yahoo","https://search.yahoo.com/search?p="],
|
|
|
|
["twitter","https://twitter.com/search?q="],
|
|
|
|
["wikipedia","https://en.wikipedia.org/wiki/"],
|
|
|
|
["youtube","https://www.youtube.com/results?search_query="],
|
|
|
|
["amazon","https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords="],
|
|
|
|
["amazonuk","https://www.amazon.co.uk/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords="],
|
|
|
|
])
|
2017-10-22 16:33:43 +01:00
|
|
|
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
function hasScheme(uri: string) {
|
|
|
|
return uri.match(/^(\w+):/)
|
|
|
|
}
|
|
|
|
|
|
|
|
/** If maybeURI doesn't have a schema, affix http:// */
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
function forceURI(maybeURI: string) {
|
|
|
|
if (hasScheme(maybeURI)) {
|
|
|
|
return maybeURI
|
2017-11-09 07:38:24 +00:00
|
|
|
}
|
2017-11-15 00:55:51 +02:00
|
|
|
|
2017-11-09 15:30:09 +00:00
|
|
|
let urlarr = maybeURI.split(" ")
|
2017-11-15 00:55:51 +02:00
|
|
|
if (SEARCH_URLS.get(urlarr[0]) != null){
|
|
|
|
return SEARCH_URLS.get(urlarr[0]) + urlarr.slice(1,urlarr.length).join(" ")
|
2017-11-09 07:38:24 +00:00
|
|
|
} else if (urlarr[0].includes('.')) {
|
2017-10-12 04:02:01 +01:00
|
|
|
return "http://" + maybeURI
|
2017-10-22 16:33:43 +01:00
|
|
|
} else {
|
2017-11-15 00:55:51 +02:00
|
|
|
return SEARCH_URLS.get("google") + maybeURI
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#background_helper
|
|
|
|
function tabSetActive(id: number) {
|
|
|
|
browser.tabs.update(id, {active: true})
|
|
|
|
}
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
|
|
|
// {{{ PAGE CONTEXT
|
|
|
|
|
2017-11-09 21:01:57 +00:00
|
|
|
/** Blur (unfocus) the active element */
|
|
|
|
//#content
|
|
|
|
export function unfocus() {
|
|
|
|
(document.activeElement as HTMLInputElement).blur()
|
|
|
|
}
|
|
|
|
|
2017-10-12 04:02:01 +01:00
|
|
|
//#content
|
|
|
|
export function scrollpx(a: number, b: number) {
|
|
|
|
window.scrollBy(a, b)
|
|
|
|
}
|
|
|
|
|
|
|
|
/** If one argument is given, scroll to that percentage down the page.
|
|
|
|
If two arguments are given, treat as x and y values to give to window.scrollTo
|
|
|
|
*/
|
|
|
|
//#content
|
|
|
|
export function scrollto(a: number, b?: number) {
|
|
|
|
a = Number(a)
|
|
|
|
// if b is undefined, Number(b) is NaN.
|
|
|
|
b = Number(b)
|
|
|
|
window.scrollTo(
|
|
|
|
b ? a : window.scrollX,
|
|
|
|
b
|
|
|
|
? b
|
|
|
|
: a.clamp(0, 100) *
|
|
|
|
(window.document.scrollingElement.scrollHeight / 100)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
//#content
|
|
|
|
export function scrollline(n = 1) {
|
|
|
|
window.scrollByLines(n)
|
|
|
|
}
|
|
|
|
//#content
|
|
|
|
export function scrollpage(n = 1) {
|
2017-11-07 12:05:14 +00:00
|
|
|
window.scrollBy(0, window.innerHeight * n)
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#content_helper
|
|
|
|
function history(n: number) {
|
|
|
|
window.history.go(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
//#content
|
|
|
|
export function forward(n = 1) {
|
|
|
|
history(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
//#content
|
|
|
|
export function back(n = 1) {
|
|
|
|
history(n * -1)
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Reload the next n tabs, starting with activeTab, possibly bypassingCache */
|
|
|
|
//#background
|
|
|
|
export async function reload(n = 1, hard = false) {
|
2017-11-09 00:41:07 +00:00
|
|
|
let tabstoreload = await getnexttabs(await activeTabId(), n)
|
2017-10-12 04:02:01 +01:00
|
|
|
let reloadProperties = {bypassCache: hard}
|
|
|
|
tabstoreload.map(n => browser.tabs.reload(n, reloadProperties))
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Reload the next n tabs, starting with activeTab. bypass cache for all */
|
|
|
|
//#background
|
|
|
|
export async function reloadhard(n = 1) {
|
|
|
|
reload(n, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
//#content
|
2017-10-22 16:33:43 +01:00
|
|
|
export function open(...urlarr: string[]) {
|
2017-11-09 15:30:09 +00:00
|
|
|
let url = urlarr.join(" ")
|
2017-10-12 04:02:01 +01:00
|
|
|
window.location.href = forceURI(url)
|
|
|
|
}
|
|
|
|
|
2017-10-23 23:44:07 +01:00
|
|
|
//#background
|
|
|
|
export function help(...urlarr: string[]) {
|
2017-11-09 15:30:09 +00:00
|
|
|
let url = urlarr.join(" ")
|
2017-10-23 23:44:07 +01:00
|
|
|
// window.location.href = "docs/modules/_excmds_.html#" + url
|
|
|
|
browser.tabs.create({url: "static/docs/modules/_excmds_.html#" + url})
|
2017-10-23 23:44:07 +01:00
|
|
|
|
2017-10-23 23:44:07 +01:00
|
|
|
}
|
|
|
|
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#content_helper
|
|
|
|
function getlinks(){
|
|
|
|
return document.getElementsByTagName('a')
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Find a likely next/previous link and follow it */
|
|
|
|
//#content
|
|
|
|
export function clicknext(dir = "next"){
|
|
|
|
let linkarray = Array.from(getlinks())
|
|
|
|
let regarray = [/\bnext|^>$|^(>>|»)$|^(>|»)|(>|»)$|\bmore\b/i, /\bprev\b|\bprevious\b|^<$|^(<<|«)$|^(<|«)|(<|«)$/i]
|
|
|
|
|
|
|
|
regarray = window.location.href.match(/rockpapershotgun/) ? [/newer/i,/older/i] : regarray
|
|
|
|
let nextreg = (dir == "next") ? regarray[0] : regarray[1]
|
|
|
|
|
|
|
|
// Might need to add more cases to this as we look at more sites
|
|
|
|
let nextlinks = linkarray.filter((link) => (link.innerText.match(nextreg) || link.rel.match(nextreg)))
|
|
|
|
|
|
|
|
// Use the last link that matches because next/prev buttons tend to be at the end of the page
|
|
|
|
// whereas lots of blogs have "VIEW MORE" etc. plastered all over their pages.
|
|
|
|
// Stops us from having to hardcode in RPS and reddit, for example.
|
|
|
|
window.location.href = nextlinks.slice(-1)[0].href
|
|
|
|
}
|
2017-11-15 12:40:26 +00:00
|
|
|
|
|
|
|
//#background
|
|
|
|
export function zoom(level=0){
|
|
|
|
level = level > 3 ? level / 100 : level
|
|
|
|
browser.tabs.setZoom(level)
|
|
|
|
}
|
|
|
|
|
2017-10-12 04:02:01 +01:00
|
|
|
// }}}
|
|
|
|
|
|
|
|
// {{{ TABS
|
|
|
|
|
|
|
|
/** Switch to the next tab by index (position on tab bar), wrapping round.
|
|
|
|
|
|
|
|
optional increment is number of tabs forwards to move.
|
|
|
|
*/
|
|
|
|
//#background
|
|
|
|
export async function tabnext(increment = 1) {
|
|
|
|
// Get an array of tabs in the current window
|
|
|
|
let current_window = await browser.windows.getCurrent()
|
|
|
|
let tabs = await browser.tabs.query({windowId: current_window.id})
|
|
|
|
|
|
|
|
// Derive the index we want
|
|
|
|
let desiredIndex = ((await activeTab()).index + increment).mod(tabs.length)
|
|
|
|
|
|
|
|
// Find and switch to the tab with that index
|
2017-10-21 12:54:48 +02:00
|
|
|
let desiredTab = tabs.find((tab: any) => {
|
2017-10-12 04:02:01 +01:00
|
|
|
return tab.index === desiredIndex
|
2017-10-21 12:54:48 +02:00
|
|
|
})
|
2017-10-12 04:02:01 +01:00
|
|
|
tabSetActive(desiredTab.id)
|
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export function tabprev(increment = 1) {
|
|
|
|
tabnext(increment * -1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: address should default to some page to which we have access
|
|
|
|
// and focus the location bar
|
|
|
|
//#background
|
2017-10-24 17:40:00 +01:00
|
|
|
export async function tabopen(...addressarr: string[]) {
|
2017-10-23 09:42:50 +01:00
|
|
|
let uri
|
2017-11-09 15:30:09 +00:00
|
|
|
let address = addressarr.join(' ')
|
2017-10-24 17:40:00 +01:00
|
|
|
if (address != "") uri = forceURI(address)
|
2017-10-23 09:42:50 +01:00
|
|
|
browser.tabs.create({url: uri})
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function tabduplicate(id?: number){
|
2017-11-09 00:41:07 +00:00
|
|
|
id = id ? id : (await activeTabId())
|
2017-10-12 04:02:01 +01:00
|
|
|
browser.tabs.duplicate(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function tabdetach(id?: number){
|
2017-11-09 00:41:07 +00:00
|
|
|
id = id ? id : (await activeTabId())
|
2017-10-12 04:02:01 +01:00
|
|
|
browser.windows.create({tabId: id})
|
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function tabclose(ids?: number[] | number) {
|
|
|
|
if (ids !== undefined) {
|
|
|
|
browser.tabs.remove(ids)
|
|
|
|
} else {
|
|
|
|
// Close the current tab
|
2017-11-09 00:41:07 +00:00
|
|
|
browser.tabs.remove(await activeTabId())
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-21 12:54:48 +02:00
|
|
|
/** restore most recently closed tab in this window unless the most recently closed item was a window */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#background
|
|
|
|
export async function undo(){
|
2017-10-21 12:54:48 +02:00
|
|
|
const current_win_id : number = (await browser.windows.getCurrent()).id
|
|
|
|
const sessions = await browser.sessions.getRecentlyClosed()
|
|
|
|
|
|
|
|
// The first session object that's a window or a tab from this window. Or undefined if sessions is empty.
|
|
|
|
let closed = sessions.find((s) => {
|
2017-10-22 16:32:11 +01:00
|
|
|
return ('window' in s || s.tab && (s.tab.windowId == current_win_id))
|
2017-10-21 12:54:48 +02:00
|
|
|
})
|
|
|
|
if (closed) {
|
|
|
|
if (closed.tab) {
|
|
|
|
browser.sessions.restore(closed.tab.sessionId)
|
|
|
|
}
|
|
|
|
else if (closed.window) {
|
|
|
|
browser.sessions.restore(closed.window.sessionId)
|
|
|
|
}
|
|
|
|
}
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function tabmove(n?: string) {
|
|
|
|
let aTab = await activeTab(),
|
|
|
|
m: number
|
|
|
|
if (!n) {
|
|
|
|
browser.tabs.move(aTab.id, {index: -1})
|
|
|
|
return
|
|
|
|
} else if (n.startsWith("+") || n.startsWith("-")) {
|
|
|
|
m = Math.max(0, Number(n) + aTab.index)
|
|
|
|
} else m = Number(n)
|
|
|
|
browser.tabs.move(aTab.id, {index: m})
|
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function pin() {
|
|
|
|
let aTab = await activeTab()
|
|
|
|
browser.tabs.update(aTab.id, {pinned: !aTab.pinned})
|
|
|
|
}
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
|
|
|
// {{{ WINDOWS
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function winopen(...args: string[]) {
|
|
|
|
let address: string
|
|
|
|
const createData = {}
|
|
|
|
if (args[0] === "-private") {
|
|
|
|
createData["incognito"] = true
|
2017-11-09 15:30:09 +00:00
|
|
|
address = args.slice(1,args.length).join(' ')
|
|
|
|
} else address = args.join(' ')
|
2017-11-14 12:23:01 +00:00
|
|
|
createData["url"] = address != "" ? forceURI(address) : null
|
2017-10-12 04:02:01 +01:00
|
|
|
browser.windows.create(createData)
|
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function winclose() {
|
|
|
|
browser.windows.remove((await browser.windows.getCurrent()).id)
|
|
|
|
}
|
|
|
|
|
2017-11-02 19:36:44 +00:00
|
|
|
|
|
|
|
// It's unclear if this will leave a session that can be restored.
|
|
|
|
// We might have to do it ourselves.
|
|
|
|
//#background
|
|
|
|
export async function qall(){
|
|
|
|
let windows = await browser.windows.getAll()
|
|
|
|
windows.map((window) => browser.windows.remove(window.id))
|
|
|
|
}
|
|
|
|
|
2017-10-12 04:02:01 +01:00
|
|
|
// }}}
|
|
|
|
|
|
|
|
// {{{ MISC
|
|
|
|
|
2017-10-23 09:42:50 +01:00
|
|
|
//#background
|
|
|
|
export function suppress(preventDefault?: boolean, stopPropagation?: boolean) {
|
|
|
|
keydown.suppress(preventDefault, stopPropagation)
|
|
|
|
}
|
|
|
|
|
2017-10-12 04:02:01 +01:00
|
|
|
//#background
|
2017-11-09 00:41:07 +00:00
|
|
|
export function mode(mode: ModeName) {
|
2017-10-12 04:02:01 +01:00
|
|
|
state.mode = mode
|
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function getnexttabs(tabid: number, n?: number) {
|
|
|
|
const curIndex: number = (await browser.tabs.get(tabid)).index
|
|
|
|
const tabs: browser.tabs.Tab[] = await browser.tabs.query({
|
|
|
|
currentWindow: true,
|
|
|
|
})
|
|
|
|
const indexFilter = ((tab: browser.tabs.Tab) => {
|
|
|
|
return (
|
|
|
|
curIndex <= tab.index &&
|
|
|
|
(n ? tab.index < curIndex + Number(n) : true)
|
|
|
|
)
|
|
|
|
}).bind(n)
|
|
|
|
return tabs.filter(indexFilter).map((tab: browser.tabs.Tab) => {
|
|
|
|
return tab.id
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Moderately slow; should load in results as they arrive, perhaps
|
|
|
|
// Todo: allow jumping to buffers once they are found
|
|
|
|
// Consider adding to buffers with incremental search
|
|
|
|
// maybe only if no other results in URL etc?
|
|
|
|
// Find out how to return context of each result
|
|
|
|
//#background
|
|
|
|
/* export async function findintabs(query: string) { */
|
|
|
|
/* const tabs = await browser.tabs.query({currentWindow: true}) */
|
|
|
|
/* console.log(query) */
|
|
|
|
/* const findintab = async tab => */
|
|
|
|
/* await browser.find.find(query, {tabId: tab.id}) */
|
|
|
|
/* let results = [] */
|
|
|
|
/* for (let tab of tabs) { */
|
|
|
|
/* let result = await findintab(tab) */
|
|
|
|
/* if (result.count > 0) { */
|
|
|
|
/* results.push({tab, result}) */
|
|
|
|
/* } */
|
|
|
|
/* } */
|
|
|
|
/* results.sort(r => r.result.count) */
|
|
|
|
/* console.log(results) */
|
|
|
|
/* return results */
|
|
|
|
/* } */
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
|
|
|
// {{{ CMDLINE
|
|
|
|
|
|
|
|
// TODO: These two don't really make sense as excmds, they're internal things.
|
|
|
|
//#content
|
|
|
|
export function showcmdline() {
|
|
|
|
CommandLineContent.show()
|
2017-10-28 13:42:54 +01:00
|
|
|
CommandLineContent.focus()
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//#content
|
|
|
|
export function hidecmdline() {
|
|
|
|
CommandLineContent.hide()
|
2017-10-28 19:20:31 +08:00
|
|
|
CommandLineContent.blur()
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Set the current value of the commandline to string */
|
|
|
|
//#background
|
2017-10-24 12:51:04 +01:00
|
|
|
export function fillcmdline(...strarr: string[]) {
|
|
|
|
let str = strarr.join(" ")
|
2017-10-12 04:02:01 +01:00
|
|
|
showcmdline()
|
2017-10-28 05:11:10 +01:00
|
|
|
messageActiveTab("commandline_frame", "fillcmdline", [str])
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
2017-11-09 15:30:09 +00:00
|
|
|
//#background
|
|
|
|
export function fillcmdline_notrail(...strarr: string[]) {
|
|
|
|
let str = strarr.join(" ")
|
|
|
|
let trailspace = false
|
|
|
|
showcmdline()
|
|
|
|
messageActiveTab("commandline_frame", "fillcmdline", [str, trailspace])
|
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function current_url(...strarr: string[]){
|
2017-11-09 15:30:09 +00:00
|
|
|
fillcmdline_notrail(...strarr, (await activeTab()).url)
|
2017-11-09 15:30:09 +00:00
|
|
|
}
|
|
|
|
|
2017-10-28 19:20:31 +08:00
|
|
|
//#background
|
2017-11-04 17:30:34 +00:00
|
|
|
export async function clipboard(excmd = "open", content = ""){
|
2017-10-28 19:20:31 +08:00
|
|
|
switch (excmd) {
|
|
|
|
case 'yank':
|
2017-10-28 13:42:54 +01:00
|
|
|
await messageActiveTab("commandline_content", "focus")
|
2017-11-04 17:30:34 +00:00
|
|
|
content = (content == "") ? (await activeTab()).url : content
|
|
|
|
messageActiveTab("commandline_frame", "setClipboard", [content])
|
2017-10-28 19:20:31 +08:00
|
|
|
break
|
|
|
|
case 'open':
|
2017-10-28 13:42:54 +01:00
|
|
|
await messageActiveTab("commandline_content", "focus")
|
|
|
|
const url = await messageActiveTab("commandline_frame", "getClipboard")
|
2017-10-28 19:20:31 +08:00
|
|
|
// todo: some url format and security check?
|
2017-11-09 00:41:07 +00:00
|
|
|
url && browser.tabs.update(await activeTabId(), {url: url})
|
2017-10-28 19:20:31 +08:00
|
|
|
break
|
|
|
|
default:
|
|
|
|
// todo: maybe we should have some common error and error handler
|
|
|
|
throw new Error(`[clipboard] unknown excmd: ${excmd}`)
|
2017-10-19 20:15:01 +01:00
|
|
|
}
|
2017-10-28 19:20:31 +08:00
|
|
|
hidecmdline()
|
2017-10-19 20:15:01 +01:00
|
|
|
}
|
|
|
|
|
2017-10-12 04:02:01 +01:00
|
|
|
// {{{ Buffer/completion stuff
|
|
|
|
// TODO: Move autocompletions out of excmds.
|
|
|
|
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#background_helper
|
|
|
|
const DEFAULT_FAVICON = browser.extension.getURL("static/defaultFavicon.svg")
|
|
|
|
|
|
|
|
/** Buffer + autocompletions */
|
|
|
|
//#background
|
|
|
|
export async function openbuffer() {
|
|
|
|
fillcmdline("buffer")
|
2017-11-15 00:41:53 +00:00
|
|
|
messageActiveTab("commandline_frame", "changecompletions", [await l(listTabs())])
|
2017-10-28 20:16:15 +08:00
|
|
|
showcmdline()
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Change active tab */
|
|
|
|
//#background
|
|
|
|
export async function buffer(n?: number | string) {
|
|
|
|
if (!n || Number(n) == 0) return // Vimperator index starts at 1
|
|
|
|
if (n === "#") {
|
|
|
|
n =
|
|
|
|
(await browser.tabs.query({currentWindow: true})).sort((a, b) => {
|
|
|
|
return a.lastAccessed < b.lastAccessed ? 1 : -1
|
|
|
|
})[1].index + 1
|
|
|
|
}
|
2017-11-07 12:02:24 +00:00
|
|
|
if (Number.isInteger(Number(n))) {
|
|
|
|
tabSetActive(
|
|
|
|
(await browser.tabs.query({
|
|
|
|
currentWindow: true,
|
|
|
|
index: Number(n) - 1,
|
|
|
|
}))[0].id
|
|
|
|
)
|
|
|
|
// hacky search by url
|
|
|
|
} else {
|
|
|
|
let currtabs = await browser.tabs.query({currentWindow: true})
|
|
|
|
// todo: choose best match
|
|
|
|
tabSetActive(currtabs.filter((t)=> (t["url"].includes(String(n)) || t["title"].toLowerCase().includes(String(n).toLowerCase())))[0].id)
|
|
|
|
}
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** List of tabs in window and the last active tab. */
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#background_helper
|
|
|
|
async function getTabs() {
|
|
|
|
const tabs = await browser.tabs.query({currentWindow: true})
|
|
|
|
const lastActive = tabs.sort((a, b) => {
|
|
|
|
return a.lastAccessed < b.lastAccessed ? 1 : -1
|
|
|
|
})[1]
|
|
|
|
tabs.sort((a, b) => {
|
|
|
|
return a.index < b.index ? -1 : 1
|
|
|
|
})
|
|
|
|
console.log(tabs)
|
|
|
|
return [tabs, lastActive]
|
|
|
|
}
|
|
|
|
|
|
|
|
/** innerHTML for a single Tab's representation in autocompletion */
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#background_helper
|
|
|
|
function formatTab(tab: browser.tabs.Tab, prev?: boolean) {
|
2017-11-15 00:41:53 +00:00
|
|
|
// This, like all this completion logic, needs to move.
|
|
|
|
const tabline = window.document.createElement('div')
|
|
|
|
tabline.className = "tabline"
|
|
|
|
|
|
|
|
const prefix = window.document.createElement('span')
|
|
|
|
if (tab.active) prefix.textContent += "%"
|
|
|
|
else if (prev) prefix.textContent += "#"
|
|
|
|
if (tab.pinned) prefix.textContent += "@"
|
|
|
|
prefix.textContent = prefix.textContent.padEnd(2)
|
|
|
|
tabline.appendChild(prefix)
|
|
|
|
|
2017-10-22 11:08:43 +01:00
|
|
|
// TODO: Dynamically set favicon dimensions. Should be able to use em.
|
2017-11-15 00:41:53 +00:00
|
|
|
const favicon = window.document.createElement('img')
|
|
|
|
favicon.src = tab.favIconUrl ? tab.favIconUrl : DEFAULT_FAVICON
|
|
|
|
tabline.appendChild(favicon)
|
|
|
|
|
|
|
|
const titlespan = window.document.createElement('span')
|
|
|
|
titlespan.textContent=`${tab.index + 1}: ${tab.title}`
|
|
|
|
tabline.appendChild(titlespan)
|
|
|
|
|
|
|
|
const url = window.document.createElement('a')
|
|
|
|
url.className = 'url'
|
|
|
|
url.href = tab.url
|
|
|
|
url.text = tab.url
|
|
|
|
url.target = '_blank'
|
|
|
|
tabline.appendChild(url)
|
|
|
|
|
|
|
|
console.log(tabline)
|
|
|
|
return tabline.outerHTML
|
2017-10-12 04:02:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** innerHTML for tab autocompletion div */
|
2017-11-03 19:10:12 +00:00
|
|
|
/** @hidden */
|
2017-10-12 04:02:01 +01:00
|
|
|
//#background_helper
|
|
|
|
async function listTabs() {
|
|
|
|
let buffers: string = "",
|
|
|
|
[tabs, lastActive] = await getTabs()
|
|
|
|
for (let tab of tabs as Array<browser.tabs.Tab>) {
|
|
|
|
buffers += tab === lastActive ? formatTab(tab, true) : formatTab(tab)
|
|
|
|
}
|
|
|
|
return buffers
|
|
|
|
}
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
|
|
|
// }}}
|
2017-11-05 14:10:11 +00:00
|
|
|
|
2017-11-09 00:41:07 +00:00
|
|
|
// {{{ SETTINGS
|
|
|
|
|
2017-11-05 14:10:11 +00:00
|
|
|
//#background
|
2017-11-09 12:13:08 +00:00
|
|
|
export async function bind(key: string, ...bindarr: string[]){
|
|
|
|
let exstring = bindarr.join(" ")
|
2017-11-05 14:10:11 +00:00
|
|
|
let nmaps = (await browser.storage.sync.get("nmaps"))["nmaps"]
|
|
|
|
nmaps = (nmaps == undefined) ? {} : nmaps
|
|
|
|
nmaps[key] = exstring
|
|
|
|
browser.storage.sync.set({nmaps})
|
|
|
|
}
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export async function unbind(key: string){
|
|
|
|
bind(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Currently, only resets key to default after extension is reloaded */
|
|
|
|
//#background
|
|
|
|
export async function reset(key: string){
|
|
|
|
bind(key)
|
|
|
|
let nmaps = (await browser.storage.sync.get("nmaps"))["nmaps"]
|
|
|
|
nmaps = (nmaps == undefined) ? {} : nmaps
|
|
|
|
delete nmaps[key]
|
|
|
|
browser.storage.sync.set({nmaps})
|
|
|
|
}
|
|
|
|
|
2017-11-09 00:41:07 +00:00
|
|
|
// }}}
|
|
|
|
|
|
|
|
// {{{ HINTMODE
|
|
|
|
|
|
|
|
//#background_helper
|
|
|
|
import {hintPageSimple} from './hinting_background'
|
|
|
|
|
|
|
|
//#background
|
|
|
|
export function hint() {
|
|
|
|
hintPageSimple()
|
|
|
|
mode('hint')
|
|
|
|
}
|
|
|
|
|
2017-11-15 00:03:34 +00:00
|
|
|
|
2017-11-09 00:41:07 +00:00
|
|
|
// }}}
|
|
|
|
|
2017-11-05 14:10:11 +00:00
|
|
|
|
2017-10-21 12:54:15 +02:00
|
|
|
// vim: tabstop=4 shiftwidth=4 expandtab
|