├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── crates ├── findex-daemon │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── findex-plugin │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── findex_internal.rs │ │ └── lib.rs └── findex │ ├── Cargo.toml │ ├── build.rs │ └── src │ ├── app_list.rs │ ├── config.rs │ ├── gui │ ├── css.rs │ ├── dialog.rs │ ├── mod.rs │ ├── result_list.rs │ ├── result_list_row.rs │ └── searchbox.rs │ └── main.rs ├── css └── style.css ├── installer.sh ├── plugins ├── README.md ├── cmd │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── github-repo │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── lib.rs └── urlopen │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── lib.rs ├── screenshot.png └── service └── findex-daemon.service /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[Bug] Title for describing a bug" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Description 11 | A clear and concise description of what the bug is. 12 | 13 | ## Do you already have Findex Installed? (If yes, how did you install?) 14 | Details about your installation process. 15 | 16 | ## To Reproduce 17 | Put steps to reproduce the behaviour here 18 | 19 | ## Expected behavior 20 | A clear and concise description of what you expected to happen. 21 | 22 | ## Screenshots 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | ## System information 26 | - Distro: 27 | - Findex Version: 28 | 29 | ## Output of `rustc --version --verbose` (if you compiled findex on your machine): 30 | ``` 31 | 32 | ``` 33 | 34 | ## Log/Output (if applicable) 35 | ``` 36 | Put Findex log or installer output here (You can find logs in ~/.findex-logs. Each file name has timestamp with it) 37 | ``` 38 | 39 | ## Additional context 40 | Add any other context about the problem here. 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Is your feature request related to a problem? Please describe. 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | ## Describe the solution you'd like 14 | A clear and concise description of what you want to happen. 15 | 16 | ## Describe alternatives you've considered 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | ## Additional context 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .* 3 | vgcore* 4 | settings.toml -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "abi_stable" 7 | version = "0.11.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "69d6512d3eb05ffe5004c59c206de7f99c34951504056ce23fc953842f12c445" 10 | dependencies = [ 11 | "abi_stable_derive", 12 | "abi_stable_shared", 13 | "const_panic", 14 | "core_extensions", 15 | "crossbeam-channel", 16 | "generational-arena", 17 | "libloading 0.7.4", 18 | "lock_api", 19 | "parking_lot", 20 | "paste", 21 | "repr_offset", 22 | "rustc_version", 23 | "serde", 24 | "serde_derive", 25 | "serde_json", 26 | ] 27 | 28 | [[package]] 29 | name = "abi_stable_derive" 30 | version = "0.11.3" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "d7178468b407a4ee10e881bc7a328a65e739f0863615cca4429d43916b05e898" 33 | dependencies = [ 34 | "abi_stable_shared", 35 | "as_derive_utils", 36 | "core_extensions", 37 | "proc-macro2", 38 | "quote", 39 | "rustc_version", 40 | "syn 1.0.109", 41 | "typed-arena", 42 | ] 43 | 44 | [[package]] 45 | name = "abi_stable_shared" 46 | version = "0.11.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "b2b5df7688c123e63f4d4d649cba63f2967ba7f7861b1664fca3f77d3dad2b63" 49 | dependencies = [ 50 | "core_extensions", 51 | ] 52 | 53 | [[package]] 54 | name = "addr2line" 55 | version = "0.24.2" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 58 | dependencies = [ 59 | "gimli", 60 | ] 61 | 62 | [[package]] 63 | name = "adler2" 64 | version = "2.0.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 67 | 68 | [[package]] 69 | name = "aho-corasick" 70 | version = "1.1.3" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 73 | dependencies = [ 74 | "memchr", 75 | ] 76 | 77 | [[package]] 78 | name = "as_derive_utils" 79 | version = "0.11.0" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "ff3c96645900a44cf11941c111bd08a6573b0e2f9f69bc9264b179d8fae753c4" 82 | dependencies = [ 83 | "core_extensions", 84 | "proc-macro2", 85 | "quote", 86 | "syn 1.0.109", 87 | ] 88 | 89 | [[package]] 90 | name = "atk" 91 | version = "0.18.2" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" 94 | dependencies = [ 95 | "atk-sys", 96 | "glib", 97 | "libc", 98 | ] 99 | 100 | [[package]] 101 | name = "atk-sys" 102 | version = "0.18.2" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" 105 | dependencies = [ 106 | "glib-sys", 107 | "gobject-sys", 108 | "libc", 109 | "system-deps", 110 | ] 111 | 112 | [[package]] 113 | name = "autocfg" 114 | version = "1.4.0" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 117 | 118 | [[package]] 119 | name = "backtrace" 120 | version = "0.3.75" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 123 | dependencies = [ 124 | "addr2line", 125 | "cfg-if", 126 | "libc", 127 | "miniz_oxide", 128 | "object", 129 | "rustc-demangle", 130 | "windows-targets", 131 | ] 132 | 133 | [[package]] 134 | name = "bitflags" 135 | version = "2.9.0" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 138 | 139 | [[package]] 140 | name = "cairo-rs" 141 | version = "0.18.5" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" 144 | dependencies = [ 145 | "bitflags", 146 | "cairo-sys-rs", 147 | "glib", 148 | "libc", 149 | "once_cell", 150 | "thiserror 1.0.69", 151 | ] 152 | 153 | [[package]] 154 | name = "cairo-sys-rs" 155 | version = "0.18.2" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" 158 | dependencies = [ 159 | "glib-sys", 160 | "libc", 161 | "system-deps", 162 | ] 163 | 164 | [[package]] 165 | name = "cfg-expr" 166 | version = "0.15.8" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" 169 | dependencies = [ 170 | "smallvec", 171 | "target-lexicon", 172 | ] 173 | 174 | [[package]] 175 | name = "cfg-if" 176 | version = "1.0.0" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 179 | 180 | [[package]] 181 | name = "cfg_aliases" 182 | version = "0.2.1" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 185 | 186 | [[package]] 187 | name = "const_panic" 188 | version = "0.2.12" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "2459fc9262a1aa204eb4b5764ad4f189caec88aea9634389c0a25f8be7f6265e" 191 | 192 | [[package]] 193 | name = "core_extensions" 194 | version = "1.5.3" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "92c71dc07c9721607e7a16108336048ee978c3a8b129294534272e8bac96c0ee" 197 | dependencies = [ 198 | "core_extensions_proc_macros", 199 | ] 200 | 201 | [[package]] 202 | name = "core_extensions_proc_macros" 203 | version = "1.5.3" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "69f3b219d28b6e3b4ac87bc1fc522e0803ab22e055da177bff0068c4150c61a6" 206 | 207 | [[package]] 208 | name = "crossbeam-channel" 209 | version = "0.5.15" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" 212 | dependencies = [ 213 | "crossbeam-utils", 214 | ] 215 | 216 | [[package]] 217 | name = "crossbeam-utils" 218 | version = "0.8.21" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 221 | 222 | [[package]] 223 | name = "daemonize" 224 | version = "0.5.0" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "ab8bfdaacb3c887a54d41bdf48d3af8873b3f5566469f8ba21b92057509f116e" 227 | dependencies = [ 228 | "libc", 229 | ] 230 | 231 | [[package]] 232 | name = "dirs" 233 | version = "6.0.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" 236 | dependencies = [ 237 | "dirs-sys", 238 | ] 239 | 240 | [[package]] 241 | name = "dirs-sys" 242 | version = "0.5.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" 245 | dependencies = [ 246 | "libc", 247 | "option-ext", 248 | "redox_users", 249 | "windows-sys 0.59.0", 250 | ] 251 | 252 | [[package]] 253 | name = "equivalent" 254 | version = "1.0.2" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 257 | 258 | [[package]] 259 | name = "field-offset" 260 | version = "0.3.6" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" 263 | dependencies = [ 264 | "memoffset", 265 | "rustc_version", 266 | ] 267 | 268 | [[package]] 269 | name = "findex" 270 | version = "0.8.3" 271 | dependencies = [ 272 | "abi_stable", 273 | "findex-plugin", 274 | "gtk", 275 | "inotify", 276 | "keybinder", 277 | "lazy_static", 278 | "parking_lot", 279 | "regex", 280 | "serde", 281 | "shellexpand", 282 | "shlex", 283 | "sublime_fuzzy", 284 | "toml", 285 | "xdg", 286 | ] 287 | 288 | [[package]] 289 | name = "findex-daemon" 290 | version = "0.8.3" 291 | dependencies = [ 292 | "daemonize", 293 | "inotify", 294 | "nix", 295 | "shellexpand", 296 | "subprocess", 297 | "sysinfo", 298 | "xdg", 299 | ] 300 | 301 | [[package]] 302 | name = "findex-plugin" 303 | version = "0.8.3" 304 | dependencies = [ 305 | "abi_stable", 306 | "gtk", 307 | "libloading 0.8.6", 308 | "serde", 309 | ] 310 | 311 | [[package]] 312 | name = "futures-channel" 313 | version = "0.3.31" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 316 | dependencies = [ 317 | "futures-core", 318 | ] 319 | 320 | [[package]] 321 | name = "futures-core" 322 | version = "0.3.31" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 325 | 326 | [[package]] 327 | name = "futures-executor" 328 | version = "0.3.31" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 331 | dependencies = [ 332 | "futures-core", 333 | "futures-task", 334 | "futures-util", 335 | ] 336 | 337 | [[package]] 338 | name = "futures-io" 339 | version = "0.3.31" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 342 | 343 | [[package]] 344 | name = "futures-macro" 345 | version = "0.3.31" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 348 | dependencies = [ 349 | "proc-macro2", 350 | "quote", 351 | "syn 2.0.101", 352 | ] 353 | 354 | [[package]] 355 | name = "futures-task" 356 | version = "0.3.31" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 359 | 360 | [[package]] 361 | name = "futures-util" 362 | version = "0.3.31" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 365 | dependencies = [ 366 | "futures-core", 367 | "futures-macro", 368 | "futures-task", 369 | "pin-project-lite", 370 | "pin-utils", 371 | "slab", 372 | ] 373 | 374 | [[package]] 375 | name = "gdk" 376 | version = "0.18.2" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" 379 | dependencies = [ 380 | "cairo-rs", 381 | "gdk-pixbuf", 382 | "gdk-sys", 383 | "gio", 384 | "glib", 385 | "libc", 386 | "pango", 387 | ] 388 | 389 | [[package]] 390 | name = "gdk-pixbuf" 391 | version = "0.18.5" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" 394 | dependencies = [ 395 | "gdk-pixbuf-sys", 396 | "gio", 397 | "glib", 398 | "libc", 399 | "once_cell", 400 | ] 401 | 402 | [[package]] 403 | name = "gdk-pixbuf-sys" 404 | version = "0.18.0" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" 407 | dependencies = [ 408 | "gio-sys", 409 | "glib-sys", 410 | "gobject-sys", 411 | "libc", 412 | "system-deps", 413 | ] 414 | 415 | [[package]] 416 | name = "gdk-sys" 417 | version = "0.18.2" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" 420 | dependencies = [ 421 | "cairo-sys-rs", 422 | "gdk-pixbuf-sys", 423 | "gio-sys", 424 | "glib-sys", 425 | "gobject-sys", 426 | "libc", 427 | "pango-sys", 428 | "pkg-config", 429 | "system-deps", 430 | ] 431 | 432 | [[package]] 433 | name = "generational-arena" 434 | version = "0.2.9" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" 437 | dependencies = [ 438 | "cfg-if", 439 | ] 440 | 441 | [[package]] 442 | name = "getrandom" 443 | version = "0.2.16" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 446 | dependencies = [ 447 | "cfg-if", 448 | "libc", 449 | "wasi", 450 | ] 451 | 452 | [[package]] 453 | name = "gimli" 454 | version = "0.31.1" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 457 | 458 | [[package]] 459 | name = "gio" 460 | version = "0.18.4" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" 463 | dependencies = [ 464 | "futures-channel", 465 | "futures-core", 466 | "futures-io", 467 | "futures-util", 468 | "gio-sys", 469 | "glib", 470 | "libc", 471 | "once_cell", 472 | "pin-project-lite", 473 | "smallvec", 474 | "thiserror 1.0.69", 475 | ] 476 | 477 | [[package]] 478 | name = "gio-sys" 479 | version = "0.18.1" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" 482 | dependencies = [ 483 | "glib-sys", 484 | "gobject-sys", 485 | "libc", 486 | "system-deps", 487 | "winapi", 488 | ] 489 | 490 | [[package]] 491 | name = "glib" 492 | version = "0.18.5" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" 495 | dependencies = [ 496 | "bitflags", 497 | "futures-channel", 498 | "futures-core", 499 | "futures-executor", 500 | "futures-task", 501 | "futures-util", 502 | "gio-sys", 503 | "glib-macros", 504 | "glib-sys", 505 | "gobject-sys", 506 | "libc", 507 | "memchr", 508 | "once_cell", 509 | "smallvec", 510 | "thiserror 1.0.69", 511 | ] 512 | 513 | [[package]] 514 | name = "glib-macros" 515 | version = "0.18.5" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" 518 | dependencies = [ 519 | "heck 0.4.1", 520 | "proc-macro-crate 2.0.0", 521 | "proc-macro-error", 522 | "proc-macro2", 523 | "quote", 524 | "syn 2.0.101", 525 | ] 526 | 527 | [[package]] 528 | name = "glib-sys" 529 | version = "0.18.1" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" 532 | dependencies = [ 533 | "libc", 534 | "system-deps", 535 | ] 536 | 537 | [[package]] 538 | name = "gobject-sys" 539 | version = "0.18.0" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" 542 | dependencies = [ 543 | "glib-sys", 544 | "libc", 545 | "system-deps", 546 | ] 547 | 548 | [[package]] 549 | name = "gtk" 550 | version = "0.18.2" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" 553 | dependencies = [ 554 | "atk", 555 | "cairo-rs", 556 | "field-offset", 557 | "futures-channel", 558 | "gdk", 559 | "gdk-pixbuf", 560 | "gio", 561 | "glib", 562 | "gtk-sys", 563 | "gtk3-macros", 564 | "libc", 565 | "pango", 566 | "pkg-config", 567 | ] 568 | 569 | [[package]] 570 | name = "gtk-sys" 571 | version = "0.18.2" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" 574 | dependencies = [ 575 | "atk-sys", 576 | "cairo-sys-rs", 577 | "gdk-pixbuf-sys", 578 | "gdk-sys", 579 | "gio-sys", 580 | "glib-sys", 581 | "gobject-sys", 582 | "libc", 583 | "pango-sys", 584 | "system-deps", 585 | ] 586 | 587 | [[package]] 588 | name = "gtk3-macros" 589 | version = "0.18.2" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" 592 | dependencies = [ 593 | "proc-macro-crate 1.3.1", 594 | "proc-macro-error", 595 | "proc-macro2", 596 | "quote", 597 | "syn 2.0.101", 598 | ] 599 | 600 | [[package]] 601 | name = "hashbrown" 602 | version = "0.15.3" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" 605 | 606 | [[package]] 607 | name = "heck" 608 | version = "0.4.1" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 611 | 612 | [[package]] 613 | name = "heck" 614 | version = "0.5.0" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 617 | 618 | [[package]] 619 | name = "indexmap" 620 | version = "2.9.0" 621 | source = "registry+https://github.com/rust-lang/crates.io-index" 622 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 623 | dependencies = [ 624 | "equivalent", 625 | "hashbrown", 626 | ] 627 | 628 | [[package]] 629 | name = "inotify" 630 | version = "0.11.0" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" 633 | dependencies = [ 634 | "bitflags", 635 | "futures-core", 636 | "inotify-sys", 637 | "libc", 638 | "tokio", 639 | ] 640 | 641 | [[package]] 642 | name = "inotify-sys" 643 | version = "0.1.5" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" 646 | dependencies = [ 647 | "libc", 648 | ] 649 | 650 | [[package]] 651 | name = "itoa" 652 | version = "1.0.15" 653 | source = "registry+https://github.com/rust-lang/crates.io-index" 654 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 655 | 656 | [[package]] 657 | name = "keybinder" 658 | version = "0.4.1" 659 | source = "registry+https://github.com/rust-lang/crates.io-index" 660 | checksum = "a0ab130e8f83d81e8eb3dfbbb73e9c3544651158ba9fe9592b83bfae8a0e2a39" 661 | dependencies = [ 662 | "libc", 663 | ] 664 | 665 | [[package]] 666 | name = "lazy_static" 667 | version = "1.5.0" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 670 | 671 | [[package]] 672 | name = "libc" 673 | version = "0.2.172" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 676 | 677 | [[package]] 678 | name = "libloading" 679 | version = "0.7.4" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" 682 | dependencies = [ 683 | "cfg-if", 684 | "winapi", 685 | ] 686 | 687 | [[package]] 688 | name = "libloading" 689 | version = "0.8.6" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" 692 | dependencies = [ 693 | "cfg-if", 694 | "windows-targets", 695 | ] 696 | 697 | [[package]] 698 | name = "libredox" 699 | version = "0.1.3" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 702 | dependencies = [ 703 | "bitflags", 704 | "libc", 705 | ] 706 | 707 | [[package]] 708 | name = "lock_api" 709 | version = "0.4.12" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 712 | dependencies = [ 713 | "autocfg", 714 | "scopeguard", 715 | ] 716 | 717 | [[package]] 718 | name = "memchr" 719 | version = "2.7.4" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 722 | 723 | [[package]] 724 | name = "memoffset" 725 | version = "0.9.1" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" 728 | dependencies = [ 729 | "autocfg", 730 | ] 731 | 732 | [[package]] 733 | name = "miniz_oxide" 734 | version = "0.8.8" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" 737 | dependencies = [ 738 | "adler2", 739 | ] 740 | 741 | [[package]] 742 | name = "mio" 743 | version = "1.0.3" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 746 | dependencies = [ 747 | "libc", 748 | "wasi", 749 | "windows-sys 0.52.0", 750 | ] 751 | 752 | [[package]] 753 | name = "nix" 754 | version = "0.30.1" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" 757 | dependencies = [ 758 | "bitflags", 759 | "cfg-if", 760 | "cfg_aliases", 761 | "libc", 762 | ] 763 | 764 | [[package]] 765 | name = "ntapi" 766 | version = "0.4.1" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" 769 | dependencies = [ 770 | "winapi", 771 | ] 772 | 773 | [[package]] 774 | name = "objc2-core-foundation" 775 | version = "0.3.1" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" 778 | dependencies = [ 779 | "bitflags", 780 | ] 781 | 782 | [[package]] 783 | name = "objc2-io-kit" 784 | version = "0.3.1" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a" 787 | dependencies = [ 788 | "libc", 789 | "objc2-core-foundation", 790 | ] 791 | 792 | [[package]] 793 | name = "object" 794 | version = "0.36.7" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 797 | dependencies = [ 798 | "memchr", 799 | ] 800 | 801 | [[package]] 802 | name = "once_cell" 803 | version = "1.21.3" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 806 | 807 | [[package]] 808 | name = "option-ext" 809 | version = "0.2.0" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 812 | 813 | [[package]] 814 | name = "pango" 815 | version = "0.18.3" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" 818 | dependencies = [ 819 | "gio", 820 | "glib", 821 | "libc", 822 | "once_cell", 823 | "pango-sys", 824 | ] 825 | 826 | [[package]] 827 | name = "pango-sys" 828 | version = "0.18.0" 829 | source = "registry+https://github.com/rust-lang/crates.io-index" 830 | checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" 831 | dependencies = [ 832 | "glib-sys", 833 | "gobject-sys", 834 | "libc", 835 | "system-deps", 836 | ] 837 | 838 | [[package]] 839 | name = "parking_lot" 840 | version = "0.12.3" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 843 | dependencies = [ 844 | "lock_api", 845 | "parking_lot_core", 846 | ] 847 | 848 | [[package]] 849 | name = "parking_lot_core" 850 | version = "0.9.10" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 853 | dependencies = [ 854 | "cfg-if", 855 | "libc", 856 | "redox_syscall", 857 | "smallvec", 858 | "windows-targets", 859 | ] 860 | 861 | [[package]] 862 | name = "paste" 863 | version = "1.0.15" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 866 | 867 | [[package]] 868 | name = "pin-project-lite" 869 | version = "0.2.16" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 872 | 873 | [[package]] 874 | name = "pin-utils" 875 | version = "0.1.0" 876 | source = "registry+https://github.com/rust-lang/crates.io-index" 877 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 878 | 879 | [[package]] 880 | name = "pkg-config" 881 | version = "0.3.32" 882 | source = "registry+https://github.com/rust-lang/crates.io-index" 883 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 884 | 885 | [[package]] 886 | name = "proc-macro-crate" 887 | version = "1.3.1" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" 890 | dependencies = [ 891 | "once_cell", 892 | "toml_edit 0.19.15", 893 | ] 894 | 895 | [[package]] 896 | name = "proc-macro-crate" 897 | version = "2.0.0" 898 | source = "registry+https://github.com/rust-lang/crates.io-index" 899 | checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" 900 | dependencies = [ 901 | "toml_edit 0.20.7", 902 | ] 903 | 904 | [[package]] 905 | name = "proc-macro-error" 906 | version = "1.0.4" 907 | source = "registry+https://github.com/rust-lang/crates.io-index" 908 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 909 | dependencies = [ 910 | "proc-macro-error-attr", 911 | "proc-macro2", 912 | "quote", 913 | "syn 1.0.109", 914 | "version_check", 915 | ] 916 | 917 | [[package]] 918 | name = "proc-macro-error-attr" 919 | version = "1.0.4" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 922 | dependencies = [ 923 | "proc-macro2", 924 | "quote", 925 | "version_check", 926 | ] 927 | 928 | [[package]] 929 | name = "proc-macro2" 930 | version = "1.0.95" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 933 | dependencies = [ 934 | "unicode-ident", 935 | ] 936 | 937 | [[package]] 938 | name = "quote" 939 | version = "1.0.40" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 942 | dependencies = [ 943 | "proc-macro2", 944 | ] 945 | 946 | [[package]] 947 | name = "redox_syscall" 948 | version = "0.5.12" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" 951 | dependencies = [ 952 | "bitflags", 953 | ] 954 | 955 | [[package]] 956 | name = "redox_users" 957 | version = "0.5.0" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" 960 | dependencies = [ 961 | "getrandom", 962 | "libredox", 963 | "thiserror 2.0.12", 964 | ] 965 | 966 | [[package]] 967 | name = "regex" 968 | version = "1.11.1" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 971 | dependencies = [ 972 | "aho-corasick", 973 | "memchr", 974 | "regex-automata", 975 | "regex-syntax", 976 | ] 977 | 978 | [[package]] 979 | name = "regex-automata" 980 | version = "0.4.9" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 983 | dependencies = [ 984 | "aho-corasick", 985 | "memchr", 986 | "regex-syntax", 987 | ] 988 | 989 | [[package]] 990 | name = "regex-syntax" 991 | version = "0.8.5" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 994 | 995 | [[package]] 996 | name = "repr_offset" 997 | version = "0.2.2" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "fb1070755bd29dffc19d0971cab794e607839ba2ef4b69a9e6fbc8733c1b72ea" 1000 | dependencies = [ 1001 | "tstr", 1002 | ] 1003 | 1004 | [[package]] 1005 | name = "rustc-demangle" 1006 | version = "0.1.24" 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" 1008 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1009 | 1010 | [[package]] 1011 | name = "rustc_version" 1012 | version = "0.4.1" 1013 | source = "registry+https://github.com/rust-lang/crates.io-index" 1014 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 1015 | dependencies = [ 1016 | "semver", 1017 | ] 1018 | 1019 | [[package]] 1020 | name = "ryu" 1021 | version = "1.0.20" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1024 | 1025 | [[package]] 1026 | name = "scopeguard" 1027 | version = "1.2.0" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1030 | 1031 | [[package]] 1032 | name = "semver" 1033 | version = "1.0.26" 1034 | source = "registry+https://github.com/rust-lang/crates.io-index" 1035 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 1036 | 1037 | [[package]] 1038 | name = "serde" 1039 | version = "1.0.219" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 1042 | dependencies = [ 1043 | "serde_derive", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "serde_derive" 1048 | version = "1.0.219" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 1051 | dependencies = [ 1052 | "proc-macro2", 1053 | "quote", 1054 | "syn 2.0.101", 1055 | ] 1056 | 1057 | [[package]] 1058 | name = "serde_json" 1059 | version = "1.0.140" 1060 | source = "registry+https://github.com/rust-lang/crates.io-index" 1061 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 1062 | dependencies = [ 1063 | "itoa", 1064 | "memchr", 1065 | "ryu", 1066 | "serde", 1067 | ] 1068 | 1069 | [[package]] 1070 | name = "serde_spanned" 1071 | version = "0.6.8" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 1074 | dependencies = [ 1075 | "serde", 1076 | ] 1077 | 1078 | [[package]] 1079 | name = "shellexpand" 1080 | version = "3.1.1" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" 1083 | dependencies = [ 1084 | "dirs", 1085 | ] 1086 | 1087 | [[package]] 1088 | name = "shlex" 1089 | version = "1.3.0" 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" 1091 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1092 | 1093 | [[package]] 1094 | name = "slab" 1095 | version = "0.4.9" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1098 | dependencies = [ 1099 | "autocfg", 1100 | ] 1101 | 1102 | [[package]] 1103 | name = "smallvec" 1104 | version = "1.15.0" 1105 | source = "registry+https://github.com/rust-lang/crates.io-index" 1106 | checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" 1107 | 1108 | [[package]] 1109 | name = "socket2" 1110 | version = "0.5.9" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" 1113 | dependencies = [ 1114 | "libc", 1115 | "windows-sys 0.52.0", 1116 | ] 1117 | 1118 | [[package]] 1119 | name = "sublime_fuzzy" 1120 | version = "0.7.0" 1121 | source = "registry+https://github.com/rust-lang/crates.io-index" 1122 | checksum = "fa7986063f7c0ab374407e586d7048a3d5aac94f103f751088bf398e07cd5400" 1123 | 1124 | [[package]] 1125 | name = "subprocess" 1126 | version = "0.2.9" 1127 | source = "registry+https://github.com/rust-lang/crates.io-index" 1128 | checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086" 1129 | dependencies = [ 1130 | "libc", 1131 | "winapi", 1132 | ] 1133 | 1134 | [[package]] 1135 | name = "syn" 1136 | version = "1.0.109" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1139 | dependencies = [ 1140 | "proc-macro2", 1141 | "quote", 1142 | "unicode-ident", 1143 | ] 1144 | 1145 | [[package]] 1146 | name = "syn" 1147 | version = "2.0.101" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 1150 | dependencies = [ 1151 | "proc-macro2", 1152 | "quote", 1153 | "unicode-ident", 1154 | ] 1155 | 1156 | [[package]] 1157 | name = "sysinfo" 1158 | version = "0.35.0" 1159 | source = "registry+https://github.com/rust-lang/crates.io-index" 1160 | checksum = "b897c8ea620e181c7955369a31be5f48d9a9121cb59fd33ecef9ff2a34323422" 1161 | dependencies = [ 1162 | "libc", 1163 | "memchr", 1164 | "ntapi", 1165 | "objc2-core-foundation", 1166 | "objc2-io-kit", 1167 | "windows", 1168 | ] 1169 | 1170 | [[package]] 1171 | name = "system-deps" 1172 | version = "6.2.2" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" 1175 | dependencies = [ 1176 | "cfg-expr", 1177 | "heck 0.5.0", 1178 | "pkg-config", 1179 | "toml", 1180 | "version-compare", 1181 | ] 1182 | 1183 | [[package]] 1184 | name = "target-lexicon" 1185 | version = "0.12.16" 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" 1187 | checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" 1188 | 1189 | [[package]] 1190 | name = "thiserror" 1191 | version = "1.0.69" 1192 | source = "registry+https://github.com/rust-lang/crates.io-index" 1193 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1194 | dependencies = [ 1195 | "thiserror-impl 1.0.69", 1196 | ] 1197 | 1198 | [[package]] 1199 | name = "thiserror" 1200 | version = "2.0.12" 1201 | source = "registry+https://github.com/rust-lang/crates.io-index" 1202 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 1203 | dependencies = [ 1204 | "thiserror-impl 2.0.12", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "thiserror-impl" 1209 | version = "1.0.69" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1212 | dependencies = [ 1213 | "proc-macro2", 1214 | "quote", 1215 | "syn 2.0.101", 1216 | ] 1217 | 1218 | [[package]] 1219 | name = "thiserror-impl" 1220 | version = "2.0.12" 1221 | source = "registry+https://github.com/rust-lang/crates.io-index" 1222 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 1223 | dependencies = [ 1224 | "proc-macro2", 1225 | "quote", 1226 | "syn 2.0.101", 1227 | ] 1228 | 1229 | [[package]] 1230 | name = "tokio" 1231 | version = "1.45.0" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" 1234 | dependencies = [ 1235 | "backtrace", 1236 | "libc", 1237 | "mio", 1238 | "pin-project-lite", 1239 | "socket2", 1240 | "windows-sys 0.52.0", 1241 | ] 1242 | 1243 | [[package]] 1244 | name = "toml" 1245 | version = "0.8.22" 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" 1247 | checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" 1248 | dependencies = [ 1249 | "serde", 1250 | "serde_spanned", 1251 | "toml_datetime", 1252 | "toml_edit 0.22.26", 1253 | ] 1254 | 1255 | [[package]] 1256 | name = "toml_datetime" 1257 | version = "0.6.9" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" 1260 | dependencies = [ 1261 | "serde", 1262 | ] 1263 | 1264 | [[package]] 1265 | name = "toml_edit" 1266 | version = "0.19.15" 1267 | source = "registry+https://github.com/rust-lang/crates.io-index" 1268 | checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" 1269 | dependencies = [ 1270 | "indexmap", 1271 | "toml_datetime", 1272 | "winnow 0.5.40", 1273 | ] 1274 | 1275 | [[package]] 1276 | name = "toml_edit" 1277 | version = "0.20.7" 1278 | source = "registry+https://github.com/rust-lang/crates.io-index" 1279 | checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" 1280 | dependencies = [ 1281 | "indexmap", 1282 | "toml_datetime", 1283 | "winnow 0.5.40", 1284 | ] 1285 | 1286 | [[package]] 1287 | name = "toml_edit" 1288 | version = "0.22.26" 1289 | source = "registry+https://github.com/rust-lang/crates.io-index" 1290 | checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" 1291 | dependencies = [ 1292 | "indexmap", 1293 | "serde", 1294 | "serde_spanned", 1295 | "toml_datetime", 1296 | "toml_write", 1297 | "winnow 0.7.10", 1298 | ] 1299 | 1300 | [[package]] 1301 | name = "toml_write" 1302 | version = "0.1.1" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" 1305 | 1306 | [[package]] 1307 | name = "tstr" 1308 | version = "0.2.4" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "7f8e0294f14baae476d0dd0a2d780b2e24d66e349a9de876f5126777a37bdba7" 1311 | dependencies = [ 1312 | "tstr_proc_macros", 1313 | ] 1314 | 1315 | [[package]] 1316 | name = "tstr_proc_macros" 1317 | version = "0.2.2" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a" 1320 | 1321 | [[package]] 1322 | name = "typed-arena" 1323 | version = "2.0.2" 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" 1325 | checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" 1326 | 1327 | [[package]] 1328 | name = "unicode-ident" 1329 | version = "1.0.18" 1330 | source = "registry+https://github.com/rust-lang/crates.io-index" 1331 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1332 | 1333 | [[package]] 1334 | name = "version-compare" 1335 | version = "0.2.0" 1336 | source = "registry+https://github.com/rust-lang/crates.io-index" 1337 | checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" 1338 | 1339 | [[package]] 1340 | name = "version_check" 1341 | version = "0.9.5" 1342 | source = "registry+https://github.com/rust-lang/crates.io-index" 1343 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1344 | 1345 | [[package]] 1346 | name = "wasi" 1347 | version = "0.11.0+wasi-snapshot-preview1" 1348 | source = "registry+https://github.com/rust-lang/crates.io-index" 1349 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1350 | 1351 | [[package]] 1352 | name = "winapi" 1353 | version = "0.3.9" 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" 1355 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1356 | dependencies = [ 1357 | "winapi-i686-pc-windows-gnu", 1358 | "winapi-x86_64-pc-windows-gnu", 1359 | ] 1360 | 1361 | [[package]] 1362 | name = "winapi-i686-pc-windows-gnu" 1363 | version = "0.4.0" 1364 | source = "registry+https://github.com/rust-lang/crates.io-index" 1365 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1366 | 1367 | [[package]] 1368 | name = "winapi-x86_64-pc-windows-gnu" 1369 | version = "0.4.0" 1370 | source = "registry+https://github.com/rust-lang/crates.io-index" 1371 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1372 | 1373 | [[package]] 1374 | name = "windows" 1375 | version = "0.61.1" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" 1378 | dependencies = [ 1379 | "windows-collections", 1380 | "windows-core", 1381 | "windows-future", 1382 | "windows-link", 1383 | "windows-numerics", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "windows-collections" 1388 | version = "0.2.0" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" 1391 | dependencies = [ 1392 | "windows-core", 1393 | ] 1394 | 1395 | [[package]] 1396 | name = "windows-core" 1397 | version = "0.61.0" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" 1400 | dependencies = [ 1401 | "windows-implement", 1402 | "windows-interface", 1403 | "windows-link", 1404 | "windows-result", 1405 | "windows-strings", 1406 | ] 1407 | 1408 | [[package]] 1409 | name = "windows-future" 1410 | version = "0.2.0" 1411 | source = "registry+https://github.com/rust-lang/crates.io-index" 1412 | checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32" 1413 | dependencies = [ 1414 | "windows-core", 1415 | "windows-link", 1416 | ] 1417 | 1418 | [[package]] 1419 | name = "windows-implement" 1420 | version = "0.60.0" 1421 | source = "registry+https://github.com/rust-lang/crates.io-index" 1422 | checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 1423 | dependencies = [ 1424 | "proc-macro2", 1425 | "quote", 1426 | "syn 2.0.101", 1427 | ] 1428 | 1429 | [[package]] 1430 | name = "windows-interface" 1431 | version = "0.59.1" 1432 | source = "registry+https://github.com/rust-lang/crates.io-index" 1433 | checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 1434 | dependencies = [ 1435 | "proc-macro2", 1436 | "quote", 1437 | "syn 2.0.101", 1438 | ] 1439 | 1440 | [[package]] 1441 | name = "windows-link" 1442 | version = "0.1.1" 1443 | source = "registry+https://github.com/rust-lang/crates.io-index" 1444 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 1445 | 1446 | [[package]] 1447 | name = "windows-numerics" 1448 | version = "0.2.0" 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" 1450 | checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" 1451 | dependencies = [ 1452 | "windows-core", 1453 | "windows-link", 1454 | ] 1455 | 1456 | [[package]] 1457 | name = "windows-result" 1458 | version = "0.3.2" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" 1461 | dependencies = [ 1462 | "windows-link", 1463 | ] 1464 | 1465 | [[package]] 1466 | name = "windows-strings" 1467 | version = "0.4.0" 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" 1469 | checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" 1470 | dependencies = [ 1471 | "windows-link", 1472 | ] 1473 | 1474 | [[package]] 1475 | name = "windows-sys" 1476 | version = "0.52.0" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1479 | dependencies = [ 1480 | "windows-targets", 1481 | ] 1482 | 1483 | [[package]] 1484 | name = "windows-sys" 1485 | version = "0.59.0" 1486 | source = "registry+https://github.com/rust-lang/crates.io-index" 1487 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1488 | dependencies = [ 1489 | "windows-targets", 1490 | ] 1491 | 1492 | [[package]] 1493 | name = "windows-targets" 1494 | version = "0.52.6" 1495 | source = "registry+https://github.com/rust-lang/crates.io-index" 1496 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1497 | dependencies = [ 1498 | "windows_aarch64_gnullvm", 1499 | "windows_aarch64_msvc", 1500 | "windows_i686_gnu", 1501 | "windows_i686_gnullvm", 1502 | "windows_i686_msvc", 1503 | "windows_x86_64_gnu", 1504 | "windows_x86_64_gnullvm", 1505 | "windows_x86_64_msvc", 1506 | ] 1507 | 1508 | [[package]] 1509 | name = "windows_aarch64_gnullvm" 1510 | version = "0.52.6" 1511 | source = "registry+https://github.com/rust-lang/crates.io-index" 1512 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1513 | 1514 | [[package]] 1515 | name = "windows_aarch64_msvc" 1516 | version = "0.52.6" 1517 | source = "registry+https://github.com/rust-lang/crates.io-index" 1518 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1519 | 1520 | [[package]] 1521 | name = "windows_i686_gnu" 1522 | version = "0.52.6" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1525 | 1526 | [[package]] 1527 | name = "windows_i686_gnullvm" 1528 | version = "0.52.6" 1529 | source = "registry+https://github.com/rust-lang/crates.io-index" 1530 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1531 | 1532 | [[package]] 1533 | name = "windows_i686_msvc" 1534 | version = "0.52.6" 1535 | source = "registry+https://github.com/rust-lang/crates.io-index" 1536 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1537 | 1538 | [[package]] 1539 | name = "windows_x86_64_gnu" 1540 | version = "0.52.6" 1541 | source = "registry+https://github.com/rust-lang/crates.io-index" 1542 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1543 | 1544 | [[package]] 1545 | name = "windows_x86_64_gnullvm" 1546 | version = "0.52.6" 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" 1548 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1549 | 1550 | [[package]] 1551 | name = "windows_x86_64_msvc" 1552 | version = "0.52.6" 1553 | source = "registry+https://github.com/rust-lang/crates.io-index" 1554 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1555 | 1556 | [[package]] 1557 | name = "winnow" 1558 | version = "0.5.40" 1559 | source = "registry+https://github.com/rust-lang/crates.io-index" 1560 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 1561 | dependencies = [ 1562 | "memchr", 1563 | ] 1564 | 1565 | [[package]] 1566 | name = "winnow" 1567 | version = "0.7.10" 1568 | source = "registry+https://github.com/rust-lang/crates.io-index" 1569 | checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" 1570 | dependencies = [ 1571 | "memchr", 1572 | ] 1573 | 1574 | [[package]] 1575 | name = "xdg" 1576 | version = "3.0.0" 1577 | source = "registry+https://github.com/rust-lang/crates.io-index" 1578 | checksum = "2fb433233f2df9344722454bc7e96465c9d03bff9d77c248f9e7523fe79585b5" 1579 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["crates/findex", "crates/findex-daemon", "crates/findex-plugin"] 3 | exclude = ["plugins/urlopen", "plugins/github-repo", "plugins/cmd"] 4 | resolver = "2" 5 | 6 | [profile.release] 7 | debug = true 8 | lto = true 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Findex 2 | 3 | ![Screenshot](screenshot.png) 4 | 5 |

