Implement open in terminal
This commit is contained in:
parent
49d4dea8b4
commit
ef040c4277
8 changed files with 238 additions and 58 deletions
95
Cargo.lock
generated
95
Cargo.lock
generated
|
|
@ -110,9 +110,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.10"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
|
@ -280,9 +280,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
version = "1.6.0"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
|
|
@ -335,6 +335,23 @@ dependencies = [
|
||||||
"zbus",
|
"zbus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ashpd"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01992ad7774250d5b7fe214e2676cb99bf92564436d8135ab44fe815e71769a9"
|
||||||
|
dependencies = [
|
||||||
|
"enumflags2",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-util",
|
||||||
|
"rand",
|
||||||
|
"serde",
|
||||||
|
"serde_repr",
|
||||||
|
"tokio",
|
||||||
|
"url",
|
||||||
|
"zbus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-broadcast"
|
name = "async-broadcast"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
|
@ -791,10 +808,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.88"
|
version = "1.0.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
|
checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1012,9 +1030,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const-random"
|
name = "const-random"
|
||||||
version = "0.1.17"
|
version = "0.1.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a"
|
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-random-macro",
|
"const-random-macro",
|
||||||
]
|
]
|
||||||
|
|
@ -1127,7 +1145,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-config"
|
name = "cosmic-config"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomicwrites",
|
"atomicwrites",
|
||||||
"cosmic-config-derive",
|
"cosmic-config-derive",
|
||||||
|
|
@ -1144,7 +1162,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-config-derive"
|
name = "cosmic-config-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
|
|
@ -1164,6 +1182,7 @@ dependencies = [
|
||||||
"i18n-embed-fl",
|
"i18n-embed-fl",
|
||||||
"image 0.24.9",
|
"image 0.24.9",
|
||||||
"lexical-sort",
|
"lexical-sort",
|
||||||
|
"libc",
|
||||||
"libcosmic",
|
"libcosmic",
|
||||||
"log",
|
"log",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
|
|
@ -1173,6 +1192,7 @@ dependencies = [
|
||||||
"paste",
|
"paste",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
"serde",
|
"serde",
|
||||||
|
"shlex",
|
||||||
"smol_str",
|
"smol_str",
|
||||||
"systemicons",
|
"systemicons",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
|
@ -1186,7 +1206,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-text"
|
name = "cosmic-text"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
source = "git+https://github.com/pop-os/cosmic-text.git#22e61965aa38ab0bd64bbdddf3848ae891edceba"
|
source = "git+https://github.com/pop-os/cosmic-text.git#a53a0b3a8c085143470a9d26ac2c2911cc479033"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
"fontdb",
|
"fontdb",
|
||||||
|
|
@ -1208,7 +1228,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-theme"
|
name = "cosmic-theme"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"almost",
|
"almost",
|
||||||
"cosmic-config",
|
"cosmic-config",
|
||||||
|
|
@ -2662,7 +2682,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced"
|
name = "iced"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_accessibility",
|
"iced_accessibility",
|
||||||
"iced_core",
|
"iced_core",
|
||||||
|
|
@ -2677,7 +2697,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_accessibility"
|
name = "iced_accessibility"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_winit",
|
"accesskit_winit",
|
||||||
|
|
@ -2686,7 +2706,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_core"
|
name = "iced_core"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"log",
|
"log",
|
||||||
|
|
@ -2703,7 +2723,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_futures"
|
name = "iced_futures"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"iced_core",
|
"iced_core",
|
||||||
|
|
@ -2716,7 +2736,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_graphics"
|
name = "iced_graphics"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
|
@ -2740,7 +2760,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_renderer"
|
name = "iced_renderer"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_graphics",
|
"iced_graphics",
|
||||||
"iced_tiny_skia",
|
"iced_tiny_skia",
|
||||||
|
|
@ -2752,7 +2772,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_runtime"
|
name = "iced_runtime"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_core",
|
"iced_core",
|
||||||
"iced_futures",
|
"iced_futures",
|
||||||
|
|
@ -2762,7 +2782,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_style"
|
name = "iced_style"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_core",
|
"iced_core",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -2772,7 +2792,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_tiny_skia"
|
name = "iced_tiny_skia"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cosmic-text",
|
"cosmic-text",
|
||||||
|
|
@ -2789,7 +2809,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_wgpu"
|
name = "iced_wgpu"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
|
@ -2808,7 +2828,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_widget"
|
name = "iced_widget"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_renderer",
|
"iced_renderer",
|
||||||
"iced_runtime",
|
"iced_runtime",
|
||||||
|
|
@ -2822,7 +2842,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_winit"
|
name = "iced_winit"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_graphics",
|
"iced_graphics",
|
||||||
"iced_runtime",
|
"iced_runtime",
|
||||||
|
|
@ -3032,6 +3052,15 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jpeg-decoder"
|
name = "jpeg-decoder"
|
||||||
version = "0.1.22"
|
version = "0.1.22"
|
||||||
|
|
@ -3166,10 +3195,10 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libcosmic"
|
name = "libcosmic"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/pop-os/libcosmic.git#ce45af20f8f1d7c803b20c8af37fdd3adac641e2"
|
source = "git+https://github.com/pop-os/libcosmic.git#be00b0ec4beb36e38aedab8ee5fd7976bf5dd141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"apply",
|
"apply",
|
||||||
"ashpd",
|
"ashpd 0.7.0",
|
||||||
"cosmic-config",
|
"cosmic-config",
|
||||||
"cosmic-theme",
|
"cosmic-theme",
|
||||||
"css-color",
|
"css-color",
|
||||||
|
|
@ -3977,9 +4006,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "open"
|
name = "open"
|
||||||
version = "5.1.0"
|
version = "5.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f2588edf622de56e7a1fed57bf203344f63c03f3d43472ba0434a92373c8f27"
|
checksum = "68b3fbb0d52bf0cbb5225ba3d2c303aa136031d43abff98284332a9981ecddec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"is-wsl",
|
"is-wsl",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
@ -4581,9 +4610,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
|
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -4598,9 +4627,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "renderdoc-sys"
|
name = "renderdoc-sys"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b"
|
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "resvg"
|
name = "resvg"
|
||||||
|
|
@ -4625,7 +4654,7 @@ version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0d8ab342bcc5436e04d3a4c1e09e17d74958bfaddf8d5fad6f85607df0f994f"
|
checksum = "c0d8ab342bcc5436e04d3a4c1e09e17d74958bfaddf8d5fad6f85607df0f994f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ashpd",
|
"ashpd 0.6.8",
|
||||||
"block",
|
"block",
|
||||||
"dispatch",
|
"dispatch",
|
||||||
"glib-sys",
|
"glib-sys",
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,13 @@ image = "0.24"
|
||||||
once_cell = "1.19"
|
once_cell = "1.19"
|
||||||
open = "5.0.2"
|
open = "5.0.2"
|
||||||
lexical-sort = "0.3.1"
|
lexical-sort = "0.3.1"
|
||||||
|
libc = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime_guess = "2"
|
mime_guess = "2"
|
||||||
notify = "6"
|
notify = "6"
|
||||||
paste = "1.0"
|
paste = "1.0"
|
||||||
serde = { version = "1", features = ["serde_derive"] }
|
serde = { version = "1", features = ["serde_derive"] }
|
||||||
|
shlex = { version = "1.3" }
|
||||||
tokio = { version = "1" }
|
tokio = { version = "1" }
|
||||||
trash = "3.2.0"
|
trash = "3.2.0"
|
||||||
xdg = { version = "2.5.2", optional = true }
|
xdg = { version = "2.5.2", optional = true }
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ light = Light
|
||||||
new-file = New file
|
new-file = New file
|
||||||
new-folder = New folder
|
new-folder = New folder
|
||||||
open-with = Open with
|
open-with = Open with
|
||||||
|
open-in-terminal = Open in terminal
|
||||||
move-to-trash = Move to trash
|
move-to-trash = Move to trash
|
||||||
restore-from-trash = Restore from trash
|
restore-from-trash = Restore from trash
|
||||||
|
|
||||||
|
|
|
||||||
83
src/app.rs
83
src/app.rs
|
|
@ -13,7 +13,10 @@ use cosmic::{
|
||||||
window, Alignment, Event, Length,
|
window, Alignment, Event, Length,
|
||||||
},
|
},
|
||||||
style, theme,
|
style, theme,
|
||||||
widget::{self, segmented_button},
|
widget::{
|
||||||
|
self,
|
||||||
|
segmented_button::{self, Entity},
|
||||||
|
},
|
||||||
Application, ApplicationExt, Element,
|
Application, ApplicationExt, Element,
|
||||||
};
|
};
|
||||||
use notify::Watcher;
|
use notify::Watcher;
|
||||||
|
|
@ -30,8 +33,9 @@ use crate::{
|
||||||
config::{AppTheme, Config, IconSizes, TabConfig, CONFIG_VERSION},
|
config::{AppTheme, Config, IconSizes, TabConfig, CONFIG_VERSION},
|
||||||
fl, home_dir,
|
fl, home_dir,
|
||||||
key_bind::{key_binds, KeyBind},
|
key_bind::{key_binds, KeyBind},
|
||||||
menu,
|
menu, mime_app,
|
||||||
operation::Operation,
|
operation::Operation,
|
||||||
|
spawn_detached::spawn_detached,
|
||||||
tab::{self, ItemMetadata, Location, Tab},
|
tab::{self, ItemMetadata, Location, Tab},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -58,6 +62,7 @@ pub enum Action {
|
||||||
NewFile,
|
NewFile,
|
||||||
NewFolder,
|
NewFolder,
|
||||||
Open,
|
Open,
|
||||||
|
OpenTerminal,
|
||||||
OpenWith,
|
OpenWith,
|
||||||
Operations,
|
Operations,
|
||||||
Paste,
|
Paste,
|
||||||
|
|
@ -78,7 +83,7 @@ pub enum Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Action {
|
impl Action {
|
||||||
pub fn message(self, entity_opt: Option<segmented_button::Entity>) -> Message {
|
pub fn message(self, entity_opt: Option<Entity>) -> Message {
|
||||||
match self {
|
match self {
|
||||||
Action::About => Message::ToggleContextPage(ContextPage::About),
|
Action::About => Message::ToggleContextPage(ContextPage::About),
|
||||||
Action::Copy => Message::Copy(entity_opt),
|
Action::Copy => Message::Copy(entity_opt),
|
||||||
|
|
@ -95,6 +100,7 @@ impl Action {
|
||||||
Action::NewFile => Message::NewItem(entity_opt, false),
|
Action::NewFile => Message::NewItem(entity_opt, false),
|
||||||
Action::NewFolder => Message::NewItem(entity_opt, true),
|
Action::NewFolder => Message::NewItem(entity_opt, true),
|
||||||
Action::Open => Message::TabMessage(entity_opt, tab::Message::Open),
|
Action::Open => Message::TabMessage(entity_opt, tab::Message::Open),
|
||||||
|
Action::OpenTerminal => Message::OpenTerminal(entity_opt),
|
||||||
Action::OpenWith => Message::ToggleContextPage(ContextPage::OpenWith),
|
Action::OpenWith => Message::ToggleContextPage(ContextPage::OpenWith),
|
||||||
Action::Operations => Message::ToggleContextPage(ContextPage::Operations),
|
Action::Operations => Message::ToggleContextPage(ContextPage::Operations),
|
||||||
Action::Paste => Message::Paste(entity_opt),
|
Action::Paste => Message::Paste(entity_opt),
|
||||||
|
|
@ -125,34 +131,35 @@ impl Action {
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
AppTheme(AppTheme),
|
AppTheme(AppTheme),
|
||||||
Config(Config),
|
Config(Config),
|
||||||
Copy(Option<segmented_button::Entity>),
|
Copy(Option<Entity>),
|
||||||
Cut(Option<segmented_button::Entity>),
|
Cut(Option<Entity>),
|
||||||
DialogCancel,
|
DialogCancel,
|
||||||
DialogComplete,
|
DialogComplete,
|
||||||
DialogUpdate(DialogPage),
|
DialogUpdate(DialogPage),
|
||||||
EditLocation(Option<segmented_button::Entity>),
|
EditLocation(Option<Entity>),
|
||||||
Key(Modifiers, Key),
|
Key(Modifiers, Key),
|
||||||
LaunchUrl(String),
|
LaunchUrl(String),
|
||||||
Modifiers(Modifiers),
|
Modifiers(Modifiers),
|
||||||
MoveToTrash(Option<segmented_button::Entity>),
|
MoveToTrash(Option<Entity>),
|
||||||
NewItem(Option<segmented_button::Entity>, bool),
|
NewItem(Option<Entity>, bool),
|
||||||
NotifyEvent(notify::Event),
|
NotifyEvent(notify::Event),
|
||||||
NotifyWatcher(WatcherWrapper),
|
NotifyWatcher(WatcherWrapper),
|
||||||
Paste(Option<segmented_button::Entity>),
|
OpenTerminal(Option<Entity>),
|
||||||
|
Paste(Option<Entity>),
|
||||||
PendingComplete(u64),
|
PendingComplete(u64),
|
||||||
PendingError(u64, String),
|
PendingError(u64, String),
|
||||||
PendingProgress(u64, f32),
|
PendingProgress(u64, f32),
|
||||||
Rename(Option<segmented_button::Entity>),
|
Rename(Option<Entity>),
|
||||||
RestoreFromTrash(Option<segmented_button::Entity>),
|
RestoreFromTrash(Option<Entity>),
|
||||||
SystemThemeModeChange(cosmic_theme::ThemeMode),
|
SystemThemeModeChange(cosmic_theme::ThemeMode),
|
||||||
TabActivate(segmented_button::Entity),
|
TabActivate(Entity),
|
||||||
TabNext,
|
TabNext,
|
||||||
TabPrev,
|
TabPrev,
|
||||||
TabClose(Option<segmented_button::Entity>),
|
TabClose(Option<Entity>),
|
||||||
TabConfig(TabConfig),
|
TabConfig(TabConfig),
|
||||||
TabMessage(Option<segmented_button::Entity>, tab::Message),
|
TabMessage(Option<Entity>, tab::Message),
|
||||||
TabNew,
|
TabNew,
|
||||||
TabRescan(segmented_button::Entity, Vec<tab::Item>),
|
TabRescan(Entity, Vec<tab::Item>),
|
||||||
ToggleContextPage(ContextPage),
|
ToggleContextPage(ContextPage),
|
||||||
WindowClose,
|
WindowClose,
|
||||||
WindowNew,
|
WindowNew,
|
||||||
|
|
@ -256,11 +263,7 @@ impl App {
|
||||||
self.pending_operations.insert(id, (operation, 0.0));
|
self.pending_operations.insert(id, (operation, 0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rescan_tab(
|
fn rescan_tab(&mut self, entity: Entity, location: Location) -> Command<Message> {
|
||||||
&mut self,
|
|
||||||
entity: segmented_button::Entity,
|
|
||||||
location: Location,
|
|
||||||
) -> Command<Message> {
|
|
||||||
let icon_sizes = self.config.tab.icon_sizes;
|
let icon_sizes = self.config.tab.icon_sizes;
|
||||||
Command::perform(
|
Command::perform(
|
||||||
async move {
|
async move {
|
||||||
|
|
@ -643,7 +646,7 @@ impl Application for App {
|
||||||
Some(&self.nav_model)
|
Some(&self.nav_model)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_nav_select(&mut self, entity: segmented_button::Entity) -> Command<Self::Message> {
|
fn on_nav_select(&mut self, entity: Entity) -> Command<Self::Message> {
|
||||||
let location_opt = self.nav_model.data::<Location>(entity).clone();
|
let location_opt = self.nav_model.data::<Location>(entity).clone();
|
||||||
|
|
||||||
if let Some(location) = location_opt {
|
if let Some(location) = location_opt {
|
||||||
|
|
@ -864,6 +867,44 @@ impl Application for App {
|
||||||
log::warn!("message did not contain notify watcher");
|
log::warn!("message did not contain notify watcher");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Message::OpenTerminal(entity_opt) => {
|
||||||
|
if let Some(terminal) = mime_app::terminal() {
|
||||||
|
let mut paths = Vec::new();
|
||||||
|
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||||
|
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
|
||||||
|
if let Location::Path(path) = &tab.location {
|
||||||
|
if let Some(items) = tab.items_opt() {
|
||||||
|
for item in items.iter() {
|
||||||
|
if item.selected {
|
||||||
|
paths.push(item.path.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if paths.is_empty() {
|
||||||
|
paths.push(path.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for path in paths {
|
||||||
|
if let Some(mut command) = terminal.command(None) {
|
||||||
|
command.current_dir(&path);
|
||||||
|
match spawn_detached(&mut command) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(err) => {
|
||||||
|
log::warn!(
|
||||||
|
"failed to launch terminal {:?} in {:?}: {}",
|
||||||
|
terminal.id,
|
||||||
|
path,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::warn!("failed to get command for {:?}", terminal.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Message::Paste(_entity_opt) => {
|
Message::Paste(_entity_opt) => {
|
||||||
log::warn!("TODO: PASTE");
|
log::warn!("TODO: PASTE");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ mod mime_app;
|
||||||
mod mime_icon;
|
mod mime_icon;
|
||||||
mod mouse_area;
|
mod mouse_area;
|
||||||
mod operation;
|
mod operation;
|
||||||
|
mod spawn_detached;
|
||||||
mod tab;
|
mod tab;
|
||||||
|
|
||||||
pub fn home_dir() -> PathBuf {
|
pub fn home_dir() -> PathBuf {
|
||||||
|
|
|
||||||
20
src/menu.rs
20
src/menu.rs
|
|
@ -57,9 +57,18 @@ pub fn context_menu<'a>(
|
||||||
.on_press(tab::Message::ContextAction(action))
|
.on_press(tab::Message::ContextAction(action))
|
||||||
};
|
};
|
||||||
|
|
||||||
let selected = tab
|
let mut selected_dir = 0;
|
||||||
.items_opt()
|
let mut selected = 0;
|
||||||
.map_or(0, |items| items.iter().filter(|x| x.selected).count());
|
tab.items_opt().map(|items| {
|
||||||
|
for item in items.iter() {
|
||||||
|
if item.selected {
|
||||||
|
selected += 1;
|
||||||
|
if item.metadata.is_dir() {
|
||||||
|
selected_dir += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let mut children: Vec<Element<_>> = Vec::new();
|
let mut children: Vec<Element<_>> = Vec::new();
|
||||||
match tab.location {
|
match tab.location {
|
||||||
|
|
@ -68,6 +77,10 @@ pub fn context_menu<'a>(
|
||||||
children.push(menu_item(fl!("open"), Action::Open).into());
|
children.push(menu_item(fl!("open"), Action::Open).into());
|
||||||
if selected == 1 {
|
if selected == 1 {
|
||||||
children.push(menu_item(fl!("open-with"), Action::OpenWith).into());
|
children.push(menu_item(fl!("open-with"), Action::OpenWith).into());
|
||||||
|
if selected_dir == 1 {
|
||||||
|
children
|
||||||
|
.push(menu_item(fl!("open-in-terminal"), Action::OpenTerminal).into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
children.push(horizontal_rule(1).into());
|
children.push(horizontal_rule(1).into());
|
||||||
children.push(menu_item(fl!("rename"), Action::Rename).into());
|
children.push(menu_item(fl!("rename"), Action::Rename).into());
|
||||||
|
|
@ -85,6 +98,7 @@ pub fn context_menu<'a>(
|
||||||
//TODO: have things like properties but they apply to the folder?
|
//TODO: have things like properties but they apply to the folder?
|
||||||
children.push(menu_item(fl!("new-file"), Action::NewFile).into());
|
children.push(menu_item(fl!("new-file"), Action::NewFile).into());
|
||||||
children.push(menu_item(fl!("new-folder"), Action::NewFolder).into());
|
children.push(menu_item(fl!("new-folder"), Action::NewFolder).into());
|
||||||
|
children.push(menu_item(fl!("open-in-terminal"), Action::OpenTerminal).into());
|
||||||
children.push(horizontal_rule(1).into());
|
children.push(horizontal_rule(1).into());
|
||||||
children.push(menu_item(fl!("select-all"), Action::SelectAll).into());
|
children.push(menu_item(fl!("select-all"), Action::SelectAll).into());
|
||||||
children.push(menu_item(fl!("paste"), Action::Paste).into());
|
children.push(menu_item(fl!("paste"), Action::Paste).into());
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use cosmic::desktop;
|
||||||
use cosmic::widget;
|
use cosmic::widget;
|
||||||
pub use mime_guess::Mime;
|
pub use mime_guess::Mime;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::{collections::HashMap, path::PathBuf, sync::Mutex, time::Instant};
|
use std::{collections::HashMap, path::PathBuf, process, sync::Mutex, time::Instant};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MimeApp {
|
pub struct MimeApp {
|
||||||
|
|
@ -18,6 +18,33 @@ pub struct MimeApp {
|
||||||
pub is_default: bool,
|
pub is_default: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MimeApp {
|
||||||
|
//TODO: move to libcosmic, support multiple files
|
||||||
|
pub fn command(&self, path_opt: Option<PathBuf>) -> Option<process::Command> {
|
||||||
|
let args_vec: Vec<String> = self.exec.as_deref().and_then(shlex::split)?;
|
||||||
|
let mut args = args_vec.iter();
|
||||||
|
let mut command = process::Command::new(args.next()?);
|
||||||
|
for arg in args {
|
||||||
|
if arg.starts_with('%') {
|
||||||
|
match arg.as_str() {
|
||||||
|
"%f" | "%F" | "%u" | "%U" => {
|
||||||
|
if let Some(path) = &path_opt {
|
||||||
|
command.arg(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
log::warn!("unsupported Exec code {:?} in {:?}", arg, self.id);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
command.arg(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
impl From<&desktop::DesktopEntryData> for MimeApp {
|
impl From<&desktop::DesktopEntryData> for MimeApp {
|
||||||
fn from(app: &desktop::DesktopEntryData) -> Self {
|
fn from(app: &desktop::DesktopEntryData) -> Self {
|
||||||
|
|
@ -46,12 +73,14 @@ fn filename_eq(path_opt: &Option<PathBuf>, filename: &str) -> bool {
|
||||||
|
|
||||||
pub struct MimeAppCache {
|
pub struct MimeAppCache {
|
||||||
cache: HashMap<Mime, Vec<MimeApp>>,
|
cache: HashMap<Mime, Vec<MimeApp>>,
|
||||||
|
terminals: Vec<MimeApp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MimeAppCache {
|
impl MimeAppCache {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut mime_app_cache = Self {
|
let mut mime_app_cache = Self {
|
||||||
cache: HashMap::new(),
|
cache: HashMap::new(),
|
||||||
|
terminals: Vec::new(),
|
||||||
};
|
};
|
||||||
mime_app_cache.reload();
|
mime_app_cache.reload();
|
||||||
mime_app_cache
|
mime_app_cache
|
||||||
|
|
@ -66,6 +95,7 @@ impl MimeAppCache {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
self.cache.clear();
|
self.cache.clear();
|
||||||
|
self.terminals.clear();
|
||||||
|
|
||||||
//TODO: get proper locale?
|
//TODO: get proper locale?
|
||||||
let locale = None;
|
let locale = None;
|
||||||
|
|
@ -83,6 +113,12 @@ impl MimeAppCache {
|
||||||
apps.push(MimeApp::from(app));
|
apps.push(MimeApp::from(app));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for category in app.categories.iter() {
|
||||||
|
if category == "TerminalEmulator" {
|
||||||
|
self.terminals.push(MimeApp::from(app));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load mimeapps.list files
|
// Load mimeapps.list files
|
||||||
|
|
@ -202,3 +238,22 @@ pub fn mime_apps(mime: &Mime) -> Vec<MimeApp> {
|
||||||
let mime_app_cache = MIME_APP_CACHE.lock().unwrap();
|
let mime_app_cache = MIME_APP_CACHE.lock().unwrap();
|
||||||
mime_app_cache.get(mime)
|
mime_app_cache.get(mime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn terminal() -> Option<MimeApp> {
|
||||||
|
let mime_app_cache = MIME_APP_CACHE.lock().unwrap();
|
||||||
|
|
||||||
|
//TODO: consider rules in https://github.com/Vladimir-csp/xdg-terminal-exec
|
||||||
|
|
||||||
|
// Look for and return preferred terminals
|
||||||
|
//TODO: fallback order beyond cosmic-term?
|
||||||
|
for id in &["com.system76.CosmicTerm"] {
|
||||||
|
for terminal in mime_app_cache.terminals.iter() {
|
||||||
|
if &terminal.id == id {
|
||||||
|
return Some(terminal.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return whatever was the first terminal found
|
||||||
|
mime_app_cache.terminals.first().map(|x| x.clone())
|
||||||
|
}
|
||||||
|
|
|
||||||
37
src/spawn_detached.rs
Normal file
37
src/spawn_detached.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
use std::{io, process};
|
||||||
|
|
||||||
|
// This code is from the open crate and retains its MIT license.
|
||||||
|
pub fn spawn_detached(command: &mut process::Command) -> io::Result<()> {
|
||||||
|
command
|
||||||
|
.stdin(process::Stdio::null())
|
||||||
|
.stdout(process::Stdio::null())
|
||||||
|
.stderr(process::Stdio::null());
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
unsafe {
|
||||||
|
use std::os::unix::process::CommandExt as _;
|
||||||
|
|
||||||
|
command.pre_exec(move || {
|
||||||
|
match libc::fork() {
|
||||||
|
-1 => return Err(io::Error::last_os_error()),
|
||||||
|
0 => (),
|
||||||
|
_ => libc::_exit(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
if libc::setsid() == -1 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
use std::os::windows::process::CommandExt;
|
||||||
|
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
|
||||||
|
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||||
|
command.creation_flags(CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
command.spawn().map(|_| ())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue