glide: Extract tridactyl-style keymaps to separate file
Vim-style navigation bindings were cluttering the main config.
Separate file makes it easier to toggle or share these bindings.
Also adds ZZ to stash all tabs as bookmarks before quitting.
Assisted-by: Claude Opus 4.5 via Claude Code
diff --git a/.config/glide/glide.ts b/.config/glide/glide.ts
index 082f9cb4..40295596 100644
--- a/.config/glide/glide.ts
+++ b/.config/glide/glide.ts
@@ -17,6 +17,10 @@
// Try typing `glide.` and see what you can do!
glide.unstable.include("hints.glide.ts");
+glide.unstable.include("tridactyl.glide.ts");
+
+glide.g.mapleader = "," // too used to using space for scrolling
+glide.buf.keymaps.del("normal", "s"); // use `s` for searching
glide.styles.add(`
.yank-notification {
@@ -38,42 +42,6 @@ glide.styles.add(`
}
`);
-glide.keymaps.set("normal", "zi", async ({ tab_id }) => {
- const zoom = await browser.tabs.getZoom(tab_id);
- await browser.tabs.setZoom(tab_id, zoom + 0.1);
-});
-
-glide.keymaps.set("normal", "zo", async ({ tab_id }) => {
- const zoom = await browser.tabs.getZoom(tab_id);
- await browser.tabs.setZoom(tab_id, zoom - 0.1);
-});
-
-glide.keymaps.set("normal", "zz", async ({ tab_id }) => {
- await browser.tabs.setZoom(tab_id, 1);
-});
-
-glide.keymaps.set("normal", "u", async () => {
- const sessions = await browser.sessions.getRecentlyClosed({ maxResults: 1 });
- const [session, ..._] = sessions;
- if (session) {
- await browser.sessions.restore(session.tab?.sessionId ?? session.window?.sessionId);
- }
-});
-
-glide.keymaps.set("normal", "H", "back");
-glide.keymaps.set("normal", "L", "forward");
-glide.keymaps.set("normal", "d", "tab_close");
-
-glide.keymaps.set("normal", "p", async ({ tab_id }) => {
- const url = await navigator.clipboard.readText();
- await browser.tabs.update(tab_id, { url });
-});
-
-glide.keymaps.set("normal", "P", async () => {
- const url = await navigator.clipboard.readText();
- await browser.tabs.create({ url });
-});
-
glide.keymaps.set("normal", "yy", async () => {
const url = glide.ctx.url;
await navigator.clipboard.writeText(url.toString());
@@ -87,3 +55,39 @@ glide.keymaps.set("normal", "yy", async () => {
setTimeout(() => notification.remove(), 2000);
});
+glide.keymaps.set("normal", "ZZ", async () => {
+ const tabs = await browser.tabs.query({});
+
+ const bookmarkTree = await browser.bookmarks.getTree();
+ const toolbarFolder = bookmarkTree[0]?.children?.find(
+ (child) => child.id === "toolbar_____" || child.title === "Bookmarks Toolbar"
+ );
+
+ if (toolbarFolder) {
+ let stashesFolder = toolbarFolder.children?.find((child) => child.title === "stashes");
+ if (!stashesFolder) {
+ stashesFolder = await browser.bookmarks.create({
+ parentId: toolbarFolder.id,
+ title: "stashes",
+ });
+ }
+
+ const timestamp = new Date().toISOString().slice(0, 19).replace("T", " ");
+ const stashFolder = await browser.bookmarks.create({
+ parentId: stashesFolder.id,
+ title: timestamp,
+ });
+
+ for (const tab of tabs) {
+ if (tab.url && !tab.url.startsWith("about:")) {
+ await browser.bookmarks.create({
+ parentId: stashFolder.id,
+ title: tab.title || tab.url,
+ url: tab.url,
+ });
+ }
+ }
+ }
+
+ await glide.excmds.execute("quit");
+});
diff --git a/.config/glide/hints.glide.ts b/.config/glide/hints.glide.ts
index 3c0f18cd..309018ba 100644
--- a/.config/glide/hints.glide.ts
+++ b/.config/glide/hints.glide.ts
@@ -1,6 +1,6 @@
// Source: https://github.com/jyn514/dotfiles/blob/master/config/glide.ts
-function shorten_unique_prefixes(haystack) {
+function shorten_unique_prefixes(haystack: string[]): string[] {
// first, construct a set of duplicates
const seen = new Set();
const duplicates = new Set();
@@ -28,12 +28,12 @@ function shorten_unique_prefixes(haystack) {
});
}
-function strip(text) {
+function strip(text: string): string {
// strip numbers, non-ascii text, and annoying-to-type characters
return text.replace(/[0-9]+/g, '').replace(/[^a-zA-Z0-9-]/g, '').toLowerCase();
}
-function labels(texts) {
+function labels(texts: string[]) {
// now shorten as much as we can without losing info
const haystack = shorten_unique_prefixes(texts);
@@ -51,7 +51,7 @@ function labels(texts) {
const base = prefix.substring(0, 2);
// try each character after the 3rd in turn.
// consider the original text, not the shortened prefix.
- for (const c of texts[index].substring(2)) {
+ for (const c of texts[index]!.substring(2)) {
const candidate = base + c;
if (!used.has(candidate)) {
result[index] = candidate;
@@ -73,7 +73,7 @@ function labels(texts) {
}
glide.o.hint_label_generator = async ({ content }) => {
- const texts = await content.map(element => [element.textContent, element.ariaLabel]);
- const haystack = texts.map(([text, label]) => strip(text) || strip(label || ""));
+ const texts: [string, string | null][] = await content.map(element => [element.textContent, element.ariaLabel]);
+ const haystack: string[] = texts.map(([text, label]) => strip(text) || strip(label || ""));
return labels(haystack);
};
diff --git a/.config/glide/tridactyl.glide.ts b/.config/glide/tridactyl.glide.ts
new file mode 100644
index 00000000..f7b6fdd7
--- /dev/null
+++ b/.config/glide/tridactyl.glide.ts
@@ -0,0 +1,45 @@
+/* navigation */
+
+// `gi` doesn't focus if no element has previously been focused
+glide.keymaps.set("normal", "gi", "keys gI");
+
+type ZoomFn = (zoom: number) => number;
+type KeymapHandler = (ctx: { tab_id: number }) => Promise<void>;
+
+const setZoom = (fn: ZoomFn): KeymapHandler => async ({ tab_id }) => {
+ const zoom = await browser.tabs.getZoom(tab_id);
+ await browser.tabs.setZoom(tab_id, fn(zoom));
+};
+
+glide.keymaps.set("normal", "zi", setZoom((z) => z + 0.1));
+glide.keymaps.set("normal", "zo", setZoom((z) => z - 0.1));
+glide.keymaps.set("normal", "zz", setZoom(() => 1));
+
+/* new pages */
+
+glide.keymaps.set("normal", "p", async ({ tab_id }) => {
+ const url = await navigator.clipboard.readText();
+ await browser.tabs.update(tab_id, { url });
+});
+
+glide.keymaps.set("normal", "P", async () => {
+ const url = await navigator.clipboard.readText();
+ await browser.tabs.create({ url });
+});
+
+glide.keymaps.set("normal", "H", "back");
+glide.keymaps.set("normal", "L", "forward");
+
+/* tab handling */
+
+glide.keymaps.set("normal", "d", "tab_close");
+
+glide.keymaps.set("normal", "u", async () => {
+ const sessions = await browser.sessions.getRecentlyClosed({ maxResults: 1 });
+ const [session, ..._] = sessions;
+ if (session) {
+ await browser.sessions.restore(session.tab?.sessionId ?? session.window?.sessionId);
+ }
+});
+
+