Findex is a highly customizable application launcher written in Rust and uses GTK3

6 | 7 | ## Table of Contents 8 | 9 | 10 | * [Findex](#findex) 11 | * [Table of Contents](#table-of-contents) 12 | * [Quick Note](#quick-note) 13 | * [Features](#features) 14 | * [Installation](#installation) 15 | * [Supported OS](#supported-os) 16 | * [Requirements](#requirements) 17 | * [Automated installation from source](#automated-installation-from-source) 18 | * [Manual installation from source](#manual-installation-from-source) 19 | * [Installation from AUR](#installation-from-aur) 20 | * [Hyprland](#hyprland) 21 | * [Notes](#notes) 22 | * [Customization](#customization) 23 | * [Plugins](#plugins) 24 | * [For users](#for-users) 25 | * [For developers](#for-developers) 26 | * [Explanation](#explanation) 27 | * [Prefix](#prefix) 28 | * [Keyboard shortcut](#keyboard-shortcut) 29 | * [`init` function](#init-function) 30 | * [`handle_query` function](#handle_query-function) 31 | * [Reporting Bugs](#reporting-bugs) 32 | 33 | 34 | ## Quick Note 35 | 36 | The tyranny of Israel on the Palestinian people is horrifying and heartbreaking. As such, we all 37 | should try our best to support the Palestinians from our position. Consider supporting the Palestinians 38 | by donating to the [Palestinian Red Crescent Society](https://www.palestinercs.org/en/Donation). 39 | 40 | [![ReadMeSupportPalestine](https://github.com/Safouene1/support-palestine-banner/blob/master/banner-support.svg)](https://www.palestinercs.org/en/Donation) 41 | 42 | Banner from: https://github.com/Safouene1/support-palestine-banner/ 43 | 44 | 45 | ## Features 46 | 47 | - Customization using CSS 48 | - Plugin system 49 | - Custom shortcut for triggering plugins 50 | - Shortcut for executing each result(upto 10) 51 | 52 | ## Installation 53 | 54 | If you are not using Findex directly from `development` branch and using latest release, 55 | check instructions from the `release` branch. 56 | 57 | ### Supported OS 58 | - Linux 59 | 60 | ### Requirements 61 | - Gtk3 62 | - libkeybinder3 63 | - Rust v1.66.0 (building from source) 64 | 65 | ### Automated installation from source 66 | - Run `./installer.sh` 67 | 68 | ### Manual installation from source 69 | - Set Rust toolchain to stable using: `rustup default stable` 70 | - Compile it using `cargo build --release` 71 | - Make `/opt/findex` directory 72 | - Copy `css/style.css` to `/opt/findex` 73 | - Copy `target/release/findex` to `/usr/bin/` 74 | - Copy `target/release/findex-daemon` to `/usr/bin/` 75 | - Add `findex-daemon` to autostart/startup applications 76 | - If using SystemD, enable & start the `findex-daemon` user service 77 | 78 | sudo systemctl enable --user findex-daemon.service 79 | sudo systemctl start --user findex-daemon.service 80 | 81 | ### Installation from AUR 82 | 83 | From repo: `findex-git` 84 | Prebuilt: `findex-bin` 85 | 86 | After that, add `findex-daemon` to autostart/startup applications 87 | 88 | ### Hyprland 89 | To setup findex for use in `Hyprland` add these configs to your `~/.config/hypr/hyprland.conf` 90 | ``` 91 | # Findex 92 | exec-once = findex-daemon 93 | bind = $mod, space, exec, echo 1 > ~/.config/findex/toggle_file 94 | windowrulev2 = float, class:^(findex)$ 95 | windowrulev2 = noanim, class:^(findex)$ 96 | windowrulev2 = noborder, class:^(findex)$ 97 | windowrulev2 = noshadow, class:^(findex)$ 98 | ``` 99 | 100 | ### Notes 101 | - Findex can't bind hotkey in Wayland. Bind hotkey to `echo 1 > ~/.config/findex/toggle_file` 102 | - Window decoration settings may not work in Wayland 103 | 104 | 105 | ## Customization 106 | 107 | Findex can be customized by applying properties to certain css classes. Below is a table containing class names and what they correspond to: 108 | 109 | | Class | Widget | 110 | |--------------------------------|-------------------------------------------------------------------| 111 | | findex-window | Top level window | 112 | | findex-container | Top level container of all widgets | 113 | | findex-query | Text input box where user gives query | 114 | | findex-results-scroll | Scrollable container containing ListBox that shows search results | 115 | | findex-results | Listbox containing search results | 116 | | findex-result-row | ListBoxRow containing single search result | 117 | | findex-result-icon | App icon of result row | 118 | | findex-result-app-name | App name of result row | 119 | | findex-result-app-description | Description of the app | 120 | | findex-result-app-command | Command of the app | 121 | | findex-result-trigger-shortcut | Shortcut for running the command in the result | 122 | | findex-result-icon-container | Container of the icon of each result | 123 | | findex-result-info-container | Container of the info of each result | 124 | | findex-query-container | Container of the search box | 125 | 126 | To customize Findex, edit the style.css file in `~/.config/findex`. If there is no such file, run Findex to generate it. 127 | 128 | Behaviour can be changed by modifying `~/.config/findex/settings.toml`. If there is no such file, run Findex to generate it. 129 | 130 | | Name | Description | Type | 131 | |------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|---------| 132 | | default_window_width | Set default width of the window | Integer | 133 | | min_content_height | Minimum content height of result | Integer | 134 | | max_content_height | Maximum content height of result | Integer | 135 | | name_match_highlight_color | Color of matches highlighted in app name | String | 136 | | min_score | Minimum Score of app name match | Integer | 137 | | result_size | Maximum amount of apps to show as result | Integer | 138 | | toggle_key | Key to toggle Findex(eg. `space`). This doesn't work in Wayland. Check [Installation](#installation) for more info. | String | 139 | | decorate_window | Show toolbar of window | Boolean | 140 | | query_placeholder | Placeholder text to show in query input box | String | 141 | | close_window_on_losing_focus | Close window when it loses focus | Boolean | 142 | | icon_size | Icon width and height will be set from this value | Integer | 143 | | entry_icon | Icon displayed beside the searchbar | String | 144 | | on_monitor | The monitor that findex is opened on (zero indexed). Warning: this feature hasn't been tested on Wayland yet. Contributions are welcome. | Integer | 145 | 146 | 147 | ## Plugins 148 | 149 | ### For users 150 | - Download the plugin. If it's not compiled, then compile it in release mode using `cargo build --release` 151 | - Go to `target/release` folder. 152 | - You'll see a file with `.so` extension. Copy that to a convenient place. 153 | - Add the following line to your `settings.toml` and edit it to make findex use the plugin: 154 | ```toml 155 | PLUGIN = { path = "PLUGIN PATH", prefix = "OPTIONAL USER DEFINED PREFIX", keyboard_shortcut = "OPTIONAL USER DEFINED KEYBOARD SHORTCUT", config = {} } 156 | ``` 157 | 158 | | Property | Description | 159 | |-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------| 160 | | path | Path to the plugin's `.so` file | 161 | | prefix | Optional user defined prefix that'll make findex use this instead of the one specified in the plugin. | 162 | | config | Plugin's configuration. Please refer to the plugin's documentation for more information. | 163 | | keyboard_shortcut | Optional custom keyboard shortcut for triggering the plugin(inserts the plugins prefix into the search box). Must be a valid Gtk accelerator. | 164 | - For more information, please refer to the documentation of the plugin you are using. 165 | 166 | **NOTE**: always make sure that the plugins you are using are compatible with the version of Findex you are using. 167 | 168 | ### For developers 169 | 170 | Only Rust based plugins are supported. 171 | 172 | - First make a `cdylib` library 173 | - Add `findex-plugin` and `abi_stable` as dependency 174 | - Add the following code into `src/lib.rs` 175 | ```rust 176 | use findex_plugin::{define_plugin, FResult}; 177 | use abi_stable::std_types::*; 178 | 179 | fn init(config: &RHashMap) -> RResult<(), RString> { 180 | // Set up your plugin using the config if necessary 181 | // Return RErr if something went wrong 182 | 183 | // Returning this indicates that the plugin initialization is successful 184 | ROk(()) 185 | } 186 | 187 | fn handle_query(query: RStr) -> RVec { 188 | let mut result = vec![]; 189 | 190 | /* Do stuff here */ 191 | 192 | RVec::from(result) 193 | } 194 | 195 | define_plugin!("prefix!", init, handle_query); 196 | // or add the following if you want to have custom shortcut for triggering the plugin. 197 | // The following sets the shortcut to Ctrl+Shift+P. 198 | // define_plugin!("prefix!", "P", init, handle_query); 199 | ``` 200 | - Edit this to create your plugin. 201 | - After writing code, follow user guide to test your plugin 202 | 203 | ### Explanation 204 | 205 | #### Prefix 206 | This is used to invoke the plugin's query handler. This is the first argument of the `define_plugin!` macro. User can 207 | overwrite this by providing a custom prefix like following: 208 | ```toml 209 | PLUGIN = { prefix = "custom_prefix!", path = "plugin_path", config = {} } 210 | ``` 211 | 212 | #### Keyboard shortcut 213 | This is used to invoke the plugin's query handler using shortcut keys. This is the second argument of the `define_plugin!` 214 | macro. Under the hood, Findex inserts the prefix for the plugin into the search box when it's pressed. 215 | ```toml 216 | PLUGIN = { keyboard_shortcut = "P", path = "plugin_path", config = {} } 217 | ``` 218 | 219 | #### `init` function 220 | The `init` function is the function that Findex calls during startup. Plugins may use this to do necessary initialization. 221 | Plugins that do not need any initialization can just return without doing anything. The first argument of the function is 222 | plugin specific configuration. 223 | 224 | The user may provide configuration in the following format: 225 | ```toml 226 | PLUGIN = { path = "plugin_path", config = { key1 = "value1", key2 = "value2" } } 227 | ``` 228 | 229 | As you can see, every key will have a string value. This function is the third argument of the `define_plugin!` macro. 230 | 231 | #### `handle_query` function 232 | This function gets called every time a user invokes the plugin by typing the prefix. The first argument is the query the 233 | user typed after the prefix. The function is expected to return a RVec containing results(if any). This function is the 234 | fourth argument of the `define_plugin!` macro. 235 | 236 | 237 | ## Reporting Bugs 238 | If you find any bugs, please create an issue and include the latest log from `${XDG_CACHE_HOME}/findex-logs`. `XDG_CACHE_HOME` is normally `~/.cache`. 239 | -------------------------------------------------------------------------------- /crates/findex-daemon/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "findex-daemon" 3 | version = "0.8.3" 4 | edition = "2021" 5 | authors = ["MD Gaziur Rahman Noor "] 6 | license = "GPL3" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | nix = { version = "0.30.1", features = ["time"] } 12 | daemonize = "0.5.0" 13 | shellexpand = "3.0.0" 14 | inotify = "0.11.0" 15 | subprocess = "0.2.9" 16 | sysinfo = "0.35.0" 17 | xdg = "3.0.0" 18 | -------------------------------------------------------------------------------- /crates/findex-daemon/src/main.rs: -------------------------------------------------------------------------------- 1 | use daemonize::Daemonize; 2 | use inotify::{Inotify, WatchMask}; 3 | use nix::libc::time_t; 4 | use nix::time::ClockId; 5 | use shellexpand::tilde; 6 | use std::ffi::OsStr; 7 | use std::fs::File; 8 | use std::io::ErrorKind; 9 | use std::time::Duration; 10 | use subprocess::{ExitStatus, Popen, PopenConfig, Redirection}; 11 | use sysinfo::{ProcessRefreshKind, RefreshKind, System}; 12 | 13 | fn findex_daemon(current_time: time_t, logs_dir: &str, config_dir: &str) { 14 | fn spawn_findex(findex_output: File) -> Popen { 15 | Popen::create( 16 | &["findex"], 17 | PopenConfig { 18 | stdout: Redirection::File(findex_output), 19 | ..Default::default() 20 | }, 21 | ) 22 | .expect("Failed to spawn Findex") 23 | } 24 | 25 | let findex_output = File::create(&*tilde(&format!( 26 | "{logs_dir}/findex-{current_time}.log" 27 | ))) 28 | .expect("Failed to create file to store findex output"); 29 | 30 | let mut findex_process = spawn_findex(findex_output.try_clone().unwrap()); 31 | 32 | let mut inotify = Inotify::init().expect("Failed to init inotify"); 33 | let watch_mask = WatchMask::CREATE | WatchMask::MODIFY | WatchMask::MOVE | WatchMask::DELETE; 34 | inotify 35 | .watches() 36 | .add(config_dir, watch_mask) 37 | .unwrap_or_else(|_| panic!("Failed to watch `{config_dir}`")); 38 | loop { 39 | if let Ok(Some(exit_status)) = findex_process.wait_timeout(Duration::from_millis(500)) { 40 | eprint!("[WARN] Findex exited unexpectedly"); 41 | match exit_status { 42 | ExitStatus::Exited(code) => eprintln!("with exit code: {code}"), 43 | ExitStatus::Signaled(signal) => eprintln!(" with signal: {signal}"), 44 | _ => eprintln!(), 45 | } 46 | 47 | println!("[INFO] Respawning Findex"); 48 | 49 | findex_process = spawn_findex(findex_output.try_clone().unwrap()); 50 | } 51 | 52 | let mut buf = [0; 1024]; 53 | match inotify.read_events(&mut buf) { 54 | Ok(mut events) => { 55 | if let Some(event) = events.next() { 56 | if event.name == Some(OsStr::new("toggle_file")) && events.next().is_none() { 57 | continue; 58 | } 59 | 60 | println!("[INFO] configs changed, restarting findex"); 61 | if findex_process.poll().is_none() { 62 | findex_process.kill().unwrap(); 63 | } 64 | findex_process = spawn_findex(findex_output.try_clone().unwrap()); 65 | } 66 | } 67 | Err(e) if e.kind() == ErrorKind::WouldBlock => continue, 68 | Err(e) => println!("[WARN] Inotify error: {e}"), 69 | } 70 | } 71 | } 72 | 73 | fn main() { 74 | if System::new_with_specifics(RefreshKind::everything().with_processes(ProcessRefreshKind::everything())) 75 | .processes_by_exact_name(OsStr::new("findex")) 76 | .count() 77 | > 0 78 | { 79 | eprintln!("[ERROR] Findex is already running"); 80 | eprintln!("[ERROR] Help: You may want to kill with `killall findex findex-daemon`"); 81 | 82 | return; 83 | } 84 | 85 | let current_time = nix::time::clock_gettime(ClockId::CLOCK_REALTIME) 86 | .unwrap() 87 | .tv_sec(); 88 | 89 | let xdg_base_directories = xdg::BaseDirectories::new(); 90 | 91 | let logs_dir = xdg_base_directories 92 | .create_cache_directory("findex-logs") 93 | .expect("Failed to create `findex-logs` folder to store logs"); 94 | 95 | let config_dir = xdg_base_directories 96 | .create_config_directory("findex") 97 | .expect("Failed to create` findex ` folder to store configs"); 98 | 99 | let config_dir_str = config_dir 100 | .to_str() 101 | .unwrap(); 102 | 103 | let logs_dir_str = logs_dir.to_str().unwrap(); 104 | 105 | let logfile = File::create(&*tilde(&format!( 106 | "{logs_dir_str}/findex-daemon-{current_time}.log" 107 | ))) 108 | .expect("Failed to create file to store logs"); 109 | 110 | let daemon = Daemonize::new() 111 | .stdout(logfile.try_clone().unwrap()) 112 | .stderr(logfile.try_clone().unwrap()); 113 | 114 | match daemon.start() { 115 | Ok(_) => findex_daemon(current_time, logs_dir_str, config_dir_str), 116 | Err(e) => eprintln!("[ERROR] Failed to start findex daemon: {e}"), 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /crates/findex-plugin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "findex-plugin" 3 | description = "Plugins library for Findex" 4 | license = "GPL-3.0" 5 | homepage = "https://github.com/mdgaziur/findex" 6 | repository = "https://github.com/mdgaziur/findex" 7 | documentation = "https://github.com/mdgaziur/findex/blob/development/crates/findex-plugin/README.md" 8 | version = "0.8.3" 9 | edition = "2021" 10 | authors = ["MD Gaziur Rahman Noor "] 11 | 12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 | 14 | [features] 15 | findex_internals = ["dep:libloading", "dep:gtk", "dep:serde"] 16 | 17 | [dependencies] 18 | libloading = { version = "0.8.6", optional = true } 19 | gtk = { version = "0.18.2", features = ["v3_24"], optional = true } 20 | serde = { version = "1", features = ["derive"], optional = true } 21 | abi_stable = "0.11.1" 22 | -------------------------------------------------------------------------------- /crates/findex-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Findex Plugins System Guide 2 | This guide explains the findex plugin system to the users and developers. 3 | 4 | ## For users 5 | - Download the plugin. If it's not compiled, then compile it in release mode using `cargo build --release` 6 | - Go to `target/release` folder. 7 | - You'll see a file with `.so` extension. Copy that to a convenient place. 8 | - Add the following line to your `settings.toml` and edit it to make findex use the plugin: 9 | ```toml 10 | PLUGIN = { path = "PLUGIN PATH", prefix = "OPTIONAL USER DEFINED PREFIX", keyboard_shortcut = "OPTIONAL USER DEFINED KEYBOARD SHORTCUT", config = {} } 11 | ``` 12 | 13 | | Property | Description | 14 | |-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------| 15 | | path | Path to the plugin's `.so` file | 16 | | prefix | Optional user defined prefix that'll make findex use this instead of the one specified in the plugin. | 17 | | config | Plugin's configuration. Please refer to the plugin's documentation for more information. | 18 | | keyboard_shortcut | Optional custom keyboard shortcut for triggering the plugin(inserts the plugins prefix into the search box). Must be a valid Gtk accelerator. | 19 | - For more information, please refer to the documentation of the plugin you are using. 20 | 21 | **NOTE**: always make sure that the plugins you are using are compatible with the version of Findex you are using. 22 | 23 | ## For developers 24 | 25 | Only Rust based plugins are supported. 26 | 27 | - First make a `cdylib` library 28 | - Add `findex-plugin` and `abi_stable` as dependency 29 | - Add the following code into `src/lib.rs` 30 | ```rust 31 | use findex_plugin::{define_plugin, FResult}; 32 | use abi_stable::std_types::*; 33 | 34 | fn init(config: &RHashMap) -> RResult<(), RString> { 35 | // Set up your plugin using the config if necessary 36 | // Return RErr if something went wrong 37 | 38 | // Returning this indicates that the plugin initialization is successful 39 | ROk(()) 40 | } 41 | 42 | fn handle_query(query: RStr) -> RVec { 43 | let mut result = vec![]; 44 | 45 | /* Do stuff here */ 46 | 47 | RVec::from(result) 48 | } 49 | 50 | define_plugin!("prefix!", init, handle_query); 51 | // or add the following if you want to have custom shortcut for triggering the plugin. 52 | // The following sets the shortcut to Ctrl+Shift+P. 53 | // define_plugin!("prefix!", "P", init, handle_query); 54 | ``` 55 | - Edit this to create your plugin. 56 | - After writing code, follow user guide to test your plugin 57 | 58 | ### Explanation 59 | 60 | #### Prefix 61 | This is used to invoke the plugin's query handler. This is the first argument of the `define_plugin!` macro. User can 62 | overwrite this by providing a custom prefix like following: 63 | ```toml 64 | PLUGIN = { prefix = "custom_prefix!", path = "plugin_path", config = {} } 65 | ``` 66 | 67 | #### Keyboard shortcut 68 | This is used to invoke the plugin's query handler using shortcut keys. This is the second argument of the `define_plugin!` 69 | macro. Under the hood, Findex inserts the prefix for the plugin into the search box when it's pressed. 70 | ```toml 71 | PLUGIN = { keyboard_shortcut = "P", path = "plugin_path", config = {} } 72 | ``` 73 | 74 | #### `init` function 75 | The `init` function is the function that Findex calls during startup. Plugins may use this to do necessary initialization. 76 | Plugins that do not need any initialization can just return without doing anything. The first argument of the function is 77 | plugin specific configuration. 78 | 79 | The user may provide configuration in the following format: 80 | ```toml 81 | PLUGIN = { path = "plugin_path", config = { key1 = "value1", key2 = "value2" } } 82 | ``` 83 | 84 | As you can see, every key will have a string value. This function is the third argument of the `define_plugin!` macro. 85 | 86 | #### `handle_query` function 87 | This function gets called every time a user invokes the plugin by typing the prefix. The first argument is the query the 88 | user typed after the prefix. The function is expected to return a RVec containing results(if any). This function is the 89 | fourth argument of the `define_plugin!` macro. 90 | -------------------------------------------------------------------------------- /crates/findex-plugin/src/findex_internal.rs: -------------------------------------------------------------------------------- 1 | use crate::FResult; 2 | use abi_stable::std_types::*; 3 | use gtk::gdk::{EventKey, ModifierType}; 4 | use gtk::{accelerator_get_label, accelerator_parse}; 5 | use libloading::{Library, Symbol}; 6 | use serde::de; 7 | use serde::de::{Deserialize, Deserializer, Error as SerdeError}; 8 | use serde::ser::{Serialize, Serializer}; 9 | use std::fmt::Formatter; 10 | 11 | pub struct PluginDefinition { 12 | pub plugin: Library, 13 | pub prefix: RString, 14 | pub keyboard_shortcut: Option, 15 | } 16 | 17 | impl PluginDefinition { 18 | /// Calls the initialization function of plugin 19 | /// 20 | /// # Safety 21 | /// User must ensure that the plugin doesn't violate memory safety 22 | pub unsafe fn plugin_init(&self, config: &RHashMap) -> RResult<(), RString> { 23 | self.plugin 24 | .get::) -> RResult<(), RString>>>( 25 | b"findex_plugin_init", 26 | ) 27 | .unwrap()(config) 28 | } 29 | 30 | /// Sends query to plugin and retrieves the result 31 | /// 32 | /// # Safety 33 | /// User must ensure that the plugin doesn't violate memory safety 34 | pub unsafe fn plugin_query_handler(&self, query: RStr) -> RVec { 35 | self.plugin 36 | .get:: RVec>>( 37 | b"findex_plugin_query_handler", 38 | ) 39 | .unwrap()(query) 40 | } 41 | } 42 | 43 | /// Loads the plugin and checks for necessary functions and symbols 44 | /// 45 | /// # Safety 46 | /// User must ensure that the plugin doesn't violate memory safety 47 | pub unsafe fn load_plugin(plugin_path: &str) -> Result { 48 | let plugin = Library::new(plugin_path).map_err(|e| e.to_string())?; 49 | let prefix = plugin 50 | .get::<*const &str>(b"FINDEX_PLUGIN_PREFIX") 51 | .map_err(|e| e.to_string())?; 52 | let keyboard_shortcut_accel = plugin 53 | .get::<*const &str>(b"FINDEX_PLUGIN_KEYBOARD_SHORTCUT") 54 | .map(|accel| **accel) 55 | .ok(); 56 | let keyboard_shortcut = if let Some(accel) = keyboard_shortcut_accel { 57 | Some( 58 | KeyboardShortcut::from_accelerator(accel) 59 | .ok_or(format!("plugin provides invalid accelerator: {accel}"))?, 60 | ) 61 | } else { 62 | None 63 | }; 64 | 65 | // We don't use them right now, but we need this to check whether the necessary functions exist or not 66 | plugin 67 | .get::) -> bool>>( 68 | b"findex_plugin_init", 69 | ) 70 | .map_err(|e| e.to_string())?; 71 | plugin 72 | .get:: RVec>>(b"findex_plugin_query_handler") 73 | .map_err(|e| e.to_string())?; 74 | 75 | Ok(PluginDefinition { 76 | prefix: RString::from(**prefix), 77 | keyboard_shortcut, 78 | plugin, 79 | }) 80 | } 81 | 82 | #[derive(Debug, PartialEq, Clone, Copy)] 83 | pub struct KeyboardShortcut { 84 | pub keyval: u32, 85 | pub modifier: ModifierType, 86 | } 87 | 88 | impl KeyboardShortcut { 89 | pub fn from_eventkey(eventkey: &EventKey) -> Self { 90 | Self { 91 | keyval: *eventkey.keyval().to_lower(), 92 | modifier: Self::clean_modifier_type(eventkey.state()), 93 | } 94 | } 95 | 96 | pub fn from_accelerator(accelerator: &str) -> Option { 97 | let (keycode, modifier) = accelerator_parse(accelerator); 98 | if keycode == 0 { 99 | None 100 | } else { 101 | Some(KeyboardShortcut { 102 | keyval: keycode, 103 | modifier, 104 | }) 105 | } 106 | } 107 | 108 | pub fn clean_modifier_type(mut modifier_type: ModifierType) -> ModifierType { 109 | modifier_type &= ModifierType::MODIFIER_MASK; 110 | modifier_type.remove(ModifierType::MOD2_MASK); 111 | modifier_type.remove(ModifierType::LOCK_MASK); 112 | modifier_type.remove(ModifierType::MOD4_MASK); 113 | 114 | modifier_type 115 | } 116 | } 117 | 118 | impl Serialize for KeyboardShortcut { 119 | fn serialize(&self, serializer: S) -> Result 120 | where 121 | S: Serializer, 122 | { 123 | serializer.serialize_str(&format!( 124 | "{}", 125 | accelerator_get_label(self.keyval, self.modifier).unwrap() 126 | )) 127 | } 128 | } 129 | 130 | impl<'de> Deserialize<'de> for KeyboardShortcut { 131 | fn deserialize(deserializer: D) -> Result 132 | where 133 | D: Deserializer<'de>, 134 | { 135 | deserializer.deserialize_str(KeyboardShortcutVisitor) 136 | } 137 | } 138 | 139 | struct KeyboardShortcutVisitor; 140 | 141 | impl<'de> de::Visitor<'de> for KeyboardShortcutVisitor { 142 | type Value = KeyboardShortcut; 143 | 144 | fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { 145 | formatter.write_str("expected a string containing valid accelerator") 146 | } 147 | 148 | fn visit_str(self, v: &str) -> Result 149 | where 150 | E: SerdeError, 151 | { 152 | KeyboardShortcut::from_accelerator(v).ok_or(E::custom("expected a valid accelerator")) 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /crates/findex-plugin/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "findex_internals")] 2 | pub mod findex_internal; 3 | 4 | use abi_stable::std_types::*; 5 | 6 | /// This struct is used to represent results by plugins and internal code of Findex. 7 | #[derive(Clone)] 8 | #[repr(C)] 9 | pub struct FResult { 10 | /// Name of the result 11 | pub name: RString, 12 | /// Optional description of the result 13 | pub desc: ROption, 14 | /// The command to execute when the user presses enter 15 | pub cmd: ApplicationCommand, 16 | /// The icon of the result 17 | pub icon: RString, 18 | /// Score of the result. This will be used to sort multiple results 19 | pub score: isize, 20 | } 21 | 22 | #[derive(Clone, PartialEq)] 23 | #[repr(C)] 24 | pub enum ApplicationCommand { 25 | /// Exact command to execute 26 | Command(RString), 27 | /// AppId of GIO AppInfo 28 | Id(RString), 29 | /// Useful for results from plugins like calculator. 30 | None, 31 | } 32 | 33 | /// This macro is used to define a Findex plugin. 34 | /// 35 | /// Example usage: 36 | /// ```rust 37 | /// use findex_plugin::{define_plugin, FResult}; 38 | /// use abi_stable::std_types::*; 39 | /// 40 | /// fn init(config: &RHashMap) -> RResult<(), RString> { 41 | /// // Set up your plugin using the config if necessary 42 | /// // Return RErr if something went wrong 43 | /// 44 | /// // Returning this indicates that the plugin initalization is successful 45 | /// ROk(()) 46 | /// } 47 | /// 48 | /// fn handle_query(query: RStr) -> RVec { 49 | /// let mut result = vec![]; 50 | /// 51 | /// /* Do stuff here */ 52 | /// 53 | /// RVec::from(result) 54 | /// } 55 | /// 56 | /// define_plugin!("prefix!", init, handle_query); 57 | /// // or, add a shortcut key 58 | /// define_plugin!("prefix!", "p", init, handle_query); 59 | /// ``` 60 | /// 61 | /// Refer to the `README.md` of this crate for more detailed explanation 62 | #[macro_export] 63 | macro_rules! define_plugin { 64 | ($prefix:literal, $init_function:ident, $query_handler:ident) => { 65 | #[no_mangle] 66 | #[used] 67 | pub static FINDEX_PLUGIN_PREFIX: &'static str = $prefix; 68 | 69 | #[no_mangle] 70 | extern "C" fn findex_plugin_init( 71 | config: &RHashMap, 72 | ) -> RResult<(), RString> { 73 | $init_function(config) 74 | } 75 | 76 | #[no_mangle] 77 | extern "C" fn findex_plugin_query_handler(query: RStr) -> RVec { 78 | $query_handler(query) 79 | } 80 | }; 81 | 82 | ($prefix:literal, $keyboard_shortcut:literal, $init_function:ident, $query_handler:ident) => { 83 | #[no_mangle] 84 | #[used] 85 | pub static FINDEX_PLUGIN_PREFIX: &'static str = $prefix; 86 | 87 | #[no_mangle] 88 | #[used] 89 | pub static FINDEX_PLUGIN_KEYBOARD_SHORTCUT: &'static str = $keyboard_shortcut; 90 | 91 | #[no_mangle] 92 | extern "C" fn findex_plugin_init( 93 | config: &RHashMap, 94 | ) -> RResult<(), RString> { 95 | $init_function(config) 96 | } 97 | 98 | #[no_mangle] 99 | extern "C" fn findex_plugin_query_handler(query: RStr) -> RVec { 100 | $query_handler(query) 101 | } 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /crates/findex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "findex" 3 | version = "0.8.3" 4 | edition = "2021" 5 | authors = ["MD Gaziur Rahman Noor "] 6 | description = "Highly customizable application finder with high performance. Written in Rust and uses GTK" 7 | homepage = "https://github.com/mdgaziur/findex" 8 | repository = "https://github.com/mdgaziur/findex" 9 | license = "GPL3" 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | 13 | [dependencies] 14 | gtk = { version = "0.18.2", features = ["v3_24"] } 15 | serde = { version = "1", features = ["derive"] } 16 | lazy_static = "1" 17 | toml = "0.8.22" 18 | shellexpand = "3.1.1" 19 | sublime_fuzzy = "0.7.0" 20 | xdg = "3.0.0" 21 | inotify = "0.11.0" 22 | parking_lot = "0.12.1" 23 | regex = "1.6.0" 24 | keybinder = { version = "0.4.0" } 25 | findex-plugin = { path = "../findex-plugin", features = ["findex_internals"] } 26 | abi_stable = "0.11.1" 27 | shlex = "1.3.0" 28 | -------------------------------------------------------------------------------- /crates/findex/build.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | fn main() { 4 | let git_commit = match Command::new("git") 5 | .args(["describe", "--tags"]) 6 | .output() { 7 | Ok(output) => { 8 | if output.status.success() { 9 | String::from_utf8_lossy(&output.stdout).to_string() 10 | } else { 11 | String::from("[git was unavailable in build time]") 12 | } 13 | }, 14 | Err(_) => String::from("[git was unavailable in build time]"), 15 | }; 16 | 17 | println!("cargo:rustc-env=GIT_COMMIT={git_commit}"); 18 | } -------------------------------------------------------------------------------- /crates/findex/src/app_list.rs: -------------------------------------------------------------------------------- 1 | use abi_stable::std_types::*; 2 | use findex_plugin::{ApplicationCommand, FResult}; 3 | use gtk::gio::AppInfo as GIOAppInfo; 4 | use gtk::prelude::*; 5 | use lazy_static::lazy_static; 6 | use parking_lot::Mutex; 7 | use std::collections::HashMap; 8 | 9 | pub type AppInfo = FResult; 10 | 11 | lazy_static! { 12 | pub static ref APPS_LIST: Mutex> = Mutex::new(Vec::new()); 13 | } 14 | 15 | fn appresult_from(app_info: &GIOAppInfo) -> AppInfo { 16 | let icon = match app_info.icon() { 17 | Some(icon) => RString::from(IconExt::to_string(&icon).unwrap().to_string()), 18 | None => RString::from("application-other"), 19 | }; 20 | 21 | AppInfo { 22 | name: RString::from(app_info.name().to_string()), 23 | desc: ROption::from(app_info.description().map(|d| RString::from(d.to_string()))), 24 | cmd: ApplicationCommand::Id(RString::from(app_info.id().unwrap().to_string())), 25 | icon, 26 | score: 0, 27 | } 28 | } 29 | 30 | pub fn strip_parameters(cmd: &str) -> String { 31 | let parameter_regex = regex::Regex::new("%.").unwrap(); 32 | parameter_regex.replace(cmd, "").to_string() 33 | } 34 | 35 | pub fn update_apps_list() { 36 | let list = GIOAppInfo::all() 37 | .into_iter() 38 | .filter(|appinfo| appinfo.commandline().is_some()) 39 | .map(|appinfo| { 40 | ( 41 | appinfo.commandline().unwrap().to_str().unwrap().to_string(), 42 | appresult_from(&appinfo), 43 | ) 44 | }) 45 | .collect::>() 46 | .iter() 47 | .map(|value| value.1.clone()) 48 | .collect(); 49 | 50 | *APPS_LIST.lock() = list; 51 | } 52 | -------------------------------------------------------------------------------- /crates/findex/src/config.rs: -------------------------------------------------------------------------------- 1 | use crate::gui::dialog::show_dialog; 2 | use abi_stable::std_types::*; 3 | use findex_plugin::findex_internal::{load_plugin, KeyboardShortcut, PluginDefinition}; 4 | use gtk::MessageType; 5 | use lazy_static::lazy_static; 6 | use serde::{Deserialize, Serialize}; 7 | use std::collections::HashMap; 8 | 9 | lazy_static! { 10 | pub static ref FINDEX_CONFIG: FindexConfig = { 11 | let settings = load_settings(); 12 | if let Err(e) = settings { 13 | FindexConfig { 14 | error: RString::from(e), 15 | ..Default::default() 16 | } 17 | } else { 18 | settings.unwrap() 19 | } 20 | }; 21 | } 22 | 23 | #[derive(Serialize, Deserialize)] 24 | #[serde(default)] 25 | pub struct FindexConfig { 26 | pub default_window_width: i32, 27 | pub min_content_height: i32, 28 | pub max_content_height: i32, 29 | pub name_match_highlight_color: RString, 30 | pub decorate_window: bool, 31 | pub close_window_on_losing_focus: bool, 32 | pub query_placeholder: RString, 33 | pub icon_size: i32, 34 | pub entry_icon: RString, 35 | pub toggle_key: RString, 36 | pub min_score: isize, 37 | pub result_size: usize, 38 | pub plugins: HashMap, 39 | #[serde(skip)] 40 | pub error: RString, 41 | /// This should get filled after configuration gets initialized 42 | #[serde(skip)] 43 | pub plugin_definitions: HashMap, 44 | pub on_monitor: ROption, 45 | } 46 | 47 | #[derive(Serialize, Deserialize)] 48 | pub struct Plugin { 49 | pub prefix: Option, 50 | pub keyboard_shortcut: Option, 51 | pub path: RString, 52 | pub config: RHashMap, 53 | } 54 | 55 | impl Default for FindexConfig { 56 | fn default() -> Self { 57 | FindexConfig { 58 | min_content_height: 0, 59 | max_content_height: 400, 60 | default_window_width: 700, 61 | name_match_highlight_color: RString::from("orange"), 62 | decorate_window: false, 63 | query_placeholder: RString::from("Search for applications"), 64 | close_window_on_losing_focus: true, 65 | icon_size: 32, 66 | entry_icon: RString::from("search"), 67 | min_score: 5, 68 | result_size: 5, 69 | toggle_key: RString::from("space"), 70 | error: RString::new(), 71 | plugins: HashMap::new(), 72 | plugin_definitions: HashMap::new(), 73 | on_monitor: RNone, 74 | } 75 | } 76 | } 77 | 78 | fn load_settings() -> Result { 79 | #[cfg(debug_assertions)] 80 | use std::path::PathBuf; 81 | 82 | #[cfg(debug_assertions)] 83 | let settings_path = PathBuf::from("settings.toml"); 84 | 85 | #[cfg(not(debug_assertions))] 86 | let settings_dir = xdg::BaseDirectories::new() 87 | .create_config_directory("findex") 88 | .expect("Failed to create config directory"); 89 | 90 | #[cfg(not(debug_assertions))] 91 | let settings_path = settings_dir.join("settings.toml"); 92 | 93 | let file = std::path::Path::new(&settings_path); 94 | let mut res = if !file.exists() { 95 | #[cfg(not(debug_assertions))] 96 | if !std::path::Path::new(&settings_dir).exists() { 97 | std::fs::create_dir(&settings_dir).unwrap(); 98 | } 99 | 100 | let settings = toml::to_string(&FindexConfig::default()).unwrap(); 101 | std::fs::write(settings_path, settings).unwrap(); 102 | 103 | Ok(FindexConfig::default()) 104 | } else { 105 | let settings = std::fs::read_to_string(&settings_path).unwrap(); 106 | 107 | toml::from_str(&settings).map_err(|e| format!("Error while parsing settings: {e}")) 108 | }; 109 | 110 | if let Ok(ref mut config) = res { 111 | for (name, plugin) in &mut config.plugins { 112 | let mut plugin_definition = 113 | match unsafe { load_plugin(&shellexpand::tilde(&plugin.path)) } { 114 | Ok(pd) => pd, 115 | Err(e) => { 116 | show_dialog( 117 | "Error", 118 | &format!("Failed to load plugin {name}: {e}"), 119 | MessageType::Error, 120 | ); 121 | continue; 122 | } 123 | }; 124 | 125 | if !plugin.config.contains_key("highlight_color") { 126 | plugin.config.insert( 127 | RString::from("highlight_color"), 128 | config.name_match_highlight_color.clone(), 129 | ); 130 | } 131 | let init_result = unsafe { plugin_definition.plugin_init(&plugin.config) }; 132 | if let RErr(e) = init_result { 133 | show_dialog( 134 | "Error", 135 | &format!("Plugin \"{name}\" failed to initialize: {e}"), 136 | MessageType::Error, 137 | ); 138 | continue; 139 | } 140 | 141 | if let Some(prefix) = &plugin.prefix { 142 | plugin_definition.prefix = prefix.clone(); 143 | } 144 | 145 | if plugin.keyboard_shortcut.is_some() { 146 | plugin_definition.keyboard_shortcut = plugin.keyboard_shortcut; 147 | } 148 | 149 | config.plugin_definitions.insert( 150 | plugin 151 | .prefix 152 | .as_ref() 153 | .cloned() 154 | .unwrap_or_else(|| plugin_definition.prefix.clone()), 155 | plugin_definition, 156 | ); 157 | } 158 | } 159 | 160 | res 161 | } 162 | -------------------------------------------------------------------------------- /crates/findex/src/gui/css.rs: -------------------------------------------------------------------------------- 1 | use gtk::prelude::*; 2 | use gtk::CssProvider; 3 | 4 | #[cfg(debug_assertions)] 5 | pub fn load_css() -> Result { 6 | #[cfg(debug_assertions)] 7 | let css_path = "./css/style.css"; 8 | 9 | let css = CssProvider::new(); 10 | css.load_from_path(css_path)?; 11 | 12 | Ok(css) 13 | } 14 | 15 | #[cfg(not(debug_assertions))] 16 | pub fn load_css() -> Result { 17 | let config_path = xdg::BaseDirectories::new() 18 | .create_config_directory("findex") 19 | .expect("Failed to create config dir"); 20 | let css_path_0 = config_path.join("style.css"); 21 | let css_path_1 = "/opt/findex/style.css"; 22 | let css = CssProvider::new(); 23 | 24 | let mut file = std::path::Path::new(&css_path_0); 25 | if !file.exists() { 26 | eprintln!( 27 | "[WARN] Stylesheet wasn't found in user's home directory. Falling backing to default one." 28 | ); 29 | 30 | file = std::path::Path::new(css_path_1); 31 | if file.exists() { 32 | std::fs::copy(css_path_1, &css_path_0).unwrap(); 33 | } else { 34 | eprintln!("[WARN] Couldn't find any stylesheet"); 35 | return Ok(css); 36 | } 37 | } 38 | 39 | css.load_from_path(css_path_0.to_str().unwrap())?; 40 | 41 | Ok(css) 42 | } 43 | -------------------------------------------------------------------------------- /crates/findex/src/gui/dialog.rs: -------------------------------------------------------------------------------- 1 | use gtk::prelude::*; 2 | use gtk::{ButtonsType, MessageDialog, MessageType}; 3 | 4 | pub fn show_dialog(title: &str, message: &str, message_type: MessageType) { 5 | let dialog = MessageDialog::builder() 6 | .title(title) 7 | .text(message) 8 | .message_type(message_type) 9 | .buttons(ButtonsType::Ok) 10 | .build(); 11 | 12 | dialog.run(); 13 | dialog.close(); 14 | } 15 | -------------------------------------------------------------------------------- /crates/findex/src/gui/mod.rs: -------------------------------------------------------------------------------- 1 | mod css; 2 | pub mod dialog; 3 | mod result_list; 4 | mod result_list_row; 5 | mod searchbox; 6 | 7 | use crate::config::FINDEX_CONFIG; 8 | use crate::gui::css::load_css; 9 | use crate::gui::result_list::{result_list_clear, result_list_new}; 10 | use crate::gui::result_list_row::handle_enter; 11 | use crate::gui::searchbox::searchbox_new; 12 | use crate::show_dialog; 13 | use abi_stable::std_types::*; 14 | use findex_plugin::findex_internal::KeyboardShortcut; 15 | use gtk::gdk::{EventKey, EventMask, ModifierType, Screen}; 16 | use gtk::prelude::*; 17 | use gtk::{Box as GtkBox, gdk, Entry, ListBox, MessageType, Orientation, ScrolledWindow, Window, WindowType}; 18 | use gtk::glib::{ControlFlow, Priority, Propagation}; 19 | use keybinder::KeyBinder; 20 | 21 | #[allow(clippy::upper_case_acronyms)] 22 | pub struct GUI { 23 | pub window: Window, 24 | search_box: Entry, 25 | result_list: ListBox, 26 | keybinder: Option>, 27 | } 28 | 29 | impl GUI { 30 | pub fn new() -> Self { 31 | let window = Window::builder() 32 | .title("Findex") 33 | .resizable(false) 34 | .default_width(FINDEX_CONFIG.default_window_width) 35 | .decorated(FINDEX_CONFIG.decorate_window) 36 | .skip_taskbar_hint(true) 37 | .skip_pager_hint(true) 38 | .deletable(false) 39 | .type_(WindowType::Toplevel) 40 | .events(EventMask::BUTTON_PRESS_MASK) 41 | .can_focus(true) 42 | .build(); 43 | window.set_keep_above(true); 44 | window.style_context().add_class("findex-window"); 45 | window.connect_destroy(|_| gtk::main_quit()); 46 | 47 | let screen = Screen::default().unwrap(); 48 | let visual = screen.rgba_visual(); 49 | window.set_visual(visual.as_ref()); 50 | 51 | match load_css() { 52 | Ok(provider) => gtk::StyleContext::add_provider_for_screen( 53 | &GtkWindowExt::screen(&window).unwrap(), 54 | &provider, 55 | gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, 56 | ), 57 | Err(e) => show_dialog( 58 | "Warning", 59 | &format!("Failed to load css: {e}"), 60 | MessageType::Warning, 61 | ), 62 | } 63 | 64 | if FINDEX_CONFIG.close_window_on_losing_focus { 65 | window.connect_focus_out_event(|window, _| { 66 | Self::hide_window(window); 67 | 68 | Propagation::Proceed 69 | }); 70 | } 71 | 72 | let container = GtkBox::builder() 73 | .parent(&window) 74 | .orientation(Orientation::Vertical) 75 | .build(); 76 | container.style_context().add_class("findex-container"); 77 | 78 | let scrolled_container = ScrolledWindow::builder() 79 | .max_content_height(FINDEX_CONFIG.max_content_height) 80 | .propagate_natural_height(true) 81 | .build(); 82 | scrolled_container 83 | .style_context() 84 | .add_class("findex-results-scroll"); 85 | 86 | if FINDEX_CONFIG.min_content_height > 0 { 87 | scrolled_container.set_min_content_height(FINDEX_CONFIG.min_content_height); 88 | scrolled_container.set_propagate_natural_height(false); 89 | } 90 | let result_list = result_list_new(&scrolled_container); 91 | let search_box = searchbox_new(&container, result_list.clone()); 92 | 93 | container.add(&scrolled_container); 94 | container.show_all(); 95 | scrolled_container.hide(); 96 | 97 | window.connect_key_press_event({ 98 | let entry = search_box.clone(); 99 | let list_box = result_list.clone(); 100 | 101 | move |window, event| { 102 | // TODO(mdgaziur): fix this hack 103 | let entry = entry.clone(); 104 | let list_box = list_box.clone(); 105 | 106 | keypress_handler(window, entry, list_box, event) 107 | } 108 | }); 109 | 110 | let keybinder = if std::env::var("WAYLAND_DISPLAY").is_err() { 111 | match KeyBinder::new(true) { 112 | Ok(instance) => Some(instance), 113 | Err(_e) => { 114 | eprintln!("[ERROR] Keybinder is not supported"); 115 | std::process::exit(1); 116 | } 117 | } 118 | } else { 119 | None 120 | }; 121 | 122 | Self { 123 | keybinder, 124 | window, 125 | result_list, 126 | search_box, 127 | } 128 | } 129 | 130 | pub fn wait_for_toggle(&mut self) { 131 | if let Some(keybinder) = &mut self.keybinder { 132 | assert!( 133 | keybinder.bind( 134 | &FINDEX_CONFIG.toggle_key, 135 | |_, payload| { 136 | Self::show_window( 137 | &payload.window, 138 | &payload.search_box, 139 | &payload.result_list, 140 | ); 141 | Self::position_window(&payload.window); 142 | }, 143 | KeypressHandlerPayload { 144 | window: self.window.clone(), 145 | result_list: self.result_list.clone(), 146 | search_box: self.search_box.clone(), 147 | }, 148 | ), 149 | "Failed to bind key" 150 | ); 151 | } else { 152 | use gtk::glib::thread_guard::ThreadGuard; 153 | use inotify::{Inotify, WatchMask}; 154 | use shellexpand::tilde; 155 | use std::fs::File; 156 | use std::path::Path; 157 | 158 | let mut inotify = Inotify::init().expect("Failed to init inotify"); 159 | let watch_mask = 160 | WatchMask::CREATE | WatchMask::MODIFY | WatchMask::MOVE | WatchMask::DELETE; 161 | let toggle_file = { 162 | if !Path::new(&*tilde("~/.config/findex/toggle_file")).is_file() { 163 | File::create(&*tilde("~/.config/findex/toggle_file")) 164 | .expect("Failed to create file that toggles findex window"); 165 | } 166 | 167 | &*tilde("~/.config/findex/toggle_file") 168 | }; 169 | inotify 170 | .watches() 171 | .add(toggle_file, watch_mask) 172 | .expect("Failed to add toggle file to inotify watch list"); 173 | let (tx, rx) = gdk::glib::MainContext::channel::<()>(Priority::default()); 174 | 175 | std::thread::spawn(move || loop { 176 | let mut buf = [0; 1024]; 177 | 178 | if let Ok(mut events) = inotify.read_events_blocking(&mut buf) { 179 | if events.next().is_some() { 180 | tx.send(()).expect("Error when notifying event"); 181 | } 182 | } 183 | }); 184 | 185 | rx.attach(None, { 186 | let window = ThreadGuard::new(self.window.clone()); 187 | let search_box = ThreadGuard::new(self.search_box.clone()); 188 | let result_list = ThreadGuard::new(self.result_list.clone()); 189 | move |()| { 190 | Self::show_window( 191 | window.get_ref(), 192 | search_box.get_ref(), 193 | result_list.get_ref(), 194 | ); 195 | ControlFlow::Continue 196 | } 197 | }); 198 | } 199 | } 200 | 201 | fn show_window(window: &Window, search_box: &Entry, result_list: &ListBox) { 202 | window.present(); 203 | 204 | if std::env::var("WAYLAND_DISPLAY").is_err() { 205 | window.present_with_time(keybinder::get_current_event_time()); 206 | } 207 | 208 | search_box.set_text(""); 209 | result_list_clear(result_list); 210 | Self::position_window(window); 211 | } 212 | 213 | fn position_window(window: &Window) { 214 | let display = gdk::Display::default().unwrap(); 215 | 216 | let monitor = if let RSome(on_monitor) = FINDEX_CONFIG.on_monitor { 217 | display.monitor(on_monitor.abs() % display.n_monitors()) 218 | } else { 219 | display.primary_monitor() 220 | }; 221 | 222 | let monitor_geo = if let Some(monitor) = monitor { 223 | monitor.geometry() 224 | } else { 225 | return; 226 | }; 227 | 228 | let screen_height = monitor_geo.height() as f32; 229 | let screen_width = monitor_geo.width() as f32; 230 | let screen_x = monitor_geo.x() as f32; 231 | let screen_y = monitor_geo.y() as f32; 232 | 233 | window.move_( 234 | ((screen_width * 0.5 - (window.allocation().width() / 2) as f32) + screen_x) as i32, 235 | ((screen_height * 0.3) + screen_y) as i32, 236 | ); 237 | } 238 | 239 | fn hide_window(window: &Window) { 240 | window.hide(); 241 | } 242 | } 243 | 244 | struct KeypressHandlerPayload { 245 | window: Window, 246 | result_list: ListBox, 247 | search_box: Entry, 248 | } 249 | 250 | fn keypress_handler( 251 | window: &Window, 252 | entry: Entry, 253 | list_box: ListBox, 254 | eventkey: &EventKey, 255 | ) -> Propagation { 256 | let modifier_type = KeyboardShortcut::clean_modifier_type(eventkey.state()); 257 | let key_name = eventkey.keyval().name().unwrap(); 258 | 259 | if key_name == "Escape" { 260 | GUI::hide_window(window); 261 | Propagation::Stop 262 | } else if key_name == "Down" || key_name == "j" && modifier_type == ModifierType::CONTROL_MASK { 263 | let row_len = list_box.children().len(); 264 | if row_len == 0 { 265 | return Propagation::Stop; 266 | } 267 | 268 | let mut row_index = 0; 269 | if let Some(selected_row) = list_box.selected_row() { 270 | row_index = selected_row.index() + 1; 271 | } 272 | 273 | if row_index as usize >= row_len { 274 | row_index = 0; 275 | } 276 | 277 | list_box.select_row(list_box.row_at_index(row_index).as_ref()); 278 | if let Some(row) = list_box.row_at_index(row_index) { 279 | row.grab_focus() 280 | } 281 | 282 | Propagation::Stop 283 | } else if key_name == "Up" || key_name == "k" && modifier_type == ModifierType::CONTROL_MASK { 284 | let row_len = list_box.children().len(); 285 | if row_len == 0 { 286 | return Propagation::Stop; 287 | } 288 | 289 | let mut row_index = 0; 290 | if let Some(selected_row) = list_box.selected_row() { 291 | row_index = selected_row.index() - 1; 292 | } 293 | 294 | if row_index < 0 { 295 | row_index = row_len as i32 - 1; 296 | } 297 | 298 | list_box.select_row(list_box.row_at_index(row_index).as_ref()); 299 | if let Some(row) = list_box.row_at_index(row_index) { 300 | row.grab_focus() 301 | } 302 | 303 | Propagation::Stop 304 | } else if key_name == "Return" { 305 | if let Some(row) = list_box.selected_row() { 306 | handle_enter(&row); 307 | } 308 | 309 | Propagation::Stop 310 | } else if modifier_type == ModifierType::CONTROL_MASK { 311 | if let Ok(row_idx) = key_name.parse::() { 312 | if let Some(row) = list_box.row_at_index(row_idx) { 313 | handle_enter(&row); 314 | 315 | Propagation::Stop 316 | } else { 317 | Propagation::Proceed 318 | } 319 | } else { 320 | Propagation::Proceed 321 | } 322 | } else { 323 | if !entry.has_focus() { 324 | entry.grab_focus(); 325 | entry.select_region(-1, -1); 326 | } 327 | 328 | Propagation::Proceed 329 | } 330 | } 331 | -------------------------------------------------------------------------------- /crates/findex/src/gui/result_list.rs: -------------------------------------------------------------------------------- 1 | use crate::gui::result_list_row::handle_interaction; 2 | use gtk::prelude::*; 3 | use gtk::{ListBox, ListBoxRow, ScrolledWindow}; 4 | 5 | pub fn result_list_new(parent: &ScrolledWindow) -> ListBox { 6 | let list_box = ListBox::builder().parent(parent).can_focus(true).build(); 7 | 8 | list_box.style_context().add_class("findex-results"); 9 | list_box.connect_row_activated(handle_click); 10 | 11 | list_box 12 | } 13 | 14 | fn handle_click(_: &ListBox, row: &ListBoxRow) { 15 | handle_interaction(row); 16 | } 17 | 18 | pub fn result_list_clear(list_box: &ListBox) { 19 | for child in list_box.children() { 20 | list_box.remove(&child); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/findex/src/gui/result_list_row.rs: -------------------------------------------------------------------------------- 1 | use crate::app_list::strip_parameters; 2 | use crate::gui::dialog::show_dialog; 3 | use crate::FINDEX_CONFIG; 4 | use abi_stable::std_types::*; 5 | use findex_plugin::ApplicationCommand; 6 | use gtk::gdk_pixbuf::{Colorspace, Pixbuf}; 7 | use gtk::gio::{AppLaunchContext, DesktopAppInfo}; 8 | use gtk::pango::EllipsizeMode; 9 | use gtk::prelude::*; 10 | use gtk::{Align, Box as GtkBox, IconLookupFlags, IconTheme, Image, Justification, Label, ListBox, ListBoxRow, MessageType, Orientation}; 11 | use shlex::split; 12 | use std::process::Command; 13 | 14 | pub fn result_list_row( 15 | listbox: &ListBox, 16 | app_icon: &str, 17 | app_name: &str, 18 | app_desc: ROption<&str>, 19 | app_cmd: &ApplicationCommand, 20 | trigger_idx: Option, 21 | ) -> ListBoxRow { 22 | let box1 = GtkBox::builder() 23 | .orientation(Orientation::Horizontal) 24 | .expand(true) 25 | .build(); 26 | box1.style_context() 27 | .add_class("findex-result-icon-container"); 28 | 29 | let app_icon = Image::builder() 30 | .pixbuf(&get_icon(app_icon)) 31 | .parent(&box1) 32 | .build(); 33 | app_icon.style_context().add_class("findex-result-icon"); 34 | 35 | let box2 = GtkBox::builder() 36 | .orientation(Orientation::Vertical) 37 | .valign(Align::Center) 38 | .parent(&box1) 39 | .build(); 40 | box2.style_context() 41 | .add_class("findex-result-info-container"); 42 | 43 | if let Some(trigger_idx) = trigger_idx { 44 | let keyboard_shortcut_label = Label::builder() 45 | .parent(&box1) 46 | .use_markup(true) 47 | .label(format!("Ctrl+{trigger_idx}")) 48 | .xalign(1f32) 49 | .expand(true) 50 | .build(); 51 | keyboard_shortcut_label 52 | .style_context() 53 | .add_class("findex-result-trigger-shortcut"); 54 | } 55 | 56 | let app_name_label = Label::builder() 57 | .parent(&box2) 58 | .use_markup(true) 59 | .label(app_name) 60 | .justify(Justification::Left) 61 | .xalign(0f32) 62 | .expand(true) 63 | .build(); 64 | app_name_label 65 | .style_context() 66 | .add_class("findex-result-app-name"); 67 | 68 | if let RSome(app_desc) = app_desc { 69 | let app_desc_label = Label::builder() 70 | .label(app_desc) 71 | .expand(true) 72 | .parent(&box2) 73 | .justify(Justification::Left) 74 | .xalign(0f32) 75 | .max_width_chars(1) 76 | .hexpand(true) 77 | .ellipsize(EllipsizeMode::End) 78 | .build(); 79 | app_desc_label 80 | .style_context() 81 | .add_class("findex-result-app-description"); 82 | } 83 | 84 | if *app_cmd != ApplicationCommand::None { 85 | let app_cmd_label = Label::builder() 86 | .label(&match app_cmd { 87 | ApplicationCommand::Command(cmd) => cmd.to_string(), 88 | ApplicationCommand::Id(id) => strip_parameters( 89 | DesktopAppInfo::new(id) 90 | .unwrap() 91 | .commandline() 92 | .unwrap() 93 | .to_str() 94 | .unwrap(), 95 | ), 96 | _ => unreachable!(), 97 | }) 98 | .expand(true) 99 | .parent(&box2) 100 | .justify(Justification::Left) 101 | .xalign(0f32) 102 | .max_width_chars(1) 103 | .hexpand(true) 104 | .ellipsize(EllipsizeMode::End) 105 | .build(); 106 | app_cmd_label 107 | .style_context() 108 | .add_class("findex-result-app-command"); 109 | } 110 | 111 | let row = ListBoxRow::builder().parent(listbox).child(&box1).build(); 112 | row.style_context().add_class("findex-result-row"); 113 | 114 | unsafe { 115 | row.set_data("app-cmd", app_cmd.clone()); 116 | } 117 | 118 | row 119 | } 120 | 121 | pub fn handle_enter(row: &ListBoxRow) { 122 | handle_interaction(row); 123 | } 124 | 125 | pub fn handle_interaction(row: &ListBoxRow) { 126 | let cmd = unsafe { row.data::("app-cmd").unwrap().as_ref() }; 127 | 128 | match cmd { 129 | ApplicationCommand::Command(cmd) => { 130 | // Ideally, plugins should provide a None variant for this, but rogue plugins 131 | // can do anything :) 132 | if cmd.is_empty() { 133 | return; 134 | } 135 | 136 | row.toplevel().unwrap().hide(); 137 | let Some(cmd) = split(cmd) else { 138 | show_dialog("Error", "Failed to launch application", MessageType::Error); 139 | return; 140 | }; 141 | 142 | let child = Command::new(&cmd[0]).args(&cmd[1..]).spawn(); 143 | 144 | if let Err(e) = child { 145 | show_dialog( 146 | "Error", 147 | &format!("Failed to launch application: {e}"), 148 | MessageType::Error, 149 | ); 150 | } 151 | } 152 | ApplicationCommand::Id(id) => { 153 | // Ideally, plugins should provide a None variant for this, but rogue plugins 154 | // can do anything :) 155 | if id.is_empty() { 156 | return; 157 | } 158 | 159 | row.toplevel().unwrap().hide(); 160 | let Some(desktop_appinfo) = DesktopAppInfo::new(id) else { 161 | show_dialog("Error", "Failed to launch application", MessageType::Error); 162 | return; 163 | }; 164 | 165 | if let Err(e) = desktop_appinfo.launch(&[], None::.as_ref()) { 166 | show_dialog( 167 | "Error", 168 | &format!("Failed to launch application: {e}"), 169 | MessageType::Error, 170 | ); 171 | } 172 | } 173 | ApplicationCommand::None => {} 174 | } 175 | } 176 | 177 | fn get_icon(icon_name: &str) -> Pixbuf { 178 | let icon; 179 | let icon_theme = IconTheme::default().unwrap(); 180 | 181 | if let Ok(i) = 182 | Pixbuf::from_file_at_size(icon_name, FINDEX_CONFIG.icon_size, FINDEX_CONFIG.icon_size) 183 | { 184 | icon = i; 185 | } else if let Ok(i) = icon_theme.load_icon( 186 | icon_name, 187 | FINDEX_CONFIG.icon_size, 188 | IconLookupFlags::FORCE_SIZE | IconLookupFlags::USE_BUILTIN, 189 | ) { 190 | icon = i.unwrap(); 191 | } else if let Ok(i) = icon_theme.load_icon( 192 | "applications-other", 193 | FINDEX_CONFIG.icon_size, 194 | IconLookupFlags::FORCE_SIZE | IconLookupFlags::USE_BUILTIN, 195 | ) { 196 | icon = i.unwrap(); 197 | } else { 198 | icon = Pixbuf::new( 199 | Colorspace::Rgb, 200 | true, 201 | 8, 202 | FINDEX_CONFIG.icon_size, 203 | FINDEX_CONFIG.icon_size, 204 | ) 205 | .unwrap(); 206 | } 207 | 208 | icon 209 | } 210 | -------------------------------------------------------------------------------- /crates/findex/src/gui/searchbox.rs: -------------------------------------------------------------------------------- 1 | use crate::app_list::{AppInfo, APPS_LIST}; 2 | use crate::config::FINDEX_CONFIG; 3 | use crate::gui::result_list::result_list_clear; 4 | use crate::gui::result_list_row::result_list_row; 5 | use abi_stable::std_types::*; 6 | use findex_plugin::findex_internal::KeyboardShortcut; 7 | use gtk::gdk::EventKey; 8 | use gtk::prelude::*; 9 | use gtk::{Box as GtkBox, Container, Entry, Image, ListBox, Orientation}; 10 | use std::cmp::min; 11 | use gtk::glib::Propagation; 12 | use sublime_fuzzy::{best_match, format_simple}; 13 | 14 | pub fn searchbox_new(parent: &impl IsA, result_list: ListBox) -> Entry { 15 | let container = GtkBox::builder() 16 | .orientation(Orientation::Horizontal) 17 | .expand(true) 18 | .parent(parent) 19 | .build(); 20 | container 21 | .style_context() 22 | .add_class("findex-query-container"); 23 | 24 | let query_icon = Image::builder() 25 | .icon_name(&FINDEX_CONFIG.entry_icon) 26 | .parent(&container) 27 | .pixel_size(FINDEX_CONFIG.icon_size) 28 | .build(); 29 | 30 | query_icon.style_context().add_class("findex-query-icon"); 31 | 32 | let entry = Entry::builder() 33 | .placeholder_text(FINDEX_CONFIG.query_placeholder.as_str()) 34 | .parent(&container) 35 | .has_focus(true) 36 | .can_focus(true) 37 | .is_focus(true) 38 | .editable(true) 39 | .sensitive(true) 40 | .expand(true) 41 | .build(); 42 | 43 | entry.connect_changed(move |entry| on_text_changed(entry, &result_list)); 44 | entry.connect_key_press_event(on_key_pressed); 45 | entry.style_context().add_class("findex-query"); 46 | 47 | entry 48 | } 49 | 50 | fn on_key_pressed(entry: &Entry, eventkey: &EventKey) -> Propagation { 51 | let keyboard_shortcut = KeyboardShortcut::from_eventkey(eventkey); 52 | 53 | // Check if any plugin has registered keyboard shortcut 54 | for plugin in FINDEX_CONFIG.plugin_definitions.values() { 55 | if plugin.keyboard_shortcut.as_ref() == Some(&keyboard_shortcut) { 56 | entry.set_text(&format!("{} ", plugin.prefix.as_str())); 57 | entry.select_region(-1, -1); 58 | return Propagation::Stop; 59 | } 60 | } 61 | 62 | Propagation::Proceed 63 | } 64 | 65 | fn on_text_changed(entry: &Entry, result_list: &ListBox) { 66 | let text = entry.text(); 67 | let mut matches: Vec = Vec::new(); 68 | result_list_clear(result_list); 69 | 70 | if let Some(plugin) = FINDEX_CONFIG 71 | .plugin_definitions 72 | .get(text.split_ascii_whitespace().next().unwrap_or("")) 73 | { 74 | let query = text.split_ascii_whitespace().collect::>()[1..].join(" "); 75 | matches = unsafe { plugin.plugin_query_handler(RStr::from(query.as_str())) }.to_vec(); 76 | } else { 77 | let apps = APPS_LIST.lock(); 78 | 79 | for app in &*apps { 80 | if let Some(match_) = best_match(&text, &app.name) { 81 | let mut app = app.clone(); 82 | if match_.score() > FINDEX_CONFIG.min_score { 83 | let formatted_name = format_simple( 84 | &match_, 85 | &app.name, 86 | &format!( 87 | "", 88 | FINDEX_CONFIG.name_match_highlight_color 89 | ), 90 | "", 91 | ); 92 | 93 | app.name = RString::from(formatted_name); 94 | app.score = match_.score(); 95 | matches.push(app); 96 | } 97 | } 98 | } 99 | } 100 | matches.sort_by(|l, r| r.score.cmp(&l.score)); 101 | 102 | let result_count = min(FINDEX_CONFIG.result_size, matches.len()); 103 | for (app_idx, app) in matches.iter().take(result_count).enumerate() { 104 | result_list_row( 105 | result_list, 106 | &app.icon, 107 | &app.name.replace('&', "&"), 108 | app.desc.as_deref(), 109 | &app.cmd, 110 | if app_idx < 10 { Some(app_idx) } else { None }, 111 | ); 112 | } 113 | 114 | let parent = result_list.parent().unwrap().parent().unwrap(); 115 | if result_list.children().is_empty() { 116 | parent.hide(); 117 | } else { 118 | parent.show(); 119 | } 120 | result_list.show_all(); 121 | result_list.select_row(result_list.row_at_index(0).as_ref()); 122 | entry.grab_focus_without_selecting(); 123 | } 124 | -------------------------------------------------------------------------------- /crates/findex/src/main.rs: -------------------------------------------------------------------------------- 1 | use crate::app_list::update_apps_list; 2 | use crate::config::FINDEX_CONFIG; 3 | use crate::gui::dialog::show_dialog; 4 | use crate::gui::GUI; 5 | use gtk::MessageType; 6 | use inotify::{Inotify, WatchMask}; 7 | use std::ffi::OsStr; 8 | 9 | mod app_list; 10 | mod config; 11 | mod gui; 12 | 13 | static FINDEX_VERSION: &str = env!("CARGO_PKG_VERSION"); 14 | 15 | fn main() { 16 | if std::env::args().any(|arg| arg == "--about") { 17 | println!("Findex v{FINDEX_VERSION} from {}", env!("GIT_COMMIT")); 18 | println!("Author: MD Gaziur Rahman Noor "); 19 | println!("License: GPL3"); 20 | println!("Report issues at: https://github.com/mdgaziur/findex/issues"); 21 | return; 22 | } 23 | 24 | println!("[INFO] Starting Findex..."); 25 | gtk::init().expect("Failed to init GTK"); 26 | if !FINDEX_CONFIG.error.is_empty() { 27 | show_dialog("Warning", &FINDEX_CONFIG.error, MessageType::Warning); 28 | } 29 | 30 | update_apps_list(); 31 | 32 | let mut inotify = Inotify::init().expect("Failed to init inotify"); 33 | let watch_mask = WatchMask::CREATE | WatchMask::MODIFY | WatchMask::MOVE | WatchMask::DELETE; 34 | let base_directories = xdg::BaseDirectories::new(); 35 | 36 | for dir in base_directories.get_data_dirs() { 37 | let watch_dir = dir.join("applications"); 38 | 39 | if !watch_dir.exists() { 40 | continue; 41 | } 42 | if let Err(e) = inotify.watches().add(&watch_dir, watch_mask) { 43 | eprintln!("[WARN] Failed to watch `{}`: {}", watch_dir.display(), e); 44 | } 45 | } 46 | 47 | let xdg_data_home = base_directories.get_data_home().unwrap().join("applications"); 48 | if xdg_data_home.exists() { 49 | if let Err(e) = inotify.watches().add(&xdg_data_home, watch_mask) { 50 | eprintln!( 51 | "[WARN] Failed to watch `{}`: {}", 52 | xdg_data_home.display(), 53 | e 54 | ); 55 | } 56 | } 57 | 58 | std::thread::spawn(move || { 59 | loop { 60 | let mut buffer = [0; 1024]; 61 | if let Ok(events) = inotify.read_events_blocking(&mut buffer) { 62 | // if we're here this means something changed inside any of the directories 63 | for event in events { 64 | println!( 65 | "[INFO] File `{}` was changed", 66 | event 67 | .name 68 | .unwrap_or_else(|| OsStr::new("unavailable")) 69 | .to_str() 70 | .unwrap_or("file name with invalid unicode chars") 71 | ); 72 | } 73 | update_apps_list(); 74 | } 75 | } 76 | }); 77 | 78 | let mut gui = GUI::new(); 79 | gui.wait_for_toggle(); 80 | println!("[INFO] listening for hotkey..."); 81 | 82 | gtk::main(); 83 | } 84 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | all: unset; 3 | } 4 | 5 | .findex-window { 6 | background: transparent; 7 | border: none; 8 | } 9 | 10 | .findex-container { 11 | background: rgb(20, 20, 20); 12 | border-radius: 10px; 13 | margin: 50px; 14 | border: 1px solid rgba(255, 255, 255, 0.1); 15 | box-shadow: 0 0 20px -17px rgba(0,0,0,1); 16 | } 17 | 18 | .findex-query { 19 | background: none; 20 | padding: 20px 24px; 21 | font-size: 25px; 22 | border: none; 23 | color: #ddd; 24 | box-shadow: none; 25 | } 26 | 27 | .findex-query selection { 28 | background: #404040; 29 | } 30 | 31 | .findex-query-icon { 32 | margin: 20px 0 20px 20px; 33 | } 34 | 35 | .findex-query-container { 36 | border: none; 37 | } 38 | 39 | .findex-results-scroll { 40 | padding: 5px; 41 | border-top: 1px solid rgba(255, 255, 255, 0.1); 42 | box-shadow: none; 43 | background-image: none; 44 | } 45 | 46 | .findex-results { 47 | background: none; 48 | border-radius: 5px; 49 | } 50 | 51 | .findex-result-row { 52 | outline: none; 53 | margin: 5px; 54 | padding: 10px; 55 | border-radius: 5px; 56 | border: 1px solid #202020; 57 | border-left: 5px solid #bbbbbb; 58 | } 59 | 60 | .findex-result-row:selected { 61 | border-left: 5px solid #50ee50; 62 | } 63 | 64 | .findex-result-trigger-shortcut { 65 | padding-right: 20px; 66 | color: #eee; 67 | } 68 | 69 | .findex-result-row:selected { 70 | background: #252525; 71 | } 72 | 73 | .findex-result-app-name { 74 | font-size: 15px; 75 | font-weight: 500; 76 | color: #ddd; 77 | } 78 | 79 | .findex-result-icon { 80 | margin-right: 20px; 81 | } 82 | 83 | .findex-result-app-description, 84 | .findex-result-app-command { 85 | color: rgba(255, 255, 255, 0.7); 86 | } 87 | 88 | .findex-result-app-name, 89 | .findex-result-app-description, 90 | .findex-result-app-command { 91 | margin-left: 7px; 92 | } 93 | 94 | .findex-result-app-command { 95 | font-style: italic; 96 | } 97 | 98 | .findex-result-row box:last-child { 99 | margin-left: 10px; 100 | } 101 | 102 | .findex-results:first-child { 103 | border-top-left-radius: 5px; 104 | border-top-right-radius: 5px; 105 | } 106 | 107 | .findex-results:last-child { 108 | border-bottom-left-radius: 5px; 109 | border-bottom-right-radius: 5px; 110 | border-bottom: 1px solid transparent; 111 | } 112 | -------------------------------------------------------------------------------- /installer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | do_installation() { 4 | echo "Installing Findex..." 5 | 6 | echo "Building Findex..." 7 | cargo build --release 8 | 9 | if [[ $? -ne 0 ]]; then 10 | echo "Findex failed to build." 11 | exit 1 12 | fi 13 | 14 | echo "Copying files..." 15 | sudo cp target/release/findex /usr/bin/findex 16 | sudo cp target/release/findex-daemon /usr/bin/findex-daemon 17 | sudo echo "" 18 | sudo mkdir -p /opt/findex 19 | sudo cp css/style.css /opt/findex 20 | sudo install -Dm644 service/*.service -t /usr/lib/systemd/user 21 | systemctl daemon-reload --user 22 | 23 | 24 | if [[ ! -f ~/.config/findex/settings.toml ]]; then 25 | touch ~/.config/findex/settings.toml 26 | fi 27 | 28 | if [[ ! -f ~/.config/findex/style.css ]]; then 29 | cp css/style.css ~/.config/findex/style.css 30 | fi 31 | 32 | echo "Installation done!" 33 | echo "Now add \"findex-daemon\" to autostart. You may follow your desktop environment's guide to do this." 34 | echo "I'm starting \"findex-daemon\" for now." 35 | findex-daemon 36 | echo "Findex can't bind hotkey in wayland." 37 | echo "To bind hotkey, bind the following command to your desired hotkey in the desktop environment you are using" 38 | echo "echo 1 > ~/.config/findex/toggle_file" 39 | echo "If you had Findex 0.6.0 installed, you may want to remove findex services from systemd." 40 | } 41 | 42 | do_removal() { 43 | echo "Removing files..." 44 | sudo rm /usr/bin/findex 45 | sudo rm /usr/bin/findex-daemon 46 | sudo rm -r /opt/findex 47 | killall findex-daemon findex 48 | systemctl stop --user findex-daemon.service 49 | systemctl disable --user findex-daemon.service 50 | sudo rm -f /usr/lib/systemd/user/findex-daemon.service 51 | systemctl daemon-reload --user 52 | echo "Removal done!" 53 | echo "If you added \"findex-daemon\" to autostart, you may remove it now." 54 | } 55 | 56 | prompt_for_installation() { 57 | while true; do 58 | read -r -p "Install findex? [Y/N] " yn 59 | case $yn in 60 | [Yy]*) 61 | do_installation 62 | break 63 | ;; 64 | [Nn]*) break ;; 65 | esac 66 | done 67 | } 68 | 69 | main() { 70 | if test -f "/usr/bin/findex"; then 71 | while true; do 72 | read -r -p "Found existing installation. Do you want to uninstall it? [Y/N] " yn 73 | case $yn in 74 | [Yy]*) 75 | do_removal 76 | prompt_for_installation 77 | exit 78 | ;; 79 | [Nn]*) exit ;; 80 | esac 81 | done 82 | fi 83 | do_installation 84 | } 85 | 86 | main 87 | -------------------------------------------------------------------------------- /plugins/README.md: -------------------------------------------------------------------------------- 1 | # Urlopen 2 | This plugin uses "url!" prefix by default. Write url after the prefix and press enter to open the url. 3 | 4 | # Github Repo 5 | This plugin uses "github!" prefix by default. After the prefix, write repo info in this format: "owner/repo". 6 | 7 | # CMD 8 | This plugin uses "cmd!" prefix by default. Type your command after the prefix. This will not open a new terminal 9 | window to execute the command. 10 | -------------------------------------------------------------------------------- /plugins/cmd/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "abi_stable" 7 | version = "0.11.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "3f69d9465d88d24382d43fa68335a92fe9d3c53a918549c693403ed9a85eff50" 10 | dependencies = [ 11 | "abi_stable_derive", 12 | "abi_stable_shared", 13 | "const_panic", 14 | "core_extensions", 15 | "crossbeam-channel", 16 | "generational-arena", 17 | "libloading", 18 | "lock_api", 19 | "parking_lot", 20 | "paste", 21 | "repr_offset", 22 | "rustc_version", 23 | "serde", 24 | "serde_derive", 25 | "serde_json", 26 | ] 27 | 28 | [[package]] 29 | name = "abi_stable_derive" 30 | version = "0.11.0" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "0aecd3efa5a5294f5c67913d45f985ccb382b3c93327581529610eeecdf4821a" 33 | dependencies = [ 34 | "abi_stable_shared", 35 | "as_derive_utils", 36 | "core_extensions", 37 | "proc-macro2", 38 | "quote", 39 | "rustc_version", 40 | "syn", 41 | "typed-arena", 42 | ] 43 | 44 | [[package]] 45 | name = "abi_stable_shared" 46 | version = "0.11.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "b2b5df7688c123e63f4d4d649cba63f2967ba7f7861b1664fca3f77d3dad2b63" 49 | dependencies = [ 50 | "core_extensions", 51 | ] 52 | 53 | [[package]] 54 | name = "aho-corasick" 55 | version = "0.7.20" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 58 | dependencies = [ 59 | "memchr", 60 | ] 61 | 62 | [[package]] 63 | name = "as_derive_utils" 64 | version = "0.11.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "ff3c96645900a44cf11941c111bd08a6573b0e2f9f69bc9264b179d8fae753c4" 67 | dependencies = [ 68 | "core_extensions", 69 | "proc-macro2", 70 | "quote", 71 | "syn", 72 | ] 73 | 74 | [[package]] 75 | name = "autocfg" 76 | version = "1.1.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 79 | 80 | [[package]] 81 | name = "bitflags" 82 | version = "1.3.2" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 85 | 86 | [[package]] 87 | name = "cfg-if" 88 | version = "0.1.10" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 91 | 92 | [[package]] 93 | name = "cfg-if" 94 | version = "1.0.0" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 97 | 98 | [[package]] 99 | name = "cmd" 100 | version = "0.1.0" 101 | dependencies = [ 102 | "abi_stable", 103 | "findex-plugin", 104 | "regex", 105 | ] 106 | 107 | [[package]] 108 | name = "const_panic" 109 | version = "0.2.7" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "58baae561b85ca19b3122a9ddd35c8ec40c3bcd14fe89921824eae73f7baffbf" 112 | 113 | [[package]] 114 | name = "core_extensions" 115 | version = "1.5.3" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "92c71dc07c9721607e7a16108336048ee978c3a8b129294534272e8bac96c0ee" 118 | dependencies = [ 119 | "core_extensions_proc_macros", 120 | ] 121 | 122 | [[package]] 123 | name = "core_extensions_proc_macros" 124 | version = "1.5.3" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "69f3b219d28b6e3b4ac87bc1fc522e0803ab22e055da177bff0068c4150c61a6" 127 | 128 | [[package]] 129 | name = "crossbeam-channel" 130 | version = "0.5.6" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" 133 | dependencies = [ 134 | "cfg-if 1.0.0", 135 | "crossbeam-utils", 136 | ] 137 | 138 | [[package]] 139 | name = "crossbeam-utils" 140 | version = "0.8.14" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" 143 | dependencies = [ 144 | "cfg-if 1.0.0", 145 | ] 146 | 147 | [[package]] 148 | name = "findex-plugin" 149 | version = "0.7.2" 150 | dependencies = [ 151 | "abi_stable", 152 | ] 153 | 154 | [[package]] 155 | name = "generational-arena" 156 | version = "0.2.8" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601" 159 | dependencies = [ 160 | "cfg-if 0.1.10", 161 | ] 162 | 163 | [[package]] 164 | name = "itoa" 165 | version = "1.0.5" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 168 | 169 | [[package]] 170 | name = "libc" 171 | version = "0.2.139" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 174 | 175 | [[package]] 176 | name = "libloading" 177 | version = "0.7.4" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" 180 | dependencies = [ 181 | "cfg-if 1.0.0", 182 | "winapi", 183 | ] 184 | 185 | [[package]] 186 | name = "lock_api" 187 | version = "0.4.9" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 190 | dependencies = [ 191 | "autocfg", 192 | "scopeguard", 193 | ] 194 | 195 | [[package]] 196 | name = "memchr" 197 | version = "2.5.0" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 200 | 201 | [[package]] 202 | name = "parking_lot" 203 | version = "0.12.1" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 206 | dependencies = [ 207 | "lock_api", 208 | "parking_lot_core", 209 | ] 210 | 211 | [[package]] 212 | name = "parking_lot_core" 213 | version = "0.9.5" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" 216 | dependencies = [ 217 | "cfg-if 1.0.0", 218 | "libc", 219 | "redox_syscall", 220 | "smallvec", 221 | "windows-sys", 222 | ] 223 | 224 | [[package]] 225 | name = "paste" 226 | version = "1.0.11" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" 229 | 230 | [[package]] 231 | name = "proc-macro2" 232 | version = "1.0.49" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" 235 | dependencies = [ 236 | "unicode-ident", 237 | ] 238 | 239 | [[package]] 240 | name = "quote" 241 | version = "1.0.23" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 244 | dependencies = [ 245 | "proc-macro2", 246 | ] 247 | 248 | [[package]] 249 | name = "redox_syscall" 250 | version = "0.2.16" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 253 | dependencies = [ 254 | "bitflags", 255 | ] 256 | 257 | [[package]] 258 | name = "regex" 259 | version = "1.7.0" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" 262 | dependencies = [ 263 | "aho-corasick", 264 | "memchr", 265 | "regex-syntax", 266 | ] 267 | 268 | [[package]] 269 | name = "regex-syntax" 270 | version = "0.6.28" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 273 | 274 | [[package]] 275 | name = "repr_offset" 276 | version = "0.2.1" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "663e92f38214b9e51fa305902788f5fb45fb60027b727556618fc53ba1946112" 279 | dependencies = [ 280 | "tstr", 281 | ] 282 | 283 | [[package]] 284 | name = "rustc_version" 285 | version = "0.4.0" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 288 | dependencies = [ 289 | "semver", 290 | ] 291 | 292 | [[package]] 293 | name = "ryu" 294 | version = "1.0.12" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 297 | 298 | [[package]] 299 | name = "scopeguard" 300 | version = "1.1.0" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 303 | 304 | [[package]] 305 | name = "semver" 306 | version = "1.0.16" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" 309 | 310 | [[package]] 311 | name = "serde" 312 | version = "1.0.152" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 315 | dependencies = [ 316 | "serde_derive", 317 | ] 318 | 319 | [[package]] 320 | name = "serde_derive" 321 | version = "1.0.152" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 324 | dependencies = [ 325 | "proc-macro2", 326 | "quote", 327 | "syn", 328 | ] 329 | 330 | [[package]] 331 | name = "serde_json" 332 | version = "1.0.91" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" 335 | dependencies = [ 336 | "itoa", 337 | "ryu", 338 | "serde", 339 | ] 340 | 341 | [[package]] 342 | name = "smallvec" 343 | version = "1.10.0" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 346 | 347 | [[package]] 348 | name = "syn" 349 | version = "1.0.107" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 352 | dependencies = [ 353 | "proc-macro2", 354 | "quote", 355 | "unicode-ident", 356 | ] 357 | 358 | [[package]] 359 | name = "tstr" 360 | version = "0.2.3" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "cca3264971090dec0feef3b455a3c178f02762f7550cf4592991ac64b3be2d7e" 363 | dependencies = [ 364 | "tstr_proc_macros", 365 | ] 366 | 367 | [[package]] 368 | name = "tstr_proc_macros" 369 | version = "0.2.2" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a" 372 | 373 | [[package]] 374 | name = "typed-arena" 375 | version = "2.0.1" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" 378 | 379 | [[package]] 380 | name = "unicode-ident" 381 | version = "1.0.6" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 384 | 385 | [[package]] 386 | name = "winapi" 387 | version = "0.3.9" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 390 | dependencies = [ 391 | "winapi-i686-pc-windows-gnu", 392 | "winapi-x86_64-pc-windows-gnu", 393 | ] 394 | 395 | [[package]] 396 | name = "winapi-i686-pc-windows-gnu" 397 | version = "0.4.0" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 400 | 401 | [[package]] 402 | name = "winapi-x86_64-pc-windows-gnu" 403 | version = "0.4.0" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 406 | 407 | [[package]] 408 | name = "windows-sys" 409 | version = "0.42.0" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 412 | dependencies = [ 413 | "windows_aarch64_gnullvm", 414 | "windows_aarch64_msvc", 415 | "windows_i686_gnu", 416 | "windows_i686_msvc", 417 | "windows_x86_64_gnu", 418 | "windows_x86_64_gnullvm", 419 | "windows_x86_64_msvc", 420 | ] 421 | 422 | [[package]] 423 | name = "windows_aarch64_gnullvm" 424 | version = "0.42.0" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" 427 | 428 | [[package]] 429 | name = "windows_aarch64_msvc" 430 | version = "0.42.0" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" 433 | 434 | [[package]] 435 | name = "windows_i686_gnu" 436 | version = "0.42.0" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" 439 | 440 | [[package]] 441 | name = "windows_i686_msvc" 442 | version = "0.42.0" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" 445 | 446 | [[package]] 447 | name = "windows_x86_64_gnu" 448 | version = "0.42.0" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" 451 | 452 | [[package]] 453 | name = "windows_x86_64_gnullvm" 454 | version = "0.42.0" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" 457 | 458 | [[package]] 459 | name = "windows_x86_64_msvc" 460 | version = "0.42.0" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" 463 | -------------------------------------------------------------------------------- /plugins/cmd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cmd" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [lib] 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | findex-plugin = { path = "../../crates/findex-plugin" } 13 | abi_stable = "0.11.1" 14 | regex = "1.7.0" -------------------------------------------------------------------------------- /plugins/cmd/src/lib.rs: -------------------------------------------------------------------------------- 1 | use findex_plugin::{ApplicationCommand, define_plugin, FResult}; 2 | use abi_stable::std_types::*; 3 | 4 | fn init(_: &RHashMap) -> RResult<(), RString> { 5 | ROk(()) 6 | } 7 | 8 | fn handle_query(query: RStr) -> RVec { 9 | if query == "" { 10 | return RVec::new(); 11 | } 12 | 13 | RVec::from(vec![FResult { 14 | cmd: ApplicationCommand::Command(RString::from(format!("{query}"))), 15 | name: RString::from(format!("Run \"{query}\"")), 16 | desc: RNone, 17 | score: isize::MAX, 18 | icon: RString::from("terminal"), 19 | }]) 20 | } 21 | 22 | define_plugin!("cmd!", "c", init, handle_query); 23 | -------------------------------------------------------------------------------- /plugins/github-repo/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "abi_stable" 7 | version = "0.11.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "3f69d9465d88d24382d43fa68335a92fe9d3c53a918549c693403ed9a85eff50" 10 | dependencies = [ 11 | "abi_stable_derive", 12 | "abi_stable_shared", 13 | "const_panic", 14 | "core_extensions", 15 | "crossbeam-channel", 16 | "generational-arena", 17 | "libloading", 18 | "lock_api", 19 | "parking_lot", 20 | "paste", 21 | "repr_offset", 22 | "rustc_version", 23 | "serde", 24 | "serde_derive", 25 | "serde_json", 26 | ] 27 | 28 | [[package]] 29 | name = "abi_stable_derive" 30 | version = "0.11.0" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "0aecd3efa5a5294f5c67913d45f985ccb382b3c93327581529610eeecdf4821a" 33 | dependencies = [ 34 | "abi_stable_shared", 35 | "as_derive_utils", 36 | "core_extensions", 37 | "proc-macro2", 38 | "quote", 39 | "rustc_version", 40 | "syn", 41 | "typed-arena", 42 | ] 43 | 44 | [[package]] 45 | name = "abi_stable_shared" 46 | version = "0.11.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "b2b5df7688c123e63f4d4d649cba63f2967ba7f7861b1664fca3f77d3dad2b63" 49 | dependencies = [ 50 | "core_extensions", 51 | ] 52 | 53 | [[package]] 54 | name = "aho-corasick" 55 | version = "0.7.20" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 58 | dependencies = [ 59 | "memchr", 60 | ] 61 | 62 | [[package]] 63 | name = "as_derive_utils" 64 | version = "0.11.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "ff3c96645900a44cf11941c111bd08a6573b0e2f9f69bc9264b179d8fae753c4" 67 | dependencies = [ 68 | "core_extensions", 69 | "proc-macro2", 70 | "quote", 71 | "syn", 72 | ] 73 | 74 | [[package]] 75 | name = "autocfg" 76 | version = "1.1.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 79 | 80 | [[package]] 81 | name = "bitflags" 82 | version = "1.3.2" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 85 | 86 | [[package]] 87 | name = "cfg-if" 88 | version = "0.1.10" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 91 | 92 | [[package]] 93 | name = "cfg-if" 94 | version = "1.0.0" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 97 | 98 | [[package]] 99 | name = "const_panic" 100 | version = "0.2.7" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "58baae561b85ca19b3122a9ddd35c8ec40c3bcd14fe89921824eae73f7baffbf" 103 | 104 | [[package]] 105 | name = "core_extensions" 106 | version = "1.5.3" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "92c71dc07c9721607e7a16108336048ee978c3a8b129294534272e8bac96c0ee" 109 | dependencies = [ 110 | "core_extensions_proc_macros", 111 | ] 112 | 113 | [[package]] 114 | name = "core_extensions_proc_macros" 115 | version = "1.5.3" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "69f3b219d28b6e3b4ac87bc1fc522e0803ab22e055da177bff0068c4150c61a6" 118 | 119 | [[package]] 120 | name = "crossbeam-channel" 121 | version = "0.5.6" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" 124 | dependencies = [ 125 | "cfg-if 1.0.0", 126 | "crossbeam-utils", 127 | ] 128 | 129 | [[package]] 130 | name = "crossbeam-utils" 131 | version = "0.8.14" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" 134 | dependencies = [ 135 | "cfg-if 1.0.0", 136 | ] 137 | 138 | [[package]] 139 | name = "findex-plugin" 140 | version = "0.7.2" 141 | dependencies = [ 142 | "abi_stable", 143 | ] 144 | 145 | [[package]] 146 | name = "generational-arena" 147 | version = "0.2.8" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601" 150 | dependencies = [ 151 | "cfg-if 0.1.10", 152 | ] 153 | 154 | [[package]] 155 | name = "github-repo" 156 | version = "0.1.0" 157 | dependencies = [ 158 | "abi_stable", 159 | "findex-plugin", 160 | "regex", 161 | ] 162 | 163 | [[package]] 164 | name = "itoa" 165 | version = "1.0.5" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 168 | 169 | [[package]] 170 | name = "libc" 171 | version = "0.2.138" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" 174 | 175 | [[package]] 176 | name = "libloading" 177 | version = "0.7.4" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" 180 | dependencies = [ 181 | "cfg-if 1.0.0", 182 | "winapi", 183 | ] 184 | 185 | [[package]] 186 | name = "lock_api" 187 | version = "0.4.9" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 190 | dependencies = [ 191 | "autocfg", 192 | "scopeguard", 193 | ] 194 | 195 | [[package]] 196 | name = "memchr" 197 | version = "2.5.0" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 200 | 201 | [[package]] 202 | name = "parking_lot" 203 | version = "0.12.1" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 206 | dependencies = [ 207 | "lock_api", 208 | "parking_lot_core", 209 | ] 210 | 211 | [[package]] 212 | name = "parking_lot_core" 213 | version = "0.9.5" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" 216 | dependencies = [ 217 | "cfg-if 1.0.0", 218 | "libc", 219 | "redox_syscall", 220 | "smallvec", 221 | "windows-sys", 222 | ] 223 | 224 | [[package]] 225 | name = "paste" 226 | version = "1.0.11" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" 229 | 230 | [[package]] 231 | name = "proc-macro2" 232 | version = "1.0.49" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" 235 | dependencies = [ 236 | "unicode-ident", 237 | ] 238 | 239 | [[package]] 240 | name = "quote" 241 | version = "1.0.23" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 244 | dependencies = [ 245 | "proc-macro2", 246 | ] 247 | 248 | [[package]] 249 | name = "redox_syscall" 250 | version = "0.2.16" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 253 | dependencies = [ 254 | "bitflags", 255 | ] 256 | 257 | [[package]] 258 | name = "regex" 259 | version = "1.7.0" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" 262 | dependencies = [ 263 | "aho-corasick", 264 | "memchr", 265 | "regex-syntax", 266 | ] 267 | 268 | [[package]] 269 | name = "regex-syntax" 270 | version = "0.6.28" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 273 | 274 | [[package]] 275 | name = "repr_offset" 276 | version = "0.2.1" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "663e92f38214b9e51fa305902788f5fb45fb60027b727556618fc53ba1946112" 279 | dependencies = [ 280 | "tstr", 281 | ] 282 | 283 | [[package]] 284 | name = "rustc_version" 285 | version = "0.4.0" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 288 | dependencies = [ 289 | "semver", 290 | ] 291 | 292 | [[package]] 293 | name = "ryu" 294 | version = "1.0.12" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 297 | 298 | [[package]] 299 | name = "scopeguard" 300 | version = "1.1.0" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 303 | 304 | [[package]] 305 | name = "semver" 306 | version = "1.0.16" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" 309 | 310 | [[package]] 311 | name = "serde" 312 | version = "1.0.151" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" 315 | dependencies = [ 316 | "serde_derive", 317 | ] 318 | 319 | [[package]] 320 | name = "serde_derive" 321 | version = "1.0.151" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" 324 | dependencies = [ 325 | "proc-macro2", 326 | "quote", 327 | "syn", 328 | ] 329 | 330 | [[package]] 331 | name = "serde_json" 332 | version = "1.0.91" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" 335 | dependencies = [ 336 | "itoa", 337 | "ryu", 338 | "serde", 339 | ] 340 | 341 | [[package]] 342 | name = "smallvec" 343 | version = "1.10.0" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 346 | 347 | [[package]] 348 | name = "syn" 349 | version = "1.0.107" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 352 | dependencies = [ 353 | "proc-macro2", 354 | "quote", 355 | "unicode-ident", 356 | ] 357 | 358 | [[package]] 359 | name = "tstr" 360 | version = "0.2.3" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "cca3264971090dec0feef3b455a3c178f02762f7550cf4592991ac64b3be2d7e" 363 | dependencies = [ 364 | "tstr_proc_macros", 365 | ] 366 | 367 | [[package]] 368 | name = "tstr_proc_macros" 369 | version = "0.2.2" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a" 372 | 373 | [[package]] 374 | name = "typed-arena" 375 | version = "2.0.1" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" 378 | 379 | [[package]] 380 | name = "unicode-ident" 381 | version = "1.0.6" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 384 | 385 | [[package]] 386 | name = "winapi" 387 | version = "0.3.9" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 390 | dependencies = [ 391 | "winapi-i686-pc-windows-gnu", 392 | "winapi-x86_64-pc-windows-gnu", 393 | ] 394 | 395 | [[package]] 396 | name = "winapi-i686-pc-windows-gnu" 397 | version = "0.4.0" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 400 | 401 | [[package]] 402 | name = "winapi-x86_64-pc-windows-gnu" 403 | version = "0.4.0" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 406 | 407 | [[package]] 408 | name = "windows-sys" 409 | version = "0.42.0" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 412 | dependencies = [ 413 | "windows_aarch64_gnullvm", 414 | "windows_aarch64_msvc", 415 | "windows_i686_gnu", 416 | "windows_i686_msvc", 417 | "windows_x86_64_gnu", 418 | "windows_x86_64_gnullvm", 419 | "windows_x86_64_msvc", 420 | ] 421 | 422 | [[package]] 423 | name = "windows_aarch64_gnullvm" 424 | version = "0.42.0" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" 427 | 428 | [[package]] 429 | name = "windows_aarch64_msvc" 430 | version = "0.42.0" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" 433 | 434 | [[package]] 435 | name = "windows_i686_gnu" 436 | version = "0.42.0" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" 439 | 440 | [[package]] 441 | name = "windows_i686_msvc" 442 | version = "0.42.0" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" 445 | 446 | [[package]] 447 | name = "windows_x86_64_gnu" 448 | version = "0.42.0" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" 451 | 452 | [[package]] 453 | name = "windows_x86_64_gnullvm" 454 | version = "0.42.0" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" 457 | 458 | [[package]] 459 | name = "windows_x86_64_msvc" 460 | version = "0.42.0" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" 463 | -------------------------------------------------------------------------------- /plugins/github-repo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "github-repo" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [lib] 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | findex-plugin = { path = "../../crates/findex-plugin" } 13 | abi_stable = "0.11.1" 14 | regex = "1.7.0" 15 | -------------------------------------------------------------------------------- /plugins/github-repo/src/lib.rs: -------------------------------------------------------------------------------- 1 | use abi_stable::std_types::*; 2 | use regex::Regex; 3 | use findex_plugin::{ApplicationCommand, define_plugin, FResult}; 4 | 5 | fn init(_: &RHashMap) -> RResult<(), RString> { 6 | ROk(()) 7 | } 8 | 9 | fn handle_query(query: RStr) -> RVec { 10 | let regex = Regex::new("[a-zA-Z0-9]+/[a-zA-Z0-9]+") 11 | .unwrap(); 12 | 13 | if !regex.is_match(query.as_str()) { 14 | return RVec::new(); 15 | } 16 | 17 | RVec::from(vec![FResult { 18 | cmd: ApplicationCommand::Command(RString::from(format!("xdg-open https://github.com/{query}"))), 19 | icon: RString::from("github"), 20 | score: isize::MAX, 21 | name: RString::from("Open github repository"), 22 | desc: RNone, 23 | }]) 24 | } 25 | 26 | define_plugin!("github!", init, handle_query); -------------------------------------------------------------------------------- /plugins/urlopen/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "abi_stable" 7 | version = "0.11.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "3f69d9465d88d24382d43fa68335a92fe9d3c53a918549c693403ed9a85eff50" 10 | dependencies = [ 11 | "abi_stable_derive", 12 | "abi_stable_shared", 13 | "const_panic", 14 | "core_extensions", 15 | "crossbeam-channel", 16 | "generational-arena", 17 | "libloading", 18 | "lock_api", 19 | "parking_lot", 20 | "paste", 21 | "repr_offset", 22 | "rustc_version", 23 | "serde", 24 | "serde_derive", 25 | "serde_json", 26 | ] 27 | 28 | [[package]] 29 | name = "abi_stable_derive" 30 | version = "0.11.0" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "0aecd3efa5a5294f5c67913d45f985ccb382b3c93327581529610eeecdf4821a" 33 | dependencies = [ 34 | "abi_stable_shared", 35 | "as_derive_utils", 36 | "core_extensions", 37 | "proc-macro2", 38 | "quote", 39 | "rustc_version", 40 | "syn", 41 | "typed-arena", 42 | ] 43 | 44 | [[package]] 45 | name = "abi_stable_shared" 46 | version = "0.11.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "b2b5df7688c123e63f4d4d649cba63f2967ba7f7861b1664fca3f77d3dad2b63" 49 | dependencies = [ 50 | "core_extensions", 51 | ] 52 | 53 | [[package]] 54 | name = "as_derive_utils" 55 | version = "0.11.0" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "ff3c96645900a44cf11941c111bd08a6573b0e2f9f69bc9264b179d8fae753c4" 58 | dependencies = [ 59 | "core_extensions", 60 | "proc-macro2", 61 | "quote", 62 | "syn", 63 | ] 64 | 65 | [[package]] 66 | name = "autocfg" 67 | version = "1.1.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 70 | 71 | [[package]] 72 | name = "bitflags" 73 | version = "1.3.2" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 76 | 77 | [[package]] 78 | name = "cfg-if" 79 | version = "0.1.10" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 82 | 83 | [[package]] 84 | name = "cfg-if" 85 | version = "1.0.0" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 88 | 89 | [[package]] 90 | name = "const_panic" 91 | version = "0.2.7" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "58baae561b85ca19b3122a9ddd35c8ec40c3bcd14fe89921824eae73f7baffbf" 94 | 95 | [[package]] 96 | name = "core_extensions" 97 | version = "1.5.3" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "92c71dc07c9721607e7a16108336048ee978c3a8b129294534272e8bac96c0ee" 100 | dependencies = [ 101 | "core_extensions_proc_macros", 102 | ] 103 | 104 | [[package]] 105 | name = "core_extensions_proc_macros" 106 | version = "1.5.3" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "69f3b219d28b6e3b4ac87bc1fc522e0803ab22e055da177bff0068c4150c61a6" 109 | 110 | [[package]] 111 | name = "crossbeam-channel" 112 | version = "0.5.6" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" 115 | dependencies = [ 116 | "cfg-if 1.0.0", 117 | "crossbeam-utils", 118 | ] 119 | 120 | [[package]] 121 | name = "crossbeam-utils" 122 | version = "0.8.14" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" 125 | dependencies = [ 126 | "cfg-if 1.0.0", 127 | ] 128 | 129 | [[package]] 130 | name = "findex-plugin" 131 | version = "0.7.2" 132 | dependencies = [ 133 | "abi_stable", 134 | ] 135 | 136 | [[package]] 137 | name = "generational-arena" 138 | version = "0.2.8" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601" 141 | dependencies = [ 142 | "cfg-if 0.1.10", 143 | ] 144 | 145 | [[package]] 146 | name = "itoa" 147 | version = "1.0.5" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 150 | 151 | [[package]] 152 | name = "libc" 153 | version = "0.2.138" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" 156 | 157 | [[package]] 158 | name = "libloading" 159 | version = "0.7.4" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" 162 | dependencies = [ 163 | "cfg-if 1.0.0", 164 | "winapi", 165 | ] 166 | 167 | [[package]] 168 | name = "lock_api" 169 | version = "0.4.9" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 172 | dependencies = [ 173 | "autocfg", 174 | "scopeguard", 175 | ] 176 | 177 | [[package]] 178 | name = "parking_lot" 179 | version = "0.12.1" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 182 | dependencies = [ 183 | "lock_api", 184 | "parking_lot_core", 185 | ] 186 | 187 | [[package]] 188 | name = "parking_lot_core" 189 | version = "0.9.5" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" 192 | dependencies = [ 193 | "cfg-if 1.0.0", 194 | "libc", 195 | "redox_syscall", 196 | "smallvec", 197 | "windows-sys", 198 | ] 199 | 200 | [[package]] 201 | name = "paste" 202 | version = "1.0.11" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" 205 | 206 | [[package]] 207 | name = "proc-macro2" 208 | version = "1.0.48" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "e9d89e5dba24725ae5678020bf8f1357a9aa7ff10736b551adbcd3f8d17d766f" 211 | dependencies = [ 212 | "unicode-ident", 213 | ] 214 | 215 | [[package]] 216 | name = "quote" 217 | version = "1.0.22" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "556d0f47a940e895261e77dc200d5eadfc6ef644c179c6f5edfc105e3a2292c8" 220 | dependencies = [ 221 | "proc-macro2", 222 | ] 223 | 224 | [[package]] 225 | name = "redox_syscall" 226 | version = "0.2.16" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 229 | dependencies = [ 230 | "bitflags", 231 | ] 232 | 233 | [[package]] 234 | name = "repr_offset" 235 | version = "0.2.1" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "663e92f38214b9e51fa305902788f5fb45fb60027b727556618fc53ba1946112" 238 | dependencies = [ 239 | "tstr", 240 | ] 241 | 242 | [[package]] 243 | name = "rustc_version" 244 | version = "0.4.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 247 | dependencies = [ 248 | "semver", 249 | ] 250 | 251 | [[package]] 252 | name = "ryu" 253 | version = "1.0.12" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 256 | 257 | [[package]] 258 | name = "scopeguard" 259 | version = "1.1.0" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 262 | 263 | [[package]] 264 | name = "semver" 265 | version = "1.0.15" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "3bfa246f936730408c0abee392cc1a50b118ece708c7f630516defd64480c7d8" 268 | 269 | [[package]] 270 | name = "serde" 271 | version = "1.0.151" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" 274 | dependencies = [ 275 | "serde_derive", 276 | ] 277 | 278 | [[package]] 279 | name = "serde_derive" 280 | version = "1.0.151" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" 283 | dependencies = [ 284 | "proc-macro2", 285 | "quote", 286 | "syn", 287 | ] 288 | 289 | [[package]] 290 | name = "serde_json" 291 | version = "1.0.90" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "8778cc0b528968fe72abec38b5db5a20a70d148116cd9325d2bc5f5180ca3faf" 294 | dependencies = [ 295 | "itoa", 296 | "ryu", 297 | "serde", 298 | ] 299 | 300 | [[package]] 301 | name = "smallvec" 302 | version = "1.10.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 305 | 306 | [[package]] 307 | name = "syn" 308 | version = "1.0.106" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "09ee3a69cd2c7e06684677e5629b3878b253af05e4714964204279c6bc02cf0b" 311 | dependencies = [ 312 | "proc-macro2", 313 | "quote", 314 | "unicode-ident", 315 | ] 316 | 317 | [[package]] 318 | name = "tstr" 319 | version = "0.2.3" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "cca3264971090dec0feef3b455a3c178f02762f7550cf4592991ac64b3be2d7e" 322 | dependencies = [ 323 | "tstr_proc_macros", 324 | ] 325 | 326 | [[package]] 327 | name = "tstr_proc_macros" 328 | version = "0.2.2" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a" 331 | 332 | [[package]] 333 | name = "typed-arena" 334 | version = "2.0.1" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" 337 | 338 | [[package]] 339 | name = "unicode-ident" 340 | version = "1.0.6" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 343 | 344 | [[package]] 345 | name = "urlopen" 346 | version = "0.1.0" 347 | dependencies = [ 348 | "abi_stable", 349 | "findex-plugin", 350 | ] 351 | 352 | [[package]] 353 | name = "winapi" 354 | version = "0.3.9" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 357 | dependencies = [ 358 | "winapi-i686-pc-windows-gnu", 359 | "winapi-x86_64-pc-windows-gnu", 360 | ] 361 | 362 | [[package]] 363 | name = "winapi-i686-pc-windows-gnu" 364 | version = "0.4.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 367 | 368 | [[package]] 369 | name = "winapi-x86_64-pc-windows-gnu" 370 | version = "0.4.0" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 373 | 374 | [[package]] 375 | name = "windows-sys" 376 | version = "0.42.0" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 379 | dependencies = [ 380 | "windows_aarch64_gnullvm", 381 | "windows_aarch64_msvc", 382 | "windows_i686_gnu", 383 | "windows_i686_msvc", 384 | "windows_x86_64_gnu", 385 | "windows_x86_64_gnullvm", 386 | "windows_x86_64_msvc", 387 | ] 388 | 389 | [[package]] 390 | name = "windows_aarch64_gnullvm" 391 | version = "0.42.0" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" 394 | 395 | [[package]] 396 | name = "windows_aarch64_msvc" 397 | version = "0.42.0" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" 400 | 401 | [[package]] 402 | name = "windows_i686_gnu" 403 | version = "0.42.0" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" 406 | 407 | [[package]] 408 | name = "windows_i686_msvc" 409 | version = "0.42.0" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" 412 | 413 | [[package]] 414 | name = "windows_x86_64_gnu" 415 | version = "0.42.0" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" 418 | 419 | [[package]] 420 | name = "windows_x86_64_gnullvm" 421 | version = "0.42.0" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" 424 | 425 | [[package]] 426 | name = "windows_x86_64_msvc" 427 | version = "0.42.0" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" 430 | -------------------------------------------------------------------------------- /plugins/urlopen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "urlopen" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [lib] 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | findex-plugin = { path = "../../crates/findex-plugin" } 13 | abi_stable = "0.11.1" 14 | -------------------------------------------------------------------------------- /plugins/urlopen/src/lib.rs: -------------------------------------------------------------------------------- 1 | use findex_plugin::{ApplicationCommand, define_plugin, FResult}; 2 | use abi_stable::std_types::*; 3 | 4 | fn init(_: &RHashMap) -> RResult<(), RString> { 5 | ROk(()) 6 | } 7 | 8 | fn handle_query(query: RStr) -> RVec { 9 | if query == "" { 10 | return RVec::new(); 11 | } 12 | 13 | RVec::from(vec![FResult { 14 | cmd: ApplicationCommand::Command(RString::from(format!("xdg-open \"{query}\""))), 15 | name: RString::from(format!("Open {query}")), 16 | desc: RNone, 17 | score: isize::MAX, 18 | icon: RString::from("browser"), 19 | }]) 20 | } 21 | 22 | define_plugin!("url!", init, handle_query); 23 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdgaziur/findex/2b03ed03dbd6951a262d9975bef1c63be0dc1db4/screenshot.png -------------------------------------------------------------------------------- /service/findex-daemon.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Findex Daemon 3 | PartOf=graphical-session.target 4 | After=graphical-session.target 5 | 6 | [Service] 7 | Type=forking 8 | ExitType=main 9 | ExecStart=/usr/bin/findex-daemon 10 | Restart=on-failure 11 | # Exponential CrashLoop Backoff 12 | RestartSteps=5 13 | RestartMaxDelaySec=60s 14 | # Give up after 6 tries 15 | StartLimitInterval=infinity 16 | StartLimitBurst=6 17 | 18 | [Install] 19 | WantedBy=graphical-session.target 20 | --------------------------------------------------------------------------------