mirror of
https://github.com/chmln/handlr.git
synced 2025-03-16 02:15:54 +01:00
Reorganize and partially rewrite
This commit is contained in:
parent
d45027a408
commit
935d1daa87
14 changed files with 749 additions and 424 deletions
397
Cargo.lock
generated
397
Cargo.lock
generated
|
@ -50,6 +50,18 @@ version = "0.11.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
|
@ -67,6 +79,12 @@ dependencies = [
|
|||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.7.3"
|
||||
|
@ -90,9 +108,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.3.0"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6"
|
||||
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
|
@ -124,6 +142,17 @@ version = "0.1.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.0-beta.1"
|
||||
|
@ -131,7 +160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "860643c53f980f0d38a5e25dfab6c3c93b2cb3aa1fe192643d17a293c6c41936"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"bitflags 1.2.1",
|
||||
"clap_derive",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
|
@ -152,8 +181,8 @@ dependencies = [
|
|||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -189,6 +218,16 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dbus"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b17a12ffaff26515889b006fc029493a3e340366a137c13cec2cdd545ea3b8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libdbus-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
|
@ -198,6 +237,17 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "2.0.2"
|
||||
|
@ -274,7 +324,7 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.2.1",
|
||||
"fuchsia-zircon-sys",
|
||||
]
|
||||
|
||||
|
@ -373,11 +423,13 @@ name = "handlr"
|
|||
version = "0.3.2"
|
||||
dependencies = [
|
||||
"ascii_table",
|
||||
"atty",
|
||||
"clap",
|
||||
"itertools",
|
||||
"json",
|
||||
"mime",
|
||||
"mime-db",
|
||||
"notify-rust",
|
||||
"once_cell",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
|
@ -436,9 +488,9 @@ checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
|||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.13.5"
|
||||
version = "0.13.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14"
|
||||
checksum = "a6e7655b9594024ad0ee439f3b5a7299369dc2a3f459b47c696f9ff676f9aa1f"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
|
@ -450,8 +502,8 @@ dependencies = [
|
|||
"httparse",
|
||||
"itoa",
|
||||
"log",
|
||||
"net2",
|
||||
"pin-project",
|
||||
"socket2",
|
||||
"time",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
|
@ -484,9 +536,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.3.2"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
|
||||
checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
@ -517,9 +569,9 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.39"
|
||||
version = "0.3.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7"
|
||||
checksum = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -553,7 +605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "f86d66d380c9c5a685aaac7a11818bdfa1f733198dfd9ec09c70b762cd12ad6f"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.12",
|
||||
"bitflags",
|
||||
"bitflags 1.2.1",
|
||||
"cfg-if",
|
||||
"rustc_version",
|
||||
"ryu",
|
||||
|
@ -562,9 +614,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.70"
|
||||
version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
|
||||
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||
|
||||
[[package]]
|
||||
name = "libdbus-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc12a3bc971424edbbf7edaf6e5740483444db63aa8e23d3751ff12a30f306f0"
|
||||
dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -575,6 +636,27 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mac-notification-sys"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dfb6b71a9a89cd38b395d994214297447e8e63b1ba5708a9a2b0b1048ceda76"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"chrono",
|
||||
"dirs 1.0.5",
|
||||
"objc-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
|
@ -698,6 +780,36 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-rust"
|
||||
version = "4.0.0-rc.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "963d07a7dc24a56e2e0036d444b37caf4f0418cfd31c4b4b018ffc92cc06b56b"
|
||||
dependencies = [
|
||||
"dbus",
|
||||
"mac-notification-sys",
|
||||
"winrt-notification",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
|
@ -708,6 +820,35 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-foundation"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||
dependencies = [
|
||||
"block",
|
||||
"objc",
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_id"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||
dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.4.0"
|
||||
|
@ -726,7 +867,7 @@ version = "0.10.29"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.2.1",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"lazy_static",
|
||||
|
@ -793,8 +934,8 @@ dependencies = [
|
|||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -810,29 +951,29 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "0.4.17"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edc93aeee735e60ecb40cf740eb319ff23eab1c5748abfdb5c180e4ce49f7791"
|
||||
checksum = "ba3a1acf4a3e70849f8a673497ef984f043f95d2d8252dcdf74d54e6a1e47e8a"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "0.4.17"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40"
|
||||
checksum = "194e88048b71a3e02eb4ee36a6995fed9b8236c11a7bb9f7247a9d9835b3f265"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.1.5"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f"
|
||||
checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
|
@ -860,8 +1001,8 @@ checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
|
|||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -872,21 +1013,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
"syn-mid",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.17"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
|
||||
checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.6"
|
||||
|
@ -980,11 +1127,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.10.4"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2"
|
||||
checksum = "3b82c9238b305f26f53443e3a4bc8528d64b8d0bee408ec949eb7bf5635ec680"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.12.1",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
|
@ -1004,7 +1151,6 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-tls",
|
||||
"url",
|
||||
|
@ -1020,7 +1166,7 @@ version = "0.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.11.0",
|
||||
"blake2b_simd",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils",
|
||||
|
@ -1037,9 +1183,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
|
@ -1057,7 +1203,7 @@ version = "0.4.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.2.1",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
|
@ -1091,22 +1237,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.110"
|
||||
version = "1.0.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
|
||||
checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.110"
|
||||
version = "1.0.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
|
||||
checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1162,6 +1308,18 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "0.3.4"
|
||||
|
@ -1175,14 +1333,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.23"
|
||||
name = "strum"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95b5f192649e48a5302a13f2feb224df883b98933222369e4b3b0fe2a5447269"
|
||||
checksum = "4ca6e4730f517e041e547ffe23d29daab8de6b73af4b6ae2a002108169f5e7da"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3384590878eb0cab3b128e844412e2d010821e7e091211b9d87324173ada7db8"
|
||||
dependencies = [
|
||||
"quote 0.3.15",
|
||||
"syn 0.11.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
dependencies = [
|
||||
"quote 0.3.15",
|
||||
"synom",
|
||||
"unicode-xid 0.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
"quote 1.0.6",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1192,8 +1377,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
dependencies = [
|
||||
"unicode-xid 0.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1244,8 +1438,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1284,8 +1478,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1375,6 +1569,12 @@ version = "0.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
|
@ -1394,9 +1594,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
|
||||
checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
|
@ -1428,9 +1628,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.62"
|
||||
version = "0.2.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551"
|
||||
checksum = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"serde",
|
||||
|
@ -1440,24 +1640,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.62"
|
||||
version = "0.2.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94"
|
||||
checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.12"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a369c5e1dfb7569e14d62af4da642a3cbc2f9a3652fe586e26ac22222aa4b04"
|
||||
checksum = "64487204d863f109eb77e8462189d111f27cb5712cc9fdb3461297a76963a2f6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
|
@ -1467,38 +1667,38 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.62"
|
||||
version = "0.2.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776"
|
||||
checksum = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"quote 1.0.6",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.62"
|
||||
version = "0.2.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a"
|
||||
checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"quote 1.0.6",
|
||||
"syn 1.0.30",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.62"
|
||||
version = "0.2.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad"
|
||||
checksum = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.39"
|
||||
version = "0.3.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642"
|
||||
checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
@ -1549,13 +1749,35 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.6.2"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
|
||||
checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
|
||||
dependencies = [
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winrt"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e30cba82e22b083dc5a422c2ee77e20dc7927271a0dc981360c57c1453cb48d"
|
||||
dependencies = [
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winrt-notification"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c31a65da50d792c6f9bd2e3216249566c4fb1d2d34f9b7d2d66d2e93f62a242"
|
||||
dependencies = [
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"winapi 0.3.8",
|
||||
"winrt",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
|
@ -1577,9 +1799,18 @@ name = "xdg-mime"
|
|||
version = "0.3.0"
|
||||
source = "git+https://github.com/ebassi/xdg-mime-rs#68f9130f316a67c6fbce440698788b94b45380c5"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
"dirs 2.0.2",
|
||||
"glob",
|
||||
"mime",
|
||||
"nom",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1945e12e16b951721d7976520b0832496ef79c31602c7a29d950de79ba74621"
|
||||
dependencies = [
|
||||
"bitflags 0.9.1",
|
||||
]
|
||||
|
|
|
@ -9,7 +9,7 @@ description = "Manage mimeapps.list and default applications with ease"
|
|||
[dependencies]
|
||||
pest = "2.1.3"
|
||||
pest_derive = "2.1.0"
|
||||
clap = { version = "3.0.0-beta.1" }
|
||||
clap = "3.0.0-beta.1"
|
||||
url = "2.1.1"
|
||||
itertools = "0.9.0"
|
||||
json = "0.12.4"
|
||||
|
@ -22,6 +22,8 @@ once_cell = "1.4.0"
|
|||
regex = { version = "1.3.9", default-features = false, features = ["std"] }
|
||||
mime-db = "0.1.5"
|
||||
xdg-mime = { git = "https://github.com/ebassi/xdg-mime-rs" }
|
||||
atty = "0.2.14"
|
||||
notify-rust = "4.0.0-rc.1"
|
||||
|
||||
[profile.release]
|
||||
opt-level=3
|
||||
|
|
5
src/apps/mod.rs
Normal file
5
src/apps/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
mod system;
|
||||
mod user;
|
||||
|
||||
pub use system::SystemApps;
|
||||
pub use user::MimeApps;
|
47
src/apps/system.rs
Normal file
47
src/apps/system.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use crate::{
|
||||
common::{DesktopEntry, Handler},
|
||||
Result,
|
||||
};
|
||||
use mime::Mime;
|
||||
use std::{collections::HashMap, convert::TryFrom, ffi::OsStr};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SystemApps(pub HashMap<Mime, Vec<Handler>>);
|
||||
|
||||
impl SystemApps {
|
||||
pub fn get_handlers(&self, mime: &Mime) -> Option<Vec<Handler>> {
|
||||
Some(self.0.get(mime)?.clone())
|
||||
}
|
||||
pub fn get_handler(&self, mime: &Mime) -> Option<Handler> {
|
||||
Some(self.get_handlers(mime)?.get(0).unwrap().clone())
|
||||
}
|
||||
pub fn populate() -> Result<Self> {
|
||||
let mut map = HashMap::<Mime, Vec<Handler>>::with_capacity(50);
|
||||
|
||||
xdg::BaseDirectories::new()?
|
||||
.get_data_dirs()
|
||||
.into_iter()
|
||||
.map(|mut data_dir| {
|
||||
data_dir.push("applications");
|
||||
data_dir
|
||||
})
|
||||
.filter_map(|data_dir| std::fs::read_dir(data_dir).ok())
|
||||
.for_each(|dir| {
|
||||
dir.filter_map(Result::ok)
|
||||
.filter(|p| {
|
||||
p.path().extension() == Some(OsStr::new("desktop"))
|
||||
})
|
||||
.filter_map(|p| DesktopEntry::try_from(p.path()).ok())
|
||||
.for_each(|entry| {
|
||||
let (file_name, mimes) = (entry.file_name, entry.mimes);
|
||||
mimes.into_iter().for_each(|mime| {
|
||||
map.entry(mime)
|
||||
.or_default()
|
||||
.push(Handler::assume_valid(file_name.clone()));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Ok(Self(map))
|
||||
}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
use crate::{DesktopEntry, Error, Handler, Mime, Result};
|
||||
use crate::{apps::SystemApps, DesktopEntry, Error, Handler, Result};
|
||||
use mime::Mime;
|
||||
use pest::Parser;
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
#[derive(Debug, pest_derive::Parser)]
|
||||
#[grammar = "ini.pest"]
|
||||
#[grammar = "common/ini.pest"]
|
||||
pub struct MimeApps {
|
||||
added_associations: HashMap<Mime, VecDeque<Handler>>,
|
||||
default_apps: HashMap<Mime, VecDeque<Handler>>,
|
||||
|
@ -42,7 +44,7 @@ impl MimeApps {
|
|||
.or_else(|| self.added_associations.get(mime))
|
||||
.map(|hs| hs.get(0).unwrap().clone())
|
||||
.or_else(|| self.system_apps.get_handler(mime))
|
||||
.ok_or(Error::NotFound)
|
||||
.ok_or(Error::NotFound(mime.to_string()))
|
||||
}
|
||||
pub fn show_handler(&self, mime: &Mime, output_json: bool) -> Result<()> {
|
||||
let handler = self.get_handler(mime)?;
|
||||
|
@ -90,7 +92,6 @@ impl MimeApps {
|
|||
let name = inner_rules.next().unwrap().as_str();
|
||||
let handlers = {
|
||||
use itertools::Itertools;
|
||||
use std::str::FromStr;
|
||||
|
||||
inner_rules
|
||||
.next()
|
||||
|
@ -104,13 +105,17 @@ impl MimeApps {
|
|||
};
|
||||
|
||||
if !handlers.is_empty() {
|
||||
match current_section_name.as_str() {
|
||||
"Added Associations" => conf
|
||||
.added_associations
|
||||
.insert(Mime(name.to_owned()), handlers),
|
||||
"Default Applications" => conf
|
||||
.default_apps
|
||||
.insert(Mime(name.to_owned()), handlers),
|
||||
match (
|
||||
Mime::from_str(name),
|
||||
current_section_name.as_str(),
|
||||
) {
|
||||
(Ok(mime), "Added Associations") => {
|
||||
conf.added_associations.insert(mime, handlers)
|
||||
}
|
||||
|
||||
(Ok(mime), "Default Applications") => {
|
||||
conf.default_apps.insert(mime, handlers)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
@ -134,7 +139,7 @@ impl MimeApps {
|
|||
|
||||
writer.write_all(b"[Added Associations]\n")?;
|
||||
for (k, v) in self.added_associations.iter().sorted() {
|
||||
writer.write_all(k.0.as_ref())?;
|
||||
writer.write_all(k.essence_str().as_ref())?;
|
||||
writer.write_all(b"=")?;
|
||||
writer.write_all(v.iter().join(";").as_ref())?;
|
||||
writer.write_all(b";\n")?;
|
||||
|
@ -142,7 +147,7 @@ impl MimeApps {
|
|||
|
||||
writer.write_all(b"\n[Default Applications]\n")?;
|
||||
for (k, v) in self.default_apps.iter().sorted() {
|
||||
writer.write_all(k.0.as_ref())?;
|
||||
writer.write_all(k.essence_str().as_ref())?;
|
||||
writer.write_all(b"=")?;
|
||||
writer.write_all(v.iter().join(";").as_ref())?;
|
||||
writer.write_all(b";\n")?;
|
||||
|
@ -158,7 +163,7 @@ impl MimeApps {
|
|||
.default_apps
|
||||
.iter()
|
||||
.sorted()
|
||||
.map(|(k, v)| vec![k.0.clone(), v.iter().join(", ")])
|
||||
.map(|(k, v)| vec![k.to_string(), v.iter().join(", ")])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ascii_table::AsciiTable::default().print(rows);
|
||||
|
@ -166,7 +171,7 @@ impl MimeApps {
|
|||
Ok(())
|
||||
}
|
||||
pub fn list_handlers(&self) -> Result<()> {
|
||||
use std::{convert::TryFrom, io::Write};
|
||||
use std::{convert::TryFrom, io::Write, os::unix::ffi::OsStrExt};
|
||||
|
||||
let stdout = std::io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
@ -188,50 +193,3 @@ impl MimeApps {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SystemApps(pub HashMap<Mime, Vec<Handler>>);
|
||||
|
||||
impl SystemApps {
|
||||
pub fn get_handlers(&self, mime: &Mime) -> Option<Vec<Handler>> {
|
||||
Some(self.0.get(mime)?.clone())
|
||||
}
|
||||
pub fn get_handler(&self, mime: &Mime) -> Option<Handler> {
|
||||
Some(self.get_handlers(mime)?.get(0).unwrap().clone())
|
||||
}
|
||||
pub fn populate() -> Result<Self> {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
let mut map = HashMap::<Mime, Vec<Handler>>::with_capacity(50);
|
||||
|
||||
xdg::BaseDirectories::new()?
|
||||
.get_data_dirs()
|
||||
.into_iter()
|
||||
.map(|mut data_dir| {
|
||||
data_dir.push("applications");
|
||||
data_dir
|
||||
})
|
||||
.filter_map(|data_dir| std::fs::read_dir(data_dir).ok())
|
||||
.for_each(|dir| {
|
||||
dir.filter_map(Result::ok)
|
||||
.filter(|p| {
|
||||
p.path()
|
||||
.extension()
|
||||
.map(std::ffi::OsStr::to_str)
|
||||
.flatten()
|
||||
== Some("desktop")
|
||||
})
|
||||
.filter_map(|p| DesktopEntry::try_from(p.path()).ok())
|
||||
.for_each(|entry| {
|
||||
let (file_name, mimes) = (entry.file_name, entry.mimes);
|
||||
mimes.into_iter().for_each(|mime| {
|
||||
map.entry(mime)
|
||||
.or_default()
|
||||
.push(Handler::assume_valid(file_name.clone()));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Ok(Self(map))
|
||||
}
|
||||
}
|
188
src/common.rs
188
src/common.rs
|
@ -1,188 +0,0 @@
|
|||
use crate::{mime_types, Error, Result};
|
||||
use std::{convert::TryFrom, path::PathBuf};
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Mime(pub String);
|
||||
|
||||
impl Mime {
|
||||
pub fn try_from_path(path: &str) -> Result<Self> {
|
||||
if let Ok(url) = url::Url::parse(path) {
|
||||
return Ok(Mime(format!("x-scheme-handler/{}", url.scheme())));
|
||||
}
|
||||
|
||||
mime_types::from_file(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Mime {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.starts_with(".") {
|
||||
mime_types::from_file(s)
|
||||
} else {
|
||||
Ok(Mime(mime_types::verify(&s)?.to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Handler(String);
|
||||
|
||||
impl std::fmt::Display for Handler {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Handler {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Self::resolve(s.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
pub fn assume_valid(name: String) -> Self {
|
||||
Self(name)
|
||||
}
|
||||
pub fn get_path(name: &str) -> Option<PathBuf> {
|
||||
xdg::BaseDirectories::new()
|
||||
.ok()?
|
||||
.find_data_file(&format!("applications/{}", name))
|
||||
}
|
||||
pub fn resolve(name: String) -> Result<Self> {
|
||||
let path = Self::get_path(&name).ok_or(Error::NotFound)?;
|
||||
DesktopEntry::try_from(path)?;
|
||||
Ok(Self(name))
|
||||
}
|
||||
pub fn get_entry(&self) -> Result<DesktopEntry> {
|
||||
DesktopEntry::try_from(Self::get_path(&self.0).unwrap())
|
||||
}
|
||||
pub fn open(&self, arg: String) -> Result<()> {
|
||||
let (cmd, args) = self.get_entry()?.get_cmd(Some(arg))?;
|
||||
if self.get_entry()?.term {
|
||||
std::process::Command::new(cmd)
|
||||
.args(args)
|
||||
.status()?;
|
||||
} else {
|
||||
std::process::Command::new(cmd)
|
||||
.args(args)
|
||||
.stdout(std::process::Stdio::null())
|
||||
.spawn()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn launch(&self, args: Vec<String>) -> Result<()> {
|
||||
let (cmd, mut base_args) = self.get_entry()?.get_cmd(None)?;
|
||||
base_args.extend_from_slice(&args);
|
||||
if self.get_entry()?.term {
|
||||
std::process::Command::new(cmd)
|
||||
.args(base_args)
|
||||
.status()?;
|
||||
} else {
|
||||
std::process::Command::new(cmd)
|
||||
.args(base_args)
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.spawn()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, pest_derive::Parser, Default, PartialEq, Eq)]
|
||||
#[grammar = "ini.pest"]
|
||||
pub struct DesktopEntry {
|
||||
pub(crate) name: String,
|
||||
pub(crate) exec: String,
|
||||
pub(crate) file_name: String,
|
||||
pub(crate) term: bool,
|
||||
pub(crate) mimes: Vec<Mime>,
|
||||
}
|
||||
|
||||
impl DesktopEntry {
|
||||
pub fn get_cmd(
|
||||
&self,
|
||||
arg: Option<String>,
|
||||
) -> Result<(String, Vec<String>)> {
|
||||
let special = regex::Regex::new("%(f|F|u|U)").unwrap();
|
||||
let mut split = shlex::split(&self.exec)
|
||||
.ok_or(Error::BadCmd)?
|
||||
.into_iter()
|
||||
.map(|s| match s.as_str() {
|
||||
"%f" | "%F" | "%u" | "%U" => arg.clone(),
|
||||
s if special.is_match(s) => Some(
|
||||
special
|
||||
.replace_all(s, arg.as_deref().unwrap_or_default())
|
||||
.into(),
|
||||
),
|
||||
_ => Some(s),
|
||||
})
|
||||
.filter_map(std::convert::identity)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok((split.remove(0), split))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PathBuf> for DesktopEntry {
|
||||
type Error = Error;
|
||||
fn try_from(p: PathBuf) -> Result<DesktopEntry> {
|
||||
use pest::Parser;
|
||||
let raw = std::fs::read_to_string(&p)?;
|
||||
let file = Self::parse(Rule::file, &raw)?.next().unwrap();
|
||||
|
||||
let mut section: &str = Default::default();
|
||||
let mut entry = Self::default();
|
||||
entry.file_name = p.file_name().unwrap().to_str().unwrap().to_owned();
|
||||
|
||||
for line in file.into_inner() {
|
||||
match line.as_rule() {
|
||||
Rule::section => {
|
||||
section = line.into_inner().as_str();
|
||||
}
|
||||
Rule::property if section == "Desktop Entry" => {
|
||||
let mut inner_rules = line.into_inner(); // { name ~ "=" ~ value }
|
||||
|
||||
let name = inner_rules.next().unwrap().as_str();
|
||||
match name {
|
||||
"Name" if entry.name.is_empty() => {
|
||||
entry.name =
|
||||
inner_rules.next().unwrap().as_str().into();
|
||||
}
|
||||
"Exec" => {
|
||||
entry.exec =
|
||||
inner_rules.next().unwrap().as_str().into();
|
||||
}
|
||||
"MimeType" => {
|
||||
let mut mimes = inner_rules
|
||||
.next()
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.split(";")
|
||||
.map(ToOwned::to_owned)
|
||||
.map(Mime)
|
||||
.collect::<Vec<_>>();
|
||||
mimes.pop();
|
||||
entry.mimes = mimes;
|
||||
}
|
||||
"Terminal" => {
|
||||
entry.term = match inner_rules.next().unwrap().as_str() {
|
||||
"true" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if !entry.name.is_empty() && !entry.exec.is_empty() {
|
||||
Ok(entry)
|
||||
} else {
|
||||
Err(Error::BadCmd)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{Error, Mime, Result};
|
||||
use crate::Result;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::path::Path;
|
||||
use xdg_mime::SharedMimeInfo;
|
||||
|
||||
static SHARED_MIME_DB: Lazy<SharedMimeInfo> = Lazy::new(SharedMimeInfo::new);
|
||||
pub static SHARED_MIME_DB: Lazy<SharedMimeInfo> =
|
||||
Lazy::new(SharedMimeInfo::new);
|
||||
|
||||
static CUSTOM_MIMES: &[&'static str] = &[
|
||||
"inode/directory",
|
||||
|
@ -11,29 +11,7 @@ static CUSTOM_MIMES: &[&'static str] = &[
|
|||
"x-scheme-handler/https",
|
||||
];
|
||||
|
||||
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Mime> {
|
||||
let guess = SHARED_MIME_DB.guess_mime_type().path(path).guess();
|
||||
|
||||
match guess.mime_type().essence_str() {
|
||||
"application/octet-stream" => Err(Error::Ambiguous),
|
||||
mime => Ok(Mime(mime.to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify(mime: &str) -> Result<&str> {
|
||||
if mime.starts_with("x-scheme-handler/") || CUSTOM_MIMES.contains(&mime) {
|
||||
return Ok(mime);
|
||||
}
|
||||
|
||||
mime_db::TYPES
|
||||
.iter()
|
||||
.find(|(m, _, _)| m == &mime)
|
||||
.ok_or(Error::BadMime(mime.to_owned()))?;
|
||||
|
||||
Ok(mime)
|
||||
}
|
||||
|
||||
pub fn list() -> Result<()> {
|
||||
pub fn autocomplete() -> Result<()> {
|
||||
use std::io::Write;
|
||||
|
||||
let stdout = std::io::stdout();
|
129
src/common/desktop_entry.rs
Normal file
129
src/common/desktop_entry.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
use crate::{Error, Result};
|
||||
use mime::Mime;
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
ffi::OsString,
|
||||
path::PathBuf,
|
||||
process::{Command, Stdio},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, pest_derive::Parser, Default, PartialEq, Eq)]
|
||||
#[grammar = "common/ini.pest"]
|
||||
pub struct DesktopEntry {
|
||||
pub(crate) name: String,
|
||||
pub(crate) exec: String,
|
||||
pub(crate) file_name: OsString,
|
||||
pub(crate) term: bool,
|
||||
pub(crate) mimes: Vec<Mime>,
|
||||
}
|
||||
|
||||
impl DesktopEntry {
|
||||
pub fn exec(&self, arguments: Vec<String>) -> Result<()> {
|
||||
let supports_multiple =
|
||||
self.exec.contains("%F") || self.exec.contains("%U");
|
||||
if arguments.is_empty() {
|
||||
self.exec_inner(None)?
|
||||
} else if supports_multiple {
|
||||
self.exec_inner(Some(arguments.join(" ")))?;
|
||||
} else {
|
||||
for arg in arguments {
|
||||
self.exec_inner(Some(arg))?;
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn exec_inner(&self, arg: Option<String>) -> Result<()> {
|
||||
let (cmd, args) = self.get_cmd(arg)?;
|
||||
let mut cmd = Command::new(cmd);
|
||||
cmd.args(args);
|
||||
if self.term {
|
||||
cmd.status()?;
|
||||
} else {
|
||||
cmd.stdout(Stdio::null()).stderr(Stdio::null()).spawn()?;
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
pub fn get_cmd(
|
||||
&self,
|
||||
arg: Option<String>,
|
||||
) -> Result<(String, Vec<String>)> {
|
||||
let special = regex::Regex::new("%(f|F|u|U)").unwrap();
|
||||
|
||||
let mut split = shlex::split(&self.exec)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.filter_map(|s| match s.as_str() {
|
||||
"%f" | "%F" | "%u" | "%U" => arg.clone(),
|
||||
s if special.is_match(s) => Some(
|
||||
special
|
||||
.replace_all(s, arg.as_deref().unwrap_or_default())
|
||||
.into(),
|
||||
),
|
||||
_ => Some(s),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok((split.remove(0), split))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PathBuf> for DesktopEntry {
|
||||
type Error = Error;
|
||||
fn try_from(p: PathBuf) -> Result<DesktopEntry> {
|
||||
use pest::Parser;
|
||||
let raw = std::fs::read_to_string(&p)?;
|
||||
let file = Self::parse(Rule::file, &raw)?.next().unwrap();
|
||||
|
||||
let mut entry = Self::default();
|
||||
entry.file_name = p.file_name().unwrap().to_owned();
|
||||
let mut section = "";
|
||||
|
||||
for line in file.into_inner() {
|
||||
match line.as_rule() {
|
||||
Rule::section => {
|
||||
section = line.into_inner().as_str();
|
||||
}
|
||||
Rule::property if section == "Desktop Entry" => {
|
||||
let mut inner_rules = line.into_inner(); // { name ~ "=" ~ value }
|
||||
|
||||
let name = inner_rules.next().unwrap().as_str();
|
||||
match name {
|
||||
"Name" if entry.name.is_empty() => {
|
||||
entry.name =
|
||||
inner_rules.next().unwrap().as_str().into();
|
||||
}
|
||||
"Exec" => {
|
||||
entry.exec =
|
||||
inner_rules.next().unwrap().as_str().into();
|
||||
}
|
||||
"MimeType" => {
|
||||
let mut mimes = inner_rules
|
||||
.next()
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.split(";")
|
||||
.filter_map(|m| Mime::from_str(m).ok())
|
||||
.collect::<Vec<_>>();
|
||||
mimes.pop();
|
||||
entry.mimes = mimes;
|
||||
}
|
||||
"Terminal" => {
|
||||
entry.term =
|
||||
inner_rules.next().unwrap().as_str() == "true"
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if !entry.name.is_empty() && !entry.exec.is_empty() {
|
||||
Ok(entry)
|
||||
} else {
|
||||
Err(Error::BadEntry(p.clone()))
|
||||
}
|
||||
}
|
||||
}
|
41
src/common/handler.rs
Normal file
41
src/common/handler.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use crate::{common::DesktopEntry, Error, Result};
|
||||
use std::{convert::TryFrom, ffi::OsString, path::PathBuf};
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Handler(OsString);
|
||||
|
||||
impl std::fmt::Display for Handler {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&self.0.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Handler {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Self::resolve(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
pub fn assume_valid(name: OsString) -> Self {
|
||||
Self(name)
|
||||
}
|
||||
pub fn get_path(name: &std::ffi::OsStr) -> Option<PathBuf> {
|
||||
let mut path = PathBuf::from("applications");
|
||||
path.push(name);
|
||||
xdg::BaseDirectories::new().ok()?.find_data_file(path)
|
||||
}
|
||||
pub fn resolve(name: OsString) -> Result<Self> {
|
||||
let path = Self::get_path(&name)
|
||||
.ok_or(Error::NotFound(name.to_string_lossy().into()))?;
|
||||
DesktopEntry::try_from(path)?;
|
||||
Ok(Self(name))
|
||||
}
|
||||
pub fn get_entry(&self) -> Result<DesktopEntry> {
|
||||
DesktopEntry::try_from(Self::get_path(&self.0).unwrap())
|
||||
}
|
||||
pub fn launch(&self, args: Vec<String>) -> Result<()> {
|
||||
self.get_entry()?.exec(args)
|
||||
}
|
||||
}
|
80
src/common/mime_types.rs
Normal file
80
src/common/mime_types.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use crate::{common::SHARED_MIME_DB, Error, Result};
|
||||
use mime::Mime;
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
// A mime derived from a path or URL
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct FlexibleMime(pub Mime);
|
||||
|
||||
impl TryFrom<&str> for FlexibleMime {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(arg: &str) -> Result<Self> {
|
||||
if let Ok(url) = url::Url::parse(arg) {
|
||||
Ok(Self(
|
||||
format!("x-scheme-handler/{}", url.scheme())
|
||||
.parse::<Mime>()
|
||||
.unwrap(),
|
||||
))
|
||||
} else {
|
||||
Self::try_from(&*PathBuf::from(arg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Path> for FlexibleMime {
|
||||
type Error = Error;
|
||||
fn try_from(path: &Path) -> Result<Self> {
|
||||
let guess = SHARED_MIME_DB.guess_mime_type().path(path).guess();
|
||||
let guess = guess.mime_type().clone();
|
||||
|
||||
if guess == mime::APPLICATION_OCTET_STREAM {
|
||||
Err(Error::Ambiguous(path.to_string_lossy().into()))
|
||||
} else {
|
||||
Ok(Self(guess))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mime derived from user input: extension(.pdf) or type like image/jpg
|
||||
#[derive(Debug)]
|
||||
pub struct MimeOrExtension(pub Mime);
|
||||
impl FromStr for MimeOrExtension {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
if s.starts_with(".") {
|
||||
Ok(Self(FlexibleMime::try_from(s)?.0))
|
||||
} else {
|
||||
Ok(Self(Mime::from_str(s)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn user_input() {
|
||||
"image/jpg".parse::<MimeOrExtension>().unwrap();
|
||||
".jpg".parse::<MimeOrExtension>().unwrap();
|
||||
"image//jpg".parse::<MimeOrExtension>().unwrap_err();
|
||||
"image".parse::<MimeOrExtension>().unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_path_with_extension() {
|
||||
assert_eq!(
|
||||
FlexibleMime::try_from(".pdf").unwrap().0,
|
||||
mime::APPLICATION_PDF
|
||||
);
|
||||
assert_eq!(
|
||||
FlexibleMime::try_from(".").unwrap().0.essence_str(),
|
||||
"inode/directory"
|
||||
);
|
||||
}
|
||||
}
|
9
src/common/mod.rs
Normal file
9
src/common/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
mod db;
|
||||
mod desktop_entry;
|
||||
mod handler;
|
||||
mod mime_types;
|
||||
|
||||
pub use self::db::{autocomplete as db_autocomplete, SHARED_MIME_DB};
|
||||
pub use desktop_entry::{DesktopEntry, Rule as PestRule};
|
||||
pub use handler::Handler;
|
||||
pub use mime_types::{FlexibleMime, MimeOrExtension};
|
26
src/error.rs
26
src/error.rs
|
@ -1,25 +1,21 @@
|
|||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Parse(#[from] pest::error::Error<crate::common::Rule>),
|
||||
Parse(#[from] pest::error::Error<crate::common::PestRule>),
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("no handler defined for this mime/extension")]
|
||||
NotFound,
|
||||
#[error("badly-formatted desktop entry")]
|
||||
BadCmd,
|
||||
#[error("could not locate config dir")]
|
||||
NoConfigDir,
|
||||
#[error("could not figure out the mime type")]
|
||||
Ambiguous,
|
||||
#[error("could not figure out the mime type from extension .{0}")]
|
||||
UnknownExtension(String),
|
||||
#[error("invalid mime {0}")]
|
||||
BadMime(String),
|
||||
#[error("either mime (via -m) or extension (via -e) must be provided")]
|
||||
MissingMimeOrExt,
|
||||
#[error(transparent)]
|
||||
Notify(#[from] notify_rust::error::Error),
|
||||
#[error(transparent)]
|
||||
Xdg(#[from] xdg::BaseDirectoriesError),
|
||||
#[error("no handler defined for this mime/extension")]
|
||||
NotFound(String),
|
||||
#[error("could not figure out the mime type .{0}")]
|
||||
Ambiguous(String),
|
||||
#[error(transparent)]
|
||||
BadMimeType(#[from] mime::FromStrError),
|
||||
#[error("Malformed desktop entry")]
|
||||
BadEntry(std::path::PathBuf),
|
||||
}
|
||||
|
||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
|
135
src/main.rs
135
src/main.rs
|
@ -1,39 +1,57 @@
|
|||
use clap::Clap;
|
||||
use error::{Error, Result};
|
||||
use notify_rust::Notification;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
mod apps;
|
||||
mod common;
|
||||
mod error;
|
||||
mod mime_types;
|
||||
mod mimeapps;
|
||||
|
||||
pub use common::{DesktopEntry, Handler, Mime};
|
||||
use common::{DesktopEntry, FlexibleMime, Handler, MimeOrExtension};
|
||||
|
||||
#[derive(Clap)]
|
||||
#[clap(global_setting = clap::AppSettings::DeriveDisplayOrder)]
|
||||
#[clap(global_setting = clap::AppSettings::DisableHelpSubcommand)]
|
||||
#[clap(version = clap::crate_version!())]
|
||||
enum Cmd {
|
||||
/// List default apps and the associated handlers
|
||||
List,
|
||||
|
||||
/// Open a path/URL with its default handler
|
||||
Open {
|
||||
path: String,
|
||||
#[clap(required = true)]
|
||||
path: Vec<String>,
|
||||
},
|
||||
|
||||
/// Set the default handler for mime/extension
|
||||
Set {
|
||||
mime: MimeOrExtension,
|
||||
handler: Handler,
|
||||
},
|
||||
|
||||
/// Unset the default handler for mime/extension
|
||||
Unset { mime: MimeOrExtension },
|
||||
|
||||
/// Launch the handler for specified extension/mime with optional arguments
|
||||
Launch {
|
||||
mime: MimeOrExtension,
|
||||
args: Vec<String>,
|
||||
},
|
||||
|
||||
/// Get handler for this mime/extension
|
||||
Get {
|
||||
#[clap(long)]
|
||||
json: bool,
|
||||
mime: Mime,
|
||||
},
|
||||
Launch {
|
||||
mime: Mime,
|
||||
args: Vec<String>,
|
||||
mime: MimeOrExtension,
|
||||
},
|
||||
|
||||
/// Add a handler for given mime/extension
|
||||
/// Note that the first handler is the default
|
||||
Add {
|
||||
mime: Mime,
|
||||
mime: MimeOrExtension,
|
||||
handler: Handler,
|
||||
},
|
||||
Set {
|
||||
mime: Mime,
|
||||
handler: Handler,
|
||||
},
|
||||
Unset {
|
||||
mime: Mime,
|
||||
},
|
||||
|
||||
#[clap(setting = clap::AppSettings::Hidden)]
|
||||
Autocomplete {
|
||||
#[clap(short)]
|
||||
|
@ -44,41 +62,60 @@ enum Cmd {
|
|||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut apps = mimeapps::MimeApps::read()?;
|
||||
let mut apps = apps::MimeApps::read()?;
|
||||
|
||||
match Cmd::parse() {
|
||||
Cmd::Set { mime, handler } => {
|
||||
apps.set_handler(mime, handler)?;
|
||||
}
|
||||
Cmd::Add { mime, handler } => {
|
||||
apps.add_handler(mime, handler)?;
|
||||
}
|
||||
Cmd::Launch { mime, args } => {
|
||||
apps.get_handler(&mime)?.launch(args)?;
|
||||
}
|
||||
Cmd::Get { mime, json } => {
|
||||
apps.show_handler(&mime, json)?;
|
||||
}
|
||||
Cmd::Open { path } => {
|
||||
apps.get_handler(&Mime::try_from_path(&path)?)?.open(path)?;
|
||||
}
|
||||
Cmd::List => {
|
||||
apps.print()?;
|
||||
}
|
||||
Cmd::Unset { mime } => {
|
||||
apps.remove_handler(&mime)?;
|
||||
}
|
||||
Cmd::Autocomplete {
|
||||
desktop_files,
|
||||
mimes,
|
||||
} => {
|
||||
if desktop_files {
|
||||
apps.list_handlers()?;
|
||||
} else if mimes {
|
||||
mime_types::list()?;
|
||||
let res = || -> Result<()> {
|
||||
match Cmd::parse() {
|
||||
Cmd::Set { mime, handler } => {
|
||||
apps.set_handler(mime.0, handler)?;
|
||||
}
|
||||
Cmd::Add { mime, handler } => {
|
||||
apps.add_handler(mime.0, handler)?;
|
||||
}
|
||||
Cmd::Launch { mime, args } => {
|
||||
apps.get_handler(&mime.0)?.launch(args)?;
|
||||
}
|
||||
Cmd::Get { mime, json } => {
|
||||
apps.show_handler(&mime.0, json)?;
|
||||
}
|
||||
Cmd::Open { path } => {
|
||||
std::process::Command::new("notify-send")
|
||||
.arg(&format!("{:?}", path))
|
||||
.spawn()?;
|
||||
apps.get_handler(
|
||||
&FlexibleMime::try_from(path.get(0).unwrap().as_str())?.0,
|
||||
)?
|
||||
.launch(path)?;
|
||||
}
|
||||
Cmd::List => {
|
||||
apps.print()?;
|
||||
}
|
||||
Cmd::Unset { mime } => {
|
||||
apps.remove_handler(&mime.0)?;
|
||||
}
|
||||
Cmd::Autocomplete {
|
||||
desktop_files,
|
||||
mimes,
|
||||
} => {
|
||||
if desktop_files {
|
||||
apps.list_handlers()?;
|
||||
} else if mimes {
|
||||
common::db_autocomplete()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}();
|
||||
|
||||
match (res, atty::is(atty::Stream::Stdout)) {
|
||||
(Err(e), true) => eprintln!("{}", e),
|
||||
(Err(e), false) => {
|
||||
Notification::new()
|
||||
.summary("handlr error")
|
||||
.body(&e.to_string())
|
||||
.show()?;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue