From e5251d23f158c7cc092121c3a7cc0438a73746ec Mon Sep 17 00:00:00 2001 From: Aylur Date: Mon, 15 Jul 2024 22:09:58 +0200 Subject: remove python and node I have no desire to work on the python version The node version has the issue of promises not working which makes it unusable but gjs works just as good if not better. Might look back into node later --- node/src/application.ts | 78 ----------------- node/src/astalify.ts | 227 ------------------------------------------------ node/src/binding.ts | 78 ----------------- node/src/imports.ts | 9 -- node/src/index.ts | 9 -- node/src/process.ts | 68 --------------- node/src/time.ts | 20 ----- node/src/variable.ts | 222 ---------------------------------------------- node/src/widgets.ts | 37 -------- 9 files changed, 748 deletions(-) delete mode 100644 node/src/application.ts delete mode 100644 node/src/astalify.ts delete mode 100644 node/src/binding.ts delete mode 100644 node/src/imports.ts delete mode 100644 node/src/index.ts delete mode 100644 node/src/process.ts delete mode 100644 node/src/time.ts delete mode 100644 node/src/variable.ts delete mode 100644 node/src/widgets.ts (limited to 'node/src') diff --git a/node/src/application.ts b/node/src/application.ts deleted file mode 100644 index 13a999c..0000000 --- a/node/src/application.ts +++ /dev/null @@ -1,78 +0,0 @@ -import gi from "node-gtk" -const Astal = gi.require("Astal", "0.1") - -type RequestHandler = { - (request: string, res: (response: any) => void): void -} - -type Config = Partial<{ - instanceName: string - gtkTheme: string - iconTheme: string - cursorTheme: string - css: string - requestHandler: RequestHandler - hold: boolean -}> - -class AstalJS extends Astal.Application { - static GTypeName = "AstalJS" - static { gi.registerClass(this) } - - eval(body: string): Promise { - return new Promise((res, rej) => { - try { - const fn = Function(`return (async function() { - ${body.includes(";") ? body : `return ${body};`} - })`) - fn()() - .then(res) - .catch(rej) - } catch (error) { - rej(error) - } - }) - } - - requestHandler?: RequestHandler - - vfunc_request(msg: string, conn: any): void { - if (typeof this.requestHandler === "function") { - this.requestHandler(msg, response => { - Astal.writeSock(conn, String(response), (_, res) => - Astal.writeSockFinish(res), - ) - }) - } else { - // @ts-expect-error missing type - super.vfunc_request(msg, conn) - } - } - - start( - { requestHandler, css, ...cfg }: Omit = {}, - callback?: (args: string[]) => any, - ) { - Object.assign(this, cfg) - - this.requestHandler = requestHandler - this.on("activate", () => { - callback?.(process.argv) - }) - - if (!this.acquireSocket()) { - console.error(`Astal instance "${this.instanceName}" already running`) - process.exit() - } - - if (css) - this.applyCss(css, false) - - // FIXME: promises never resolve - // https://github.com/romgrk/node-gtk/issues/121 - // https://gitlab.gnome.org/GNOME/gjs/-/issues/468 - App.run([]) - } -} - -export const App = new AstalJS diff --git a/node/src/astalify.ts b/node/src/astalify.ts deleted file mode 100644 index 9f83e71..0000000 --- a/node/src/astalify.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { Astal, Gtk } from "./imports.js" -import Binding, { kebabify, type Connectable, type Subscribable } from "./binding.js" - -export type Widget = InstanceType & { - className: string - css: string - cursor: Cursor - hook( - object: Connectable, - signal: string, - callback: (self: Widget, ...args: any[]) => void, - ): Widget - hook( - object: Subscribable, - callback: (self: Widget, ...args: any[]) => void, - ): Widget -} - - -function setter(prop: string) { - return `set${prop.charAt(0).toUpperCase() + prop.slice(1)}` -} - -function hook( - self: any, - object: Connectable | Subscribable, - signalOrCallback: string | ((self: any, ...args: any[]) => void), - callback?: (self: any, ...args: any[]) => void, -) { - if (typeof object.connect === "function" && callback) { - const id = object.connect(signalOrCallback, (_: any, ...args: unknown[]) => { - callback(self, ...args) - }) - self.connect("destroy", () => { - (object.disconnect as Connectable["disconnect"])(id) - }) - } - - else if (typeof object.subscribe === "function" && typeof signalOrCallback === "function") { - const unsub = object.subscribe((...args: unknown[]) => { - signalOrCallback(self, ...args) - }) - self.connect("destroy", unsub) - } - - return self -} - -function setChild(parent: any, child: any) { - if (parent instanceof Gtk.Bin) { - if (parent.getChild()) - parent.remove(parent.getChild()!) - } - if (parent instanceof Gtk.Container) - parent.add(child) -} - -function ctor(self: any, config: any, ...children: any[]) { - const { setup, child, ...props } = config - props.visible ??= true - - const bindings = Object.keys(props).reduce((acc: any, prop) => { - if (props[prop] instanceof Binding) { - const bind = [prop, props[prop]] - prop === "child" - ? setChild(self, props[prop].get()) - : self[setter(prop)](props[prop].get()) - - delete props[prop] - return [...acc, bind] - } - return acc - }, []) - - const onHandlers = Object.keys(props).reduce((acc: any, key) => { - if (key.startsWith("on")) { - const sig = kebabify(key).split("-").slice(1).join("-") - const handler = [sig, props[key]] - delete props[key] - return [...acc, handler] - } - return acc - }, []) - - Object.assign(self, props) - Object.assign(self, { - hook(obj: any, sig: any, callback: any) { - return hook(self, obj, sig, callback) - }, - }) - - if (child instanceof Binding) { - setChild(self, child.get()) - self.connect("destroy", child.subscribe(v => { - setChild(self, v) - })) - } else if (self instanceof Gtk.Container && child instanceof Gtk.Widget) { - self.add(child) - } - - for (const [signal, callback] of onHandlers) - self.connect(signal, callback) - - if (self instanceof Gtk.Container && children) { - for (const child of children) - self.add(child) - } - - for (const [prop, bind] of bindings) { - self.connect("destroy", bind.subscribe((v: any) => { - self[`${setter(prop)}`](v) - })) - } - - setup?.(self) - return self -} - -function proxify< - C extends { new(...args: any[]): any }, ->(klass: C) { - Object.defineProperty(klass.prototype, "className", { - get() { return Astal.widgetGetClassNames(this).join(" ") }, - set(v) { Astal.widgetSetClassNames(this, v.split(/\s+/)) }, - }) - - Object.defineProperty(klass.prototype, "css", { - get() { return Astal.widgetGetCss(this) }, - set(v) { Astal.widgetSetCss(this, v) }, - }) - - Object.defineProperty(klass.prototype, "cursor", { - get() { return Astal.widgetGetCursor(this) }, - set(v) { Astal.widgetSetCursor(this, v) }, - }) - - const proxy = new Proxy(klass, { - construct(_, [conf, ...children]) { - const self = new klass - return ctor(self, conf, ...children) - }, - apply(_t, _a, [conf, ...children]) { - const self = new klass - return ctor(self, conf, ...children) - }, - }) - - return proxy -} - -export default function astalify< - C extends typeof Gtk.Widget, - P extends Record, - N extends string = "Widget", ->(klass: C) { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - type Astal = Omit & { - new(props: P, ...children: InstanceType[]): Widget - (props: P, ...children: InstanceType[]): Widget - } - - return proxify(klass) as unknown as Astal -} - - -type BindableProps = { - [K in keyof T]: Binding> | T[K]; -} - -type SigHandler< - W extends { new(...args: any): Gtk.Widget }, - Args extends Array, -> = ((self: Widget, ...args: Args) => unknown) | string | string[] - -export type ConstructProps< - Self extends { new(...args: any[]): any }, - Props = unknown, - Signals extends Record<`on${string}`, Array> = Record<`on${string}`, any[]> -> = Partial<{ - [S in keyof Signals]: SigHandler -}> & Partial<{ - [Key in `on${string}`]: SigHandler -}> & BindableProps & { - onDestroy?: (self: Widget) => unknown - onDraw?: (self: Widget) => unknown - setup?: (self: Widget) => void -} - -type Cursor = - | "default" - | "help" - | "pointer" - | "context-menu" - | "progress" - | "wait" - | "cell" - | "crosshair" - | "text" - | "vertical-text" - | "alias" - | "copy" - | "no-drop" - | "move" - | "not-allowed" - | "grab" - | "grabbing" - | "all-scroll" - | "col-resize" - | "row-resize" - | "n-resize" - | "e-resize" - | "s-resize" - | "w-resize" - | "ne-resize" - | "nw-resize" - | "sw-resize" - | "se-resize" - | "ew-resize" - | "ns-resize" - | "nesw-resize" - | "nwse-resize" - | "zoom-in" - | "zoom-out" diff --git a/node/src/binding.ts b/node/src/binding.ts deleted file mode 100644 index a8b6d55..0000000 --- a/node/src/binding.ts +++ /dev/null @@ -1,78 +0,0 @@ -export const kebabify = (str: string) => str - .replace(/([a-z])([A-Z])/g, "$1-$2") - .replaceAll("_", "-") - .toLowerCase() - -export interface Subscribable { - subscribe(callback: () => void): () => void - get(): T - [key: string]: any -} - -export interface Connectable { - connect(signal: string, callback: (...args: any[]) => unknown): number - disconnect(id: number): void - [key: string]: any -} - -export default class Binding { - private emitter: Subscribable | Connectable - private prop?: string - private transformFn = (v: any) => v - - static bind< - T extends Connectable, - P extends keyof T, - >(object: T, property: P): Binding - - static bind(object: Subscribable): Binding - - static bind(emitter: Connectable | Subscribable, prop?: string) { - return new Binding(emitter, prop) - } - - private constructor(emitter: Connectable | Subscribable, prop?: string) { - this.emitter = emitter - this.prop = prop && kebabify(prop) - } - - toString() { - return `Binding<${this.emitter}${this.prop ? `, "${this.prop}"` : ""}>` - } - - as(fn: (v: Value) => T): Binding { - const bind = new Binding(this.emitter, this.prop) - bind.transformFn = (v: Value) => fn(this.transformFn(v)) - return bind as unknown as Binding - } - - get(): Value { - if (typeof this.emitter.get === "function") - return this.transformFn(this.emitter.get()) - - if (typeof this.prop === "string") - return this.transformFn(this.emitter[this.prop]) - - throw Error("can not get value of binding") - } - - subscribe(callback: (value: Value) => void): () => void { - if (typeof this.emitter.subscribe === "function") { - return this.emitter.subscribe(() => { - callback(this.get()) - }) - } - else if (typeof this.emitter.connect === "function") { - const signal = `notify::${this.prop}` - const id = this.emitter.connect(signal, () => { - callback(this.get()) - }) - return () => { - (this.emitter.disconnect as Connectable["disconnect"])(id) - } - } - throw Error(`${this.emitter} is not bindable`) - } -} - -export const { bind } = Binding diff --git a/node/src/imports.ts b/node/src/imports.ts deleted file mode 100644 index c2a9c71..0000000 --- a/node/src/imports.ts +++ /dev/null @@ -1,9 +0,0 @@ -import gi from "node-gtk" - -export { gi } -export const Gtk = gi.require("Gtk", "3.0") -export const Gdk = gi.require("Gdk", "3.0") -export const GLib = gi.require("GLib", "2.0") -export const Gio = gi.require("Gio", "3.0") -export const GObject = gi.require("GObject", "2.0") -export const Astal = gi.require("Astal", "0.1") diff --git a/node/src/index.ts b/node/src/index.ts deleted file mode 100644 index 5270469..0000000 --- a/node/src/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { subprocess, exec, execAsync } from "./process.js" -export { interval, timeout, idle } from "./time.js" -export { bind } from "./binding.js" -export { Variable } from "./variable.js" -export * as Widget from "./widgets.js" -export { App } from "./application.js" - -// for convinience -export { Astal, Gtk, Gdk, GLib, GObject, Gio, gi } from "./imports.js" diff --git a/node/src/process.ts b/node/src/process.ts deleted file mode 100644 index 604e142..0000000 --- a/node/src/process.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Astal } from "./imports.js" - -type Process = ReturnType - -type Args = { - cmd: string | string[], - out?: (stdout: string) => Out, - err?: (stderr: string) => Err, -} - -export function args(argsOrCmd: Args | string | string[], onOut: O, onErr: E) { - const params = Array.isArray(argsOrCmd) || typeof argsOrCmd === "string" - return { - cmd: params ? argsOrCmd : argsOrCmd.cmd, - err: params ? onErr : argsOrCmd.err || onErr, - out: params ? onOut : argsOrCmd.out || onOut, - } -} - -export function subprocess(args: Args): Process -export function subprocess( - cmd: string | string[], - onOut?: (stdout: string) => void, - onErr?: (stderr: string) => void, -): Process -export function subprocess( - argsOrCmd: Args | string | string[], - onOut: (stdout: string) => void = console.log, - onErr: (stderr: string) => void = console.error, -) { - const { cmd, err, out } = args(argsOrCmd, onOut, onErr) - const proc = Array.isArray(cmd) - ? Astal.Process.subprocessv(cmd) - : Astal.Process.subprocess(cmd) - - proc.connect("stdout", (_: any, stdout: string) => out(stdout)) - proc.connect("stderr", (_: any, stderr: string) => err(stderr)) - return proc -} - -export function exec( - args: Args -): Out | Err -export function exec( - cmd: string | string[], - onOut?: (stdout: string) => Out, - onErr?: (stderr: string) => Err, -): Out | Err -export function exec( - argsOrCmd: Args | string | string[], - onOut: (stdout: string) => Out = out => out as Out, - onErr: (stderr: string) => Err = out => out as Err, -): Out | Err { - const { cmd, err, out } = args(argsOrCmd, onOut, onErr) - return Array.isArray(cmd) - ? out(Astal.Process.execv(cmd)!) as Out - : err(Astal.Process.exec(cmd)!) as Err -} - -export function execAsync(cmd: string | string[]): Promise { - const proc = Array.isArray(cmd) - ? Astal.Process.execAsyncv(cmd) - : Astal.Process.execAsync(cmd) - return new Promise((resolve, reject) => { - proc.connect("stdout", (_: any, out: string) => resolve(out)) - proc.connect("stderr", (_: any, err: string) => reject(err)) - }) -} diff --git a/node/src/time.ts b/node/src/time.ts deleted file mode 100644 index e72a276..0000000 --- a/node/src/time.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Astal } from "./imports.js" - - -export function interval(interval: number, callback: () => void) { - const t = Astal.Time.interval(interval, null) - t.connect("now", callback) - return t -} - -export function timeout(timeout: number, callback: () => void) { - const t = Astal.Time.timeout(timeout, null) - t.connect("now", callback) - return t -} - -export function idle(callback: () => void) { - const t = Astal.Time.idle(null) - t.connect("now", callback) - return t -} diff --git a/node/src/variable.ts b/node/src/variable.ts deleted file mode 100644 index c5fb927..0000000 --- a/node/src/variable.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { Astal } from "./imports.js" -import { interval } from "./time.js" -import { subprocess, execAsync } from "./process.js" -import Binding, { type Connectable } from "./binding.js" - -class VariableWrapper extends Function { - private variable!: InstanceType - private errHandler? = console.error - - private _value: T - private _poll?: InstanceType - private _watch?: InstanceType - - private pollInterval = 1000 - private pollExec?: string[] | string - private pollTransform?: (stdout: string, prev: T) => T - private pollFn?: (prev: T) => T | Promise - - private watchTransform?: (stdout: string, prev: T) => T - private watchExec?: string[] | string - - constructor(init: T) { - super() - this._value = init - this.variable = new Astal.VariableBase - this.variable.connect("dropped", () => { - this.stopWatch() - this.stopPoll() - }) - this.variable.connect("error", (_: any, err: string) => this.errHandler?.(err)) - return new Proxy(this, { - apply: (target, _, args) => target._call(args[0]), - }) - } - - private _call(transform?: (value: T) => R): Binding { - const b = Binding.bind(this) - return transform ? b.as(transform) : b as unknown as Binding - } - - toString() { - return String(`Variable<${this.get()}>`) - } - - get(): T { return this._value } - set(value: T) { - if (value !== this._value) { - this._value = value - this.variable.emit("changed") - } - } - - startPoll() { - if (this._poll) - return - - if (this.pollFn) { - this._poll = interval(this.pollInterval, () => { - const v = this.pollFn!(this.get()) - if (v instanceof Promise) { - v.then(v => this.set(v)) - .catch(err => this.variable.emit("error", err)) - } else { - this.set(v) - } - }) - } else if (this.pollExec) { - this._poll = interval(this.pollInterval, () => { - execAsync(this.pollExec!) - .then(v => this.set(this.pollTransform!(v, this.get()))) - .catch(err => this.variable.emit("error", err)) - }) - } - } - - startWatch() { - if (this._watch) - return - - this._watch = subprocess({ - cmd: this.watchExec!, - out: out => this.set(this.watchTransform!(out, this.get())), - err: err => this.variable.emit("error", err), - }) - } - - stopPoll() { - this._poll?.cancel() - delete this._poll - } - - stopWatch() { - this._watch?.kill() - delete this._watch - } - - isPolling() { return !!this._poll } - isWatching() { return !!this._watch } - - drop() { - this.variable.emit("dropped") - this.variable.runDispose() - } - - onDropped(callback: () => void) { - this.variable.connect("dropped", callback) - return this as unknown as Variable - } - - onError(callback: (err: string) => void) { - delete this.errHandler - this.variable.connect("error", (_: any, err: string) => callback(err)) - return this as unknown as Variable - } - - subscribe(callback: (value: T) => void) { - const id = this.variable.connect("changed", () => { - callback(this.get()) - }) - return () => this.variable.disconnect(id) - } - - poll( - interval: number, - exec: string | string[], - transform?: (stdout: string, prev: T) => T - ): Variable - - poll( - interval: number, - callback: (prev: T) => T | Promise - ): Variable - - poll( - interval: number, - exec: string | string[] | ((prev: T) => T | Promise), - transform: (stdout: string, prev: T) => T = out => out as T, - ) { - this.stopPoll() - this.pollInterval = interval - this.pollTransform = transform - if (typeof exec === "function") { - this.pollFn = exec - delete this.pollExec - } else { - this.pollExec = exec - delete this.pollFn - } - this.startPoll() - return this as unknown as Variable - } - - watch( - exec: string | string[], - transform: (stdout: string, prev: T) => T = out => out as T, - ) { - this.stopWatch() - this.watchExec = exec - this.watchTransform = transform - this.startWatch() - return this as unknown as Variable - } - - observe( - objs: Array<[obj: Connectable, signal: string]>, - callback: (...args: any[]) => T): Variable - - observe( - obj: Connectable, - signal: string, - callback: (...args: any[]) => T): Variable - - observe( - objs: Connectable | Array<[obj: Connectable, signal: string]>, - sigOrFn: string | ((...args: any[]) => T), - callback?: (...args: any[]) => T, - ) { - const f = typeof sigOrFn === "function" ? sigOrFn : callback ?? (() => this.get()) - const set = (_: Connectable, ...args: any[]) => this.set(f(...args)) - - if (Array.isArray(objs)) { - for (const obj of objs) { - const [o, s] = obj - o.connect(s, set) - } - } else { - if (typeof sigOrFn === "string") - objs.connect(sigOrFn, set) - } - - return this as unknown as Variable - } - - static derive | Binding>, - Args extends { - [K in keyof Deps]: Deps[K] extends Variable - ? T : Deps[K] extends Binding ? T : never - }, - >(deps: Deps, fn: (...args: Args) => V) { - const update = () => fn(...deps.map(d => d.get()) as Args) - const derived = new Variable(update()) - const unsubs = deps.map(dep => dep.subscribe(() => derived.set(update()))) - derived.onDropped(() => unsubs.map(unsub => unsub())) - return derived - } -} - -export interface Variable extends Omit, "bind"> { - (transform: (value: T) => R): Binding - (): Binding -} - -export const Variable = new Proxy(VariableWrapper as any, { - apply: (_t, _a, args) => new VariableWrapper(args[0]), -}) as { - derive: typeof VariableWrapper["derive"] - (init: T): Variable - new (init: T): Variable -} - -export default Variable diff --git a/node/src/widgets.ts b/node/src/widgets.ts deleted file mode 100644 index 2ce256a..0000000 --- a/node/src/widgets.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* eslint-disable max-len */ -import { Astal, Gtk } from "./imports.js" -import astalify, { type ConstructProps } from "./astalify.js" -import type GtkT from "@girs/node-gtk-3.0/node-gtk-3.0" -import type AstalT from "@girs/node-astal-0.1/node-astal-0.1" - -export { astalify, ConstructProps } - -// Label -export const Label = astalify(Gtk.Label) -export type LabelProps = ConstructProps - -// Icon -export const Icon = astalify(Astal.Icon) -export type IconProps = ConstructProps - -// Button -export const Button = astalify(Astal.Button) -export type ButtonProps = ConstructProps - -// Window -export const Window = astalify(Astal.Window) -export type WindowProps = ConstructProps - -// Box -export const Box = astalify(Astal.Box) -export type BoxProps = ConstructProps - -// CenterBox -export const CenterBox = astalify(Astal.CenterBox) -export type CenterBoxProps = ConstructProps - -// EventBox -export const EventBox = astalify(Astal.EventBox) -export type EventBoxProps = ConstructProps -- cgit v1.2.3