From e5f7fe430d582c96b911b79dad03fad7c2d6aa9e Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Tue, 29 Aug 2023 15:43:13 +0300 Subject: refactor(tazjin/gio-list-apps): refactor into dynamic Emacs module Instead of producing a binary that gets called by Emacs, with input/output serialisation, use a dynamic Emacs module that lets Emacs more-or-less directly call the relevant GTK functions. I'm doing this mostly as an experiment. Might be interesting to end up with a dynamic module that I can dump some experimental code into that improves my workflows. To do this, I've exposed the emacs binary used by my Emacs configuration in an additional `passthru` field. This ensures that the module is linked against the right version of Emacs. Change-Id: I1426994fe3455ed1b2a685c5a09705e29fa40950 Reviewed-on: https://cl.tvl.fyi/c/depot/+/9163 Tested-by: BuildkiteCI Reviewed-by: tazjin Autosubmit: tazjin --- users/tazjin/emacs/config/functions.el | 9 +- users/tazjin/emacs/default.nix | 10 ++- users/tazjin/gio-list-apps/Cargo.lock | 146 ++++++++++++++++++++++++++++----- users/tazjin/gio-list-apps/Cargo.toml | 5 +- users/tazjin/gio-list-apps/default.nix | 9 +- users/tazjin/gio-list-apps/src/lib.rs | 31 +++++++ users/tazjin/gio-list-apps/src/main.rs | 20 ----- 7 files changed, 178 insertions(+), 52 deletions(-) create mode 100644 users/tazjin/gio-list-apps/src/lib.rs delete mode 100644 users/tazjin/gio-list-apps/src/main.rs (limited to 'users/tazjin') diff --git a/users/tazjin/emacs/config/functions.el b/users/tazjin/emacs/config/functions.el index df36c7eb882c..3739d25122ef 100644 --- a/users/tazjin/emacs/config/functions.el +++ b/users/tazjin/emacs/config/functions.el @@ -2,6 +2,8 @@ (require 'dash) (require 'map) +(require 'gio-list-apps) ;; native module! + (defun goto-line-with-feedback () "Show line numbers temporarily, while prompting for the line number input" (interactive) @@ -336,12 +338,7 @@ names, instead of only their names (which might change)." "Use `//users/tazjin/gio-list-apps' to retrieve a list of installed (and visible) XDG apps, and let users launch them." (interactive) - (let* ((apps-json (s-lines (s-trim (shell-command-to-string "gio-list-apps")))) - (apps (seq-map (lambda (app) - (let ((parsed (json-parse-string app :object-type 'alist))) - (cons (cdr (assoc 'name parsed)) - (cdr (assoc 'commandline parsed))))) - apps-json)) + (let* ((apps (taz-list-xdg-apps)) ;; Display the command that will be run as an annotation (completion-extra-properties diff --git a/users/tazjin/emacs/default.nix b/users/tazjin/emacs/default.nix index e9acf57da1dc..022d78ff4b85 100644 --- a/users/tazjin/emacs/default.nix +++ b/users/tazjin/emacs/default.nix @@ -13,7 +13,6 @@ pkgs.makeOverridable # $PATH for binaries that need to be available to Emacs emacsBinPath = lib.makeBinPath [ - depot.users.tazjin.gio-list-apps (currentTelega pkgs.emacsPackages) pkgs.libwebp # for dwebp, required by telega ]; @@ -100,6 +99,9 @@ pkgs.makeOverridable tvlPackages.rcirc tvlPackages.term-switcher tvlPackages.tvl + + # Dynamic/native modules + depot.users.tazjin.gio-list-apps ]))); # Tired of telega.el runtime breakages through tdlib @@ -138,6 +140,12 @@ pkgs.makeOverridable '').overrideAttrs (_: { passthru = { + # Expose original Emacs used for my configuration. + inherit emacs; + + # Expose the pure emacs with all packages. + emacsWithPackages = tazjinsEmacs f; + # Call overrideEmacs with a function (pkgs -> pkgs) to modify the # packages that should be included in this Emacs distribution. overrideEmacs = f': self l f'; diff --git a/users/tazjin/gio-list-apps/Cargo.lock b/users/tazjin/gio-list-apps/Cargo.lock index f35779556603..b475b35a6cba 100644 --- a/users/tazjin/gio-list-apps/Cargo.lock +++ b/users/tazjin/gio-list-apps/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + [[package]] name = "autocfg" version = "1.1.0" @@ -24,12 +30,96 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "emacs" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6797a940189d353de79bec32abe717aeeecd79a08236e84404c888354e040665" +dependencies = [ + "anyhow", + "ctor", + "emacs-macros", + "emacs_module", + "once_cell", + "rustc_version", + "thiserror", +] + +[[package]] +name = "emacs-macros" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69656fdfe7c2608b87164964db848b5c3795de7302e3130cce7131552c6be161" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "emacs_module" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3067bc974045ed2c6db333bd4fc30d3bdaafa6421a9a889fa7b2826b6f7f2fa" + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "futures-channel" version = "0.3.28" @@ -116,8 +206,8 @@ dependencies = [ name = "gio-list-apps" version = "0.1.0" dependencies = [ + "emacs", "gio", - "serde_json", ] [[package]] @@ -203,6 +293,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "indexmap" version = "2.0.0" @@ -213,12 +309,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - [[package]] name = "libc" version = "0.2.147" @@ -308,10 +398,28 @@ dependencies = [ ] [[package]] -name = "ryu" -version = "1.0.15" +name = "rustc_version" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" @@ -333,17 +441,6 @@ dependencies = [ "syn 2.0.29", ] -[[package]] -name = "serde_json" -version = "1.0.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" -dependencies = [ - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_spanned" version = "0.6.3" @@ -368,6 +465,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "syn" version = "1.0.109" @@ -375,6 +478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", + "quote", "unicode-ident", ] diff --git a/users/tazjin/gio-list-apps/Cargo.toml b/users/tazjin/gio-list-apps/Cargo.toml index f08260b9880b..eb62d1fcaf42 100644 --- a/users/tazjin/gio-list-apps/Cargo.toml +++ b/users/tazjin/gio-list-apps/Cargo.toml @@ -3,8 +3,9 @@ name = "gio-list-apps" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib"] [dependencies] +emacs = "0.18.0" gio = "0.18.1" -serde_json = "1.0.105" diff --git a/users/tazjin/gio-list-apps/default.nix b/users/tazjin/gio-list-apps/default.nix index 200bf435420d..c63f4dd48786 100644 --- a/users/tazjin/gio-list-apps/default.nix +++ b/users/tazjin/gio-list-apps/default.nix @@ -1,9 +1,14 @@ -{ pkgs, lib, ... }: +{ depot, pkgs, lib, ... }: pkgs.rustPlatform.buildRustPackage { name = "gio-list-apps"; src = lib.cleanSource ./.; cargoLock.lockFile = ./Cargo.lock; nativeBuildInputs = [ pkgs.pkg-config ]; - buildInputs = [ pkgs.gtk3 ]; + buildInputs = [ pkgs.gtk3 depot.users.tazjin.emacs.emacs ]; + + postInstall = '' + mkdir -p $out/share/emacs/site-lisp + ln -s $out/lib/libgio_list_apps.so $out/share/emacs/site-lisp/gio-list-apps.so + ''; } diff --git a/users/tazjin/gio-list-apps/src/lib.rs b/users/tazjin/gio-list-apps/src/lib.rs new file mode 100644 index 000000000000..55eb8dc0be20 --- /dev/null +++ b/users/tazjin/gio-list-apps/src/lib.rs @@ -0,0 +1,31 @@ +use emacs::{defun, Env, IntoLisp, Result, Value}; +use gio::traits::AppInfoExt; +use gio::AppInfo; + +emacs::plugin_is_GPL_compatible!(); + +#[emacs::module(defun_prefix = "taz", mod_in_name = false)] +fn init(_: &Env) -> Result<()> { + Ok(()) +} + +/// Returns an alist of the currently available XDG applications (through their +/// `.desktop' shortcuts), and the command line parameters needed to start them. +/// +/// Hidden applications or applications without specified command-line +/// parameters are not included. +#[defun] +fn list_xdg_apps(env: &Env) -> Result { + let mut visible_apps: Vec = vec![]; + + for app in AppInfo::all().into_iter().filter(AppInfo::should_show) { + if let Some(cmd) = app + .commandline() + .and_then(|p| Some(p.to_str()?.to_string())) + { + visible_apps.push(env.cons(app.name().as_str().into_lisp(env)?, cmd.into_lisp(env)?)?); + } + } + + env.list(&visible_apps) +} diff --git a/users/tazjin/gio-list-apps/src/main.rs b/users/tazjin/gio-list-apps/src/main.rs deleted file mode 100644 index c6b6b98d4d9c..000000000000 --- a/users/tazjin/gio-list-apps/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use gio::traits::AppInfoExt; -use gio::AppInfo; -use serde_json::json; - -fn main() { - for app in AppInfo::all() { - if app.should_show() { - if let Some(cmd) = app.commandline() { - println!( - "{}", - json!({ - "name": app.name().as_str(), - "display_name": app.display_name().as_str(), - "commandline": cmd, - }) - ); - } - } - } -} -- cgit 1.4.1