From e721f625c8871cc015e05fd77b8fe4065d4ec7c1 Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Thu, 19 Apr 2018 11:22:33 +0100 Subject: [PATCH 01/15] release 1.9.3 --- doc/changelog.md | 7 +++++++ src/manifest.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/changelog.md b/doc/changelog.md index eba6baa8..b47aaff6 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,5 +1,12 @@ # Tridactyl changelogs +## Release 1.9.3 + +- Fix unbind issues +- Add more default binds from Vimperator +- Change the `^` bind to `` (matches vim) +- :bmark now supports folders + ## Release 1.9.2 - Fix #392 (bug with keyseq) diff --git a/src/manifest.json b/src/manifest.json index 3260da8b..9db2fa4c 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Tridactyl", - "version": "1.9.2", + "version": "1.9.3", "icons": { "64": "static/logo/Tridactyl_64px.png", "100": "static/logo/Tridactyl_100px.png", From 5ef46f194e7af76f3cd95709e7203f1572b5a539 Mon Sep 17 00:00:00 2001 From: Oliver Blanthorn Date: Thu, 19 Apr 2018 12:16:34 +0100 Subject: [PATCH 02/15] Add changelogs to new tab page. --- scripts/newtab.md.sh | 23 ++++++++++++++++++++--- src/static/newtab.css | 41 +++++++++++++++++++++++++++++++++++++++++ src/static/newtab.md | 3 +++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/scripts/newtab.md.sh b/scripts/newtab.md.sh index 6464909e..02123c71 100755 --- a/scripts/newtab.md.sh +++ b/scripts/newtab.md.sh @@ -5,7 +5,24 @@ cd src/static newtab="../../generated/static/newtab.html" +newtabtemp="../../generated/static/newtab.temp.html" -sed "/REPLACETHIS/,$ d" newtab.template.html > "$newtab" -marked newtab.md >> "$newtab" -sed "1,/REPLACETHIS/ d" newtab.template.html >> "$newtab" +sed "/REPLACETHIS/,$ d" newtab.template.html > "$newtabtemp" +marked newtab.md >> "$newtabtemp" +sed "1,/REPLACETHIS/ d" newtab.template.html >> "$newtabtemp" + +# Why think when you can pattern match? + +sed "/REPLACE_ME_WITH_THE_CHANGE_LOG_USING_SED/,$ d" "$newtabtemp" > "$newtab" +echo """ + + +
+""" >> "$newtab" +marked ../../doc/changelog.md >> "$newtab" +echo """ +
+""" >> "$newtab" +sed "1,/REPLACE_ME_WITH_THE_CHANGE_LOG_USING_SED/ d" "$newtabtemp" >> "$newtab" + +rm "$newtabtemp" diff --git a/src/static/newtab.css b/src/static/newtab.css index d49cc7dc..2bb06a64 100644 --- a/src/static/newtab.css +++ b/src/static/newtab.css @@ -6,6 +6,47 @@ body { margin: auto; } +input[id^="spoiler"]{ + display: none; +} + +/* Borrowed from https://codepen.io/oloman/pen/odnqy */ +input[id^="spoiler"] + label { + display: block; + width: 8em; + margin: 0 auto; + padding: 0.25em, 0.25em; + background: #1f9947; + color: #fff; + text-align: center; + font-size: 12pt; + border-radius: 2px; + cursor: pointer; + transition: all .6s; +} +input[id^="spoiler"]:checked + label { + color: #333; + background: #ccc; +} +input[id^="spoiler"] ~ .spoiler { + width: 90%; + height: 0; + overflow: hidden; + opacity: 0; + margin: 10px auto 0; + padding: 10px; + background: #eee; + border: 1px solid #ccc; + border-radius: 2px; + transition: all .6s; +} +input[id^="spoiler"]:checked + label + .spoiler{ + height: auto; + opacity: 1; + padding: 10px; +} + + h1 { padding-top: 1em; } diff --git a/src/static/newtab.md b/src/static/newtab.md index 2aa6263d..989c466e 100644 --- a/src/static/newtab.md +++ b/src/static/newtab.md @@ -12,6 +12,9 @@ Tridactyl has to override your new tab page due to WebExtension limitations. You - If you're enjoying Tridactyl (or not), please leave a review on [addons.mozilla.org][amo]. + +REPLACE_ME_WITH_THE_CHANGE_LOG_USING_SED + ## Highlighted features: - `f`/`F` — enter the "hint mode" to select a link to follow. `F` to open it in a background tab. From bd7b5f0bdc587ea8bf0fe0543efbcbc0903d07bc Mon Sep 17 00:00:00 2001 From: Oliver Blanthorn Date: Thu, 19 Apr 2018 12:19:10 +0100 Subject: [PATCH 03/15] Remove welcome to new users as we have `tutor` for that now --- src/static/newtab.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/newtab.md b/src/static/newtab.md index 989c466e..2d215484 100644 --- a/src/static/newtab.md +++ b/src/static/newtab.md @@ -2,7 +2,7 @@ # Tridactyl REPLACE_ME_WITH_THE_VERSION_USING_SED -Tridactyl has to override your new tab page due to WebExtension limitations. You can learn how to change it at the bottom of the page, otherwise please read on for some tips and tricks. (If you've just installed Tridactyl for the first time and are seeing this page, hello! Welcome! You'll probably be seeing this page a lot until you figure out how to disable it or uninstall the addon). +Tridactyl has to override your new tab page due to WebExtension limitations. You can learn how to change it at the bottom of the page, otherwise please read on for some tips and tricks. - You can view the main help page by typing [`:help`][help], and access the tutorial with [`:tutor`][tutor]. From 3dee8a453be2fc1a1a7e575a48f9a0b452056d25 Mon Sep 17 00:00:00 2001 From: Oliver Blanthorn Date: Thu, 19 Apr 2018 12:27:20 +0100 Subject: [PATCH 04/15] Warn users about native messenger update This commit should be reverted once the native messenger has been released. --- src/static/newtab.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/static/newtab.md b/src/static/newtab.md index 2d215484..249b4956 100644 --- a/src/static/newtab.md +++ b/src/static/newtab.md @@ -12,6 +12,8 @@ Tridactyl has to override your new tab page due to WebExtension limitations. You - If you're enjoying Tridactyl (or not), please leave a review on [addons.mozilla.org][amo]. +- **NB:** Tridactyl will soon support a native messenger. When this version is released, Firefox **will not update to it** unless you click the menu in the top right and allow it to update. A small yellow exclamation mark will appear on the menu's icon to notify you of this fact; please keep an eye out for it over the next week or so. + REPLACE_ME_WITH_THE_CHANGE_LOG_USING_SED From ec51fbba8843fd7077b642dc9058e67da8f307fd Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Thu, 19 Apr 2018 15:21:56 +0100 Subject: [PATCH 05/15] Fix newtab redirection Broken by hijack code. I've just assumed any page we load content.ts on manually doesn't need hijacking. Other solutions are available. --- src/content.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/content.ts b/src/content.ts index 8a411024..61bef721 100644 --- a/src/content.ts +++ b/src/content.ts @@ -47,8 +47,11 @@ import * as keyseq from "./keyseq" l: prom => prom.then(console.log).catch(console.error), }) -dom.setupFocusHandler() -dom.hijackPageListenerFunctions() +// Don't hijack on the newtab page. +if ("exportFunction" in window) { + dom.setupFocusHandler() + dom.hijackPageListenerFunctions() +} if ( window.location.protocol === "moz-extension:" && From a11d7704a80cfd5dffeefb1794750e4f91ccc20e Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Thu, 19 Apr 2018 16:35:10 +0100 Subject: [PATCH 06/15] Special case 'about:blank' and '' in :open --- src/excmds.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/excmds.ts b/src/excmds.ts index 47e59cb0..33a8d8a0 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -87,7 +87,7 @@ // Shared import * as Messaging from "./messaging" -import { l } from "./lib/webext" +import { l, browserBg, activeTabId } from "./lib/webext" import state from "./state" import * as UrlUtil from "./url_util" import * as config from "./config" @@ -114,7 +114,7 @@ import { flatten } from "./itertools" import "./number.mod" import { ModeName } from "./state" import * as keydown from "./keydown_background" -import { activeTab, activeTabId, firefoxVersionAtLeast, openInNewTab } from "./lib/webext" +import { activeTab, firefoxVersionAtLeast, openInNewTab } from "./lib/webext" import * as CommandLineBackground from "./commandline_background" /** @hidden */ @@ -375,10 +375,16 @@ export async function reloadhard(n = 1) { "searchengine": "google" or any of [[SEARCH_URLS]] */ //#content -export function open(...urlarr: string[]) { +export async function open(...urlarr: string[]) { let url = urlarr.join(" ") - if (url === "") url = config.get("newtab") || browser.extension.getURL("static/newtab.html") - window.location.href = forceURI(url) + + // Setting window.location to about:blank results in a page we can't access, tabs.update works. + // tabs.update goes to the new tab page if url === "". + if (["", "about:blank"].includes(url)) { + browserBg.tabs.update(await activeTabId(), { url }) + } else { + window.location.href = forceURI(url) + } } /** @hidden */ From 07b0a20923c4af40be048f61d6dc03c6163ecc44 Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Thu, 19 Apr 2018 16:33:17 +0100 Subject: [PATCH 07/15] Simplify newtab redirect code --- src/content.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/content.ts b/src/content.ts index 61bef721..e7e7a5bc 100644 --- a/src/content.ts +++ b/src/content.ts @@ -57,8 +57,5 @@ if ( window.location.protocol === "moz-extension:" && window.location.pathname === "/static/newtab.html" ) { - ;(window as any).tri.config.getAsync("newtab").then(newtab => { - if (newtab !== "") - window.location.href = (window as any).tri.excmds.forceURI(newtab) - }) + config.getAsync("newtab").then(newtab => newtab && excmds.open(newtab)) } From 4c7efaaef540895bdd8b9035eb5dd120ab63d3e1 Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Thu, 19 Apr 2018 17:35:05 +0100 Subject: [PATCH 08/15] Stop treating "std::map" or "Error: foo" as URIs. Forbid unusual URIs in :open, etc. Fix #352. ``` If the uri looks like it might contain a schema and a domain, try url() test for a non-whitespace, non-colon character after the colon to avoid false positives like "error: can't reticulate spline" and "std::map". These heuristics mean that very unusual URIs will be coerced to something else by this function. if (/^[a-zA-Z0-9+.-]+:[^\s:]/.test(maybeURI)) { ``` --- src/excmds.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/excmds.ts b/src/excmds.ts index 33a8d8a0..8ba103fc 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -137,15 +137,24 @@ function searchURL(provider: string, query: string) { return UrlUtil.interpolateSearchItem(new URL(searchurlprovider), query) } -/** If maybeURI doesn't have a schema, affix http:// */ +/** Take a string and find a way to interpret it as a URI or search query. */ /** @hidden */ export function forceURI(maybeURI: string): string { // Need undefined to be able to open about:newtab if (maybeURI == "") return undefined - try { - return new URL(maybeURI).href - } catch (e) { - if (e.name !== "TypeError") throw e + + // If the uri looks like it might contain a schema and a domain, try url() + // test for a non-whitespace, non-colon character after the colon to avoid + // false positives like "error: can't reticulate spline" and "std::map". + // + // These heuristics mean that very unusual URIs will be coerced to + // something else by this function. + if (/^[a-zA-Z0-9+.-]+:[^\s:]/.test(maybeURI)) { + try { + return new URL(maybeURI).href + } catch (e) { + if (e.name !== "TypeError") throw e + } } // Else if search keyword: From 8ee9db1360112c94d148b33dfbfb9cfaafd4762a Mon Sep 17 00:00:00 2001 From: Colin Caine Date: Fri, 20 Apr 2018 13:59:52 +0100 Subject: [PATCH 09/15] Fix exportFunction detection --- src/content.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/content.ts b/src/content.ts index e7e7a5bc..18f81c53 100644 --- a/src/content.ts +++ b/src/content.ts @@ -48,9 +48,11 @@ import * as keyseq from "./keyseq" }) // Don't hijack on the newtab page. -if ("exportFunction" in window) { +if (webext.inContentScript()) { dom.setupFocusHandler() dom.hijackPageListenerFunctions() +} else { + console.error("No export func") } if ( From 4e77b65123a80e82bdf98f62e683a1b15dc68b8c Mon Sep 17 00:00:00 2001 From: Oliver Blanthorn Date: Fri, 20 Apr 2018 12:24:15 +0100 Subject: [PATCH 10/15] Add jumplist for inputs bound to `g;` Currently repeated use of `g;` will only take you to the most recently used input. Cycling through recently used inputs is a WIP. --- src/config.ts | 1 + src/dom.ts | 31 +++++++++++++++++++++---------- src/excmds.ts | 35 +++++++++++++++++++++++++++++++++++ src/state.ts | 7 +++++++ 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/config.ts b/src/config.ts index 3cb8aa1c..d0d57576 100644 --- a/src/config.ts +++ b/src/config.ts @@ -79,6 +79,7 @@ const DEFAULTS = o({ r: "reload", R: "reloadhard", gi: "focusinput -l", + "g;": "changelistjump -1", gt: "tabnext_gt", gT: "tabprev", // "": "tabnext_gt", // c-n is reserved for new window diff --git a/src/dom.ts b/src/dom.ts index 6de54202..eaac5ceb 100644 --- a/src/dom.ts +++ b/src/dom.ts @@ -1,6 +1,8 @@ import { MsgSafeNode } from "./msgsafe" import * as config from "./config" import { flatten } from "./itertools" +import state from "./state" +import { activeTabId } from "./lib/webext" // From saka-key lib/dom.js, under Apachev2 @@ -432,8 +434,8 @@ export function focus(e: HTMLElement): void { //#content_helper let LAST_USED_INPUT: HTMLElement = null -export function getLastUsedInput () { - return LAST_USED_INPUT +export function getLastUsedInput() { + return LAST_USED_INPUT } /** WARNING: This function can potentially recieve malicious input! For the @@ -447,17 +449,24 @@ export function getLastUsedInput () { function onPageFocus(elem: HTMLElement, args: any[]): void { if (isTextEditable(elem)) { LAST_USED_INPUT = elem - config.getAsync("allowautofocus").then((allow) => { - if (allow === "true") - elem.focus(args) - }); + config.getAsync("allowautofocus").then(allow => { + if (allow === "true") elem.focus(args) + }) } } +async function setInput(el) { + let tab = await activeTabId() + console.log(tab) + // store maximum of 10 elements to stop this getting bonkers huge + const arr = state.prevInputs.concat({ tab, inputId: el.id }) + state.prevInputs = arr.slice(Math.max(arr.length - 10, 0)) +} + /** Replaces the page's HTMLElement.prototype.focus with our own, onPageFocus */ function hijackPageFocusFunction(): void { - let exportedName = "onPageFocus"; - exportFunction(onPageFocus, window, {defineAs: exportedName}) + let exportedName = "onPageFocus" + exportFunction(onPageFocus, window, { defineAs: exportedName }) let eval_str = `HTMLElement.prototype.focus = ((realFocus, ${exportedName}) => { return function (...args) { @@ -465,14 +474,16 @@ function hijackPageFocusFunction(): void { } })(HTMLElement.prototype.focus, ${exportedName})` - window.eval(eval_str + `;delete ${exportedName}`) + window.eval(eval_str + `;delete ${exportedName}`) } export function setupFocusHandler(): void { // Handles when a user selects an input document.addEventListener("focusin", e => { - if (isTextEditable(e.target as HTMLElement)) + if (isTextEditable(e.target as HTMLElement)) { LAST_USED_INPUT = e.target as HTMLElement + setInput(e.target as HTMLInputElement) + } }) // Handles when the page tries to select an input hijackPageFocusFunction() diff --git a/src/excmds.ts b/src/excmds.ts index 8ba103fc..0d43a81e 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -852,6 +852,41 @@ export function focusinput(nth: number | string) { } } +/** + * Focus the tab which contains the last focussed input element. If you're lucky, it will focus the right input, too. + * + * Currently just goes to the last focussed input; being able to jump forwards and backwards is planned. + */ +//#background +export async function changelistjump(n?: number) { + let tail = state.prevInputs[state.prevInputs.length - 1] + let jumppos = tail.jumppos ? tail.jumppos : state.prevInputs.length - 1 + const input = state.prevInputs[jumppos] + await browser.tabs.update(input.tab, { active: true }) + const id = input.inputId + // Not all elements have an ID, so this will do for now. + if (id) focusbyid(input.inputId) + else focusinput("-l") + + // Really want to bin the input we just focussed ^ and edit the real last input to tell us where to jump to next. + // It doesn't work in practice as the focus events get added after we try to delete them. + // Even editing focusbyid/focusinput doesn't work to try to delete their own history doesn't work. + // I'm bored of working on it for now, though. + // Probable solution: add an event listener to state.prevInputs changing, delete the focussed element, then delete event listener. + // + // let arr = state.prevInputs + // arr.splice(-2,2) + + // tail.jumppos = jumppos - 1 + // arr = arr.concat(tail) + // state.prevInputs = arr +} + +//#content +export function focusbyid(id: string) { + document.getElementById(id).focus() +} + // }}} // {{{ TABS diff --git a/src/state.ts b/src/state.ts index 2de687f2..6174b19a 100644 --- a/src/state.ts +++ b/src/state.ts @@ -28,6 +28,13 @@ export type ModeName = class State { mode: ModeName = "normal" cmdHistory: string[] = [] + prevInputs: { inputId: string; tab: number; jumppos?: number }[] = [ + { + inputId: undefined, + tab: undefined, + jumppos: undefined, + }, + ] last_ex_str: string = "" } From bcbbbe6607b9c22a135839ccba5140926aa69a63 Mon Sep 17 00:00:00 2001 From: Oliver Blanthorn Date: Fri, 20 Apr 2018 17:15:55 +0100 Subject: [PATCH 11/15] Remove errant log. --- src/dom.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dom.ts b/src/dom.ts index eaac5ceb..e06866f6 100644 --- a/src/dom.ts +++ b/src/dom.ts @@ -457,7 +457,6 @@ function onPageFocus(elem: HTMLElement, args: any[]): void { async function setInput(el) { let tab = await activeTabId() - console.log(tab) // store maximum of 10 elements to stop this getting bonkers huge const arr = state.prevInputs.concat({ tab, inputId: el.id }) state.prevInputs = arr.slice(Math.max(arr.length - 10, 0)) From 027371029c8913f087bd7061bb14e91b08715ce6 Mon Sep 17 00:00:00 2001 From: Oliver Blanthorn Date: Fri, 20 Apr 2018 17:25:10 +0100 Subject: [PATCH 12/15] Fix annoying inputmode bug --- src/controller.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/controller.ts b/src/controller.ts index e2a9cc56..0d334b84 100644 --- a/src/controller.ts +++ b/src/controller.ts @@ -41,14 +41,13 @@ function* ParserController() { if ( state.mode != "ignore" && state.mode != "hint" && - state.mode != "input" && state.mode != "find" ) { if (isTextEditable(keyevent.target)) { if (state.mode !== "insert") { state.mode = "insert" } - } else if (state.mode === "insert") { + } else if (["insert", "input"].includes(state.mode)) { state.mode = "normal" } } From 0ee2b4085392542d08834914e9b71e735bb369a9 Mon Sep 17 00:00:00 2001 From: Oliver Blanthorn Date: Fri, 20 Apr 2018 19:32:09 +0100 Subject: [PATCH 13/15] Add `hint -W [exstr]` to execute exstr on hint's href --- src/config.ts | 1 + src/excmds.ts | 6 +++++- src/hinting.ts | 11 +++++++++++ src/hinting_background.ts | 6 ++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index d0d57576..195ad9bf 100644 --- a/src/config.ts +++ b/src/config.ts @@ -156,6 +156,7 @@ const DEFAULTS = o({ bdelete: "tabclose", sanitize: "sanitise", tutorial: "tutor", + openwith: "hint -W", }), followpagepatterns: o({ next: "^(next|newer)\\b|»|>>|more", diff --git a/src/excmds.ts b/src/excmds.ts index 0d43a81e..4a8af5ce 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -121,6 +121,8 @@ import * as CommandLineBackground from "./commandline_background" export const cmd_params = new Map>() // } +// }}} + /** @hidden */ function hasScheme(uri: string) { return uri.match(/^([\w-]+):/) @@ -1845,6 +1847,7 @@ import * as hinting from "./hinting_background" - `bind ;c hint -c [class*="expand"],[class="togg"]` works particularly well on reddit and HN - -w open in new window -wp open in new private window + - `-W excmd...` append hint href to excmd and execute, e.g, `hint -W open` and other such bad ideas. Excepting the custom selector mode and background hint mode, each of these hint modes is available by default as `;