diff options
| author | Jomar Milan <jomarm@pyrodax.com> | 2026-08-25 22:55:39 -0700 |
|---|---|---|
| committer | Jomar Milan <jomarm@pyrodax.com> | 2026-08-25 22:55:39 -0700 |
| commit | cceee3279435b12fd25330447e3f031bbc34a21f (patch) | |
| tree | 9b12bedcabff57f4f7901a7cf2727293ab0b47ab | |
| parent | 8e11743a9f0017310d2ba01103df31c9a6ff615d (diff) | |
| parent | d5272ffc9d4103bf3fc2dc6e5df6cfa734582b62 (diff) | |
Merge notification click and OSC 777 feature branch
Merges the branch from https://github.com/MacaylaMarvelous81/tabby-osc-notify/pull/1
which implements tab focus when clicking a notification and handling for OSC 777
notifications.
| -rw-r--r-- | README.md | 8 | ||||
| -rw-r--r-- | package-lock.json | 12 | ||||
| -rw-r--r-- | package.json | 3 | ||||
| -rw-r--r-- | src/osc-notify-decorator.ts | 24 | ||||
| -rw-r--r-- | src/osc-notify-middleware.ts | 27 |
5 files changed, 54 insertions, 20 deletions
@@ -1,11 +1,12 @@ # osc-notify This is a [Tabby](https://github.com/Eugeny/tabby) plugin. It creates a system -notification when an OSC 9 escape code sequence is printed. OSC 9 is in this -format: +notification when certain OSC escape code sequences are printed. The following +OSC escape codes are supported: ```sh OSC 9 ; [message] ST +OSC 777 ; notify ; [title] ; [body] ST ``` ### Example commands @@ -16,4 +17,7 @@ printf "\033]9;hello\a" # for tmux, use the passthrough escape sequence. allow-passthrough should be # enabled printf "\033Ptmux;\033\x1b]9;hello\x07\033\\" + +# creates a notification titled 'Build' with body 'Done' +printf "\033]777;notify;Build;Done\a" ``` diff --git a/package-lock.json b/package-lock.json index b847053..b3f1930 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "tabby-osc-notify", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tabby-osc-notify", - "version": "1.0.0", + "version": "1.1.0", "license": "MIT", "dependencies": { "@angular/core": "^15", "rxjs": "^7.8.1", + "tabby-core": "^1.0.197-nightly.1", "tabby-terminal": "^1.0.197-nightly.1" }, "devDependencies": { @@ -3283,11 +3284,10 @@ } }, "node_modules/tabby-core": { - "version": "1.0.231-nightly.0", - "resolved": "https://registry.npmjs.org/tabby-core/-/tabby-core-1.0.231-nightly.0.tgz", - "integrity": "sha512-CpOLTw9XWLeSJoAXGf6CIH1m5DULvmNTIncy0n0n8PAewQZmhMf5JYMzwiBzey+54LDZ/yit9aBRgat7yGx+Eg==", + "version": "1.0.197-nightly.1", + "resolved": "https://registry.npmjs.org/tabby-core/-/tabby-core-1.0.197-nightly.1.tgz", + "integrity": "sha512-GS4Q3orewMdZk4HAJp1vVg/Pv+FcN7E3o6TJHaUtPHRTWSeNM4MOoHY2HJINgcjaFuInthe4+8dK1W2aIECy2Q==", "license": "MIT", - "peer": true, "peerDependencies": { "@angular/animations": "^15", "@angular/common": "^15", diff --git a/package.json b/package.json index b12143b..81c3c25 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tabby-osc-notify", - "version": "1.0.0", + "version": "1.1.0", "main": "dist/index.js", "typings": "dist/index.d.ts", "scripts": { @@ -32,6 +32,7 @@ "dependencies": { "@angular/core": "^15", "rxjs": "^7.8.1", + "tabby-core": "^1.0.197-nightly.1", "tabby-terminal": "^1.0.197-nightly.1" }, "allowScripts": { diff --git a/src/osc-notify-decorator.ts b/src/osc-notify-decorator.ts index 7d32f1c..4beb029 100644 --- a/src/osc-notify-decorator.ts +++ b/src/osc-notify-decorator.ts @@ -1,25 +1,41 @@ import OscNotifyMiddleware from "./osc-notify-middleware"; import { Injectable } from "@angular/core"; import { TerminalDecorator, BaseSession, BaseTerminalTabComponent } from "tabby-terminal"; +import { AppService, HostWindowService } from "tabby-core"; @Injectable() export default class OscNotifyDecorator extends TerminalDecorator { + constructor( + private app: AppService, + private hostWindow: HostWindowService, + ) { + super(); + } + attach(tab: BaseTerminalTabComponent<any>): void { // Subscribe to attach to future sessions in this tab tab.sessionChanged$.subscribe((session) => { if (session) { - this.attachToSession(session, (<any>tab).title); + this.attachToSession(session, tab); } }); // Attach the current session for this tab if (tab.session) { - this.attachToSession(tab.session, (<any>tab).title); + this.attachToSession(tab.session, tab); } } - private attachToSession(session: BaseSession, tabTitle: string) { - const middleware = new OscNotifyMiddleware(tabTitle); + private attachToSession(session: BaseSession, tab: BaseTerminalTabComponent<any>) { + const middleware = new OscNotifyMiddleware( + () => (<any>tab).customTitle || (<any>tab).title, + () => { + this.hostWindow.bringToFront(); + const parent = this.app.getParentTab(tab); + this.app.selectTab(parent ?? tab); + parent?.focus(tab); + }, + ); session.middleware.push(middleware); } diff --git a/src/osc-notify-middleware.ts b/src/osc-notify-middleware.ts index 15548f4..5bd7108 100644 --- a/src/osc-notify-middleware.ts +++ b/src/osc-notify-middleware.ts @@ -5,12 +5,14 @@ const oscPrefix = Buffer.from("\x1b]"); const oscSuffix = Buffer.from("\x07"); export default class OscNotifyMiddleware extends SessionMiddleware { - tabTitle: string; + getTitle: () => string; + onClick: () => void; - constructor(tabTitle: string) { + constructor(getTitle: () => string, onClick: () => void) { super(); - this.tabTitle = tabTitle; + this.getTitle = getTitle; + this.onClick = onClick; } get cwdReported$(): Observable<string> { @@ -22,6 +24,7 @@ export default class OscNotifyMiddleware extends SessionMiddleware { private cwdReported = new Subject<string>(); private copyRequested = new Subject<string>(); + private notifications: Notification[] = []; feedFromSession(data: Buffer): void { let startIndex = 0; @@ -36,10 +39,12 @@ export default class OscNotifyMiddleware extends SessionMiddleware { const oscCode = parseInt(oscCodeString); if (oscCode === 9) { - // TODO: onclick switch to tab - new Notification(this.tabTitle, { - body: oscParams[0] - }); + const body = oscParams.slice().join(";"); + this.showNotification(this.getTitle(), body); + } else if (oscCode === 777 && oscParams[0] === "notify") { + const title = oscParams[1] || this.getTitle(); + const body = oscParams.slice(2).join(";"); + this.showNotification(title, body); } else { continue; } @@ -48,7 +53,15 @@ export default class OscNotifyMiddleware extends SessionMiddleware { super.feedFromSession(data); } + private showNotification(title: string, body: string): void { + const notification = new Notification(title || "Terminal", { body }); + notification.onclick = () => this.onClick(); + this.notifications.push(notification); + } + close(): void { + this.notifications.forEach((notification) => notification.close()); + this.notifications = []; this.cwdReported.complete(); this.copyRequested.complete(); super.close(); |
