eufon

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit a19eb2c8de508f842c4707af957d47b4e45d0b56
parent 771d80c70d624b9477eb539785237b84a3a019de
Author: Daniel Barlow <dan@telent.net>
Date:   Sun, 14 Aug 2022 14:07:49 +0000

Merge branch 'main' of gti.telent.net:dan/eufon

Diffstat:
Dcrier/crier.fnl | 273-------------------------------------------------------------------------------
Acrier/init.fnl | 273+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdefault.nix | 9++++++---
Aeufon.fnl | 200+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfennelrun.lua | 6++++--
Minit.lua | 3++-
Rjust/just.fnl -> just/init.fnl | 0
Mmodeline.fnl | 2+-
Drc.fnl | 198-------------------------------------------------------------------------------
Rsaturn/main.fnl -> saturn/init.fnl | 0
10 files changed, 486 insertions(+), 478 deletions(-)

diff --git a/crier/crier.fnl b/crier/crier.fnl @@ -1,273 +0,0 @@ -(local lgi (require :lgi)) -(local dbus (require :dbus_proxy)) -(local Gio lgi.Gio) -(local GLib lgi.GLib) -(local GV lgi.GLib.Variant) -(local GtkLayerShell lgi.GtkLayerShell) -(local variant dbus.variant) -(local Gtk lgi.Gtk) - -(fn relpath [filename] - (.. "crier/" filename)) - -(local dbus-service-attrs - { - :bus dbus.Bus.SESSION - :name "org.freedesktop.Notifications" - :interface "org.freedesktop.Notifications" - :path "/org/freedesktop/Notifications" - }) - -(local bus (dbus.Proxy:new - { - :bus dbus.Bus.SESSION - :name "org.freedesktop.DBus" - :interface "org.freedesktop.DBus" - :path "/org/freedesktop/DBus" - })) - - -(local DBUS_NAME_FLAG_DO_NOT_QUEUE 4) -(local DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1) -(local DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2) -(local DBUS_REQUEST_NAME_REPLY_EXISTS 3) -(local DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4) - - -(let [ret (bus:RequestName dbus-service-attrs.name - DBUS_NAME_FLAG_DO_NOT_QUEUE)] - (match ret - DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER - true - - DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER - true - - DBUS_REQUEST_NAME_REPLY_IN_QUEUE - (error "unexpected DBUS_REQUEST_NAME_REPLY_IN_QUEUE") - - DBUS_REQUEST_NAME_REPLY_EXISTS - (error "already running"))) - -(let [css (: (io.open (relpath "styles.css")) :read "*a") - style_provider (Gtk.CssProvider)] - (style_provider:load_from_data css) - (Gtk.StyleContext.add_provider_for_screen - (lgi.Gdk.Screen.get_default) - style_provider - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - )) - -;; for each open message there is a widget -;; when a message is closed, we need to find its widget -;; and remove it from the container -;; if there are no messages left, hide the windox - -(fn make-window [] - (let [window (Gtk.Window {:on_destroy Gtk.main_quit}) - box (Gtk.Box { - :orientation Gtk.Orientation.VERTICAL - })] - (window:add box) - (when true - (GtkLayerShell.init_for_window window) - (GtkLayerShell.set_layer window GtkLayerShell.Layer.TOP) - (GtkLayerShell.auto_exclusive_zone_enable window) - - (GtkLayerShell.set_margin window GtkLayerShell.Edge.TOP 1) - (GtkLayerShell.set_margin window GtkLayerShell.Edge.BOTTOM 10) - - (GtkLayerShell.set_anchor window GtkLayerShell.Edge.TOP 1) - (GtkLayerShell.set_anchor window GtkLayerShell.Edge.LEFT 1) - (GtkLayerShell.set_anchor window GtkLayerShell.Edge.RIGHT 1)) - (window:hide) - {:window window :box box})) - -(local window (make-window)) - -(local notifications {}) - -(fn update-window [] - (each [id widget (pairs notifications)] - (if (not (widget.widget:get_parent)) - (window.box:pack_start widget.widget false false 5))) - (if (next notifications) - (window.window:show_all) - (window.window:hide))) - -(var notification-id 10) -(fn next-notification-id [] - (set notification-id (+ notification-id 1)) - notification-id) - -(fn delete-notification [id] - (let [widget (. notifications id)] - (if widget - (do - (tset notifications id nil) - (window.box:remove widget.widget) - (update-window) - true) - (values nil "no notification with that id")))) - - -(fn update-notification-widget [widget noti] - (doto widget - (: :set-summary noti.summary) - (: :set-body noti.body) - (: :set-icon noti.app-icon) - (: :set-buttons noti.actions))) - -(fn emit-action [id action] - (bus.connection:emit_signal - nil ; destination - dbus-service-attrs.path - dbus-service-attrs.interface - "ActionInvoked" - (GV "(us)" [id action]))) - -(fn make-notification-widget [id] - (let [summary (Gtk.Label { :name "summary" }) - body (Gtk.Label) - icon (Gtk.Image) - event-box (Gtk.EventBox { - :on_button_press_event #(emit-action id "default") - }) - messages (Gtk.Box { :orientation Gtk.Orientation.VERTICAL}) - icon-and-messages (Gtk.Box { - :name "notification" - :orientation Gtk.Orientation.HORIZONTAL - }) - buttons (Gtk.Box { :orientation Gtk.Orientation.HORIZONTAL}) - with-buttons (Gtk.Box { :orientation Gtk.Orientation.VERTICAL}) - ] - (messages:pack_start summary false false 0) - (messages:pack_start body true false 0) - (icon-and-messages:pack_start icon false false 0) - (icon-and-messages:pack_start messages true true 0) - (with-buttons:pack_start icon-and-messages false false 0) - (with-buttons:pack_start buttons false false 0) - (event-box:add with-buttons) - { - :set-summary (fn [self value] - (set summary.label value)) - :set-body (fn [self value] - (set body.label value)) - :set-buttons (fn [self actions] - (each [_ child (ipairs (buttons:get_children))] - (print child) - (child:destroy)) - (when actions - (each [key label (pairs actions)] - (if (not (= key "default")) - (buttons:pack_start (Gtk.Button { - :on_clicked - #(emit-action id key) - :label label }) - true false 0))))) - :set-icon (fn [self value] - (when value - (icon:set_from_icon_name - value - Gtk.IconSize.DND - ))) - :widget event-box - })) - -(fn timeout-ms [noti] - (if (or (not noti.timeout) (= noti.timeout -1)) - 5000 - (> noti.timeout 0) - noti.timeout - (= noti.timeout 0) - nil)) - -(fn add-notification [noti] - (let [id (if (= noti.id 0) (next-notification-id) noti.id) - widget (or (. notifications id) (make-notification-widget id)) - timeout (timeout-ms noti)] - (when timeout - (lgi.GLib.timeout_add - lgi.GLib.PRIORITY_DEFAULT timeout #(do (delete-notification id) nil))) - - (update-notification-widget widget noti) - (tset notifications id widget) - (update-window) - id)) - -(fn parse-actions [list] - (let [out {}] - (for [i 1 (# list) 2] - (tset out (. list i) (. list (+ 1 i)))) - out)) - -(fn make-notification [sender id icon summary body actions hints timeout] - { - :sender sender - :id id - :app-icon icon - :summary summary - :body body - :actions (parse-actions actions) - :hints hints - :timeout timeout - }) - - -(local interface-info - (let [xml (: (io.open (relpath "interface.xml") "r") :read "*a") - node-info (Gio.DBusNodeInfo.new_for_xml xml)] - (. node-info.interfaces 1))) - -(local dbus-methods - { - "GetCapabilities" #["actions" "body" "persistence"] - "GetServerInformation" #(values "crier" "telent" "0.1" "1.2") - "Notify" #(add-notification (make-notification $...)) - "CloseNotification" (fn [id] - (let [(won err) (delete-notification id)] - (if won (values) (error err)))) - }) - -(fn args-signature [args] - (var sig "") - (each [_ v (ipairs args)] - (set sig (.. sig v.signature))) - sig) - -(fn handle-dbus-method-call [conn sender path interface method params invocation] - (when (and (= path dbus-service-attrs.path) - (= interface dbus-service-attrs.interface)) - (let [p (dbus.variant.strip params) - info (interface-info:lookup_method method) - sig (args-signature info.out_args)] - (match (table.pack (pcall (. dbus-methods method) (table.unpack p))) - [true & vals] - (invocation:return_value (GV (.. "(" sig ")") vals)) - _ - (invocation:return_value nil))))) - -(fn handle-dbus-get [conn sender path interface name] - (when (and (= path dbus-service-attrs.path) - (= interface dbus-service-attrs.interface) - (= name "Visible")) - (lgi.GLib.Variant "b" true))) - -(Gio.DBusConnection.register_object - bus.connection - dbus-service-attrs.path - interface-info - (lgi.GObject.Closure handle-dbus-method-call) - (lgi.GObject.Closure handle-dbus-get) - (lgi.GObject.Closure (fn [a] (print "set")))) - - -(add-notification { - :app-icon "dialog-information" - :body "This is an example notifiddcation." - :id 3 - :sender "notify-send" - :summary "Hello world!" - }) - -(Gtk:main) diff --git a/crier/init.fnl b/crier/init.fnl @@ -0,0 +1,273 @@ +(local lgi (require :lgi)) +(local dbus (require :dbus_proxy)) +(local Gio lgi.Gio) +(local GLib lgi.GLib) +(local GV lgi.GLib.Variant) +(local GtkLayerShell lgi.GtkLayerShell) +(local variant dbus.variant) +(local Gtk lgi.Gtk) + +(fn relpath [filename] + (.. (os.getenv "EUFON_PATH") "/crier/" filename)) + +(local dbus-service-attrs + { + :bus dbus.Bus.SESSION + :name "org.freedesktop.Notifications" + :interface "org.freedesktop.Notifications" + :path "/org/freedesktop/Notifications" + }) + +(local bus (dbus.Proxy:new + { + :bus dbus.Bus.SESSION + :name "org.freedesktop.DBus" + :interface "org.freedesktop.DBus" + :path "/org/freedesktop/DBus" + })) + + +(local DBUS_NAME_FLAG_DO_NOT_QUEUE 4) +(local DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1) +(local DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2) +(local DBUS_REQUEST_NAME_REPLY_EXISTS 3) +(local DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4) + + +(let [ret (bus:RequestName dbus-service-attrs.name + DBUS_NAME_FLAG_DO_NOT_QUEUE)] + (match ret + DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER + true + + DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER + true + + DBUS_REQUEST_NAME_REPLY_IN_QUEUE + (error "unexpected DBUS_REQUEST_NAME_REPLY_IN_QUEUE") + + DBUS_REQUEST_NAME_REPLY_EXISTS + (error "already running"))) + +(let [css (: (io.open (relpath "styles.css")) :read "*a") + style_provider (Gtk.CssProvider)] + (style_provider:load_from_data css) + (Gtk.StyleContext.add_provider_for_screen + (lgi.Gdk.Screen.get_default) + style_provider + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + )) + +;; for each open message there is a widget +;; when a message is closed, we need to find its widget +;; and remove it from the container +;; if there are no messages left, hide the windox + +(fn make-window [] + (let [window (Gtk.Window {:on_destroy Gtk.main_quit}) + box (Gtk.Box { + :orientation Gtk.Orientation.VERTICAL + })] + (window:add box) + (when true + (GtkLayerShell.init_for_window window) + (GtkLayerShell.set_layer window GtkLayerShell.Layer.TOP) + (GtkLayerShell.auto_exclusive_zone_enable window) + + (GtkLayerShell.set_margin window GtkLayerShell.Edge.TOP 1) + (GtkLayerShell.set_margin window GtkLayerShell.Edge.BOTTOM 10) + + (GtkLayerShell.set_anchor window GtkLayerShell.Edge.TOP 1) + (GtkLayerShell.set_anchor window GtkLayerShell.Edge.LEFT 1) + (GtkLayerShell.set_anchor window GtkLayerShell.Edge.RIGHT 1)) + (window:hide) + {:window window :box box})) + +(local window (make-window)) + +(local notifications {}) + +(fn update-window [] + (each [id widget (pairs notifications)] + (if (not (widget.widget:get_parent)) + (window.box:pack_start widget.widget false false 5))) + (if (next notifications) + (window.window:show_all) + (window.window:hide))) + +(var notification-id 10) +(fn next-notification-id [] + (set notification-id (+ notification-id 1)) + notification-id) + +(fn delete-notification [id] + (let [widget (. notifications id)] + (if widget + (do + (tset notifications id nil) + (window.box:remove widget.widget) + (update-window) + true) + (values nil "no notification with that id")))) + + +(fn update-notification-widget [widget noti] + (doto widget + (: :set-summary noti.summary) + (: :set-body noti.body) + (: :set-icon noti.app-icon) + (: :set-buttons noti.actions))) + +(fn emit-action [id action] + (bus.connection:emit_signal + nil ; destination + dbus-service-attrs.path + dbus-service-attrs.interface + "ActionInvoked" + (GV "(us)" [id action]))) + +(fn make-notification-widget [id] + (let [summary (Gtk.Label { :name "summary" }) + body (Gtk.Label) + icon (Gtk.Image) + event-box (Gtk.EventBox { + :on_button_press_event #(emit-action id "default") + }) + messages (Gtk.Box { :orientation Gtk.Orientation.VERTICAL}) + icon-and-messages (Gtk.Box { + :name "notification" + :orientation Gtk.Orientation.HORIZONTAL + }) + buttons (Gtk.Box { :orientation Gtk.Orientation.HORIZONTAL}) + with-buttons (Gtk.Box { :orientation Gtk.Orientation.VERTICAL}) + ] + (messages:pack_start summary false false 0) + (messages:pack_start body true false 0) + (icon-and-messages:pack_start icon false false 0) + (icon-and-messages:pack_start messages true true 0) + (with-buttons:pack_start icon-and-messages false false 0) + (with-buttons:pack_start buttons false false 0) + (event-box:add with-buttons) + { + :set-summary (fn [self value] + (set summary.label value)) + :set-body (fn [self value] + (set body.label value)) + :set-buttons (fn [self actions] + (each [_ child (ipairs (buttons:get_children))] + (print child) + (child:destroy)) + (when actions + (each [key label (pairs actions)] + (if (not (= key "default")) + (buttons:pack_start (Gtk.Button { + :on_clicked + #(emit-action id key) + :label label }) + true false 0))))) + :set-icon (fn [self value] + (when value + (icon:set_from_icon_name + value + Gtk.IconSize.DND + ))) + :widget event-box + })) + +(fn timeout-ms [noti] + (if (or (not noti.timeout) (= noti.timeout -1)) + 5000 + (> noti.timeout 0) + noti.timeout + (= noti.timeout 0) + nil)) + +(fn add-notification [noti] + (let [id (if (= noti.id 0) (next-notification-id) noti.id) + widget (or (. notifications id) (make-notification-widget id)) + timeout (timeout-ms noti)] + (when timeout + (lgi.GLib.timeout_add + lgi.GLib.PRIORITY_DEFAULT timeout #(do (delete-notification id) nil))) + + (update-notification-widget widget noti) + (tset notifications id widget) + (update-window) + id)) + +(fn parse-actions [list] + (let [out {}] + (for [i 1 (# list) 2] + (tset out (. list i) (. list (+ 1 i)))) + out)) + +(fn make-notification [sender id icon summary body actions hints timeout] + { + :sender sender + :id id + :app-icon icon + :summary summary + :body body + :actions (parse-actions actions) + :hints hints + :timeout timeout + }) + + +(local interface-info + (let [xml (: (io.open (relpath "interface.xml") "r") :read "*a") + node-info (Gio.DBusNodeInfo.new_for_xml xml)] + (. node-info.interfaces 1))) + +(local dbus-methods + { + "GetCapabilities" #["actions" "body" "persistence"] + "GetServerInformation" #(values "crier" "telent" "0.1" "1.2") + "Notify" #(add-notification (make-notification $...)) + "CloseNotification" (fn [id] + (let [(won err) (delete-notification id)] + (if won (values) (error err)))) + }) + +(fn args-signature [args] + (var sig "") + (each [_ v (ipairs args)] + (set sig (.. sig v.signature))) + sig) + +(fn handle-dbus-method-call [conn sender path interface method params invocation] + (when (and (= path dbus-service-attrs.path) + (= interface dbus-service-attrs.interface)) + (let [p (dbus.variant.strip params) + info (interface-info:lookup_method method) + sig (args-signature info.out_args)] + (match (table.pack (pcall (. dbus-methods method) (table.unpack p))) + [true & vals] + (invocation:return_value (GV (.. "(" sig ")") vals)) + _ + (invocation:return_value nil))))) + +(fn handle-dbus-get [conn sender path interface name] + (when (and (= path dbus-service-attrs.path) + (= interface dbus-service-attrs.interface) + (= name "Visible")) + (lgi.GLib.Variant "b" true))) + +(Gio.DBusConnection.register_object + bus.connection + dbus-service-attrs.path + interface-info + (lgi.GObject.Closure handle-dbus-method-call) + (lgi.GObject.Closure handle-dbus-get) + (lgi.GObject.Closure (fn [a] (print "set")))) + + +(add-notification { + :app-icon "dialog-information" + :body "This is an example notifiddcation." + :id 3 + :sender "notify-send" + :summary "Hello world!" + }) + +(Gtk:main) diff --git a/default.nix b/default.nix @@ -79,9 +79,12 @@ stdenv.mkDerivation { substitute bin/eufonctl.sh $out/bin/eufonctl \ --replace SOCAT=socat SOCAT=${socat}/bin/socat makeWrapper ${kiwmi}/bin/kiwmi $out/bin/eufon \ - --set LUA_PATH ".;$out/?.fnl;$LUA_PATH" \ - --set LUA_CPATH ".;$out/?.so;$LUA_CPATH" \ - --prefix PATH : ${kiwmi}/bin \ + --set LUA_PATH "$out/?.lua;$LUA_PATH" \ + --set LUA_CPATH "$LUA_CPATH" \ + --prefix PATH : ${kiwmi}/bin:${luaWithPackages}/bin \ + --set EUFON_PATH "$out" \ + --set GIO_EXTRA_MODULES "${glib-networking}/lib/gio/modules" \ + --set GI_TYPELIB_PATH "$GI_TYPELIB_PATH" \ --add-flags "-c $out/init.lua" chmod +x $out/bin/eufon diff --git a/eufon.fnl b/eufon.fnl @@ -0,0 +1,200 @@ +;; -*- mode: Fennel; + +(local { : view } (require :fennel)) + +(local texture (require :texture)) +(local matrix (require :matrix)) +(local socket-repl (require :socket-repl)) + +(local app-state + { + :in-overview false + :focus-view nil + :views [] + }) + +(let [repl-socket-name + (.. + (: (os.getenv "XDG_RUNTIME_DIR") :gsub "/$" "") + "/kiwmi-repl." + (os.getenv "WAYLAND_DISPLAY") + ".socket" + )] + (socket-repl.start repl-socket-name)) + +(fn resize-wayland-backend [output] + (when (string.find (output:name) "^WL-") + (output:set_mode 360 720 0))) + +(fn kill-window [] + (print "DIE") + true) + +(fn launch [] + (print "WHOOSH") + true) + +(fn eufon-path [f] + (.. (os.getenv "EUFON_PATH") "/" f)) + +(fn show-overview [] + (let [facets 64 + angle (/ (* 2 math.pi) facets) + scale 0.6 + y-offset (+ (* 1 680) + (/ (* 360 facets) (* 2 math.pi))) + ] + (each [i view (ipairs app-state.views)] + (doto view + (: :set_matrix + (-> matrix.identity + (matrix.scale scale scale) + (matrix.translate (* 2 180) (+ y-offset)) + (matrix.rotate (/ (* (- i 2 + ) angle) 1)) + (matrix.translate (* -2 180) (- y-offset)) + (matrix.translate 120 150) + )) + (: :show))))) + + +(fn hide-overview [] + (each [k view (pairs app-state.views)] + (view:set_matrix matrix.identity) + (if (= (view:id) (app-state.focus-view:id)) + (doto view + (: :show) + (: :focus)) + (view:hide)))) + +(fn carousel [] + (let [was app-state.in-overview] + (if was + (hide-overview) + (show-overview)) + (: (kiwmi:active_output) :redraw) + (tset app-state :in-overview (not was)))) + +(fn placements [output] + (let [(width height) (output:size) + bar-height (/ height 15)] + { + + :application { + :x 0 + :y 0 + :w width + :h (- height (* bar-height 1.1)) + } + :bar { + :x 0 + :y (- height (* bar-height 1.1)) + :w width + :h (* bar-height 1.1) + } + :kill { + :x (- (* width 0.25) (/ bar-height 2)) + :y (- height bar-height) + :w bar-height + :h bar-height + :on-press kill-window + } + :launch { + :x (- (* width 0.5) (/ bar-height 2)) + :y (- height bar-height) + :w bar-height + :h bar-height + :on-press launch + } + :overview { + :x (- (* width 0.75) (/ bar-height 2)) + :y (- height bar-height) + :w bar-height + :h bar-height + :on-press carousel + } + })) + +(fn choose-view-at [x y] + (let [view (kiwmi:view_at x y)] + (tset app-state :focus-view view) + (tset app-state :in-overview false) + (hide-overview) + true)) + +(let [cursor (kiwmi:cursor)] + (cursor:on "button_up" + (fn [button-id] + (when app-state.in-overview + (let [geom (placements (kiwmi:active_output)) + (x y) (cursor:pos)] + (if (< y geom.application.h) + (choose-view-at x y) + false)))))) + +(kiwmi:on + "output" + (fn [output] + (resize-wayland-backend output) + (let [(width height) (output:size) + r (output:renderer) + kill (texture.from-file r (eufon-path "close-window.png")) + launch (texture.from-file r (eufon-path "launcher.png")) + overview (texture.from-file r (eufon-path "carousel.png"))] + (output:on "render" + (fn [{: output : renderer}] + (let [buttons (placements output)] + (renderer:draw_rect :#77000077 + buttons.bar.x buttons.bar.y + buttons.bar.w buttons.bar.h) + (renderer:draw_texture + kill + matrix.identity + buttons.kill.x buttons.kill.y + 0.7) + (renderer:draw_texture + launch + matrix.identity + buttons.launch.x buttons.launch.y + 0.7) + (renderer:draw_texture + overview + matrix.identity + buttons.overview.x buttons.overview.y + 0.7))))))) + + +(let [cursor (kiwmi:cursor)] + (cursor:on "button_down" + (fn [button] + (let [(x y) (cursor:pos)] + (each [name attribs (pairs (placements (kiwmi:active_output)))] + (if (and + (<= attribs.x x) + (< x (+ attribs.x attribs.w)) + (<= attribs.y y) + (< y (+ attribs.y attribs.h))) + (if attribs.on-press (attribs.on-press)))))))) + +(kiwmi:on "view" + (fn [view] + (let [geom (placements (kiwmi:active_output))] + (view:resize geom.application.w geom.application.h) + (view:move geom.application.x geom.application.y)) + (view:focus) + (view:show) + (tset app-state :focus-view view) + (table.insert app-state.views view) + (view:on "request_move" #(view:imove)) + (view:on "request_resize" (fn [ev] (view:iresize ev.edges))))) + +(kiwmi:spawn "swaybg -c '#ff00ff'") +(kiwmi:spawn "lua -l fennelrun modeline") +;(kiwmi:spawn "lua -l fennelrun saturn") +(kiwmi:spawn "lua -l fennelrun crier") +(kiwmi:spawn "lua -l fennelrun just https://brvt.telent.net") +;(kiwmi:spawn "foot") + +;; Local Variables: +;; inferior-lisp-program: "eufonctl" +;; End: diff --git a/fennelrun.lua b/fennelrun.lua @@ -1,4 +1,6 @@ local fennel = require("fennel") table.insert(package.loaders or package.searchers, fennel.searcher) --- print(fennel.view(arg)) -fennel.dofile(arg[0], { correlate = true }) +fennel.path = os.getenv("EUFON_PATH") .. "/?.fnl;" .. + os.getenv("EUFON_PATH") .. "/?/init.fnl;" + +require(arg[0]) diff --git a/init.lua b/init.lua @@ -3,4 +3,5 @@ print(os.getenv("LUA_CPATH")) local fennel = require("fennel") table.insert(package.loaders or package.searchers, fennel.searcher) -fennel.dofile("rc.fnl") +fennel.path = fennel.path .. ";" .. os.getenv("EUFON_PATH") .. "/?.fnl" +require("eufon") diff --git a/just/just.fnl b/just/init.fnl diff --git a/modeline.fnl b/modeline.fnl @@ -9,7 +9,7 @@ ;(local battery (require :blinkenlicht.metric.battery)) (local cpustat (require :blinkenlicht.metric.cpustat)) -(stylesheet "modeline.css") +(stylesheet (.. (os.getenv "EUFON_PATH") "/modeline.css")) (fn battery-icon-codepoint [status percent] (if (= status "Charging") 0xf0e7 diff --git a/rc.fnl b/rc.fnl @@ -1,198 +0,0 @@ -;; -*- mode: Fennel; - -(local { : view } (require :fennel)) - -(local texture (require :texture)) -(local matrix (require :matrix)) -(local socket-repl (require :socket-repl)) - -(local app-state - { - :in-overview false - :focus-view nil - :views [] - }) - -(let [repl-socket-name - (.. - (: (os.getenv "XDG_RUNTIME_DIR") :gsub "/$" "") - "/kiwmi-repl." - (os.getenv "WAYLAND_DISPLAY") - ".socket" - )] - (socket-repl.start repl-socket-name)) - -(fn resize-wayland-backend [output] - (when (string.find (output:name) "^WL-") - (output:set_mode 360 720 0))) - -(fn kill-window [] - (print "DIE") - true) - -(fn launch [] - (print "WHOOSH") - true) - -(fn show-overview [] - (let [facets 64 - angle (/ (* 2 math.pi) facets) - scale 0.6 - y-offset (+ (* 1 680) - (/ (* 360 facets) (* 2 math.pi))) - ] - (each [i view (ipairs app-state.views)] - (doto view - (: :set_matrix - (-> matrix.identity - (matrix.scale scale scale) - (matrix.translate (* 2 180) (+ y-offset)) - (matrix.rotate (/ (* (- i 2 - ) angle) 1)) - (matrix.translate (* -2 180) (- y-offset)) - (matrix.translate 120 150) - )) - (: :show))))) - - -(fn hide-overview [] - (each [k view (pairs app-state.views)] - (view:set_matrix matrix.identity) - (if (= (view:id) (app-state.focus-view:id)) - (doto view - (: :show) - (: :focus)) - (view:hide)))) - -(fn carousel [] - (let [was app-state.in-overview] - (if was - (hide-overview) - (show-overview)) - (: (kiwmi:active_output) :redraw) - (tset app-state :in-overview (not was)))) - -(fn placements [output] - (let [(width height) (output:size) - bar-height (/ height 15)] - { - - :application { - :x 0 - :y 0 - :w width - :h (- height (* bar-height 1.1)) - } - :bar { - :x 0 - :y (- height (* bar-height 1.1)) - :w width - :h (* bar-height 1.1) - } - :kill { - :x (- (* width 0.25) (/ bar-height 2)) - :y (- height bar-height) - :w bar-height - :h bar-height - :on-press kill-window - } - :launch { - :x (- (* width 0.5) (/ bar-height 2)) - :y (- height bar-height) - :w bar-height - :h bar-height - :on-press launch - } - :overview { - :x (- (* width 0.75) (/ bar-height 2)) - :y (- height bar-height) - :w bar-height - :h bar-height - :on-press carousel - } - })) - -(fn choose-view-at [x y] - (let [view (kiwmi:view_at x y)] - (tset app-state :focus-view view) - (tset app-state :in-overview false) - (hide-overview) - true)) - -(let [cursor (kiwmi:cursor)] - (cursor:on "button_up" - (fn [button-id] - (when app-state.in-overview - (let [geom (placements (kiwmi:active_output)) - (x y) (cursor:pos)] - (if (< y geom.application.h) - (choose-view-at x y) - false)))))) - -(kiwmi:on - "output" - (fn [output] - (resize-wayland-backend output) - (let [(width height) (output:size) - r (output:renderer) - kill (texture.from-file r "close-window.png") - launch (texture.from-file r "launcher.png") - overview (texture.from-file r "carousel.png")] - (output:on "render" - (fn [{: output : renderer}] - (let [buttons (placements output)] - (renderer:draw_rect :#77000077 - buttons.bar.x buttons.bar.y - buttons.bar.w buttons.bar.h) - (renderer:draw_texture - kill - matrix.identity - buttons.kill.x buttons.kill.y - 0.7) - (renderer:draw_texture - launch - matrix.identity - buttons.launch.x buttons.launch.y - 0.7) - (renderer:draw_texture - overview - matrix.identity - buttons.overview.x buttons.overview.y - 0.7))))))) - - -(let [cursor (kiwmi:cursor)] - (cursor:on "button_down" - (fn [button] - (let [(x y) (cursor:pos)] - (each [name attribs (pairs (placements (kiwmi:active_output)))] - (if (and - (<= attribs.x x) - (< x (+ attribs.x attribs.w)) - (<= attribs.y y) - (< y (+ attribs.y attribs.h))) - (if attribs.on-press (attribs.on-press)))))))) - -(kiwmi:on "view" - (fn [view] - (let [geom (placements (kiwmi:active_output))] - (view:resize geom.application.w geom.application.h) - (view:move geom.application.x geom.application.y)) - (view:focus) - (view:show) - (tset app-state :focus-view view) - (table.insert app-state.views view) - (view:on "request_move" #(view:imove)) - (view:on "request_resize" (fn [ev] (view:iresize ev.edges))))) - - -;(kiwmi:spawn "swaybg -c '#ff00ff'") -(kiwmi:spawn "lua -l fennelrun modeline.fnl") -(kiwmi:spawn "lua -l fennelrun saturn/main.fnl") -(kiwmi:spawn "lua -l fennelrun crier/crier.fnl") -(kiwmi:spawn "lua -l fennelrun just/just.fnl") -;(kiwmi:spawn "foot") - -;; Local Variables: -;; inferior-lisp-program: "eufonctl" -;; End: diff --git a/saturn/main.fnl b/saturn/init.fnl