feat: rewrite audiomenu in Python
There is no reason for it to be a Rust program
This commit is contained in:
parent
c65e793a85
commit
66cd7b90b6
12 changed files with 290 additions and 857 deletions
2
scripts/audiomenu/.envrc
Normal file
2
scripts/audiomenu/.envrc
Normal file
|
@ -0,0 +1,2 @@
|
|||
source_up
|
||||
source .venv/bin/activate
|
2
scripts/audiomenu/.gitignore
vendored
2
scripts/audiomenu/.gitignore
vendored
|
@ -1 +1 @@
|
|||
/target
|
||||
.venv
|
||||
|
|
1
scripts/audiomenu/.python-version
Normal file
1
scripts/audiomenu/.python-version
Normal file
|
@ -0,0 +1 @@
|
|||
3.12
|
553
scripts/audiomenu/Cargo.lock
generated
553
scripts/audiomenu/Cargo.lock
generated
|
@ -1,553 +0,0 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "audiomenu"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"duct",
|
||||
"miette",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-ext"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "duct"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6ce170a0e8454fa0f9b0e5ca38a6ba17ed76a50916839d217eb5357e05cdfde"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"os_pipe",
|
||||
"shared_child",
|
||||
"shared_thread",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "is_ci"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "miette"
|
||||
version = "7.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"backtrace-ext",
|
||||
"cfg-if",
|
||||
"miette-derive",
|
||||
"owo-colors",
|
||||
"supports-color",
|
||||
"supports-hyperlinks",
|
||||
"supports-unicode",
|
||||
"terminal_size",
|
||||
"textwrap",
|
||||
"unicode-width 0.1.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miette-derive"
|
||||
version = "7.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "4.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shared_child"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e297bd52991bbe0686c086957bee142f13df85d1e79b0b21630a99d374ae9dc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shared_thread"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7a6f98357c6bb0ebace19b22220e5543801d9de90ffe77f8abb27c056bac064"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "supports-color"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
|
||||
dependencies = [
|
||||
"is_ci",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "supports-hyperlinks"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b"
|
||||
|
||||
[[package]]
|
||||
name = "supports-unicode"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
|
||||
dependencies = [
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
|
||||
dependencies = [
|
||||
"unicode-linebreak",
|
||||
"unicode-width 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-linebreak"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|
@ -1,18 +0,0 @@
|
|||
[package]
|
||||
name = "audiomenu"
|
||||
description = "fuzzel script to select the default audio device for pipewire+wireplumber"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.23", features = ["derive", "env"] }
|
||||
duct = "1.0.0"
|
||||
miette = { version = "7.4.0", features = ["fancy"] }
|
||||
serde = { version = "1.0.215", features = ["derive"] }
|
||||
serde_json = "1.0.133"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
opt-level = 's'
|
||||
panic = "abort"
|
||||
strip = true
|
0
scripts/audiomenu/README.md
Normal file
0
scripts/audiomenu/README.md
Normal file
236
scripts/audiomenu/audiomenu.py
Normal file
236
scripts/audiomenu/audiomenu.py
Normal file
|
@ -0,0 +1,236 @@
|
|||
# pyright: strict, reportAny=false
|
||||
from dataclasses import dataclass
|
||||
import json
|
||||
import subprocess
|
||||
from typing import Self
|
||||
import typing
|
||||
import click
|
||||
|
||||
|
||||
def expect[T](typ: type[T], value: object) -> T:
|
||||
if not isinstance(value, typ):
|
||||
raise ValueError(
|
||||
f"expected value to be of type {typ} but was of type {type(value)}"
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PWNodeProps:
|
||||
object_id: int
|
||||
node_description: str
|
||||
node_name: str
|
||||
media_class: str
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, data: dict[str, object]) -> Self:
|
||||
return cls(
|
||||
object_id=expect(int, data["object.id"]),
|
||||
node_description=expect(str, data.get("node.description", "(unknown)")),
|
||||
node_name=expect(str, data["node.name"]),
|
||||
media_class=expect(str, data.get("media.class", "(unknown)")),
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PWNodeInfo:
|
||||
props: PWNodeProps
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, data: dict[str, object]) -> Self:
|
||||
props = typing.cast(dict[str, object], expect(dict, data["props"]))
|
||||
return cls(PWNodeProps.from_json(props))
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PWNode:
|
||||
node_type: str
|
||||
info: PWNodeInfo | None
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, data: dict[str, object]) -> Self:
|
||||
info = data.get("info", None)
|
||||
if info is not None:
|
||||
info = PWNodeInfo.from_json(
|
||||
typing.cast(dict[str, object], expect(dict, info))
|
||||
)
|
||||
return cls(node_type=expect(str, data["type"]), info=info)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class AudioDevice:
|
||||
id: int
|
||||
name: str
|
||||
volume: float
|
||||
muted: bool
|
||||
default: bool
|
||||
|
||||
@staticmethod
|
||||
def get_volume(id: int | str) -> tuple[float, bool]:
|
||||
wpctl_output = subprocess.run(
|
||||
["wpctl", "get-volume", str(id)],
|
||||
encoding="UTF-8",
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
match wpctl_output.stdout.strip().split(sep=" "):
|
||||
case ["Volume:", value]:
|
||||
return (float(value), False)
|
||||
case ["Volume:", value, "[MUTED]"]:
|
||||
return (float(value), True)
|
||||
case _:
|
||||
raise ValueError(f"Unexpected wpctl output: {wpctl_output.stdout}")
|
||||
|
||||
@classmethod
|
||||
def from_pw_node(cls, node: PWNode, default: str) -> Self:
|
||||
if node.info is None:
|
||||
raise ValueError(f"Node is not a valid audio device {node}")
|
||||
|
||||
id = node.info.props.object_id
|
||||
volume, muted = cls.get_volume(id)
|
||||
|
||||
return cls(
|
||||
id=id,
|
||||
name=node.info.props.node_description,
|
||||
volume=volume,
|
||||
muted=muted,
|
||||
default=node.info.props.node_name == default,
|
||||
)
|
||||
|
||||
def menu_item(self) -> str:
|
||||
id = f"id={self.id:<3}"
|
||||
|
||||
if self.default:
|
||||
id = f"[{id}]"
|
||||
else:
|
||||
id = f" {id} "
|
||||
|
||||
if self.muted:
|
||||
return f"{id} {self.volume:>4.0%} [MUTED] {self.name}"
|
||||
else:
|
||||
return f"{id} {self.volume:>4.0%} {self.name}"
|
||||
|
||||
|
||||
def get_nodes(data: list[dict[str, object]]) -> list[PWNode]:
|
||||
def is_audio_node(node: object) -> bool:
|
||||
if not isinstance(node, dict):
|
||||
return False
|
||||
|
||||
node = typing.cast(dict[str, object], node)
|
||||
if node["type"] != "PipeWire:Interface:Node":
|
||||
return False
|
||||
info = node.get("info", None)
|
||||
if info is None or not isinstance(info, dict):
|
||||
return False
|
||||
info = typing.cast(dict[str, object], info)
|
||||
props = info.get("props", None)
|
||||
if props is None or not isinstance(props, dict):
|
||||
return False
|
||||
props = typing.cast(dict[str, object], props)
|
||||
if (media_class := props.get("media.class", None)) is not None:
|
||||
return isinstance(media_class, str) and media_class.startswith("Audio")
|
||||
return False
|
||||
|
||||
return [
|
||||
PWNode.from_json(typing.cast(dict[str, object], expect(dict, node)))
|
||||
for node in data
|
||||
if is_audio_node(node)
|
||||
]
|
||||
|
||||
|
||||
def pw_dump() -> list[dict[str, object]]:
|
||||
dump_output = subprocess.run(
|
||||
["pw-dump"], encoding="UTF-8", check=True, capture_output=True
|
||||
)
|
||||
data = json.loads(dump_output.stdout)
|
||||
return typing.cast(list[dict[str, object]], expect(list, data))
|
||||
|
||||
|
||||
def get_defaults_metadata(data: list[dict[str, object]]) -> list[dict[str, object]]:
|
||||
return typing.cast(
|
||||
list[dict[str, object]],
|
||||
expect(
|
||||
list,
|
||||
next(
|
||||
node
|
||||
for node in data
|
||||
if node["type"] == "PipeWire:Interface:Metadata"
|
||||
and expect(dict, node["props"])["metadata.name"] == "default"
|
||||
)["metadata"],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def get_sinks() -> list[AudioDevice]:
|
||||
data = pw_dump()
|
||||
default = next(
|
||||
typing.cast(dict[str, str], expect(dict, data["value"]))["name"]
|
||||
for data in get_defaults_metadata(data)
|
||||
if data["key"] == "default.audio.sink"
|
||||
)
|
||||
return [
|
||||
AudioDevice.from_pw_node(node, default)
|
||||
for node in get_nodes(data)
|
||||
if node.info is not None and node.info.props.media_class == "Audio/Sink"
|
||||
]
|
||||
|
||||
|
||||
def get_sources() -> list[AudioDevice]:
|
||||
data = pw_dump()
|
||||
default = next(
|
||||
typing.cast(dict[str, str], expect(dict, data["value"]))["name"]
|
||||
for data in get_defaults_metadata(data)
|
||||
if data["key"] == "default.audio.source"
|
||||
)
|
||||
return [
|
||||
AudioDevice.from_pw_node(node, default)
|
||||
for node in get_nodes(data)
|
||||
if node.info is not None and node.info.props.media_class == "Audio/Source"
|
||||
]
|
||||
|
||||
|
||||
@click.group(name="audiomenu")
|
||||
def main() -> None:
|
||||
pass
|
||||
|
||||
|
||||
def select(options: list[str], prompt:str) -> int | None:
|
||||
menu_output = subprocess.run(
|
||||
["fuzzel", "--dmenu", f"--prompt={prompt}"],
|
||||
input="\n".join(options),
|
||||
encoding="UTF-8",
|
||||
capture_output=True,
|
||||
)
|
||||
if menu_output.returncode == 2:
|
||||
return None
|
||||
menu_output.check_returncode()
|
||||
selected = menu_output.stdout.rstrip()
|
||||
return options.index(selected)
|
||||
|
||||
|
||||
@main.command()
|
||||
def select_sink() -> None:
|
||||
devices = get_sinks()
|
||||
selected = select([device.menu_item() for device in devices], prompt="Select Sink>")
|
||||
if selected is None:
|
||||
click.echo("No sink selected")
|
||||
return
|
||||
|
||||
device = devices[selected]
|
||||
_ = subprocess.run(["wpctl", "set-default", str(device.id)], check=True)
|
||||
|
||||
|
||||
@main.command()
|
||||
def select_source() -> None:
|
||||
devices = get_sources()
|
||||
selected = select([device.menu_item() for device in devices], prompt="Select Source>")
|
||||
if selected is None:
|
||||
click.echo("No source selected")
|
||||
return
|
||||
|
||||
device = devices[selected]
|
||||
_ = subprocess.run(["wpctl", "set-default", str(device.id)], check=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,22 +1,6 @@
|
|||
{
|
||||
lib,
|
||||
rustPlatform,
|
||||
cleanRustSrc,
|
||||
}:
|
||||
let
|
||||
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
|
||||
inherit (cargoToml.package) name version description;
|
||||
pname = name;
|
||||
src = cleanRustSrc ./.;
|
||||
in
|
||||
rustPlatform.buildRustPackage {
|
||||
inherit pname version src;
|
||||
cargoLock.lockFile = ./Cargo.lock;
|
||||
useNextest = true;
|
||||
meta = {
|
||||
inherit description;
|
||||
license = lib.licenses.mit;
|
||||
homepage = "https://github.com/jalil-salame/configuration.nix";
|
||||
mainProgram = name;
|
||||
};
|
||||
}
|
||||
{ writers, python3Packages }:
|
||||
writers.writePython3 "audiomenu" {
|
||||
libraries = [ python3Packages.click ];
|
||||
# line too long, but I like my code well documented
|
||||
flakeIgnore = [ "E501" ];
|
||||
} ./jpassmenu.py
|
||||
|
|
9
scripts/audiomenu/pyproject.toml
Normal file
9
scripts/audiomenu/pyproject.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[project]
|
||||
name = "audiomenu"
|
||||
version = "0.1.0"
|
||||
description = "fuzzel script to select the default audio device for pipewire+wireplumber"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"click>=8.1.7",
|
||||
]
|
|
@ -1,231 +0,0 @@
|
|||
use std::{
|
||||
fmt::{Display, Write as _},
|
||||
io::{Read, Write as _},
|
||||
process::{Command, Stdio},
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use duct::cmd;
|
||||
use miette::{bail, Context, IntoDiagnostic, Result};
|
||||
use serde::Deserialize;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
miette::set_panic_hook();
|
||||
Opts::parse().run()
|
||||
}
|
||||
|
||||
/// fuzzel script to select the default audio device for pipewire+wireplumber
|
||||
#[derive(Debug, Parser)]
|
||||
struct Opts {
|
||||
#[clap(subcommand)]
|
||||
cmd: Cmd,
|
||||
}
|
||||
|
||||
impl Opts {
|
||||
fn run(self) -> Result<()> {
|
||||
self.cmd.run()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
enum Cmd {
|
||||
/// Select audio sink (speakers/headphones)
|
||||
SelectSink,
|
||||
/// Select audio source (microphone)
|
||||
SelectSource,
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
fn run(self) -> Result<()> {
|
||||
let id = match self {
|
||||
Cmd::SelectSink => {
|
||||
let devices = get_sinks().wrap_err("failed to get sinks")?;
|
||||
let selected = select(
|
||||
devices.iter().map(|dev| dev.name.as_ref()),
|
||||
Some("Select input>"),
|
||||
)
|
||||
.wrap_err("failed to select a default sink")?;
|
||||
if selected.is_empty() {
|
||||
eprintln!("did not select a device");
|
||||
return Ok(());
|
||||
}
|
||||
let Some(dev) = devices.into_iter().find(|dev| dev.name == selected) else {
|
||||
bail!("couldn't find a device matching `{selected}`");
|
||||
};
|
||||
dev.id
|
||||
}
|
||||
Cmd::SelectSource => {
|
||||
let devices = get_sources().wrap_err("failed to get sinks")?;
|
||||
let selected = select(
|
||||
devices.iter().map(|dev| dev.name.as_ref()),
|
||||
Some("Select output>"),
|
||||
)
|
||||
.wrap_err("failed to select a default source")?;
|
||||
if selected.is_empty() {
|
||||
eprintln!("did not select a device");
|
||||
return Ok(());
|
||||
}
|
||||
let Some(dev) = devices.into_iter().find(|dev| dev.name == selected) else {
|
||||
bail!("couldn't find a device matching `{selected}`");
|
||||
};
|
||||
dev.id
|
||||
}
|
||||
};
|
||||
cmd!("wpctl", "set-default", id.to_string())
|
||||
.run()
|
||||
.map(drop)
|
||||
.into_diagnostic()
|
||||
.wrap_err("failed to set default input")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PWNode {
|
||||
#[serde(rename = "type")]
|
||||
node_type: Box<str>,
|
||||
#[serde(default)]
|
||||
info: PWNodeInfo,
|
||||
// json ignores the rest of the fields by default
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
struct PWNodeInfo {
|
||||
props: PWNodeProps,
|
||||
// json ignores the rest of the fields by default
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
struct PWNodeProps {
|
||||
#[serde(rename = "object.id")]
|
||||
object_id: u32,
|
||||
#[serde(rename = "node.description", default)]
|
||||
node_description: Box<str>,
|
||||
#[serde(rename = "media.class", default)]
|
||||
media_class: Box<str>,
|
||||
// json ignores the rest of the fields by default
|
||||
}
|
||||
|
||||
struct AudioDevice<S> {
|
||||
id: u32,
|
||||
name: Box<str>,
|
||||
_side: S,
|
||||
}
|
||||
|
||||
/// Output (e.g. speakers)
|
||||
struct AudioSink;
|
||||
|
||||
/// Input (e.g. microphone)
|
||||
struct AudioSource;
|
||||
|
||||
fn get_sinks() -> Result<Vec<AudioDevice<AudioSink>>> {
|
||||
get_devices()
|
||||
}
|
||||
|
||||
fn get_sources() -> Result<Vec<AudioDevice<AudioSource>>> {
|
||||
get_devices()
|
||||
}
|
||||
|
||||
fn get_devices<S>() -> Result<Vec<AudioDevice<S>>>
|
||||
where
|
||||
AudioDevice<S>: TryFrom<PWNode>,
|
||||
{
|
||||
Ok(get_nodes()?
|
||||
.into_iter()
|
||||
.filter_map(|node| AudioDevice::<S>::try_from(node).ok())
|
||||
.collect())
|
||||
}
|
||||
|
||||
impl TryFrom<PWNode> for AudioDevice<AudioSource> {
|
||||
type Error = miette::Report;
|
||||
|
||||
fn try_from(value: PWNode) -> std::result::Result<Self, Self::Error> {
|
||||
if value.node_type.as_ref() != "PipeWire:Interface:Node" {
|
||||
bail!(
|
||||
"invalid type: `{}`, expected `PipeWire:Interface:Node`",
|
||||
value.node_type
|
||||
)
|
||||
}
|
||||
let class = value.info.props.media_class;
|
||||
match class.as_ref() {
|
||||
"Audio/Source" => Ok(Self {
|
||||
id: value.info.props.object_id,
|
||||
name: value.info.props.node_description,
|
||||
_side: AudioSource,
|
||||
}),
|
||||
_ => bail!("invalid media.class: `{class}`, expected `Audio/Source`"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PWNode> for AudioDevice<AudioSink> {
|
||||
type Error = miette::Report;
|
||||
|
||||
fn try_from(value: PWNode) -> std::result::Result<Self, Self::Error> {
|
||||
if value.node_type.as_ref() != "PipeWire:Interface:Node" {
|
||||
bail!(
|
||||
"invalid type: `{}`, expected `PipeWire:Interface:Node`",
|
||||
value.node_type
|
||||
)
|
||||
}
|
||||
let class = value.info.props.media_class;
|
||||
match class.as_ref() {
|
||||
"Audio/Sink" => Ok(Self {
|
||||
id: value.info.props.object_id,
|
||||
name: value.info.props.node_description,
|
||||
_side: AudioSink,
|
||||
}),
|
||||
_ => bail!("invalid media.class: `{class}`, expected `Audio/Sink`"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_nodes() -> Result<Vec<PWNode>> {
|
||||
let dump = cmd!("pw-dump")
|
||||
.read()
|
||||
.into_diagnostic()
|
||||
.wrap_err("failed to get devices with pw-dump")?;
|
||||
serde_json::from_str(&dump)
|
||||
.into_diagnostic()
|
||||
.wrap_err("failed to parse pw-dump output")
|
||||
}
|
||||
|
||||
fn select<T, It>(options: It, prompt: Option<&str>) -> Result<Box<str>>
|
||||
where
|
||||
T: Display,
|
||||
It: IntoIterator<Item = T>,
|
||||
{
|
||||
let append_line = |mut s: String, it| {
|
||||
writeln!(s, "{it}").unwrap();
|
||||
s
|
||||
};
|
||||
let options = options.into_iter().fold(String::new(), append_line);
|
||||
let mut menu = Command::new("fuzzel");
|
||||
menu.arg("--dmenu");
|
||||
if let Some(prompt) = prompt {
|
||||
menu.arg(format!("--prompt={prompt}"));
|
||||
}
|
||||
Ok(pipe_to_stdin_and_return_stdout(&mut menu, options)?
|
||||
.trim()
|
||||
.into())
|
||||
}
|
||||
|
||||
fn pipe_to_stdin_and_return_stdout(cmd: &mut Command, data: impl Display) -> Result<String> {
|
||||
let mut child = cmd
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("failed to run {cmd:?}"))?;
|
||||
let mut stdin = child.stdin.take().expect("stdin not piped");
|
||||
write!(stdin, "{data}")
|
||||
.into_diagnostic()
|
||||
.wrap_err("failed to send data to process' stdin")?;
|
||||
drop(stdin);
|
||||
let mut stdout = child.stdout.take().expect("stdout not piped");
|
||||
let mut buf = String::new();
|
||||
stdout
|
||||
.read_to_string(&mut buf)
|
||||
.into_diagnostic()
|
||||
.wrap_err("failed to retrieve output from process")?;
|
||||
Ok(buf)
|
||||
}
|
34
scripts/audiomenu/uv.lock
generated
Normal file
34
scripts/audiomenu/uv.lock
generated
Normal file
|
@ -0,0 +1,34 @@
|
|||
version = 1
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "audiomenu"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "click", specifier = ">=8.1.7" }]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/cd/0f/62ca20172d4f87d93cf89665fbaedcd560ac48b465bd1d92bfc7ea6b0a41/click-8.2.0.tar.gz", hash = "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d", size = 235857 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/58/1f37bf81e3c689cc74ffa42102fa8915b59085f54a6e4a80bc6265c0f6bf/click-8.2.0-py3-none-any.whl", hash = "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c", size = 102156 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
||||
]
|
|
@ -1,38 +1,7 @@
|
|||
{ lib, ... }:
|
||||
let
|
||||
# Clean the package source leaving only the relevant rust files
|
||||
cleanRustSrc =
|
||||
pname: src:
|
||||
lib.cleanSourceWith {
|
||||
inherit src;
|
||||
name = "${pname}-source";
|
||||
# Adapted from <https://github.com/ipetkov/crane/blob/master/lib/filterCargoSources.nix>
|
||||
# no need to pull in crane for just this
|
||||
filter =
|
||||
orig_path: type:
|
||||
let
|
||||
path_str = toString orig_path;
|
||||
base = baseNameOf path_str;
|
||||
parentDir = baseNameOf (dirOf path_str);
|
||||
matchesSuffix = lib.any (suffix: lib.hasSuffix suffix base) [
|
||||
# Rust sources
|
||||
".rs"
|
||||
# TOML files are often used to configure cargo based tools (e.g. .cargo/config.toml)
|
||||
".toml"
|
||||
];
|
||||
isCargoLock = base == "Cargo.lock";
|
||||
# .cargo/config.toml is captured above
|
||||
isOldStyleCargoConfig = parentDir == ".cargo" && base == "config";
|
||||
in
|
||||
type == "directory" || matchesSuffix || isCargoLock || isOldStyleCargoConfig;
|
||||
};
|
||||
# callPackage but for my rust Packages
|
||||
callRustPackage =
|
||||
pkgs: pname: nixSrc:
|
||||
pkgs.callPackage nixSrc { cleanRustSrc = cleanRustSrc pname; };
|
||||
packages = pkgs: {
|
||||
jpassmenu = pkgs.callPackage ./jpassmenu/package.nix { };
|
||||
audiomenu = callRustPackage pkgs "audiomenu" ./audiomenu/package.nix;
|
||||
audiomenu = pkgs.callPackage ./audiomenu/package.nix { };
|
||||
};
|
||||
in
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue