diff options
| -rw-r--r-- | glide/.config/glide/glide.ts | 391 | ||||
| -rw-r--r-- | glide/.config/glide/sitesearch.glide.ts | 147 | ||||
| -rw-r--r-- | glide/.config/glide/tabbar.glide.ts | 256 | ||||
| -rw-r--r-- | oni/home/config/common.scm | 11 | ||||
| -rw-r--r-- | oni/home/config/data.scm | 1 | ||||
| -rw-r--r-- | oni/home/config/pop-os.scm | 148 | ||||
| -rw-r--r-- | oni/home/config/pop-os/emacs.el | 111 | ||||
| -rw-r--r-- | oni/home/services/emacs/org-mem.el | 6 | ||||
| -rw-r--r-- | oni/packages/emacs-config.scm | 39 | ||||
| -rw-r--r-- | oni/packages/emacs.scm | 24 | ||||
| -rw-r--r-- | wezterm/.config/wezterm/wezterm.lua | 7 |
11 files changed, 648 insertions, 493 deletions
diff --git a/glide/.config/glide/glide.ts b/glide/.config/glide/glide.ts index 5baeac2..49c66de 100644 --- a/glide/.config/glide/glide.ts +++ b/glide/.config/glide/glide.ts @@ -90,10 +90,14 @@ const keyboard_quit = glide.excmds.create({ glide.findbar.close(); } + if (glide.commandline.is_active()) { + glide.commandline.close(); + } + glide.excmds.execute('mode_change normal'); }); -glide.keymaps.set('insert', '<C-g>', 'keyboard_quit'); +glide.keymaps.set(['insert', 'command', 'normal'], '<C-g>', 'keyboard_quit'); // Search const search_next = glide.excmds.create({ @@ -128,7 +132,8 @@ glide.keymaps.set('insert', '<C-s>', 'search_next'); glide.keymaps.set('insert', '<C-r>', 'search_prev'); async function installPuntAddons() { - await glide.addons.install("https://addons.mozilla.org/firefox/downloads/file/4677239/1password_x_password_manager-8.12.1.3.xpi"); + await glide.addons.install("https://addons.mozilla.org/firefox/downloads/file/4677239/1password_x_password_manager-8.12.1.3.xpi"); + await glide.addons.install('https://addons.mozilla.org/firefox/downloads/file/4508409/vue_js_devtools-7.7.7.xpi'); } async function installPersonalAddons() { @@ -265,137 +270,6 @@ glide.keymaps.set("normal", "gh", async () => { }); }, { description: "Jump to heading in current page" }); -// From https://github.com/glide-browser/glide/discussions/147#discussioncomment-15337351 - -/** - * custom search providers - */ -const search_info: Record<string, { url: string, sep: string }> = { - 'youtube': { - url: "https://www.youtube.com/results?search_query=", sep: "+" - } -} as const - -/* -* pick tabs via a selection of bookmarks and history -*/ - -glide.keymaps.set("normal", "<leader>t", async () => { - - //let combined: Array<Browser.Bookmarks.BookmarkTreeNode | Browser.History.HistoryItem> = [] - let combined = [] - const bookmarks = await browser.bookmarks.getRecent(20); - bookmarks.forEach(bmark => combined.push({ title: bmark.title, url: bmark.url, type: 'B' })); - - const history = await browser.history.search({ text: "", maxResults: 100 }); - history.forEach(entry => combined.push({ title: entry.title, url: entry.url, type: 'H' })); - - const tabs = await browser.tabs.query({}); - tabs.forEach(entry => combined.push({ title: entry.title ?? 'Unnamed Tab', url: entry.url, type: 'T' })); - - // filtering - const newtab = (await browser.runtime.getManifest()).chrome_url_overrides?.newtab - const startpage = glide.prefs.get("browser.startup.homepage") - - let filtered_combined = combined.filter(e => e.url !== startpage && e.url !== newtab) - - glide.commandline.show({ - title: "open", - options: filtered_combined.map((entry) => ({ - label: entry.title, - render() { - return DOM.create_element("div", { - style: { - display: "flex", - alignItems: "center", - gap: "8px", - }, - children: [ - DOM.create_element("span", [entry.type], { - style: { color: "#777", fontSize: "0.9em" }, - }), - DOM.create_element("span", [entry.title]), - DOM.create_element("span", [entry.url], { - style: { color: "#777", fontSize: "0.9em" }, - }), - ], - }); - }, - async execute({ input: input }) { - - - if (entry.title.toLowerCase().includes(input.toLowerCase())) { - const tab = await glide.tabs.get_first({ - url: entry.url, - }); - if (tab) { - const windowid = tab.windowId; - if (windowid === undefined) { - return - } - await browser.windows.update(windowid, { - focused: true - }) - await browser.tabs.update(tab.id, { - active: true, - }); - } else { - - await browser.tabs.update((await glide.tabs.active()).id, { - active: true, - url: entry.url, - }); - } - } else { - const terms = input.split(" ",) - const first = terms[0] - if (terms.length > 1 && first !== undefined && first in search_info) { - let info = search_info[first]; - let query = info?.url + terms.slice(1).join(info?.sep) - browser.tabs.create({ - active: true, - url: query - }); - return; - } - - let url: URL; - try { - url = new URL(input) - } catch (_) { - try { - url = new URL("http://" + input) // firefox automatically makes this https - - // avoids single word searches becoming URLs - if (url.hostname.split(".").length == 1 && url.hostname !== "localhost") { - throw "probably not a hostname"; - } - } catch (_) { // probably not a url - browser.search.search({ - query: terms.filter(s => s).join(" "), - disposition: "NEW_TAB", - }) - return - } - - } - // so it IS a URL! - - const tab = await glide.tabs.get_first({ url }); - - if (tab) { - browser.tabs.update(tab.id, { active: true }); - } - else { - browser.tabs.create({ active: true, url }); - } - } - - }, - })), - }); -}, { description: "Open the site searcher" }); - glide.keymaps.set('normal', 'ab', async () => { const currentTab = await glide.tabs.get_first({ active: true }); @@ -469,255 +343,8 @@ glide.keymaps.set('normal', '<C-x>4b', 'split_window'); glide.keymaps.set('normal', '<C-x>1', 'unsplit_window'); glide.keymaps.set('normal', '<A-o>', 'other_window'); -// Status bar -// https://github.com/glide-browser/glide/discussions/147#discussioncomment-15573076 - -const status_bar_id = "glide-status-bar" - -const mode_colors: Record<keyof GlideModes, string> = { - "command": "--glide-mode-command", - "hint": "--glide-mode-hint", - "ignore": "--glide-mode-ignore", - "insert": "--glide-mode-insert", - "normal": "--glide-mode-normal", - "op-pending": "--glide-mode-op-pending", - "visual": "--glide-mode-visual", -} -const fallback_mode_color = "--glide-fallback-mode" - -glide.autocmds.create("ConfigLoaded", async () => { - const existing = document.getElementById(status_bar_id) - if (existing) { - existing.remove() - } - - const status_bar = DOM.create_element("div", { - id: status_bar_id, - children: [ - DOM.create_element("div", { - className: "glide-status-tabs", - children: [] - }), - DOM.create_element("div", { - className: "glide-status-right", - children: [] - }) - ] - }) - - const browser = document.getElementById("browser") - if (browser) { - browser.appendChild(status_bar) - } - - setTimeout(() => { - update_status_bar() - }, 100) -}) - -glide.autocmds.create("WindowLoaded", async () => { - let status_bar = document.getElementById(status_bar_id) as HTMLElement - if (!status_bar) { - status_bar = DOM.create_element("div", { - id: status_bar_id, - children: [ - DOM.create_element("div", { - className: "glide-status-tabs", - children: [] - }), - DOM.create_element("div", { - className: "glide-status-right", - children: [] - }) - ] - }) as HTMLElement - - const browser = document.getElementById("browser") - if (browser) { - browser.appendChild(status_bar) - } - } - - await update_status_bar() -}) - -function ensure_status_bar() { - let status_bar = document.getElementById(status_bar_id) as HTMLElement - if (!status_bar) { - status_bar = DOM.create_element("div", { - id: status_bar_id, - children: [ - DOM.create_element("div", { - className: "glide-status-tabs", - children: [] - }), - DOM.create_element("div", { - className: "glide-status-right", - children: [] - }) - ] - }) as HTMLElement - - const browser = document.getElementById("browser") - if (browser) { - browser.appendChild(status_bar) - } - } else { - let tabs = status_bar.querySelector(".glide-status-tabs") - let right = status_bar.querySelector(".glide-status-right") - if (!tabs || !right) { - status_bar.innerHTML = "" - status_bar.appendChild(DOM.create_element("div", { - className: "glide-status-tabs", - children: [] - })) - status_bar.appendChild(DOM.create_element("div", { - className: "glide-status-right", - children: [] - })) - } - } - return status_bar -} - -async function update_status_bar() { - // Ensure status bar exists - const status_bar = ensure_status_bar() as HTMLElement - if (!status_bar) return - - const tabs_container = status_bar.querySelector(".glide-status-tabs") - const right = status_bar.querySelector(".glide-status-right") - if (!tabs_container || !right) { - // If elements don't exist, recreate them - ensure_status_bar() - return - } - - try { - const tabs = await glide.tabs.query({}); - const active_tab = await glide.tabs.active(); - const tab_index = tabs.findIndex(t => t.id == active_tab.id); - const url = active_tab.url; - const title = active_tab.title || "Untitled"; - - let display_url = url || "about:blank"; - - if (display_url.length > 50) { - display_url = display_url.substring(0, 47) + "..."; - } - - tabs_container.textContent = `[${tab_index + 1}/${tabs.length}]`; - right.textContent = `${title} | ${display_url}`; - } catch (e) { - tabs_container.textContent = e; - right.textContent = "Error loading tabs" - } -} - -glide.autocmds.create("ModeChanged", "*", (args) => { - const style_id = "glide-custom-mode-indicator" - glide.styles.remove(style_id) - glide.styles.add(` - #browser { - border-bottom: 3px solid var(${mode_colors[args.new_mode] ?? fallback_mode_color}) - } - `, { id: style_id }) -}) - -glide.autocmds.create("UrlEnter", /.*/, async () => { - await update_status_bar() -}) - -browser.tabs.onActivated.addListener(async () => { - await update_status_bar() -}) - -browser.tabs.onUpdated.addListener(async (tabId, changeInfo) => { - if (changeInfo.url || changeInfo.title) { - await update_status_bar() - } -}) - -browser.tabs.onCreated.addListener(async () => { - await update_status_bar() -}) - -browser.tabs.onRemoved.addListener(async () => { - await update_status_bar() -}) - -glide.styles.add(` - #${status_bar_id} { - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 24px; - background-color: #1e1e1e; - color: #d4d4d4; - font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', 'Courier New', monospace; - font-size: 12px; - display: flex; - justify-content: space-between; - align-items: center; - padding: 0 12px; - border-top: 1px solid #3e3e3e; - z-index: 10000; - box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.3); - overflow: hidden; - } - - #${status_bar_id} .glide-status-tabs { - display: flex; - align-items: center; - gap: 0; - flex: 1; - overflow-x: auto; - overflow-y: hidden; - scrollbar-width: none; - -ms-overflow-style: none; - } - - #${status_bar_id} .glide-status-tabs::-webkit-scrollbar { - display: none; - } - - #${status_bar_id} .glide-tab-item { - color: #858585; - cursor: pointer; - padding: 2px 4px; - border-radius: 2px; - white-space: nowrap; - transition: background-color 0.2s ease, color 0.2s ease; - } - - #${status_bar_id} .glide-tab-item:hover { - background-color: #2e2e2e; - color: #d4d4d4; - } - - #${status_bar_id} .glide-tab-item.active { - color: #569cd6; - font-weight: 600; - background-color: #2a2a2a; - } - - #${status_bar_id} .glide-tab-separator { - color: #3e3e3e; - user-select: none; - } - - #${status_bar_id} .glide-status-right { - color: #858585; - margin-left: 12px; - white-space: nowrap; - flex-shrink: 0; - } - - #browser { - padding-bottom: 24px; - } - `, { id: "glide-status-bar-styles" }); +glide.include('sitesearch.glide.ts'); +glide.include('tabbar.glide.ts'); const toggle_reader_mode = glide.excmds.create({ name: 'toggle_reader_mode', diff --git a/glide/.config/glide/sitesearch.glide.ts b/glide/.config/glide/sitesearch.glide.ts new file mode 100644 index 0000000..f575015 --- /dev/null +++ b/glide/.config/glide/sitesearch.glide.ts @@ -0,0 +1,147 @@ +// From https://github.com/glide-browser/glide/discussions/147#discussioncomment-15337351 + +/** + * custom search providers + */ +const search_info: Record<string, { url: string, sep: string }> = { + 'youtube': { + url: "https://www.youtube.com/results?search_query=", sep: "+" + } +} as const + +/* + * pick tabs via a selection of bookmarks and history + */ +glide.keymaps.set("normal", "<leader>t", async () => { + + //let combined: Array<Browser.Bookmarks.BookmarkTreeNode | Browser.History.HistoryItem> = [] + let combined = [] + const tabs = await browser.tabs.query({}); + tabs.forEach(entry => combined.push({ + title: entry.title ?? 'Unnamed Tab', + url: entry.url, + type: 'T', + favIconUrl: entry.favIconUrl + })); + + const bookmarks = await browser.bookmarks.search({}); + bookmarks + .filter(bmark => bmark.type !== 'folder') + .forEach(bmark => combined.push({ title: bmark.title, url: bmark.url, type: 'B', favIconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAE/ElEQVR4Xu2cW2wUVRjHvzPdXdou0gvUemniegnRQtquimBNa4kpJfrCJrQ+Gewjb5oQfJPLG8akjzxawpMtyeKDpuBDkWqEBNMFEcUINEQTTEVrwbZ7mTmeb9xZ5j6zZXbd7X4n2YdOz3xz5rf//3fOmZ1zGPgsyelvY7m0vIcz/jpw3iNOi/k8teKqMQYLHNg5YNJnI7teG3drIPNq/cTZb95lirKPAx/wqlul/5+TGLy/d6j/tF37HQEJMD0CzNgaBmPmMT6yu3/UfNAWkKoaLo9xDs1VqorVNtsCyQII4YAif+J0hXAoBO2bWqCxfh20Nm8wVNto+nu1rSzleXcXFuHXO/Pqx64IuyX0djMAOnXm/B6FQ9KpgZtjHRDreBzCobpS3kNZYi/eX4JLV6/D8krafL05YbWntYMFQMnp2eZc5t4tJ1v1vdwFG9Y3lqXx5bpINifDzKUrVkhS3ajWuxUATU59/R4HZcyucR2PtUH388+Wq91lvQ4qCSEZCmOnR4b6EnisAGjizMxsfnxjaeDAti5oa20qScNvdg8GGveZy19a4nFxRJYVyIoPFxYxl8s/3TDkJBwnDQ/1txgBTZ23npmPVO2ANCB4g+lMDhQTJEzcF1LXDNxEHlLF80BBLoBiT7bDtq2bA/2mtWDlUJC+4QhpRUAyK+nzcxdWDwjP3PLcU9DW0hS41coNCO8lJ6yWEQlaXx4aUEnkI4K+dPBooKG/++hDQzzMnbEn2gFdoLfacjpLgPQEmh+JQm+8E6IN9erhJQJkFSbOAgZ74yokAuRgXFTSYO+LpQe0vWdLILkjt+vtQOJoQUJnP4W//r4Hd+bvwuL9f2xjY4/86KbW0uagSgak3fn8nwtw8/ZvFkiYuF/peoEAIQEnSG8N7CBAGoEff5mz2I0A6fSBOennW7cNiiFApsxzMfUDAUIC2IvZFQKUp0KAPEZNBIgAPdzAmhRECiIFGQiUYrJK3byLyCgHUQ6iHEQ5qBgNUJL2oEWACFAxhrLWJQWRgkhBtgSq4WcffcPpiSI9UfRnZZqL0VzMn1KcapGCSEFWAlLiTfWgkvzCU141pyDW3gZ1x4+pYOT9HwD/3X4JgUau5gDVfXwIWFenev/8yjWQDxxxVVFNAUJrSfv3GYAox0+4Wq1mABWstT5qVIx4a8zNajUDSG8ts6fcrFYTgOysZYbkZLU1D8jRWmZCDlZb84DcrOXHakEAYmJF9PDuvp14PV+LWez61aAedygnT4FyclK9hPTOsPjs9RwM6iv4Pb+oxx12C+omXFb7lBKQGlt7n9ncYxWFyr2yb0CMpcRiurgW7X9XUIAMXEP5AYQL6UKRcDyx89U5AmR+T/qri6lwJJTQw6mIHFQpCorWR2z3ECCL5b8hAuTxnjQBcgGE457G+rA67jEXshiOvyRptCESGidAOgKFtRoMUtF1kcK4hxSUJ6ACYmxBioTiDYwVxj2OgCanZqaL2SsoqKlGObp5XHmIS6K0grvU7Ih3pqRIOOEGxzgO8tgWx3wj1QQIVx3iwroCoJamI29s7z7s58sxDI7c9u+oVkBLyyvw/fUbD5pvmmt5QTIAUjdyy2Rn/ew8VQ0KkmVZhZPO/LeJgN1cqyhAWBkhZTO5pNNOMFrASgeEysFVhhocQcd2rlU0IO0Er93vKhUQJuQ/RL7Rcg4OArkknfDaDtAJ1L+Y5wqFFVK3lAAAAABJRU5ErkJggg==' })); + + const topsites = await browser.topSites.get({includeFavicon: true}); + topsites + .forEach(s => combined.push({ title: s.title, url: s.url, type: 'S', favIconUrl: s.favicon})); + + const history = await browser.history.search({ text: "", maxResults: 100 }); + history.forEach(entry => combined.push({ title: entry.title, url: entry.url, type: 'H', favIconUrl: null })); + + // filtering + const newtab = (await browser.runtime.getManifest()).chrome_url_overrides?.newtab + const startpage = glide.prefs.get("browser.startup.homepage") + + let filtered_combined = combined.filter(e => e.url !== startpage && e.url !== newtab) + + glide.commandline.show({ + title: "open", + options: filtered_combined.map((entry) => ({ + label: entry.title, + render() { + return DOM.create_element("div", { + style: { + display: "flex", + alignItems: "center", + gap: "8px", + }, + children: [ + entry.favIconUrl + ? DOM.create_element("img", [], { + src: entry.favIconUrl, + style: { + width: '16px', + height: '16px', + } + }) + : DOM.create_element("span", [entry.type], { + style: { color: "#777", fontSize: "0.9em" }, + }), + DOM.create_element("span", [entry.title]), + DOM.create_element("span", [entry.url], { + style: { color: "#777", fontSize: "0.9em" }, + }), + ], + }); + }, + async execute({ input: input }) { + if (entry.title.toLowerCase().includes(input.toLowerCase())) { + const tab = await glide.tabs.get_first({ + url: entry.url, + }); + if (tab) { + const windowid = tab.windowId; + if (windowid === undefined) { + return + } + await browser.windows.update(windowid, { + focused: true + }) + await browser.tabs.update(tab.id, { + active: true, + }); + } else { + + await browser.tabs.create({ + active: true, + url: entry.url, + windowId: browser.windows.getCurrent().id, + }); + } + } else { + const terms = input.split(" ",) + const first = terms[0] + if (terms.length > 1 && first !== undefined && first in search_info) { + let info = search_info[first]; + let query = info?.url + terms.slice(1).join(info?.sep) + browser.tabs.create({ + active: true, + url: query + }); + return; + } + + let url: URL; + try { + url = new URL(input) + } catch (_) { + try { + url = new URL("http://" + input) // firefox automatically makes this https + + // avoids single word searches becoming URLs + if (url.hostname.split(".").length == 1 && url.hostname !== "localhost") { + throw "probably not a hostname"; + } + } catch (_) { // probably not a url + browser.search.search({ + query: terms.filter(s => s).join(" "), + disposition: "NEW_TAB", + }) + return + } + + } + // so it IS a URL! + + const tab = await glide.tabs.get_first({ url: url.href }); + + if (tab) { + browser.tabs.update(tab.id, { active: true }); + } + else { + browser.tabs.create({ active: true, url }); + } + } + + }, + })), + }); +}, { description: "Open the site searcher" }); diff --git a/glide/.config/glide/tabbar.glide.ts b/glide/.config/glide/tabbar.glide.ts new file mode 100644 index 0000000..3ad7817 --- /dev/null +++ b/glide/.config/glide/tabbar.glide.ts @@ -0,0 +1,256 @@ +// Status bar +// https://github.com/glide-browser/glide/discussions/147#discussioncomment-15573076 + +const status_bar_id = "glide-status-bar" + +const mode_colors: Record<keyof GlideModes, string> = { + "command": "--glide-mode-command", + "hint": "--glide-mode-hint", + "ignore": "--glide-mode-ignore", + "insert": "--glide-mode-insert", + "normal": "--glide-mode-normal", + "op-pending": "--glide-mode-op-pending", + "visual": "--glide-mode-visual", +} +const fallback_mode_color = "--glide-fallback-mode" + +glide.autocmds.create("ConfigLoaded", async () => { + const existing = document.getElementById(status_bar_id) + if (existing) { + existing.remove() + } + + const status_bar = DOM.create_element("div", { + id: status_bar_id, + children: [ + DOM.create_element("div", { + className: "glide-status-tabs", + children: [] + }), + DOM.create_element("div", { + className: "glide-status-right", + children: [] + }) + ] + }) + + const browser = document.getElementById("browser") + if (browser) { + browser.appendChild(status_bar) + } + + setTimeout(() => { + update_status_bar() + }, 100) +}) + +glide.autocmds.create("WindowLoaded", async () => { + let status_bar = document.getElementById(status_bar_id) as HTMLElement + if (!status_bar) { + status_bar = DOM.create_element("div", { + id: status_bar_id, + children: [ + DOM.create_element("div", { + className: "glide-status-tabs", + children: [] + }), + DOM.create_element("div", { + className: "glide-status-right", + children: [] + }) + ] + }) as HTMLElement + + const browser = document.getElementById("browser") + if (browser) { + browser.appendChild(status_bar) + } + } + + await update_status_bar() +}) + +function ensure_status_bar() { + let status_bar = document.getElementById(status_bar_id) as HTMLElement + if (!status_bar) { + status_bar = DOM.create_element("div", { + id: status_bar_id, + children: [ + DOM.create_element("div", { + className: "glide-status-tabs", + children: [] + }), + DOM.create_element("div", { + className: "glide-status-right", + children: [] + }) + ] + }) as HTMLElement + + const browser = document.getElementById("browser") + if (browser) { + browser.appendChild(status_bar) + } + } else { + let tabs = status_bar.querySelector(".glide-status-tabs") + let right = status_bar.querySelector(".glide-status-right") + if (!tabs || !right) { + status_bar.innerHTML = "" + status_bar.appendChild(DOM.create_element("div", { + className: "glide-status-tabs", + children: [] + })) + status_bar.appendChild(DOM.create_element("div", { + className: "glide-status-right", + children: [] + })) + } + } + return status_bar +} + +async function update_status_bar() { + // Ensure status bar exists + const status_bar = ensure_status_bar() as HTMLElement + if (!status_bar) return + + const tabs_container = status_bar.querySelector(".glide-status-tabs") + const right = status_bar.querySelector(".glide-status-right") + if (!tabs_container || !right) { + // If elements don't exist, recreate them + ensure_status_bar() + return + } + + try { + const current_window = await browser.windows.getCurrent(); + const tabs = await browser.tabs.query({ + windowId: current_window.id, + }); + const active_tab = await glide.tabs.active(); + const tab_index = tabs.findIndex(t => t.id == active_tab.id); + const url = active_tab.url; + const title = active_tab.title || "Untitled"; + + let display_url = url || "about:blank"; + + if (display_url.length > 50) { + display_url = display_url.substring(0, 47) + "..."; + } + + tabs_container.textContent = `[${tab_index + 1}/${tabs.length}]`; + right.textContent = `${title} | ${display_url}`; + } catch (e) { + tabs_container.textContent = e; + right.textContent = "Error loading tabs" + } +} + +glide.autocmds.create("ModeChanged", "*", (args) => { + const style_id = "glide-custom-mode-indicator" + glide.styles.remove(style_id) + glide.styles.add(` + #browser { + border-bottom: 3px solid var(${mode_colors[args.new_mode] ?? fallback_mode_color}) + } + `, { id: style_id }) +}) + +glide.autocmds.create("UrlEnter", /.*/, async () => { + await update_status_bar() +}) + +browser.tabs.onActivated.addListener(async () => { + await update_status_bar() +}) + +browser.tabs.onUpdated.addListener(async (tabId, changeInfo) => { + if (changeInfo.url || changeInfo.title) { + await update_status_bar() + } +}) + +browser.tabs.onCreated.addListener(async () => { + await update_status_bar() +}) + +browser.tabs.onRemoved.addListener(async () => { + await update_status_bar() +}); + +browser.windows.onFocusChanged.addListener(async (windowId) => { + await update_status_bar(); +}); + +glide.styles.add(` + #${status_bar_id} { + position: fixed; + bottom: 0; + left: 0; + right: 0; + height: 24px; + background-color: #1e1e1e; + color: #d4d4d4; + font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', 'Courier New', monospace; + font-size: 12px; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 12px; + border-top: 1px solid #3e3e3e; + z-index: 10000; + box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.3); + overflow: hidden; + } + + #${status_bar_id} .glide-status-tabs { + display: flex; + align-items: center; + gap: 0; + flex: 1; + overflow-x: auto; + overflow-y: hidden; + scrollbar-width: none; + -ms-overflow-style: none; + } + + #${status_bar_id} .glide-status-tabs::-webkit-scrollbar { + display: none; + } + + #${status_bar_id} .glide-tab-item { + color: #858585; + cursor: pointer; + padding: 2px 4px; + border-radius: 2px; + white-space: nowrap; + transition: background-color 0.2s ease, color 0.2s ease; + } + + #${status_bar_id} .glide-tab-item:hover { + background-color: #2e2e2e; + color: #d4d4d4; + } + + #${status_bar_id} .glide-tab-item.active { + color: #569cd6; + font-weight: 600; + background-color: #2a2a2a; + } + + #${status_bar_id} .glide-tab-separator { + color: #3e3e3e; + user-select: none; + } + + #${status_bar_id} .glide-status-right { + color: #858585; + margin-left: 12px; + white-space: nowrap; + flex-shrink: 0; + } + + #browser { + padding-bottom: 24px; + } + `, { id: "glide-status-bar-styles" }); diff --git a/oni/home/config/common.scm b/oni/home/config/common.scm index 3a91393..2b52f58 100644 --- a/oni/home/config/common.scm +++ b/oni/home/config/common.scm @@ -225,16 +225,7 @@ LocalForward 19999 localhost:19999")) (make-channel-introduction "7677db76330121a901604dfbad19077893865f35" (openpgp-fingerprint - "13E7 6CD6 E649 C28C 3385 4DF5 5E5A A665 6149 17F7")))) - (channel - (name 'guix-rust-past-crates) - (url "https://codeberg.org/guix/guix-rust-past-crates.git") - (branch "trunk") - (introduction - (make-channel-introduction - "1db24ca92c28255b28076792b93d533eabb3dc6a" - (openpgp-fingerprint - "F4C2D1DF3FDEEA63D1D30776ACC66D09CA528292"))))))) + "13E7 6CD6 E649 C28C 3385 4DF5 5E5A A665 6149 17F7"))))))) (define home-zsh-services (list (service home-zsh-service-type diff --git a/oni/home/config/data.scm b/oni/home/config/data.scm index a45c697..2cf41a0 100644 --- a/oni/home/config/data.scm +++ b/oni/home/config/data.scm @@ -159,6 +159,7 @@ (service home-emacs-golden-ratio-service-type) (service home-emacs-pinentry-service-type) (service home-emacs-org-caldav-service-type) + (service home-emacs-org-mem-service-type) (service home-mbsync-service-type) diff --git a/oni/home/config/pop-os.scm b/oni/home/config/pop-os.scm index ab6b7c0..8bae7c7 100644 --- a/oni/home/config/pop-os.scm +++ b/oni/home/config/pop-os.scm @@ -4,21 +4,10 @@ #:use-module ((gnu home services gnupg) #:select (home-gpg-agent-service-type home-gpg-agent-configuration)) - #:use-module ((gnu packages) - #:select (specification->package+output)) - #:use-module ((gnu packages admin) - #:select (htop)) - #:use-module ((gnu packages emacs) - #:select (emacs)) - #:use-module (gnu packages emacs-xyz) - #:use-module ((gnu packages hunspell) - #:select (hunspell - hunspell-dict-en-ca)) - #:use-module ((gnu packages music) - #:select (playerctl)) - #:use-module ((gnu packages pulseaudio) - #:select (pamixer)) - #:use-module (gnu packages xdisorg) + #:use-module (gnu packages) + #:use-module (gnu packages emacs) + #:use-module (gnu packages music) + #:use-module (gnu packages pulseaudio) #:use-module ((gnu services) #:select (service)) #:use-module ((guix gexp) @@ -32,6 +21,7 @@ #:select (home-environment-service)) #:use-module ((oni home services flameshot) #:select (home-flameshot-service-type)) + #:use-module (oni home services git) #:use-module (oni home services herbstluftwm) #:use-module ((oni home services mail) #:select (home-mbsync-service-type)) @@ -39,37 +29,7 @@ #:use-module (oni home services rofi) #:use-module (oni home services xdisorg) #:use-module (oni packages emacs) - #:use-module ((oni packages emacs-config) - #:select (emacs-oni-bookmark - emacs-oni-browse-url - emacs-oni-common-lisp - emacs-oni-compilation - emacs-oni-core - emacs-oni-css - emacs-oni-diff-hl - emacs-oni-dired - emacs-oni-elisp - emacs-oni-git-commit - emacs-oni-grep - emacs-oni-gui - emacs-oni-html - emacs-oni-log-edit - emacs-oni-magit - emacs-oni-org - emacs-oni-org-roam - emacs-oni-package - emacs-oni-php - emacs-oni-project - emacs-oni-projectile - emacs-oni-scheme - emacs-oni-shr - emacs-oni-tramp - emacs-oni-web-mode - emacs-oni-yaml - emacs-oni-lua - emacs-oni-sh - emacs-oni-js - emacs-oni-elfeed)) + #:use-module (oni packages emacs-config) #:use-module ((oni packages fonts) #:select (font-comfortaa font-annotation-mono)) @@ -128,7 +88,7 @@ '(("focus=on") ("class=Emacs" "tag=dev" "index=01" "switchtag=on" "hook=emacs") - ("class~'URxvt|kitty'" "tag=dev" "index=1" + ("class~'URxvt|kitty|wezterm'" "tag=dev" "index=1" "switchtag=on" "hook=urxvt") ("class~'Conkeror|[Ff]irefox|Chromium|glide-glide'" "tag=web" "index=0" "switchtag=on") @@ -206,10 +166,38 @@ (home-module (packages (append foreign-distro-compatibility-packages - (list (specification->package+output "font-fantasque-sans") - (specification->package+output "font-dosis") - (specification->package+output "font-comic-neue") - emacs-oni-core + (map specification->package '("font-fantasque-sans" + "font-dosis" + "wezterm" + "tree-sitter-vue" + "tree-sitter-typescript" + "tree-sitter-css" + "emacs-popup" + "emacs-git-messenger" + "emacs-csv-mode" + "htop" + "emacs-deft" + "emacs-dashboard" + "emacs-typescript-mode" + "hunspell" + "hunspell-dict-en-ca" + "emacs-dired-git-info" + "playerctl" + "pamixer" + ;; need to have a file + ;; /etc/udev/rules.d/40-monitor-hotplug.rules + ;; ACTION=="change", SUBSYSTEM=="drm", RUN+="/var/guix/profiles/per-user/tomwillemsen/guix-home/profile/bin/autorandr --batch --change --default default" + "autorandr" + "emacs-guix" + "emacs-rainbow-identifiers" + "emacs-forge" + "emacs-vundo" + "emacs-sops" + "emacs-dockerfile-mode" + "emacs-slack" + "emacs-combobulate" + "emacs-prodigy")) + (list emacs-oni-core emacs-oni-compilation emacs-oni-common-lisp emacs-oni-browse-url @@ -231,47 +219,28 @@ emacs-oni-grep emacs-oni-shr emacs-oni-css - emacs-dockerfile-mode emacs-oni-yaml - emacs-oni-web-mode + ;; emacs-oni-web-mode emacs-oni-php emacs-oni-projectile - htop - ;; emacs-php-ts-mode emacs-oni-lua emacs-oni-sh - emacs-deft - emacs-dashboard - emacs-flycheck-phpstan - emacs-org-mem - emacs-typescript-mode emacs-oni-js - hunspell - hunspell-dict-en-ca - emacs-dired-git-info emacs-oni-elfeed + emacs-oni-eshell + emacs-oni-outline + emacs-oni-sql + emacs-oni-logview - shutdown-rofi - playerctl - pamixer - ;; need to have a file - ;; /etc/udev/rules.d/40-monitor-hotplug.rules - ;; ACTION=="change", SUBSYSTEM=="drm", RUN+="/var/guix/profiles/per-user/tomwillemsen/guix-home/profile/bin/autorandr --batch --change --default default" - autorandr - - emacs-guix - emacs-rainbow-identifiers - emacs-forge - - emacs-vundo + emacs-flycheck-phpstan + emacs-vue-ts-mode - emacs-sops))) + shutdown-rofi))) (services (append home-zsh-services (list home-channels-service home-dunst-default-service home-environment-service - home-kitty-service home-rofi-default-service (service home-emacs-service-type @@ -294,7 +263,8 @@ "(with-eval-after-load 'project (require 'oni-project))\n" "(require 'oni-gui)\n" "(provide 'oni-gnus)\n" - "(add-to-list 'auto-mode-alist '(\"\\.vue$\" . web-mode))\n"))))) + ;; "(add-to-list 'auto-mode-alist '(\"\\.vue$\" . web-mode))\n" + ))))) (service home-emacs-org-journal-service-type) (service home-wakatime-service-type (home-wakatime-configuration @@ -312,4 +282,22 @@ (home-gpg-agent-configuration (ssh-support? #t) (extra-content - "allow-emacs-pinentry\n")))))))) + "allow-emacs-pinentry\n"))) + + (service home-git-service-type + (home-git-configuration + (user-name "Tom Willemse") + (user-email "tom@ryuslash.org") + (sendemail-sendmailcmd "/usr/bin/msmtp") + (init-default-branch "main") + (init-default-branchname "main") + (advice-detached-head #f) + (extra " +[diff \"org\"] + xfuncname = \"^\\\\*+ +(.+)\" +[diff \"lisp\"] + xfuncname = \"^[[:space:]]*?\\\\(def\\\\w+? ((\\\\w|-|'|:|=|<|>)+)\" +") + (ignore-patterns '("GPATH" "GTAGS" "GRTAGS")))) + + (service home-emacs-org-mem-service-type)))))) diff --git a/oni/home/config/pop-os/emacs.el b/oni/home/config/pop-os/emacs.el index c4aa16e..8b517ef 100644 --- a/oni/home/config/pop-os/emacs.el +++ b/oni/home/config/pop-os/emacs.el @@ -57,18 +57,24 @@ ;; ("t" "Test" artisan-test-transient) ("mm" "Make Migration" artisan-make-migration-transient) ("mM" "Make Model" artisan-make-model-transient) - ("mf" "Make Factory" artisan-make-factory-transient) - ("mFf" "Make Filament Form" artisan-make-filament-form-transient)]) + ("mf" "Make Factory" artisan-make-factory-transient)]) (defun artisan-punt-composer-install () (interactive) (let ((default-directory (expand-file-name "punt" (project-root (project-current))))) (async-shell-command "docker exec -it punt-backend composer install"))) -(defun artisan-chanced-composer-install () - (interactive) - (let ((default-directory (expand-file-name "chanced" (project-root (project-current))))) - (async-shell-command "docker exec -it chanced-backend composer install"))) +(defun artisan-chanced-composer-install (brand) + (interactive + (list (oni-read-brand))) + (mapcar (lambda (b) + (let ((default-directory (expand-file-name b (project-root (project-current)))) + (containers '(("chanced" . "chanced-backend") + ("punt" . "punt-backend") + ("filament" . "chanced-admin-panel")))) + (async-shell-command (format "docker exec -it %s composer install" (map-elt containers b)) + (get-buffer-create (format "*%s-composer*" (upcase b)))))) + (if (string= brand "all") '("chanced" "punt" "filament") (list brand)))) (defun artisan-punt-run-command (command) (interactive @@ -128,8 +134,11 @@ buffers.") (defun oni-read-brand () "Ask for Chanced or Punt." - (nth 1 (read-multiple-choice "Chanced or Punt? " '((?c "chanced" "Chanced") - (?p "punt" "Punt"))))) + (nth 1 (read-multiple-choice "Which application? " + '((?a "all" "All") + (?c "chanced" "Chanced") + (?p "punt" "Punt") + (?f "filament" "Filament"))))) (cl-defun artisan-run-test (name &key file filter stop-on-failure-p) (interactive @@ -147,7 +156,7 @@ buffers.") (command (with-current-buffer buffer (format "../../chanced-scripts/test %s %s %s %s" name - (if filter (format "--filter='::%s$'" filter) "") + (if filter (format "--filter='::%s( |$)'" filter) "") (if stop-on-failure-p "--stop-on-defect" "") (or file ""))))) (cl-letf (((symbol-function 'compilation-buffer-name) @@ -390,9 +399,9 @@ Optional argument STOPP means stop on any defect." (add-hook 'dashboard-mode-hook 'olivetti-mode) (add-hook 'dashboard-after-initialize-hook (lambda () (setq truncate-lines t))) -(setq browse-url-browser-function #'browse-url-firefox) -(setq browse-url-generic-args '("run" "--branch=stable" "--arch=x86_64" "--command=launch-script.sh" "--file-forwarding" "app.zen_browser.zen")) -(setq browse-url-generic-program "/usr/bin/flatpak") +(setq browse-url-browser-function #'browse-url-generic) +(setq browse-url-generic-args nil) +(setq browse-url-generic-program "~/Downloads/glide/glide") (defun oni-fixup-phpstan-filenames (errors) "Change the file name from each error in ERRORS to one on local disk." @@ -1247,8 +1256,10 @@ Optional argument STOPP means stop on any defect." (require 'oni-js) -(with-eval-after-load 'sh-script - (require 'oni-sh)) +(with-eval-after-load 'sh-script (require 'oni-sh)) +(with-eval-after-load 'sql (require 'oni-sql)) +(with-eval-after-load 'outline (require 'oni-outline)) +(with-eval-after-load 'logview (require 'oni-logview)) (eval-when-compile (require 'magit-section)) @@ -1270,5 +1281,73 @@ Optional argument STOPP means stop on any defect." (add-hook 'magit-status-sections-hook #'oni-magit-insert-locked-files 20)) -(setq elfeed-feeds - '("https://www.reddit.com/r/PHP/.rss")) +(with-eval-after-load 'elfeed + (setq elfeed-feeds + '(("https://www.reddit.com/r/PHP/.rss" php) + ("https://phpreads.com/feed" php) + ("https://phpstan.org/rss.xml" php) + ("https://lobste.rs/t/php.rss" php)) + elfeed-curl-program-name "curl")) + +(setq git-messenger:show-detail t) +(global-set-key (kbd "C-c g .") '("Show commit at point" . git-messenger:popup-message)) +(global-set-key (kbd "C-c g b") '("Git Blame current file" . magit-blame)) +(global-set-key (kbd "C-c g l") '("Show file's git log" . magit-log-buffer-file)) + +(defun my-set-agenda-files (&rest _) + (setq org-agenda-files + (cl-loop + for file in (org-mem-all-files) + unless (string-search "archive" file) + when (seq-find (lambda (entry) + (or (org-mem-entry-active-timestamps entry) + (org-mem-entry-todo-state entry) + (org-mem-entry-scheduled entry) + (org-mem-entry-deadline entry))) + (org-mem-entries-in file)) + collect file))) +(add-hook 'org-mem-post-full-scan-functions #'my-set-agenda-files) + +;;; Prodigy services + +(with-eval-after-load 'prodigy + (prodigy-define-tag + :name 'tunnel + :command "~/code/diamond-interactive/social-api/toolbox/connect_db.sh" + :args (lambda (&rest args) + (let ((service (map-elt args :service))) + (list "-e" + (if (prodigy-service-tagged-with? service 'production) + "prd" + "stg") + "-a" + (cond + ((prodigy-service-tagged-with? service 'chanced) + "chanced") + ((prodigy-service-tagged-with? service 'punt) + "punt") + (t (error "Unknown project"))) + "-k" + (expand-file-name "~/.ssh/id_ed25519.pub")))) + :cwd "~/code/diamond-interactive/social-api" + :stop-signal 'kill + :ready-message "Waiting for connections...") + + (prodigy-define-service + :name "Chanced Production Database Connection" + :tags '(chanced production tunnel)) + + (prodigy-define-service + :name "Chanced Staging Database Connection" + :tags '(chanced staging tunnel)) + + (prodigy-define-service + :name "Punt Production Database Connection" + :tags '(punt production tunnel)) + + (prodigy-define-service + :name "Punt Staging Database Connection" + :tags '(punt staging tunnel))) + +(autoload 'vue-ts-mode "vue-ts-mode" nil t) +(add-to-list 'auto-mode-alist (cons (rx ".vue" eos) 'vue-ts-mode)) diff --git a/oni/home/services/emacs/org-mem.el b/oni/home/services/emacs/org-mem.el index e69de29..55b521f 100644 --- a/oni/home/services/emacs/org-mem.el +++ b/oni/home/services/emacs/org-mem.el @@ -0,0 +1,6 @@ +(use-package org-mem + :ensure nil + :init + (setq org-mem-watch-dirs (list (expand-file-name "~/documents/gtd/")) + org-mem-do-sync-with-org-id t) + (org-mem-updater-mode)) diff --git a/oni/packages/emacs-config.scm b/oni/packages/emacs-config.scm index 112267c..6794a62 100644 --- a/oni/packages/emacs-config.scm +++ b/oni/packages/emacs-config.scm @@ -38,7 +38,7 @@ (define-public emacs-oni-config (let - ((commit "ea20080f5ce3a4e7f87455308afc30d21d5a8a24") + ((commit "b3b63e7322acd6fe373454bf5c8a41a97f000938") (revision "0")) (package (name "emacs-oni-config") (version (git-version "0.0.1" revision commit)) @@ -52,10 +52,9 @@ (file-name (git-file-name name version)) (sha256 (base32 - "10vm54szp1dwxlk9gmk22jjq27ci129c0cpg788m6xz8yc69sinf")))) + "0nj8gyzvajza2bsq20a2k1hljsmqw6a18l6bakff4d8l0wbmamzn")))) (build-system emacs-build-system) - (home-page - "https://code.ryuslash.org/emacs-config/") + (home-page "https://code.ryuslash.org/emacs-config/") (synopsis "My Emacs configuration") (description "This package provides my configuration for emacs") @@ -1022,3 +1021,35 @@ Emacs"))) (synopsis "My configuration for JavaScript.") (description "This package provides my configuration for editing JavaScript files."))) + +(define-public emacs-oni-outline + (package + (inherit emacs-oni-config) + (name "emacs-oni-outline") + (arguments + '(#:include '("oni-outline\\.el$"))) + (synopsis "My configuration for outline-mode and outline-minor-mode") + (description + "This package provides my configuration for outline modes."))) + +(define-public emacs-oni-sql + (package + (inherit emacs-oni-config) + (name "emacs-oni-sql") + (arguments + '(#:include '("oni-sql\\.el$"))) + (synopsis "My configuration for sql-mode") + (description + "This package provides my configuration for sql mode."))) + +(define-public emacs-oni-logview + (package + (inherit emacs-oni-config) + (name "emacs-oni-logview") + (arguments + '(#:include '("oni-logview\\.el$"))) + (synopsis "My configuration for logview-mode") + (propagated-inputs + (list emacs-logview)) + (description + "This package provides my configuration for logview mode."))) diff --git a/oni/packages/emacs.scm b/oni/packages/emacs.scm index dbbfc05..105a855 100644 --- a/oni/packages/emacs.scm +++ b/oni/packages/emacs.scm @@ -996,4 +996,26 @@ enabled.") (description "Major mode for editing Phel language source files.") (license license:gpl3+)))) -emacs-phel-mode +(define-public emacs-vue-ts-mode + (let ((commit "efc7031f50bbfd2a3293aee4fcb34bf0503b7f83") + (revision "0")) + (package + (name "emacs-vue-ts-mode") + (version (git-version "0" revision commit)) + (source + (origin + (uri (git-reference + (url "https://github.com/8uff3r/vue-ts-mode.git") + (commit commit))) + (method git-fetch) + (file-name (git-file-name name version)) + (sha256 + (base32 "148czg4vk301ikl60rw2pxmgapmlwz32jkg4jj5dkym0nrcq04vh")))) + (arguments + (list #:include + #~(list "^vue-ts-mode.el"))) + (build-system emacs-build-system) + (home-page "https://github.com/8uff3r/vue-ts-mode") + (synopsis "Emacs major mode for Vue based on Tree-sitter") + (description "Emacs major mode for Vue based on Tree-sitter") + (license license:gpl3+)))) diff --git a/wezterm/.config/wezterm/wezterm.lua b/wezterm/.config/wezterm/wezterm.lua index dc03d78..c122e66 100644 --- a/wezterm/.config/wezterm/wezterm.lua +++ b/wezterm/.config/wezterm/wezterm.lua @@ -1,6 +1,13 @@ local wezterm = require 'wezterm' local config = {} +config.default_cursor_style = 'SteadyBar' + +config.colors = { + foreground = '#bfbfbf', + background = '#222424', +} + config.keys = { { key = 'E', |
