feat(plugins): use protocol buffers for serializing across the wasm boundary (#2686)
* work * almost done with command protobuffers * done translating command data structures * mid transferring of every command to protobuff command * transferred plugin_command.rs, now moving on to shim.rs * plugin command working with protobufs * protobuffers in update * protobuf event tests * various TODOs and comments * fix zellij-tile * clean up prost deps * remove version mismatch error * fix panic * some cleanups * clean up event protobuffers * clean up command protobuffers * clean up various protobufs * refactor protobufs * update comments * some transformation fixes * use protobufs for workers * style(fmt): rustfmt * style(fmt): rustfmt * chore(build): add protoc * chore(build): authenticate protoc
This commit is contained in:
parent
c3e140cb4b
commit
1bedfc9002
47 changed files with 6045 additions and 1072 deletions
4
.github/workflows/e2e.yml
vendored
4
.github/workflows/e2e.yml
vendored
|
|
@ -30,6 +30,10 @@ jobs:
|
||||||
options: -v ${{ github.workspace }}/target:/usr/src/zellij --name ssh
|
options: -v ${{ github.workspace }}/target:/usr/src/zellij --name ssh
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
- name: Install Protoc
|
||||||
|
uses: arduino/setup-protoc@v2
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Add WASM target
|
- name: Add WASM target
|
||||||
run: rustup target add wasm32-wasi
|
run: rustup target add wasm32-wasi
|
||||||
- name: Install musl-tools
|
- name: Install musl-tools
|
||||||
|
|
|
||||||
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
|
|
@ -48,6 +48,11 @@ jobs:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install Protoc
|
||||||
|
uses: arduino/setup-protoc@v2
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
13
.github/workflows/rust.yml
vendored
13
.github/workflows/rust.yml
vendored
|
|
@ -22,6 +22,11 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
- name: Install Protoc
|
||||||
|
uses: arduino/setup-protoc@v2
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Setup toolchain
|
- name: Setup toolchain
|
||||||
run: rustup show
|
run: rustup show
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
@ -40,6 +45,10 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
- name: Install Protoc
|
||||||
|
uses: arduino/setup-protoc@v2
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Setup toolchain
|
- name: Setup toolchain
|
||||||
run: rustup show
|
run: rustup show
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
@ -63,6 +72,10 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
- name: Install Protoc
|
||||||
|
uses: arduino/setup-protoc@v2
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Setup toolchain
|
- name: Setup toolchain
|
||||||
run: rustup show
|
run: rustup show
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
|
||||||
97
Cargo.lock
generated
97
Cargo.lock
generated
|
|
@ -382,6 +382,12 @@ version = "1.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cache-padded"
|
name = "cache-padded"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
|
@ -1491,6 +1497,15 @@ version = "1.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
|
checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
|
@ -1836,6 +1851,12 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389"
|
checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multimap"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "names"
|
name = "names"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
|
@ -2152,6 +2173,16 @@ dependencies = [
|
||||||
"sha-1",
|
"sha-1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "petgraph"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset",
|
||||||
|
"indexmap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
@ -2297,6 +2328,16 @@ dependencies = [
|
||||||
"getopts",
|
"getopts",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettyplease"
|
||||||
|
version = "0.1.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"syn 1.0.96",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
|
@ -2336,6 +2377,60 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prost"
|
||||||
|
version = "0.11.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"prost-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prost-build"
|
||||||
|
version = "0.11.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"heck 0.4.0",
|
||||||
|
"itertools",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"multimap",
|
||||||
|
"petgraph",
|
||||||
|
"prettyplease",
|
||||||
|
"prost",
|
||||||
|
"prost-types",
|
||||||
|
"regex",
|
||||||
|
"syn 1.0.96",
|
||||||
|
"tempfile",
|
||||||
|
"which",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prost-derive"
|
||||||
|
version = "0.11.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"itertools",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.96",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prost-types"
|
||||||
|
version = "0.11.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13"
|
||||||
|
dependencies = [
|
||||||
|
"prost",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ptr_meta"
|
name = "ptr_meta"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|
@ -4518,6 +4613,8 @@ dependencies = [
|
||||||
"notify-debouncer-full",
|
"notify-debouncer-full",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
"prost",
|
||||||
|
"prost-build",
|
||||||
"regex",
|
"regex",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,14 @@ impl<'de> ZellijWorker<'de> for TestWorker {
|
||||||
fn on_message(&mut self, message: String, payload: String) {
|
fn on_message(&mut self, message: String, payload: String) {
|
||||||
if message == "ping" {
|
if message == "ping" {
|
||||||
self.number_of_messages_received += 1;
|
self.number_of_messages_received += 1;
|
||||||
post_message_to_plugin(
|
post_message_to_plugin(PluginMessage {
|
||||||
"pong".into(),
|
worker_name: None,
|
||||||
format!(
|
name: "pong".into(),
|
||||||
|
payload: format!(
|
||||||
"{}, received {} messages",
|
"{}, received {} messages",
|
||||||
payload, self.number_of_messages_received
|
payload, self.number_of_messages_received
|
||||||
),
|
),
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -143,22 +144,30 @@ impl ZellijPlugin for State {
|
||||||
start_or_reload_plugin(plugin_url)
|
start_or_reload_plugin(plugin_url)
|
||||||
},
|
},
|
||||||
Key::Ctrl('g') => {
|
Key::Ctrl('g') => {
|
||||||
open_file(std::path::PathBuf::from("/path/to/my/file.rs").as_path());
|
open_file(FileToOpen {
|
||||||
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
},
|
},
|
||||||
Key::Ctrl('h') => {
|
Key::Ctrl('h') => {
|
||||||
open_file_floating(std::path::PathBuf::from("/path/to/my/file.rs").as_path());
|
open_file_floating(FileToOpen {
|
||||||
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
},
|
},
|
||||||
Key::Ctrl('i') => {
|
Key::Ctrl('i') => {
|
||||||
open_file_with_line(
|
open_file(FileToOpen {
|
||||||
std::path::PathBuf::from("/path/to/my/file.rs").as_path(),
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
42,
|
line_number: Some(42),
|
||||||
);
|
..Default::default()
|
||||||
|
});
|
||||||
},
|
},
|
||||||
Key::Ctrl('j') => {
|
Key::Ctrl('j') => {
|
||||||
open_file_with_line_floating(
|
open_file_floating(FileToOpen {
|
||||||
std::path::PathBuf::from("/path/to/my/file.rs").as_path(),
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
42,
|
line_number: Some(42),
|
||||||
);
|
..Default::default()
|
||||||
|
});
|
||||||
},
|
},
|
||||||
Key::Ctrl('k') => {
|
Key::Ctrl('k') => {
|
||||||
open_terminal(std::path::PathBuf::from("/path/to/my/file.rs").as_path());
|
open_terminal(std::path::PathBuf::from("/path/to/my/file.rs").as_path());
|
||||||
|
|
@ -169,16 +178,18 @@ impl ZellijPlugin for State {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
Key::Ctrl('m') => {
|
Key::Ctrl('m') => {
|
||||||
open_command_pane(
|
open_command_pane(CommandToRun {
|
||||||
std::path::PathBuf::from("/path/to/my/file.rs").as_path(),
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
vec!["arg1".to_owned(), "arg2".to_owned()],
|
args: vec!["arg1".to_owned(), "arg2".to_owned()],
|
||||||
);
|
..Default::default()
|
||||||
|
});
|
||||||
},
|
},
|
||||||
Key::Ctrl('n') => {
|
Key::Ctrl('n') => {
|
||||||
open_command_pane_floating(
|
open_command_pane_floating(CommandToRun {
|
||||||
std::path::PathBuf::from("/path/to/my/file.rs").as_path(),
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
vec!["arg1".to_owned(), "arg2".to_owned()],
|
args: vec!["arg1".to_owned(), "arg2".to_owned()],
|
||||||
);
|
..Default::default()
|
||||||
|
});
|
||||||
},
|
},
|
||||||
Key::Ctrl('o') => {
|
Key::Ctrl('o') => {
|
||||||
switch_tab_to(1);
|
switch_tab_to(1);
|
||||||
|
|
@ -225,7 +236,11 @@ impl ZellijPlugin for State {
|
||||||
},
|
},
|
||||||
Event::SystemClipboardFailure => {
|
Event::SystemClipboardFailure => {
|
||||||
// this is just to trigger the worker message
|
// this is just to trigger the worker message
|
||||||
post_message_to("test", "ping", "gimme_back_my_payload");
|
post_message_to(PluginMessage {
|
||||||
|
worker_name: Some("test".into()),
|
||||||
|
name: "ping".into(),
|
||||||
|
payload: "gimme_back_my_payload".into(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,16 @@ impl ZellijPlugin for State {
|
||||||
EventType::FileSystemUpdate,
|
EventType::FileSystemUpdate,
|
||||||
EventType::FileSystemDelete,
|
EventType::FileSystemDelete,
|
||||||
]);
|
]);
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_name_search",
|
worker_name: Some("file_name_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::ScanFolder).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::ScanFolder).unwrap(),
|
||||||
"",
|
payload: "".into(),
|
||||||
);
|
});
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_contents_search",
|
worker_name: Some("file_contents_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::ScanFolder).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::ScanFolder).unwrap(),
|
||||||
"",
|
payload: "".into(),
|
||||||
);
|
});
|
||||||
self.search_state.loading = true;
|
self.search_state.loading = true;
|
||||||
set_timeout(0.5); // for displaying loading animation
|
set_timeout(0.5); // for displaying loading animation
|
||||||
}
|
}
|
||||||
|
|
@ -191,48 +191,48 @@ impl ZellijPlugin for State {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.to_string_lossy().to_string())
|
.map(|p| p.to_string_lossy().to_string())
|
||||||
.collect();
|
.collect();
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_name_search",
|
worker_name: Some("file_name_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::FileSystemCreate).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::FileSystemCreate).unwrap(),
|
||||||
&serde_json::to_string(&paths).unwrap(),
|
payload: serde_json::to_string(&paths).unwrap(),
|
||||||
);
|
});
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_contents_search",
|
worker_name: Some("file_contents_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::FileSystemCreate).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::FileSystemCreate).unwrap(),
|
||||||
&serde_json::to_string(&paths).unwrap(),
|
payload: serde_json::to_string(&paths).unwrap(),
|
||||||
);
|
});
|
||||||
},
|
},
|
||||||
Event::FileSystemUpdate(paths) => {
|
Event::FileSystemUpdate(paths) => {
|
||||||
let paths: Vec<String> = paths
|
let paths: Vec<String> = paths
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.to_string_lossy().to_string())
|
.map(|p| p.to_string_lossy().to_string())
|
||||||
.collect();
|
.collect();
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_name_search",
|
worker_name: Some("file_name_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::FileSystemUpdate).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::FileSystemUpdate).unwrap(),
|
||||||
&serde_json::to_string(&paths).unwrap(),
|
payload: serde_json::to_string(&paths).unwrap(),
|
||||||
);
|
});
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_contents_search",
|
worker_name: Some("file_contents_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::FileSystemUpdate).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::FileSystemUpdate).unwrap(),
|
||||||
&serde_json::to_string(&paths).unwrap(),
|
payload: serde_json::to_string(&paths).unwrap(),
|
||||||
);
|
});
|
||||||
},
|
},
|
||||||
Event::FileSystemDelete(paths) => {
|
Event::FileSystemDelete(paths) => {
|
||||||
let paths: Vec<String> = paths
|
let paths: Vec<String> = paths
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.to_string_lossy().to_string())
|
.map(|p| p.to_string_lossy().to_string())
|
||||||
.collect();
|
.collect();
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_name_search",
|
worker_name: Some("file_name_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::FileSystemDelete).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::FileSystemDelete).unwrap(),
|
||||||
&serde_json::to_string(&paths).unwrap(),
|
payload: serde_json::to_string(&paths).unwrap(),
|
||||||
);
|
});
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_contents_search",
|
worker_name: Some("file_contents_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::FileSystemDelete).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::FileSystemDelete).unwrap(),
|
||||||
&serde_json::to_string(&paths).unwrap(),
|
payload: serde_json::to_string(&paths).unwrap(),
|
||||||
);
|
});
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
dbg!("Unknown event {:?}", event);
|
dbg!("Unknown event {:?}", event);
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,11 @@ impl Search {
|
||||||
match serde_json::from_str::<MessageToSearch>(&message) {
|
match serde_json::from_str::<MessageToSearch>(&message) {
|
||||||
Ok(MessageToSearch::ScanFolder) => {
|
Ok(MessageToSearch::ScanFolder) => {
|
||||||
self.scan_hd();
|
self.scan_hd();
|
||||||
post_message_to_plugin(
|
post_message_to_plugin(PluginMessage {
|
||||||
serde_json::to_string(&MessageToPlugin::DoneScanningFolder).unwrap(),
|
worker_name: None,
|
||||||
"".to_owned(),
|
name: serde_json::to_string(&MessageToPlugin::DoneScanningFolder).unwrap(),
|
||||||
);
|
payload: "".to_owned(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
Ok(MessageToSearch::Search) => {
|
Ok(MessageToSearch::Search) => {
|
||||||
if let Some(current_search_term) = self.read_search_term_from_hd_cache() {
|
if let Some(current_search_term) = self.read_search_term_from_hd_cache() {
|
||||||
|
|
@ -115,16 +116,19 @@ impl Search {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(file_names_search_results) = file_names_search_results {
|
if let Some(file_names_search_results) = file_names_search_results {
|
||||||
post_message_to_plugin(
|
post_message_to_plugin(PluginMessage {
|
||||||
serde_json::to_string(&MessageToPlugin::UpdateFileNameSearchResults).unwrap(),
|
name: serde_json::to_string(&MessageToPlugin::UpdateFileNameSearchResults).unwrap(),
|
||||||
serde_json::to_string(&file_names_search_results).unwrap(),
|
payload: serde_json::to_string(&file_names_search_results).unwrap(),
|
||||||
);
|
..Default::default()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if let Some(file_contents_search_results) = file_contents_search_results {
|
if let Some(file_contents_search_results) = file_contents_search_results {
|
||||||
post_message_to_plugin(
|
post_message_to_plugin(PluginMessage {
|
||||||
serde_json::to_string(&MessageToPlugin::UpdateFileContentsSearchResults).unwrap(),
|
name: serde_json::to_string(&MessageToPlugin::UpdateFileContentsSearchResults)
|
||||||
serde_json::to_string(&file_contents_search_results).unwrap(),
|
.unwrap(),
|
||||||
);
|
payload: serde_json::to_string(&file_contents_search_results).unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn rescan_files(&mut self, paths: String) {
|
pub fn rescan_files(&mut self, paths: String) {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use crate::search::{MessageToSearch, ResultsOfSearch};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use zellij_tile::prelude::{
|
use zellij_tile::prelude::{
|
||||||
hide_self, open_file, open_file_floating, open_file_with_line, open_file_with_line_floating,
|
hide_self, open_file, open_file_floating, open_terminal, open_terminal_floating,
|
||||||
open_terminal, open_terminal_floating, post_message_to, Key,
|
post_message_to, FileToOpen, Key, PluginMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CURRENT_SEARCH_TERM: &str = "/data/current_search_term";
|
pub const CURRENT_SEARCH_TERM: &str = "/data/current_search_term";
|
||||||
|
|
@ -88,18 +88,32 @@ impl SearchState {
|
||||||
match self.selected_search_result_entry() {
|
match self.selected_search_result_entry() {
|
||||||
Some(SearchResult::File { path, .. }) => {
|
Some(SearchResult::File { path, .. }) => {
|
||||||
if self.should_open_floating {
|
if self.should_open_floating {
|
||||||
open_file_floating(&PathBuf::from(path))
|
open_file_floating(FileToOpen {
|
||||||
|
path: PathBuf::from(path),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
open_file(&PathBuf::from(path));
|
open_file(FileToOpen {
|
||||||
|
path: PathBuf::from(path),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(SearchResult::LineInFile {
|
Some(SearchResult::LineInFile {
|
||||||
path, line_number, ..
|
path, line_number, ..
|
||||||
}) => {
|
}) => {
|
||||||
if self.should_open_floating {
|
if self.should_open_floating {
|
||||||
open_file_with_line_floating(&PathBuf::from(path), line_number);
|
open_file_floating(FileToOpen {
|
||||||
|
path: PathBuf::from(path),
|
||||||
|
line_number: Some(line_number),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
open_file_with_line(&PathBuf::from(path), line_number);
|
open_file(FileToOpen {
|
||||||
|
path: PathBuf::from(path),
|
||||||
|
line_number: Some(line_number),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => eprintln!("Search results not found"),
|
None => eprintln!("Search results not found"),
|
||||||
|
|
@ -153,16 +167,16 @@ impl SearchState {
|
||||||
match std::fs::write(CURRENT_SEARCH_TERM, &self.search_term) {
|
match std::fs::write(CURRENT_SEARCH_TERM, &self.search_term) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
if !self.search_term.is_empty() {
|
if !self.search_term.is_empty() {
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_name_search",
|
worker_name: Some("file_name_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::Search).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::Search).unwrap(),
|
||||||
"",
|
payload: "".into(),
|
||||||
);
|
});
|
||||||
post_message_to(
|
post_message_to(PluginMessage {
|
||||||
"file_contents_search",
|
worker_name: Some("file_contents_search".into()),
|
||||||
&serde_json::to_string(&MessageToSearch::Search).unwrap(),
|
name: serde_json::to_string(&MessageToSearch::Search).unwrap(),
|
||||||
"",
|
payload: "".into(),
|
||||||
);
|
});
|
||||||
self.file_name_search_results.clear();
|
self.file_name_search_results.clear();
|
||||||
self.file_contents_search_results.clear();
|
self.file_contents_search_results.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,10 @@ impl State {
|
||||||
self.path = p;
|
self.path = p;
|
||||||
refresh_directory(self);
|
refresh_directory(self);
|
||||||
},
|
},
|
||||||
FsEntry::File(p, _) => open_file(p.strip_prefix(ROOT).unwrap()),
|
FsEntry::File(p, _) => open_file(FileToOpen {
|
||||||
|
path: p.strip_prefix(ROOT).unwrap().into(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,28 @@
|
||||||
use crate::plugins::plugin_map::{PluginEnv, PluginMap, RunningPlugin, Subscriptions};
|
use crate::plugins::plugin_map::{PluginEnv, PluginMap, RunningPlugin, Subscriptions};
|
||||||
use crate::plugins::plugin_worker::{plugin_worker, RunningWorker};
|
use crate::plugins::plugin_worker::{plugin_worker, RunningWorker};
|
||||||
use crate::plugins::zellij_exports::{wasi_read_string, wasi_write_object, zellij_exports};
|
use crate::plugins::zellij_exports::{wasi_write_object, zellij_exports};
|
||||||
use crate::plugins::PluginId;
|
use crate::plugins::PluginId;
|
||||||
use highway::{HighwayHash, PortableHash};
|
use highway::{HighwayHash, PortableHash};
|
||||||
use log::info;
|
use log::info;
|
||||||
use semver::Version;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fmt, fs,
|
fs,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use wasmer::{ChainableNamedResolver, Instance, Module, Store};
|
use wasmer::{ChainableNamedResolver, Instance, Module, Store};
|
||||||
use wasmer_wasi::{Pipe, WasiState};
|
use wasmer_wasi::{Pipe, WasiState};
|
||||||
|
use zellij_utils::prost::Message;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
logging_pipe::LoggingPipe, screen::ScreenInstruction, thread_bus::ThreadSenders,
|
logging_pipe::LoggingPipe, screen::ScreenInstruction, thread_bus::ThreadSenders,
|
||||||
ui::loading_indication::LoadingIndication, ClientId,
|
ui::loading_indication::LoadingIndication, ClientId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use zellij_utils::plugin_api::action::ProtobufPluginConfiguration;
|
||||||
use zellij_utils::{
|
use zellij_utils::{
|
||||||
consts::{VERSION, ZELLIJ_CACHE_DIR, ZELLIJ_SESSION_CACHE_DIR, ZELLIJ_TMP_DIR},
|
consts::{ZELLIJ_CACHE_DIR, ZELLIJ_SESSION_CACHE_DIR, ZELLIJ_TMP_DIR},
|
||||||
data::PluginCapabilities,
|
data::PluginCapabilities,
|
||||||
errors::prelude::*,
|
errors::prelude::*,
|
||||||
input::command::TerminalAction,
|
input::command::TerminalAction,
|
||||||
|
|
@ -43,116 +44,6 @@ macro_rules! display_loading_stage {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Custom error for plugin version mismatch.
|
|
||||||
///
|
|
||||||
/// This is thrown when, during starting a plugin, it is detected that the plugin version doesn't
|
|
||||||
/// match the zellij version. This is treated as a fatal error and leads to instantaneous
|
|
||||||
/// termination.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct VersionMismatchError {
|
|
||||||
zellij_version: String,
|
|
||||||
plugin_version: String,
|
|
||||||
plugin_path: PathBuf,
|
|
||||||
// true for builtin plugins
|
|
||||||
builtin: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for VersionMismatchError {}
|
|
||||||
|
|
||||||
impl VersionMismatchError {
|
|
||||||
pub fn new(
|
|
||||||
zellij_version: &str,
|
|
||||||
plugin_version: &str,
|
|
||||||
plugin_path: &PathBuf,
|
|
||||||
builtin: bool,
|
|
||||||
) -> Self {
|
|
||||||
VersionMismatchError {
|
|
||||||
zellij_version: zellij_version.to_owned(),
|
|
||||||
plugin_version: plugin_version.to_owned(),
|
|
||||||
plugin_path: plugin_path.to_owned(),
|
|
||||||
builtin,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for VersionMismatchError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
let first_line = if self.builtin {
|
|
||||||
"It seems your version of zellij was built with outdated core plugins."
|
|
||||||
} else {
|
|
||||||
"If you're seeing this error a plugin version doesn't match the current
|
|
||||||
zellij version."
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}
|
|
||||||
Detected versions:
|
|
||||||
|
|
||||||
- Plugin version: {}
|
|
||||||
- Zellij version: {}
|
|
||||||
- Offending plugin: {}
|
|
||||||
|
|
||||||
If you're a user:
|
|
||||||
Please contact the distributor of your zellij version and report this error
|
|
||||||
to them.
|
|
||||||
|
|
||||||
If you're a developer:
|
|
||||||
Please run zellij with updated plugins. The easiest way to achieve this
|
|
||||||
is to build zellij with `cargo xtask install`. Also refer to the docs:
|
|
||||||
https://github.com/zellij-org/zellij/blob/main/CONTRIBUTING.md#building
|
|
||||||
",
|
|
||||||
first_line,
|
|
||||||
self.plugin_version.trim_end(),
|
|
||||||
self.zellij_version.trim_end(),
|
|
||||||
self.plugin_path.display()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns `Ok` if the plugin version matches the zellij version.
|
|
||||||
// Returns an `Err` otherwise.
|
|
||||||
fn assert_plugin_version(instance: &Instance, plugin_env: &PluginEnv) -> Result<()> {
|
|
||||||
let err_context = || {
|
|
||||||
format!(
|
|
||||||
"failed to determine plugin version for plugin {}",
|
|
||||||
plugin_env.plugin.path.display()
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let plugin_version_func = match instance.exports.get_function("plugin_version") {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(_) => {
|
|
||||||
return Err(anyError::new(VersionMismatchError::new(
|
|
||||||
VERSION,
|
|
||||||
"Unavailable",
|
|
||||||
&plugin_env.plugin.path,
|
|
||||||
plugin_env.plugin.is_builtin(),
|
|
||||||
)))
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let plugin_version = plugin_version_func
|
|
||||||
.call(&[])
|
|
||||||
.map_err(anyError::new)
|
|
||||||
.and_then(|_| wasi_read_string(&plugin_env.wasi_env))
|
|
||||||
.and_then(|string| Version::parse(&string).context("failed to parse plugin version"))
|
|
||||||
.with_context(err_context)?;
|
|
||||||
let zellij_version = Version::parse(VERSION)
|
|
||||||
.context("failed to parse zellij version")
|
|
||||||
.with_context(err_context)?;
|
|
||||||
if plugin_version != zellij_version {
|
|
||||||
return Err(anyError::new(VersionMismatchError::new(
|
|
||||||
VERSION,
|
|
||||||
&plugin_version.to_string(),
|
|
||||||
&plugin_env.plugin.path,
|
|
||||||
plugin_env.plugin.is_builtin(),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PluginLoader<'a> {
|
pub struct PluginLoader<'a> {
|
||||||
plugin_cache: Arc<Mutex<HashMap<PathBuf, Module>>>,
|
plugin_cache: Arc<Mutex<HashMap<PathBuf, Module>>>,
|
||||||
plugin_path: PathBuf,
|
plugin_path: PathBuf,
|
||||||
|
|
@ -645,10 +536,8 @@ impl<'a> PluginLoader<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
module: Module,
|
module: Module,
|
||||||
) -> Result<(Instance, PluginEnv, Arc<Mutex<Subscriptions>>)> {
|
) -> Result<(Instance, PluginEnv, Arc<Mutex<Subscriptions>>)> {
|
||||||
let err_context = || format!("Failed to create environment for plugin");
|
|
||||||
let (instance, plugin_env, subscriptions) =
|
let (instance, plugin_env, subscriptions) =
|
||||||
self.create_plugin_instance_env_and_subscriptions(&module)?;
|
self.create_plugin_instance_env_and_subscriptions(&module)?;
|
||||||
assert_plugin_version(&instance, &plugin_env).with_context(err_context)?;
|
|
||||||
// Only do an insert when everything went well!
|
// Only do an insert when everything went well!
|
||||||
let cloned_plugin = self.plugin.clone();
|
let cloned_plugin = self.plugin.clone();
|
||||||
self.plugin_cache
|
self.plugin_cache
|
||||||
|
|
@ -724,9 +613,17 @@ impl<'a> PluginLoader<'a> {
|
||||||
}
|
}
|
||||||
start_function.call(&[]).with_context(err_context)?;
|
start_function.call(&[]).with_context(err_context)?;
|
||||||
|
|
||||||
|
let protobuf_plugin_configuration: ProtobufPluginConfiguration = self
|
||||||
|
.plugin
|
||||||
|
.userspace_configuration
|
||||||
|
.clone()
|
||||||
|
.try_into()
|
||||||
|
.map_err(|e| anyhow!("Failed to serialize user configuration: {:?}", e))?;
|
||||||
|
let protobuf_bytes = protobuf_plugin_configuration.encode_to_vec();
|
||||||
wasi_write_object(
|
wasi_write_object(
|
||||||
&plugin_env.wasi_env,
|
&plugin_env.wasi_env,
|
||||||
&self.plugin.userspace_configuration.inner(),
|
&protobuf_bytes,
|
||||||
|
// &self.plugin.userspace_configuration.inner(),
|
||||||
)
|
)
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
load_function.call(&[]).with_context(err_context)?;
|
load_function.call(&[]).with_context(err_context)?;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::plugins::plugin_loader::VersionMismatchError;
|
|
||||||
use crate::plugins::plugin_map::PluginEnv;
|
use crate::plugins::plugin_map::PluginEnv;
|
||||||
use crate::plugins::zellij_exports::wasi_write_object;
|
use crate::plugins::zellij_exports::wasi_write_object;
|
||||||
use wasmer::Instance;
|
use wasmer::Instance;
|
||||||
|
|
@ -6,7 +5,9 @@ use wasmer::Instance;
|
||||||
use zellij_utils::async_channel::{unbounded, Receiver, Sender};
|
use zellij_utils::async_channel::{unbounded, Receiver, Sender};
|
||||||
use zellij_utils::async_std::task;
|
use zellij_utils::async_std::task;
|
||||||
use zellij_utils::errors::prelude::*;
|
use zellij_utils::errors::prelude::*;
|
||||||
use zellij_utils::{consts::VERSION, input::plugins::PluginConfig};
|
use zellij_utils::input::plugins::PluginConfig;
|
||||||
|
use zellij_utils::plugin_api::message::ProtobufMessage;
|
||||||
|
use zellij_utils::prost::Message;
|
||||||
|
|
||||||
pub struct RunningWorker {
|
pub struct RunningWorker {
|
||||||
pub instance: Instance,
|
pub instance: Instance,
|
||||||
|
|
@ -31,29 +32,19 @@ impl RunningWorker {
|
||||||
}
|
}
|
||||||
pub fn send_message(&self, message: String, payload: String) -> Result<()> {
|
pub fn send_message(&self, message: String, payload: String) -> Result<()> {
|
||||||
let err_context = || format!("Failed to send message to worker");
|
let err_context = || format!("Failed to send message to worker");
|
||||||
|
let protobuf_message = ProtobufMessage {
|
||||||
|
name: message,
|
||||||
|
payload,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let protobuf_bytes = protobuf_message.encode_to_vec();
|
||||||
let work_function = self
|
let work_function = self
|
||||||
.instance
|
.instance
|
||||||
.exports
|
.exports
|
||||||
.get_function(&self.name)
|
.get_function(&self.name)
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
wasi_write_object(&self.plugin_env.wasi_env, &(message, payload))
|
wasi_write_object(&self.plugin_env.wasi_env, &protobuf_bytes).with_context(err_context)?;
|
||||||
.with_context(err_context)?;
|
work_function.call(&[]).with_context(err_context)?;
|
||||||
work_function.call(&[]).or_else::<anyError, _>(|e| {
|
|
||||||
match e.downcast::<serde_json::Error>() {
|
|
||||||
Ok(_) => panic!(
|
|
||||||
"{}",
|
|
||||||
anyError::new(VersionMismatchError::new(
|
|
||||||
VERSION,
|
|
||||||
"Unavailable",
|
|
||||||
&self.plugin_config.path,
|
|
||||||
self.plugin_config.is_builtin(),
|
|
||||||
))
|
|
||||||
),
|
|
||||||
Err(e) => Err(e).with_context(err_context),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
assertion_line: 2334
|
assertion_line: 2709
|
||||||
expression: "format!(\"{:#?}\", new_tab_event)"
|
expression: "format!(\"{:#?}\", new_tab_event)"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
GoToTabName(
|
GoToTabName(
|
||||||
"my tab name\n\r",
|
"my tab name",
|
||||||
(
|
(
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
assertion_line: 4220
|
assertion_line: 4225
|
||||||
expression: "format!(\"{:#?}\", go_to_tab_event)"
|
expression: "format!(\"{:#?}\", go_to_tab_event)"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
GoToTabName(
|
GoToTabName(
|
||||||
"{\"fake_config_key_1\": \"fake_config_value_1\", \"fake_config_key_2\": \"fake_config_value_2\"}\n\r",
|
"{\"fake_config_key_1\": \"fake_config_value_1\", \"fake_config_key_2\": \"fake_config_value_2\"}",
|
||||||
(
|
(
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
assertion_line: 1171
|
assertion_line: 1449
|
||||||
expression: "format!(\"{:#?}\", new_tab_event)"
|
expression: "format!(\"{:#?}\", new_tab_event)"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -9,8 +9,6 @@ Some(
|
||||||
102,
|
102,
|
||||||
111,
|
111,
|
||||||
111,
|
111,
|
||||||
10,
|
|
||||||
13,
|
|
||||||
],
|
],
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{PluginId, PluginInstruction};
|
use super::{PluginId, PluginInstruction};
|
||||||
use crate::plugins::plugin_loader::{PluginLoader, VersionMismatchError};
|
use crate::plugins::plugin_loader::PluginLoader;
|
||||||
use crate::plugins::plugin_map::{AtomicEvent, PluginEnv, PluginMap, RunningPlugin, Subscriptions};
|
use crate::plugins::plugin_map::{AtomicEvent, PluginEnv, PluginMap, RunningPlugin, Subscriptions};
|
||||||
use crate::plugins::plugin_worker::MessageToWorker;
|
use crate::plugins::plugin_worker::MessageToWorker;
|
||||||
use crate::plugins::watch_filesystem::watch_filesystem;
|
use crate::plugins::watch_filesystem::watch_filesystem;
|
||||||
|
|
@ -14,13 +14,15 @@ use std::{
|
||||||
use wasmer::{Instance, Module, Store, Value};
|
use wasmer::{Instance, Module, Store, Value};
|
||||||
use zellij_utils::async_std::task::{self, JoinHandle};
|
use zellij_utils::async_std::task::{self, JoinHandle};
|
||||||
use zellij_utils::notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap};
|
use zellij_utils::notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap};
|
||||||
|
use zellij_utils::plugin_api::event::ProtobufEvent;
|
||||||
|
|
||||||
|
use zellij_utils::prost::Message;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
background_jobs::BackgroundJob, screen::ScreenInstruction, thread_bus::ThreadSenders,
|
background_jobs::BackgroundJob, screen::ScreenInstruction, thread_bus::ThreadSenders,
|
||||||
ui::loading_indication::LoadingIndication, ClientId,
|
ui::loading_indication::LoadingIndication, ClientId,
|
||||||
};
|
};
|
||||||
use zellij_utils::{
|
use zellij_utils::{
|
||||||
consts::VERSION,
|
|
||||||
data::{Event, EventType, PluginCapabilities},
|
data::{Event, EventType, PluginCapabilities},
|
||||||
errors::prelude::*,
|
errors::prelude::*,
|
||||||
input::{
|
input::{
|
||||||
|
|
@ -737,26 +739,17 @@ pub fn apply_event_to_plugin(
|
||||||
plugin_bytes: &mut Vec<(PluginId, ClientId, Vec<u8>)>,
|
plugin_bytes: &mut Vec<(PluginId, ClientId, Vec<u8>)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let err_context = || format!("Failed to apply event to plugin {plugin_id}");
|
let err_context = || format!("Failed to apply event to plugin {plugin_id}");
|
||||||
|
let protobuf_event: ProtobufEvent = event
|
||||||
|
.clone()
|
||||||
|
.try_into()
|
||||||
|
.map_err(|e| anyhow!("Failed to convert to protobuf: {:?}", e))?;
|
||||||
let update = instance
|
let update = instance
|
||||||
.exports
|
.exports
|
||||||
.get_function("update")
|
.get_function("update")
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
wasi_write_object(&plugin_env.wasi_env, &event).with_context(err_context)?;
|
wasi_write_object(&plugin_env.wasi_env, &protobuf_event.encode_to_vec())
|
||||||
let update_return =
|
.with_context(err_context)?;
|
||||||
update
|
let update_return = update.call(&[]).with_context(err_context)?;
|
||||||
.call(&[])
|
|
||||||
.or_else::<anyError, _>(|e| match e.downcast::<serde_json::Error>() {
|
|
||||||
Ok(_) => panic!(
|
|
||||||
"{}",
|
|
||||||
anyError::new(VersionMismatchError::new(
|
|
||||||
VERSION,
|
|
||||||
"Unavailable",
|
|
||||||
&plugin_env.plugin.path,
|
|
||||||
plugin_env.plugin.is_builtin(),
|
|
||||||
))
|
|
||||||
),
|
|
||||||
Err(e) => Err(e).with_context(err_context),
|
|
||||||
})?;
|
|
||||||
let should_render = match update_return.get(0) {
|
let should_render = match update_return.get(0) {
|
||||||
Some(Value::I32(n)) => *n == 1,
|
Some(Value::I32(n)) => *n == 1,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -22,6 +22,8 @@ use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use zellij_utils::data::Event;
|
use zellij_utils::data::Event;
|
||||||
|
|
||||||
|
// use zellij_tile::shim::plugin_api::event::ProtobufEvent;
|
||||||
|
|
||||||
/// This trait should be implemented - once per plugin - on a struct (normally representing the
|
/// This trait should be implemented - once per plugin - on a struct (normally representing the
|
||||||
/// plugin state). This struct should then be registered with the
|
/// plugin state). This struct should then be registered with the
|
||||||
/// [`register_plugin!`](register_plugin) macro.
|
/// [`register_plugin!`](register_plugin) macro.
|
||||||
|
|
@ -104,22 +106,31 @@ macro_rules! register_plugin {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn load() {
|
fn load() {
|
||||||
STATE.with(|state| {
|
STATE.with(|state| {
|
||||||
let configuration = $crate::shim::object_from_stdin()
|
use std::collections::BTreeMap;
|
||||||
.context($crate::PLUGIN_MISMATCH)
|
use std::convert::TryInto;
|
||||||
.to_stdout()
|
use zellij_tile::shim::plugin_api::action::ProtobufPluginConfiguration;
|
||||||
.unwrap();
|
use zellij_tile::shim::prost::Message;
|
||||||
state.borrow_mut().load(configuration);
|
let protobuf_bytes: Vec<u8> = $crate::shim::object_from_stdin().unwrap();
|
||||||
|
let protobuf_configuration: ProtobufPluginConfiguration =
|
||||||
|
ProtobufPluginConfiguration::decode(protobuf_bytes.as_slice()).unwrap();
|
||||||
|
let plugin_configuration: BTreeMap<String, String> =
|
||||||
|
BTreeMap::try_from(&protobuf_configuration).unwrap();
|
||||||
|
state.borrow_mut().load(plugin_configuration);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn update() -> bool {
|
pub fn update() -> bool {
|
||||||
|
let err_context = "Failed to deserialize event";
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use zellij_tile::shim::plugin_api::event::ProtobufEvent;
|
||||||
|
use zellij_tile::shim::prost::Message;
|
||||||
STATE.with(|state| {
|
STATE.with(|state| {
|
||||||
let object = $crate::shim::object_from_stdin()
|
let protobuf_bytes: Vec<u8> = $crate::shim::object_from_stdin().unwrap();
|
||||||
.context($crate::PLUGIN_MISMATCH)
|
let protobuf_event: ProtobufEvent =
|
||||||
.to_stdout()
|
ProtobufEvent::decode(protobuf_bytes.as_slice()).unwrap();
|
||||||
.unwrap();
|
let event = protobuf_event.try_into().unwrap();
|
||||||
state.borrow_mut().update(object)
|
state.borrow_mut().update(event)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,18 +179,15 @@ macro_rules! register_worker {
|
||||||
}
|
}
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn $worker_name() {
|
pub fn $worker_name() {
|
||||||
|
use zellij_tile::shim::plugin_api::message::ProtobufMessage;
|
||||||
|
use zellij_tile::shim::prost::Message;
|
||||||
let worker_display_name = std::stringify!($worker_name);
|
let worker_display_name = std::stringify!($worker_name);
|
||||||
|
let protobuf_bytes: Vec<u8> = $crate::shim::object_from_stdin()
|
||||||
// read message from STDIN
|
.unwrap();
|
||||||
let (message, payload): (String, String) = $crate::shim::object_from_stdin()
|
let protobuf_message: ProtobufMessage = ProtobufMessage::decode(protobuf_bytes.as_slice())
|
||||||
.unwrap_or_else(|e| {
|
.unwrap();
|
||||||
eprintln!(
|
let message = protobuf_message.name;
|
||||||
"Failed to deserialize message to worker \"{}\": {:?}",
|
let payload = protobuf_message.payload;
|
||||||
worker_display_name, e
|
|
||||||
);
|
|
||||||
Default::default()
|
|
||||||
});
|
|
||||||
$worker_static_name.with(|worker_instance| {
|
$worker_static_name.with(|worker_instance| {
|
||||||
let mut worker_instance = worker_instance.borrow_mut();
|
let mut worker_instance = worker_instance.borrow_mut();
|
||||||
worker_instance.on_message(message, payload);
|
worker_instance.on_message(message, payload);
|
||||||
|
|
|
||||||
|
|
@ -1,375 +1,559 @@
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::{io, path::Path};
|
use std::{io, path::Path};
|
||||||
use zellij_utils::data::*;
|
use zellij_utils::data::*;
|
||||||
use zellij_utils::errors::prelude::*;
|
use zellij_utils::errors::prelude::*;
|
||||||
|
pub use zellij_utils::plugin_api;
|
||||||
|
use zellij_utils::plugin_api::plugin_command::ProtobufPluginCommand;
|
||||||
|
use zellij_utils::plugin_api::plugin_ids::{ProtobufPluginIds, ProtobufZellijVersion};
|
||||||
|
|
||||||
|
pub use zellij_utils::prost::{self, *};
|
||||||
|
|
||||||
// Subscription Handling
|
// Subscription Handling
|
||||||
|
|
||||||
/// Subscribe to a list of [`Event`]s represented by their [`EventType`]s that will then trigger the `update` method
|
/// Subscribe to a list of [`Event`]s represented by their [`EventType`]s that will then trigger the `update` method
|
||||||
pub fn subscribe(event_types: &[EventType]) {
|
pub fn subscribe(event_types: &[EventType]) {
|
||||||
object_to_stdout(&event_types);
|
let event_types: HashSet<EventType> = event_types.iter().cloned().collect();
|
||||||
unsafe { host_subscribe() };
|
let plugin_command = PluginCommand::Subscribe(event_types);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsubscribe to a list of [`Event`]s represented by their [`EventType`]s.
|
/// Unsubscribe to a list of [`Event`]s represented by their [`EventType`]s.
|
||||||
pub fn unsubscribe(event_types: &[EventType]) {
|
pub fn unsubscribe(event_types: &[EventType]) {
|
||||||
object_to_stdout(&event_types);
|
let event_types: HashSet<EventType> = event_types.iter().cloned().collect();
|
||||||
unsafe { host_unsubscribe() };
|
let plugin_command = PluginCommand::Unsubscribe(event_types);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin Settings
|
// Plugin Settings
|
||||||
|
|
||||||
/// Sets the plugin as selectable or unselectable to the user. Unselectable plugins might be desired when they do not accept user input.
|
/// Sets the plugin as selectable or unselectable to the user. Unselectable plugins might be desired when they do not accept user input.
|
||||||
pub fn set_selectable(selectable: bool) {
|
pub fn set_selectable(selectable: bool) {
|
||||||
unsafe { host_set_selectable(selectable as i32) };
|
let plugin_command = PluginCommand::SetSelectable(selectable);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query Functions
|
// Query Functions
|
||||||
/// Returns the unique Zellij pane ID for the plugin as well as the Zellij process id.
|
/// Returns the unique Zellij pane ID for the plugin as well as the Zellij process id.
|
||||||
pub fn get_plugin_ids() -> PluginIds {
|
pub fn get_plugin_ids() -> PluginIds {
|
||||||
unsafe { host_get_plugin_ids() };
|
let plugin_command = PluginCommand::GetPluginIds;
|
||||||
object_from_stdin().unwrap()
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
|
let protobuf_plugin_ids =
|
||||||
|
ProtobufPluginIds::decode(bytes_from_stdin().unwrap().as_slice()).unwrap();
|
||||||
|
PluginIds::try_from(protobuf_plugin_ids).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the version of the running Zellij instance - can be useful to check plugin compatibility
|
/// Returns the version of the running Zellij instance - can be useful to check plugin compatibility
|
||||||
pub fn get_zellij_version() -> String {
|
pub fn get_zellij_version() -> String {
|
||||||
unsafe { host_get_zellij_version() };
|
let plugin_command = PluginCommand::GetZellijVersion;
|
||||||
object_from_stdin().unwrap()
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
|
let protobuf_zellij_version =
|
||||||
|
ProtobufZellijVersion::decode(bytes_from_stdin().unwrap().as_slice()).unwrap();
|
||||||
|
protobuf_zellij_version.version
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host Functions
|
// Host Functions
|
||||||
|
|
||||||
/// Open a file in the user's default `$EDITOR` in a new pane
|
/// Open a file in the user's default `$EDITOR` in a new pane
|
||||||
pub fn open_file<P: AsRef<Path>>(path: P) {
|
pub fn open_file(file_to_open: FileToOpen) {
|
||||||
object_to_stdout(&path.as_ref());
|
let plugin_command = PluginCommand::OpenFile(file_to_open);
|
||||||
unsafe { host_open_file() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a file in the user's default `$EDITOR` in a new floating pane
|
/// Open a file in the user's default `$EDITOR` in a new floating pane
|
||||||
pub fn open_file_floating<P: AsRef<Path>>(path: P) {
|
pub fn open_file_floating(file_to_open: FileToOpen) {
|
||||||
object_to_stdout(&path.as_ref());
|
let plugin_command = PluginCommand::OpenFileFloating(file_to_open);
|
||||||
unsafe { host_open_file_floating() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
}
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
/// Open a file to a specific line in the user's default `$EDITOR` (if it supports it, most do) in a new pane
|
|
||||||
pub fn open_file_with_line<P: AsRef<Path>>(path: P, line: usize) {
|
|
||||||
object_to_stdout(&(path.as_ref(), line));
|
|
||||||
unsafe { host_open_file_with_line() };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Open a file to a specific line in the user's default `$EDITOR` (if it supports it, most do) in a new floating pane
|
|
||||||
pub fn open_file_with_line_floating<P: AsRef<Path>>(path: P, line: usize) {
|
|
||||||
object_to_stdout(&(path.as_ref(), line));
|
|
||||||
unsafe { host_open_file_with_line_floating() };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a new terminal pane to the specified location on the host filesystem
|
/// Open a new terminal pane to the specified location on the host filesystem
|
||||||
pub fn open_terminal<P: AsRef<Path>>(path: P) {
|
pub fn open_terminal<P: AsRef<Path>>(path: P) {
|
||||||
object_to_stdout(&path.as_ref());
|
let file_to_open = FileToOpen::new(path.as_ref().to_path_buf());
|
||||||
unsafe { host_open_terminal() };
|
let plugin_command = PluginCommand::OpenTerminal(file_to_open);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a new floating terminal pane to the specified location on the host filesystem
|
/// Open a new floating terminal pane to the specified location on the host filesystem
|
||||||
pub fn open_terminal_floating<P: AsRef<Path>>(path: P) {
|
pub fn open_terminal_floating<P: AsRef<Path>>(path: P) {
|
||||||
object_to_stdout(&path.as_ref());
|
let file_to_open = FileToOpen::new(path.as_ref().to_path_buf());
|
||||||
unsafe { host_open_terminal_floating() };
|
let plugin_command = PluginCommand::OpenTerminalFloating(file_to_open);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a new command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI).
|
/// Open a new command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI).
|
||||||
pub fn open_command_pane<P: AsRef<Path>, A: AsRef<str>>(path: P, args: Vec<A>) {
|
// pub fn open_command_pane<P: AsRef<Path>, A: AsRef<str>>(path: P, args: Vec<A>) {
|
||||||
object_to_stdout(&(
|
pub fn open_command_pane(command_to_run: CommandToRun) {
|
||||||
path.as_ref(),
|
let plugin_command = PluginCommand::OpenCommandPane(command_to_run);
|
||||||
args.iter().map(|a| a.as_ref()).collect::<Vec<&str>>(),
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
));
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
unsafe { host_open_command_pane() };
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a new floating command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI).
|
/// Open a new floating command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI).
|
||||||
pub fn open_command_pane_floating<P: AsRef<Path>, A: AsRef<str>>(path: P, args: Vec<A>) {
|
// pub fn open_command_pane_floating<P: AsRef<Path>, A: AsRef<str>>(path: P, args: Vec<A>) {
|
||||||
object_to_stdout(&(
|
pub fn open_command_pane_floating(command_to_run: CommandToRun) {
|
||||||
path.as_ref(),
|
let plugin_command = PluginCommand::OpenCommandPaneFloating(command_to_run);
|
||||||
args.iter().map(|a| a.as_ref()).collect::<Vec<&str>>(),
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
));
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
unsafe { host_open_command_pane_floating() };
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the focused tab to the specified index (corresponding with the default tab names, to starting at `1`, `0` will be considered as `1`).
|
/// Change the focused tab to the specified index (corresponding with the default tab names, to starting at `1`, `0` will be considered as `1`).
|
||||||
pub fn switch_tab_to(tab_idx: u32) {
|
pub fn switch_tab_to(tab_idx: u32) {
|
||||||
unsafe { host_switch_tab_to(tab_idx) };
|
let plugin_command = PluginCommand::SwitchTabTo(tab_idx);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a timeout in seconds (or fractions thereof) after which the plugins [update](./plugin-api-events#update) method will be called with the [`Timer`](./plugin-api-events.md#timer) event.
|
/// Set a timeout in seconds (or fractions thereof) after which the plugins [update](./plugin-api-events#update) method will be called with the [`Timer`](./plugin-api-events.md#timer) event.
|
||||||
pub fn set_timeout(secs: f64) {
|
pub fn set_timeout(secs: f64) {
|
||||||
unsafe { host_set_timeout(secs) };
|
let plugin_command = PluginCommand::SetTimeout(secs as f32);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn exec_cmd(cmd: &[&str]) {
|
pub fn exec_cmd(cmd: &[&str]) {
|
||||||
object_to_stdout(&cmd);
|
let plugin_command =
|
||||||
unsafe { host_exec_cmd() };
|
PluginCommand::ExecCmd(cmd.iter().cloned().map(|s| s.to_owned()).collect());
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hide the plugin pane (suppress it) from the UI
|
/// Hide the plugin pane (suppress it) from the UI
|
||||||
pub fn hide_self() {
|
pub fn hide_self() {
|
||||||
unsafe { host_hide_self() };
|
let plugin_command = PluginCommand::HideSelf;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show the plugin pane (unsuppress it if it is suppressed), focus it and switch to its tab
|
/// Show the plugin pane (unsuppress it if it is suppressed), focus it and switch to its tab
|
||||||
pub fn show_self(should_float_if_hidden: bool) {
|
pub fn show_self(should_float_if_hidden: bool) {
|
||||||
unsafe { host_show_self(should_float_if_hidden as i32) };
|
let plugin_command = PluginCommand::ShowSelf(should_float_if_hidden);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch to the specified Input Mode (eg. `Normal`, `Tab`, `Pane`)
|
/// Switch to the specified Input Mode (eg. `Normal`, `Tab`, `Pane`)
|
||||||
pub fn switch_to_input_mode(mode: &InputMode) {
|
pub fn switch_to_input_mode(mode: &InputMode) {
|
||||||
object_to_stdout(&mode);
|
let plugin_command = PluginCommand::SwitchToMode(*mode);
|
||||||
unsafe { host_switch_to_mode() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provide a stringified [`layout`](https://zellij.dev/documentation/layouts.html) to be applied to the current session. If the layout has multiple tabs, they will all be opened.
|
/// Provide a stringified [`layout`](https://zellij.dev/documentation/layouts.html) to be applied to the current session. If the layout has multiple tabs, they will all be opened.
|
||||||
pub fn new_tabs_with_layout(layout: &str) {
|
pub fn new_tabs_with_layout(layout: &str) {
|
||||||
println!("{}", layout);
|
let plugin_command = PluginCommand::NewTabsWithLayout(layout.to_owned());
|
||||||
unsafe { host_new_tabs_with_layout() }
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a new tab with the default layout
|
/// Open a new tab with the default layout
|
||||||
pub fn new_tab() {
|
pub fn new_tab() {
|
||||||
unsafe { host_new_tab() }
|
let plugin_command = PluginCommand::NewTab;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change focus to the next tab or loop back to the first
|
/// Change focus to the next tab or loop back to the first
|
||||||
pub fn go_to_next_tab() {
|
pub fn go_to_next_tab() {
|
||||||
unsafe { host_go_to_next_tab() }
|
let plugin_command = PluginCommand::GoToNextTab;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change focus to the previous tab or loop back to the last
|
/// Change focus to the previous tab or loop back to the last
|
||||||
pub fn go_to_previous_tab() {
|
pub fn go_to_previous_tab() {
|
||||||
unsafe { host_go_to_previous_tab() }
|
let plugin_command = PluginCommand::GoToPreviousTab;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_panic(info: &std::panic::PanicInfo) {
|
pub fn report_panic(info: &std::panic::PanicInfo) {
|
||||||
println!("");
|
let panic_payload = if let Some(s) = info.payload().downcast_ref::<&str>() {
|
||||||
println!("A panic occured in a plugin");
|
format!("{}", s)
|
||||||
println!("{:#?}", info);
|
} else {
|
||||||
unsafe { host_report_panic() };
|
format!("<NO PAYLOAD>")
|
||||||
|
};
|
||||||
|
let panic_stringified = format!("{}\n\r{:#?}", panic_payload, info).replace("\n", "\r\n");
|
||||||
|
let plugin_command = PluginCommand::ReportPanic(panic_stringified);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either Increase or Decrease the size of the focused pane
|
/// Either Increase or Decrease the size of the focused pane
|
||||||
pub fn resize_focused_pane(resize: Resize) {
|
pub fn resize_focused_pane(resize: Resize) {
|
||||||
object_to_stdout(&resize);
|
let plugin_command = PluginCommand::Resize(resize);
|
||||||
unsafe { host_resize() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either Increase or Decrease the size of the focused pane in a specified direction (eg. `Left`, `Right`, `Up`, `Down`).
|
/// Either Increase or Decrease the size of the focused pane in a specified direction (eg. `Left`, `Right`, `Up`, `Down`).
|
||||||
pub fn resize_focused_pane_with_direction(resize: Resize, direction: Direction) {
|
pub fn resize_focused_pane_with_direction(resize: Resize, direction: Direction) {
|
||||||
object_to_stdout(&(resize, direction));
|
let resize_strategy = ResizeStrategy {
|
||||||
unsafe { host_resize_with_direction() };
|
resize,
|
||||||
|
direction: Some(direction),
|
||||||
|
invert_on_boundaries: false,
|
||||||
|
};
|
||||||
|
let plugin_command = PluginCommand::ResizeWithDirection(resize_strategy);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change focus tot he next pane in chronological order
|
/// Change focus tot he next pane in chronological order
|
||||||
pub fn focus_next_pane() {
|
pub fn focus_next_pane() {
|
||||||
unsafe { host_focus_next_pane() };
|
let plugin_command = PluginCommand::FocusNextPane;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change focus to the previous pane in chronological order
|
/// Change focus to the previous pane in chronological order
|
||||||
pub fn focus_previous_pane() {
|
pub fn focus_previous_pane() {
|
||||||
unsafe { host_focus_previous_pane() };
|
let plugin_command = PluginCommand::FocusPreviousPane;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the focused pane in the specified direction
|
/// Change the focused pane in the specified direction
|
||||||
pub fn move_focus(direction: Direction) {
|
pub fn move_focus(direction: Direction) {
|
||||||
object_to_stdout(&direction);
|
let plugin_command = PluginCommand::MoveFocus(direction);
|
||||||
unsafe { host_move_focus() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the focused pane in the specified direction, if the pane is on the edge of the screen, the next tab is focused (next if right edge, previous if left edge).
|
/// Change the focused pane in the specified direction, if the pane is on the edge of the screen, the next tab is focused (next if right edge, previous if left edge).
|
||||||
pub fn move_focus_or_tab(direction: Direction) {
|
pub fn move_focus_or_tab(direction: Direction) {
|
||||||
object_to_stdout(&direction);
|
let plugin_command = PluginCommand::MoveFocusOrTab(direction);
|
||||||
unsafe { host_move_focus_or_tab() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Detach the user from the active session
|
/// Detach the user from the active session
|
||||||
pub fn detach() {
|
pub fn detach() {
|
||||||
unsafe { host_detach() };
|
let plugin_command = PluginCommand::Detach;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Edit the scrollback of the focused pane in the user's default `$EDITOR`
|
/// Edit the scrollback of the focused pane in the user's default `$EDITOR`
|
||||||
pub fn edit_scrollback() {
|
pub fn edit_scrollback() {
|
||||||
unsafe { host_edit_scrollback() };
|
let plugin_command = PluginCommand::EditScrollback;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write bytes to the `STDIN` of the focused pane
|
/// Write bytes to the `STDIN` of the focused pane
|
||||||
pub fn write(bytes: Vec<u8>) {
|
pub fn write(bytes: Vec<u8>) {
|
||||||
object_to_stdout(&bytes);
|
let plugin_command = PluginCommand::Write(bytes);
|
||||||
unsafe { host_write() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write characters to the `STDIN` of the focused pane
|
/// Write characters to the `STDIN` of the focused pane
|
||||||
pub fn write_chars(chars: &str) {
|
pub fn write_chars(chars: &str) {
|
||||||
println!("{}", chars);
|
let plugin_command = PluginCommand::WriteChars(chars.to_owned());
|
||||||
unsafe { host_write_chars() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Focused the previously focused tab (regardless of the tab position)
|
/// Focused the previously focused tab (regardless of the tab position)
|
||||||
pub fn toggle_tab() {
|
pub fn toggle_tab() {
|
||||||
unsafe { host_toggle_tab() };
|
let plugin_command = PluginCommand::ToggleTab;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch the position of the focused pane with a different pane
|
/// Switch the position of the focused pane with a different pane
|
||||||
pub fn move_pane() {
|
pub fn move_pane() {
|
||||||
unsafe { host_move_pane() };
|
let plugin_command = PluginCommand::MovePane;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch the position of the focused pane with a different pane in the specified direction (eg. `Down`, `Up`, `Left`, `Right`).
|
/// Switch the position of the focused pane with a different pane in the specified direction (eg. `Down`, `Up`, `Left`, `Right`).
|
||||||
pub fn move_pane_with_direction(direction: Direction) {
|
pub fn move_pane_with_direction(direction: Direction) {
|
||||||
object_to_stdout(&direction);
|
let plugin_command = PluginCommand::MovePaneWithDirection(direction);
|
||||||
unsafe { host_move_pane_with_direction() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the scroll buffer of the focused pane
|
/// Clear the scroll buffer of the focused pane
|
||||||
pub fn clear_screen() {
|
pub fn clear_screen() {
|
||||||
unsafe { host_clear_screen() };
|
let plugin_command = PluginCommand::ClearScreen;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the focused pane up 1 line
|
/// Scroll the focused pane up 1 line
|
||||||
pub fn scroll_up() {
|
pub fn scroll_up() {
|
||||||
unsafe { host_scroll_up() };
|
let plugin_command = PluginCommand::ScrollUp;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the focused pane down 1 line
|
/// Scroll the focused pane down 1 line
|
||||||
pub fn scroll_down() {
|
pub fn scroll_down() {
|
||||||
unsafe { host_scroll_down() };
|
let plugin_command = PluginCommand::ScrollDown;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the focused pane all the way to the top of the scrollbuffer
|
/// Scroll the focused pane all the way to the top of the scrollbuffer
|
||||||
pub fn scroll_to_top() {
|
pub fn scroll_to_top() {
|
||||||
unsafe { host_scroll_to_top() };
|
let plugin_command = PluginCommand::ScrollToTop;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the focused pane all the way to the bottom of the scrollbuffer
|
/// Scroll the focused pane all the way to the bottom of the scrollbuffer
|
||||||
pub fn scroll_to_bottom() {
|
pub fn scroll_to_bottom() {
|
||||||
unsafe { host_scroll_to_bottom() };
|
let plugin_command = PluginCommand::ScrollToBottom;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the focused pane up one page
|
/// Scroll the focused pane up one page
|
||||||
pub fn page_scroll_up() {
|
pub fn page_scroll_up() {
|
||||||
unsafe { host_page_scroll_up() };
|
let plugin_command = PluginCommand::PageScrollUp;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the focused pane down one page
|
/// Scroll the focused pane down one page
|
||||||
pub fn page_scroll_down() {
|
pub fn page_scroll_down() {
|
||||||
unsafe { host_page_scroll_down() };
|
let plugin_command = PluginCommand::PageScrollDown;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toggle the focused pane to be fullscreen or normal sized
|
/// Toggle the focused pane to be fullscreen or normal sized
|
||||||
pub fn toggle_focus_fullscreen() {
|
pub fn toggle_focus_fullscreen() {
|
||||||
unsafe { host_toggle_focus_fullscreen() };
|
let plugin_command = PluginCommand::ToggleFocusFullscreen;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toggle the UI pane frames on or off
|
/// Toggle the UI pane frames on or off
|
||||||
pub fn toggle_pane_frames() {
|
pub fn toggle_pane_frames() {
|
||||||
unsafe { host_toggle_pane_frames() };
|
let plugin_command = PluginCommand::TogglePaneFrames;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Embed the currently focused pane (make it stop floating) or turn it to a float pane if it is not
|
/// Embed the currently focused pane (make it stop floating) or turn it to a float pane if it is not
|
||||||
pub fn toggle_pane_embed_or_eject() {
|
pub fn toggle_pane_embed_or_eject() {
|
||||||
unsafe { host_toggle_pane_embed_or_eject() };
|
let plugin_command = PluginCommand::TogglePaneEmbedOrEject;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn undo_rename_pane() {
|
pub fn undo_rename_pane() {
|
||||||
unsafe { host_undo_rename_pane() };
|
let plugin_command = PluginCommand::UndoRenamePane;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close the focused pane
|
/// Close the focused pane
|
||||||
pub fn close_focus() {
|
pub fn close_focus() {
|
||||||
unsafe { host_close_focus() };
|
let plugin_command = PluginCommand::CloseFocus;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turn the `STDIN` synchronization of the current tab on or off
|
/// Turn the `STDIN` synchronization of the current tab on or off
|
||||||
pub fn toggle_active_tab_sync() {
|
pub fn toggle_active_tab_sync() {
|
||||||
unsafe { host_toggle_active_tab_sync() };
|
let plugin_command = PluginCommand::ToggleActiveTabSync;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close the focused tab
|
/// Close the focused tab
|
||||||
pub fn close_focused_tab() {
|
pub fn close_focused_tab() {
|
||||||
unsafe { host_close_focused_tab() };
|
let plugin_command = PluginCommand::CloseFocusedTab;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn undo_rename_tab() {
|
pub fn undo_rename_tab() {
|
||||||
unsafe { host_undo_rename_tab() };
|
let plugin_command = PluginCommand::UndoRenameTab;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compeltely quit Zellij for this and all other connected clients
|
/// Compeltely quit Zellij for this and all other connected clients
|
||||||
pub fn quit_zellij() {
|
pub fn quit_zellij() {
|
||||||
unsafe { host_quit_zellij() };
|
let plugin_command = PluginCommand::QuitZellij;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change to the previous [swap layout](https://zellij.dev/documentation/swap-layouts.html)
|
/// Change to the previous [swap layout](https://zellij.dev/documentation/swap-layouts.html)
|
||||||
pub fn previous_swap_layout() {
|
pub fn previous_swap_layout() {
|
||||||
unsafe { host_previous_swap_layout() };
|
let plugin_command = PluginCommand::PreviousSwapLayout;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change to the next [swap layout](https://zellij.dev/documentation/swap-layouts.html)
|
/// Change to the next [swap layout](https://zellij.dev/documentation/swap-layouts.html)
|
||||||
pub fn next_swap_layout() {
|
pub fn next_swap_layout() {
|
||||||
unsafe { host_next_swap_layout() };
|
let plugin_command = PluginCommand::NextSwapLayout;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change focus to the tab with the specified name
|
/// Change focus to the tab with the specified name
|
||||||
pub fn go_to_tab_name(tab_name: &str) {
|
pub fn go_to_tab_name(tab_name: &str) {
|
||||||
println!("{}", tab_name);
|
let plugin_command = PluginCommand::GoToTabName(tab_name.to_owned());
|
||||||
unsafe { host_go_to_tab_name() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change focus to the tab with the specified name or create it if it does not exist
|
/// Change focus to the tab with the specified name or create it if it does not exist
|
||||||
pub fn focus_or_create_tab(tab_name: &str) {
|
pub fn focus_or_create_tab(tab_name: &str) {
|
||||||
print!("{}", tab_name);
|
let plugin_command = PluginCommand::FocusOrCreateTab(tab_name.to_owned());
|
||||||
unsafe { host_focus_or_create_tab() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn go_to_tab(tab_index: i32) {
|
pub fn go_to_tab(tab_index: u32) {
|
||||||
unsafe { host_go_to_tab(tab_index) };
|
let plugin_command = PluginCommand::GoToTab(tab_index);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_or_reload_plugin(url: &str) {
|
pub fn start_or_reload_plugin(url: &str) {
|
||||||
println!("{}", url);
|
let plugin_command = PluginCommand::StartOrReloadPlugin(url.to_owned());
|
||||||
unsafe { host_start_or_reload_plugin() };
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closes a terminal pane with the specified id
|
/// Closes a terminal pane with the specified id
|
||||||
pub fn close_terminal_pane(terminal_pane_id: i32) {
|
pub fn close_terminal_pane(terminal_pane_id: u32) {
|
||||||
unsafe { host_close_terminal_pane(terminal_pane_id) };
|
let plugin_command = PluginCommand::CloseTerminalPane(terminal_pane_id);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closes a plugin pane with the specified id
|
/// Closes a plugin pane with the specified id
|
||||||
pub fn close_plugin_pane(plugin_pane_id: i32) {
|
pub fn close_plugin_pane(plugin_pane_id: u32) {
|
||||||
unsafe { host_close_plugin_pane(plugin_pane_id) };
|
let plugin_command = PluginCommand::ClosePluginPane(plugin_pane_id);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the focus to the terminal pane with the specified id, unsuppressing it if it was suppressed and switching to its tab and layer (eg. floating/tiled).
|
/// Changes the focus to the terminal pane with the specified id, unsuppressing it if it was suppressed and switching to its tab and layer (eg. floating/tiled).
|
||||||
pub fn focus_terminal_pane(terminal_pane_id: i32, should_float_if_hidden: bool) {
|
pub fn focus_terminal_pane(terminal_pane_id: u32, should_float_if_hidden: bool) {
|
||||||
unsafe { host_focus_terminal_pane(terminal_pane_id, should_float_if_hidden as i32) };
|
let plugin_command = PluginCommand::FocusTerminalPane(terminal_pane_id, should_float_if_hidden);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the focus to the plugin pane with the specified id, unsuppressing it if it was suppressed and switching to its tab and layer (eg. floating/tiled).
|
/// Changes the focus to the plugin pane with the specified id, unsuppressing it if it was suppressed and switching to its tab and layer (eg. floating/tiled).
|
||||||
pub fn focus_plugin_pane(plugin_pane_id: i32, should_float_if_hidden: bool) {
|
pub fn focus_plugin_pane(plugin_pane_id: u32, should_float_if_hidden: bool) {
|
||||||
unsafe { host_focus_plugin_pane(plugin_pane_id, should_float_if_hidden as i32) };
|
let plugin_command = PluginCommand::FocusPluginPane(plugin_pane_id, should_float_if_hidden);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the name (the title that appears in the UI) of the terminal pane with the specified id.
|
/// Changes the name (the title that appears in the UI) of the terminal pane with the specified id.
|
||||||
pub fn rename_terminal_pane<S: AsRef<str>>(terminal_pane_id: i32, new_name: S) {
|
pub fn rename_terminal_pane<S: AsRef<str>>(terminal_pane_id: u32, new_name: S)
|
||||||
object_to_stdout(&(terminal_pane_id, new_name.as_ref()));
|
where
|
||||||
unsafe { host_rename_terminal_pane() };
|
S: ToString,
|
||||||
|
{
|
||||||
|
let plugin_command = PluginCommand::RenameTerminalPane(terminal_pane_id, new_name.to_string());
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the name (the title that appears in the UI) of the plugin pane with the specified id.
|
/// Changes the name (the title that appears in the UI) of the plugin pane with the specified id.
|
||||||
pub fn rename_plugin_pane<S: AsRef<str>>(plugin_pane_id: i32, new_name: S) {
|
pub fn rename_plugin_pane<S: AsRef<str>>(plugin_pane_id: u32, new_name: S)
|
||||||
object_to_stdout(&(plugin_pane_id, new_name.as_ref()));
|
where
|
||||||
unsafe { host_rename_plugin_pane() };
|
S: ToString,
|
||||||
|
{
|
||||||
|
let plugin_command = PluginCommand::RenamePluginPane(plugin_pane_id, new_name.to_string());
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the name (the title that appears in the UI) of the tab with the specified position.
|
/// Changes the name (the title that appears in the UI) of the tab with the specified position.
|
||||||
pub fn rename_tab<S: AsRef<str>>(tab_position: i32, new_name: S) {
|
pub fn rename_tab<S: AsRef<str>>(tab_position: u32, new_name: S)
|
||||||
object_to_stdout(&(tab_position, new_name.as_ref()));
|
where
|
||||||
unsafe { host_rename_tab() };
|
S: ToString,
|
||||||
|
{
|
||||||
|
let plugin_command = PluginCommand::RenameTab(tab_position, new_name.to_string());
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility Functions
|
// Utility Functions
|
||||||
|
|
@ -408,6 +592,14 @@ pub fn object_from_stdin<T: DeserializeOwned>() -> Result<T> {
|
||||||
serde_json::from_str(&json).with_context(err_context)
|
serde_json::from_str(&json).with_context(err_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn bytes_from_stdin() -> Result<Vec<u8>> {
|
||||||
|
let err_context = || "failed to deserialize bytes from stdin".to_string();
|
||||||
|
let mut json = String::new();
|
||||||
|
io::stdin().read_line(&mut json).with_context(err_context)?;
|
||||||
|
serde_json::from_str(&json).with_context(err_context)
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn object_to_stdout(object: &impl Serialize) {
|
pub fn object_to_stdout(object: &impl Serialize) {
|
||||||
// TODO: no crashy
|
// TODO: no crashy
|
||||||
|
|
@ -415,91 +607,22 @@ pub fn object_to_stdout(object: &impl Serialize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Post a message to a worker of this plugin, for more information please see [Plugin Workers](https://zellij.dev/documentation/plugin-api-workers.md)
|
/// Post a message to a worker of this plugin, for more information please see [Plugin Workers](https://zellij.dev/documentation/plugin-api-workers.md)
|
||||||
pub fn post_message_to<S: AsRef<str>>(worker_name: S, message: S, payload: S) {
|
pub fn post_message_to(plugin_message: PluginMessage) {
|
||||||
match serde_json::to_string(&(worker_name.as_ref(), message.as_ref(), payload.as_ref())) {
|
let plugin_command = PluginCommand::PostMessageTo(plugin_message);
|
||||||
Ok(serialized) => println!("{}", serialized),
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
Err(e) => eprintln!("Failed to serialize message: {:?}", e),
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
}
|
unsafe { host_run_plugin_command() };
|
||||||
unsafe { host_post_message_to() };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Post a message to this plugin, for more information please see [Plugin Workers](https://zellij.dev/documentation/plugin-api-workers.md)
|
/// Post a message to this plugin, for more information please see [Plugin Workers](https://zellij.dev/documentation/plugin-api-workers.md)
|
||||||
pub fn post_message_to_plugin<S: AsRef<str>>(message: S, payload: S) {
|
pub fn post_message_to_plugin(plugin_message: PluginMessage) {
|
||||||
match serde_json::to_string(&(message.as_ref(), payload.as_ref())) {
|
let plugin_command = PluginCommand::PostMessageToPlugin(plugin_message);
|
||||||
Ok(serialized) => println!("{}", serialized),
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
Err(e) => eprintln!("Failed to serialize message: {:?}", e),
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
}
|
unsafe { host_run_plugin_command() };
|
||||||
unsafe { host_post_message_to_plugin() };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link(wasm_import_module = "zellij")]
|
#[link(wasm_import_module = "zellij")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn host_subscribe();
|
fn host_run_plugin_command();
|
||||||
fn host_unsubscribe();
|
|
||||||
fn host_set_selectable(selectable: i32);
|
|
||||||
fn host_get_plugin_ids();
|
|
||||||
fn host_get_zellij_version();
|
|
||||||
fn host_open_file();
|
|
||||||
fn host_open_file_floating();
|
|
||||||
fn host_open_file_with_line();
|
|
||||||
fn host_open_file_with_line_floating();
|
|
||||||
fn host_open_terminal();
|
|
||||||
fn host_open_terminal_floating();
|
|
||||||
fn host_open_command_pane();
|
|
||||||
fn host_open_command_pane_floating();
|
|
||||||
fn host_switch_tab_to(tab_idx: u32);
|
|
||||||
fn host_set_timeout(secs: f64);
|
|
||||||
fn host_exec_cmd();
|
|
||||||
fn host_report_panic();
|
|
||||||
fn host_post_message_to();
|
|
||||||
fn host_post_message_to_plugin();
|
|
||||||
fn host_hide_self();
|
|
||||||
fn host_show_self(should_float_if_hidden: i32);
|
|
||||||
fn host_switch_to_mode();
|
|
||||||
fn host_new_tabs_with_layout();
|
|
||||||
fn host_new_tab();
|
|
||||||
fn host_go_to_next_tab();
|
|
||||||
fn host_go_to_previous_tab();
|
|
||||||
fn host_resize();
|
|
||||||
fn host_resize_with_direction();
|
|
||||||
fn host_focus_next_pane();
|
|
||||||
fn host_focus_previous_pane();
|
|
||||||
fn host_move_focus();
|
|
||||||
fn host_move_focus_or_tab();
|
|
||||||
fn host_detach();
|
|
||||||
fn host_edit_scrollback();
|
|
||||||
fn host_write();
|
|
||||||
fn host_write_chars();
|
|
||||||
fn host_toggle_tab();
|
|
||||||
fn host_move_pane();
|
|
||||||
fn host_move_pane_with_direction();
|
|
||||||
fn host_clear_screen();
|
|
||||||
fn host_scroll_up();
|
|
||||||
fn host_scroll_down();
|
|
||||||
fn host_scroll_to_top();
|
|
||||||
fn host_scroll_to_bottom();
|
|
||||||
fn host_page_scroll_up();
|
|
||||||
fn host_page_scroll_down();
|
|
||||||
fn host_toggle_focus_fullscreen();
|
|
||||||
fn host_toggle_pane_frames();
|
|
||||||
fn host_toggle_pane_embed_or_eject();
|
|
||||||
fn host_undo_rename_pane();
|
|
||||||
fn host_close_focus();
|
|
||||||
fn host_toggle_active_tab_sync();
|
|
||||||
fn host_close_focused_tab();
|
|
||||||
fn host_undo_rename_tab();
|
|
||||||
fn host_quit_zellij();
|
|
||||||
fn host_previous_swap_layout();
|
|
||||||
fn host_next_swap_layout();
|
|
||||||
fn host_go_to_tab_name();
|
|
||||||
fn host_focus_or_create_tab();
|
|
||||||
fn host_go_to_tab(tab_index: i32);
|
|
||||||
fn host_start_or_reload_plugin();
|
|
||||||
fn host_close_terminal_pane(terminal_pane: i32);
|
|
||||||
fn host_close_plugin_pane(plugin_pane: i32);
|
|
||||||
fn host_focus_terminal_pane(terminal_pane: i32, should_float_if_hidden: i32);
|
|
||||||
fn host_focus_plugin_pane(plugin_pane: i32, should_float_if_hidden: i32);
|
|
||||||
fn host_rename_terminal_pane();
|
|
||||||
fn host_rename_plugin_pane();
|
|
||||||
fn host_rename_tab();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ shellexpand = "3.0.0"
|
||||||
uuid = { version = "0.8.2", features = ["serde", "v4"] }
|
uuid = { version = "0.8.2", features = ["serde", "v4"] }
|
||||||
async-channel = "1.8.0"
|
async-channel = "1.8.0"
|
||||||
include_dir = "0.7.3"
|
include_dir = "0.7.3"
|
||||||
|
prost = "0.11.9"
|
||||||
|
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||||
|
|
@ -55,6 +56,8 @@ notify-debouncer-full = "0.1.0"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = { version = "1.6.0", features = ["backtrace"] }
|
insta = { version = "1.6.0", features = ["backtrace"] }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
prost-build = "0.11.9"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# If this feature is NOT set (default):
|
# If this feature is NOT set (default):
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
21
zellij-utils/build.rs
Normal file
21
zellij-utils/build.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
use prost_build;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut prost_build = prost_build::Config::new();
|
||||||
|
prost_build.include_file("generated_plugin_api.rs");
|
||||||
|
let mut proto_files = vec![];
|
||||||
|
for entry in fs::read_dir("src/plugin_api").unwrap() {
|
||||||
|
let entry_path = entry.unwrap().path();
|
||||||
|
if entry_path.is_file() {
|
||||||
|
if let Some(extension) = entry_path.extension() {
|
||||||
|
if extension == "proto" {
|
||||||
|
proto_files.push(entry_path.display().to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prost_build
|
||||||
|
.compile_protos(&proto_files, &["src/plugin_api"])
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,9 @@ use crate::input::actions::Action;
|
||||||
use crate::input::config::ConversionError;
|
use crate::input::config::ConversionError;
|
||||||
use clap::ArgEnum;
|
use clap::ArgEnum;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use strum_macros::{EnumDiscriminants, EnumIter, EnumString, ToString};
|
use strum_macros::{EnumDiscriminants, EnumIter, EnumString, ToString};
|
||||||
|
|
||||||
|
|
@ -810,3 +810,144 @@ pub enum CopyDestination {
|
||||||
Primary,
|
Primary,
|
||||||
System,
|
System,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct FileToOpen {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub line_number: Option<usize>,
|
||||||
|
pub cwd: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileToOpen {
|
||||||
|
pub fn new<P: AsRef<Path>>(path: P) -> Self {
|
||||||
|
FileToOpen {
|
||||||
|
path: path.as_ref().to_path_buf(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn with_line_number(mut self, line_number: usize) -> Self {
|
||||||
|
self.line_number = Some(line_number);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn with_cwd(mut self, cwd: PathBuf) -> Self {
|
||||||
|
self.cwd = Some(cwd);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct CommandToRun {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub args: Vec<String>,
|
||||||
|
pub cwd: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandToRun {
|
||||||
|
pub fn new<P: AsRef<Path>>(path: P) -> Self {
|
||||||
|
CommandToRun {
|
||||||
|
path: path.as_ref().to_path_buf(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn new_with_args<P: AsRef<Path>, A: AsRef<str>>(path: P, args: Vec<A>) -> Self {
|
||||||
|
CommandToRun {
|
||||||
|
path: path.as_ref().to_path_buf(),
|
||||||
|
args: args.into_iter().map(|a| a.as_ref().to_owned()).collect(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct PluginMessage {
|
||||||
|
pub name: String,
|
||||||
|
pub payload: String,
|
||||||
|
pub worker_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginMessage {
|
||||||
|
pub fn new_to_worker(worker_name: &str, message: &str, payload: &str) -> Self {
|
||||||
|
PluginMessage {
|
||||||
|
name: message.to_owned(),
|
||||||
|
payload: payload.to_owned(),
|
||||||
|
worker_name: Some(worker_name.to_owned()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn new_to_plugin(message: &str, payload: &str) -> Self {
|
||||||
|
PluginMessage {
|
||||||
|
name: message.to_owned(),
|
||||||
|
payload: payload.to_owned(),
|
||||||
|
worker_name: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum PluginCommand {
|
||||||
|
Subscribe(HashSet<EventType>),
|
||||||
|
Unsubscribe(HashSet<EventType>),
|
||||||
|
SetSelectable(bool),
|
||||||
|
GetPluginIds,
|
||||||
|
GetZellijVersion,
|
||||||
|
OpenFile(FileToOpen),
|
||||||
|
OpenFileFloating(FileToOpen),
|
||||||
|
OpenTerminal(FileToOpen), // only used for the path as cwd
|
||||||
|
OpenTerminalFloating(FileToOpen), // only used for the path as cwd
|
||||||
|
OpenCommandPane(CommandToRun),
|
||||||
|
OpenCommandPaneFloating(CommandToRun),
|
||||||
|
SwitchTabTo(u32), // tab index
|
||||||
|
SetTimeout(f32), // seconds
|
||||||
|
ExecCmd(Vec<String>),
|
||||||
|
PostMessageTo(PluginMessage),
|
||||||
|
PostMessageToPlugin(PluginMessage),
|
||||||
|
HideSelf,
|
||||||
|
ShowSelf(bool), // bool - should float if hidden
|
||||||
|
SwitchToMode(InputMode),
|
||||||
|
NewTabsWithLayout(String), // raw kdl layout
|
||||||
|
NewTab,
|
||||||
|
GoToNextTab,
|
||||||
|
GoToPreviousTab,
|
||||||
|
Resize(Resize),
|
||||||
|
ResizeWithDirection(ResizeStrategy),
|
||||||
|
FocusNextPane,
|
||||||
|
FocusPreviousPane,
|
||||||
|
MoveFocus(Direction),
|
||||||
|
MoveFocusOrTab(Direction),
|
||||||
|
Detach,
|
||||||
|
EditScrollback,
|
||||||
|
Write(Vec<u8>), // bytes
|
||||||
|
WriteChars(String),
|
||||||
|
ToggleTab,
|
||||||
|
MovePane,
|
||||||
|
MovePaneWithDirection(Direction),
|
||||||
|
ClearScreen,
|
||||||
|
ScrollUp,
|
||||||
|
ScrollDown,
|
||||||
|
ScrollToTop,
|
||||||
|
ScrollToBottom,
|
||||||
|
PageScrollUp,
|
||||||
|
PageScrollDown,
|
||||||
|
ToggleFocusFullscreen,
|
||||||
|
TogglePaneFrames,
|
||||||
|
TogglePaneEmbedOrEject,
|
||||||
|
UndoRenamePane,
|
||||||
|
CloseFocus,
|
||||||
|
ToggleActiveTabSync,
|
||||||
|
CloseFocusedTab,
|
||||||
|
UndoRenameTab,
|
||||||
|
QuitZellij,
|
||||||
|
PreviousSwapLayout,
|
||||||
|
NextSwapLayout,
|
||||||
|
GoToTabName(String),
|
||||||
|
FocusOrCreateTab(String),
|
||||||
|
GoToTab(u32), // tab index
|
||||||
|
StartOrReloadPlugin(String), // plugin url (eg. file:/path/to/plugin.wasm)
|
||||||
|
CloseTerminalPane(u32), // terminal pane id
|
||||||
|
ClosePluginPane(u32), // plugin pane id
|
||||||
|
FocusTerminalPane(u32, bool), // terminal pane id, should_float_if_hidden
|
||||||
|
FocusPluginPane(u32, bool), // plugin pane id, should_float_if_hidden
|
||||||
|
RenameTerminalPane(u32, String), // terminal pane id, new name
|
||||||
|
RenamePluginPane(u32, String), // plugin pane id, new name
|
||||||
|
RenameTab(u32, String), // tab index, new name
|
||||||
|
ReportPanic(String), // stringified panic
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ pub mod errors;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod kdl;
|
pub mod kdl;
|
||||||
pub mod pane_size;
|
pub mod pane_size;
|
||||||
|
pub mod plugin_api;
|
||||||
pub mod position;
|
pub mod position;
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
pub mod shared;
|
pub mod shared;
|
||||||
|
|
@ -23,3 +24,5 @@ pub use ::{
|
||||||
anyhow, async_channel, async_std, clap, interprocess, lazy_static, libc, miette, nix,
|
anyhow, async_channel, async_std, clap, interprocess, lazy_static, libc, miette, nix,
|
||||||
notify_debouncer_full, regex, serde, signal_hook, tempfile, termwiz, vte,
|
notify_debouncer_full, regex, serde, signal_hook, tempfile, termwiz, vte,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use ::prost;
|
||||||
|
|
|
||||||
246
zellij-utils/src/plugin_api/action.proto
Normal file
246
zellij-utils/src/plugin_api/action.proto
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "input_mode.proto";
|
||||||
|
import "resize.proto";
|
||||||
|
|
||||||
|
package api.action;
|
||||||
|
|
||||||
|
message Action {
|
||||||
|
ActionName name = 1;
|
||||||
|
oneof optional_payload {
|
||||||
|
SwitchToModePayload switch_to_mode_payload = 2;
|
||||||
|
WritePayload write_payload = 3;
|
||||||
|
WriteCharsPayload write_chars_payload = 4;
|
||||||
|
SwitchToModePayload switch_mode_for_all_clients_payload = 5;
|
||||||
|
resize.Resize resize_payload = 6;
|
||||||
|
resize.ResizeDirection move_focus_payload = 7;
|
||||||
|
resize.ResizeDirection move_focus_or_tab_payload = 8;
|
||||||
|
MovePanePayload move_pane_payload = 9;
|
||||||
|
DumpScreenPayload dump_screen_payload = 10;
|
||||||
|
ScrollAtPayload scroll_up_at_payload = 11;
|
||||||
|
ScrollAtPayload scroll_down_at_payload = 12;
|
||||||
|
NewPanePayload new_pane_payload = 13;
|
||||||
|
EditFilePayload edit_file_payload = 14;
|
||||||
|
NewFloatingPanePayload new_floating_pane_payload = 15;
|
||||||
|
NewTiledPanePayload new_tiled_pane_payload = 16;
|
||||||
|
bytes pane_name_input_payload = 17;
|
||||||
|
uint32 go_to_tab_payload = 18;
|
||||||
|
GoToTabNamePayload go_to_tab_name_payload = 19;
|
||||||
|
bytes tab_name_input_payload = 20;
|
||||||
|
RunCommandAction run_payload = 21;
|
||||||
|
Position left_click_payload = 22;
|
||||||
|
Position right_click_payload = 23;
|
||||||
|
Position middle_click_payload = 24;
|
||||||
|
LaunchOrFocusPluginPayload launch_or_focus_plugin_payload = 25;
|
||||||
|
Position left_mouse_release_payload = 26;
|
||||||
|
Position right_mouse_release_payload = 27;
|
||||||
|
Position middle_mouse_release_payload = 28;
|
||||||
|
Position mouse_hold_left_payload = 29;
|
||||||
|
Position mouse_hold_right_payload = 30;
|
||||||
|
Position mouse_hold_middle_payload = 31;
|
||||||
|
bytes search_input_payload = 32;
|
||||||
|
SearchDirection search_payload = 33;
|
||||||
|
SearchOption search_toggle_option_payload = 34;
|
||||||
|
NewPluginPanePayload new_tiled_plugin_pane_payload = 35;
|
||||||
|
NewPluginPanePayload new_floating_plugin_pane_payload = 36;
|
||||||
|
string start_or_reload_plugin_payload = 37;
|
||||||
|
uint32 close_terminal_pane_payload = 38;
|
||||||
|
uint32 close_plugin_pane_payload = 39;
|
||||||
|
PaneIdAndShouldFloat focus_terminal_pane_with_id_payload = 40;
|
||||||
|
PaneIdAndShouldFloat focus_plugin_pane_with_id_payload = 41;
|
||||||
|
IdAndName rename_terminal_pane_payload = 42;
|
||||||
|
IdAndName rename_plugin_pane_payload = 43;
|
||||||
|
IdAndName rename_tab_payload = 44;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message IdAndName {
|
||||||
|
bytes name = 1;
|
||||||
|
uint32 id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PaneIdAndShouldFloat {
|
||||||
|
uint32 pane_id = 1;
|
||||||
|
bool should_float_if_hidden = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NewPluginPanePayload {
|
||||||
|
string plugin_url = 1;
|
||||||
|
optional string pane_name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SearchDirection {
|
||||||
|
Up = 0;
|
||||||
|
Down = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SearchOption {
|
||||||
|
CaseSensitivity = 0;
|
||||||
|
WholeWord = 1;
|
||||||
|
Wrap = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LaunchOrFocusPluginPayload {
|
||||||
|
string plugin_url = 1;
|
||||||
|
bool should_float = 2;
|
||||||
|
optional PluginConfiguration plugin_configuration = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GoToTabNamePayload {
|
||||||
|
string tab_name = 1;
|
||||||
|
bool create = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NewFloatingPanePayload {
|
||||||
|
optional RunCommandAction command = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NewTiledPanePayload {
|
||||||
|
optional RunCommandAction command = 1;
|
||||||
|
optional resize.ResizeDirection direction = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MovePanePayload {
|
||||||
|
optional resize.ResizeDirection direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EditFilePayload {
|
||||||
|
string file_to_edit = 1;
|
||||||
|
optional uint32 line_number = 2;
|
||||||
|
optional string cwd = 3;
|
||||||
|
optional resize.ResizeDirection direction = 4;
|
||||||
|
bool should_float = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ScrollAtPayload {
|
||||||
|
Position position = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NewPanePayload {
|
||||||
|
optional resize.ResizeDirection direction = 1;
|
||||||
|
optional string pane_name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchToModePayload {
|
||||||
|
input_mode.InputMode input_mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WritePayload {
|
||||||
|
bytes bytes_to_write = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WriteCharsPayload {
|
||||||
|
string chars = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DumpScreenPayload {
|
||||||
|
string file_path = 1;
|
||||||
|
bool include_scrollback = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ActionName {
|
||||||
|
Quit = 0;
|
||||||
|
Write = 1;
|
||||||
|
WriteChars = 2;
|
||||||
|
SwitchToMode = 3;
|
||||||
|
SwitchModeForAllClients = 4;
|
||||||
|
Resize = 5;
|
||||||
|
FocusNextPane = 6;
|
||||||
|
FocusPreviousPane = 7;
|
||||||
|
SwitchFocus = 8;
|
||||||
|
MoveFocus = 9;
|
||||||
|
MoveFocusOrTab = 10;
|
||||||
|
MovePane = 11;
|
||||||
|
MovePaneBackwards = 12;
|
||||||
|
ClearScreen = 13;
|
||||||
|
DumpScreen = 14;
|
||||||
|
EditScrollback = 15;
|
||||||
|
ScrollUp = 16;
|
||||||
|
ScrollUpAt = 17;
|
||||||
|
ScrollDown = 18;
|
||||||
|
ScrollDownAt = 19;
|
||||||
|
ScrollToBottom = 20;
|
||||||
|
ScrollToTop = 21;
|
||||||
|
PageScrollUp = 22;
|
||||||
|
PageScrollDown = 23;
|
||||||
|
HalfPageScrollUp = 24;
|
||||||
|
HalfPageScrollDown = 25;
|
||||||
|
ToggleFocusFullscreen = 26;
|
||||||
|
TogglePaneFrames = 27;
|
||||||
|
ToggleActiveSyncTab = 28;
|
||||||
|
NewPane = 29;
|
||||||
|
EditFile = 30;
|
||||||
|
NewFloatingPane = 31;
|
||||||
|
NewTiledPane = 32;
|
||||||
|
TogglePaneEmbedOrFloating = 33;
|
||||||
|
ToggleFloatingPanes = 34;
|
||||||
|
CloseFocus = 35;
|
||||||
|
PaneNameInput = 36;
|
||||||
|
UndoRenamePane = 37;
|
||||||
|
NewTab = 38;
|
||||||
|
NoOp = 39;
|
||||||
|
GoToNextTab = 40;
|
||||||
|
GoToPreviousTab = 41;
|
||||||
|
CloseTab = 42;
|
||||||
|
GoToTab = 43;
|
||||||
|
GoToTabName = 44;
|
||||||
|
ToggleTab = 45;
|
||||||
|
TabNameInput = 46;
|
||||||
|
UndoRenameTab = 47;
|
||||||
|
Run = 48;
|
||||||
|
Detach = 49;
|
||||||
|
LeftClick = 50;
|
||||||
|
RightClick = 51;
|
||||||
|
MiddleClick = 52;
|
||||||
|
LaunchOrFocusPlugin = 53;
|
||||||
|
LeftMouseRelease = 54;
|
||||||
|
RightMouseRelease = 55;
|
||||||
|
MiddleMouseRelease = 56;
|
||||||
|
MouseHoldLeft = 57;
|
||||||
|
MouseHoldRight = 58;
|
||||||
|
MouseHoldMiddle = 59;
|
||||||
|
SearchInput = 60;
|
||||||
|
Search = 61;
|
||||||
|
SearchToggleOption = 62;
|
||||||
|
ToggleMouseMode = 63;
|
||||||
|
PreviousSwapLayout = 64;
|
||||||
|
NextSwapLayout = 65;
|
||||||
|
QueryTabNames = 66;
|
||||||
|
NewTiledPluginPane = 67;
|
||||||
|
NewFloatingPluginPane = 68;
|
||||||
|
StartOrReloadPlugin = 69;
|
||||||
|
CloseTerminalPane = 70;
|
||||||
|
ClosePluginPane = 71;
|
||||||
|
FocusTerminalPaneWithId = 72;
|
||||||
|
FocusPluginPaneWithId = 73;
|
||||||
|
RenameTerminalPane = 74;
|
||||||
|
RenamePluginPane = 75;
|
||||||
|
RenameTab = 76;
|
||||||
|
BreakPane = 77;
|
||||||
|
BreakPaneRight = 78;
|
||||||
|
BreakPaneLeft = 79;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Position {
|
||||||
|
int64 line = 1;
|
||||||
|
int64 column = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RunCommandAction {
|
||||||
|
string command = 1;
|
||||||
|
repeated string args = 2;
|
||||||
|
optional string cwd = 3;
|
||||||
|
optional resize.ResizeDirection direction = 4;
|
||||||
|
optional string pane_name = 5;
|
||||||
|
bool hold_on_close = 6;
|
||||||
|
bool hold_on_start = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PluginConfiguration {
|
||||||
|
repeated NameAndValue name_and_value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NameAndValue {
|
||||||
|
string name = 1;
|
||||||
|
string value = 2;
|
||||||
|
}
|
||||||
1304
zellij-utils/src/plugin_api/action.rs
Normal file
1304
zellij-utils/src/plugin_api/action.rs
Normal file
File diff suppressed because it is too large
Load diff
9
zellij-utils/src/plugin_api/command.proto
Normal file
9
zellij-utils/src/plugin_api/command.proto
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package api.command;
|
||||||
|
|
||||||
|
message Command {
|
||||||
|
string path = 1;
|
||||||
|
repeated string args = 2;
|
||||||
|
optional string cwd = 3;
|
||||||
|
}
|
||||||
26
zellij-utils/src/plugin_api/command.rs
Normal file
26
zellij-utils/src/plugin_api/command.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
pub use super::generated_api::api::command::Command as ProtobufCommand;
|
||||||
|
use crate::data::CommandToRun;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufCommand> for CommandToRun {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_command: ProtobufCommand) -> Result<Self, &'static str> {
|
||||||
|
let path = PathBuf::from(protobuf_command.path);
|
||||||
|
let args = protobuf_command.args;
|
||||||
|
let cwd = protobuf_command.cwd.map(|c| PathBuf::from(c));
|
||||||
|
Ok(CommandToRun { path, args, cwd })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<CommandToRun> for ProtobufCommand {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(command_to_run: CommandToRun) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufCommand {
|
||||||
|
path: command_to_run.path.display().to_string(),
|
||||||
|
args: command_to_run.args,
|
||||||
|
cwd: command_to_run.cwd.map(|c| c.display().to_string()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
162
zellij-utils/src/plugin_api/event.proto
Normal file
162
zellij-utils/src/plugin_api/event.proto
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "input_mode.proto";
|
||||||
|
import "key.proto";
|
||||||
|
import "style.proto";
|
||||||
|
import "action.proto";
|
||||||
|
|
||||||
|
package api.event;
|
||||||
|
|
||||||
|
enum EventType {
|
||||||
|
/// The input mode or relevant metadata changed
|
||||||
|
ModeUpdate = 0;
|
||||||
|
/// The tab state in the app was changed
|
||||||
|
TabUpdate = 1;
|
||||||
|
/// The pane state in the app was changed
|
||||||
|
PaneUpdate = 2;
|
||||||
|
/// A key was pressed while the user is focused on this plugin's pane
|
||||||
|
Key = 3;
|
||||||
|
/// A mouse event happened while the user is focused on this plugin's pane
|
||||||
|
Mouse = 4;
|
||||||
|
/// A timer expired set by the `set_timeout` method exported by `zellij-tile`.
|
||||||
|
Timer = 5;
|
||||||
|
/// Text was copied to the clipboard anywhere in the app
|
||||||
|
CopyToClipboard = 6;
|
||||||
|
/// Failed to copy text to clipboard anywhere in the app
|
||||||
|
SystemClipboardFailure = 7;
|
||||||
|
/// Input was received anywhere in the app
|
||||||
|
InputReceived = 8;
|
||||||
|
/// This plugin became visible or invisible
|
||||||
|
Visible = 9;
|
||||||
|
/// A message from one of the plugin's workers
|
||||||
|
CustomMessage = 10;
|
||||||
|
/// A file was created somewhere in the Zellij CWD folder
|
||||||
|
FileSystemCreate = 11;
|
||||||
|
/// A file was accessed somewhere in the Zellij CWD folder
|
||||||
|
FileSystemRead = 12;
|
||||||
|
/// A file was modified somewhere in the Zellij CWD folder
|
||||||
|
FileSystemUpdate = 13;
|
||||||
|
/// A file was deleted somewhere in the Zellij CWD folder
|
||||||
|
FileSystemDelete = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EventNameList {
|
||||||
|
repeated EventType event_types = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Event {
|
||||||
|
EventType name = 1;
|
||||||
|
oneof payload {
|
||||||
|
ModeUpdatePayload mode_update_payload = 2;
|
||||||
|
TabUpdatePayload tab_update_payload = 3;
|
||||||
|
PaneUpdatePayload pane_update_payload = 4;
|
||||||
|
key.Key key_payload = 5;
|
||||||
|
MouseEventPayload mouse_event_payload = 6;
|
||||||
|
float timer_payload = 7;
|
||||||
|
CopyDestination copy_to_clipboard_payload = 8;
|
||||||
|
bool visible_payload = 9;
|
||||||
|
CustomMessagePayload custom_message_payload = 10;
|
||||||
|
FileListPayload file_list_payload = 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message FileListPayload {
|
||||||
|
repeated string paths = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CustomMessagePayload {
|
||||||
|
string message_name = 1;
|
||||||
|
string payload = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CopyDestination {
|
||||||
|
Command = 0;
|
||||||
|
Primary = 1;
|
||||||
|
System = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MouseEventPayload {
|
||||||
|
MouseEventName mouse_event_name = 1;
|
||||||
|
oneof mouse_event_payload {
|
||||||
|
uint32 line_count = 2;
|
||||||
|
action.Position position = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MouseEventName {
|
||||||
|
MouseScrollUp = 0;
|
||||||
|
MouseScrollDown = 1;
|
||||||
|
MouseLeftClick = 2;
|
||||||
|
MouseRightClick = 3;
|
||||||
|
MouseHold = 4;
|
||||||
|
MouseRelease = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TabUpdatePayload {
|
||||||
|
repeated TabInfo tab_info = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PaneUpdatePayload {
|
||||||
|
repeated PaneManifest pane_manifest = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PaneManifest {
|
||||||
|
uint32 tab_index = 1;
|
||||||
|
repeated PaneInfo panes = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PaneInfo {
|
||||||
|
uint32 id = 1;
|
||||||
|
bool is_plugin = 2;
|
||||||
|
bool is_focused = 3;
|
||||||
|
bool is_fullscreen = 4;
|
||||||
|
bool is_floating = 5;
|
||||||
|
bool is_suppressed = 6;
|
||||||
|
string title = 7;
|
||||||
|
bool exited = 8;
|
||||||
|
optional int32 exit_status = 9;
|
||||||
|
bool is_held = 10;
|
||||||
|
uint32 pane_x = 11;
|
||||||
|
uint32 pane_content_x = 12;
|
||||||
|
uint32 pane_y = 13;
|
||||||
|
uint32 pane_content_y = 14;
|
||||||
|
uint32 pane_rows = 15;
|
||||||
|
uint32 pane_content_rows = 16;
|
||||||
|
uint32 pane_columns = 17;
|
||||||
|
uint32 pane_content_columns = 18;
|
||||||
|
optional action.Position cursor_coordinates_in_pane = 19;
|
||||||
|
optional string terminal_command = 20;
|
||||||
|
optional string plugin_url = 21;
|
||||||
|
bool is_selectable = 22;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TabInfo {
|
||||||
|
uint32 position = 1;
|
||||||
|
string name = 2;
|
||||||
|
bool active = 3;
|
||||||
|
uint32 panes_to_hide = 4;
|
||||||
|
bool is_fullscreen_active = 5;
|
||||||
|
bool is_sync_panes_active = 6;
|
||||||
|
bool are_floating_panes_visible = 7;
|
||||||
|
repeated uint32 other_focused_clients = 8;
|
||||||
|
optional string active_swap_layout_name = 9;
|
||||||
|
bool is_swap_layout_dirty = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ModeUpdatePayload {
|
||||||
|
input_mode.InputMode current_mode = 1;
|
||||||
|
repeated InputModeKeybinds keybinds = 2;
|
||||||
|
style.Style style = 3;
|
||||||
|
bool arrow_fonts_support = 4;
|
||||||
|
optional string session_name = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InputModeKeybinds {
|
||||||
|
input_mode.InputMode mode = 1;
|
||||||
|
repeated KeyBind key_bind = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message KeyBind {
|
||||||
|
key.Key key = 1;
|
||||||
|
repeated action.Action action = 2;
|
||||||
|
}
|
||||||
1059
zellij-utils/src/plugin_api/event.rs
Normal file
1059
zellij-utils/src/plugin_api/event.rs
Normal file
File diff suppressed because it is too large
Load diff
9
zellij-utils/src/plugin_api/file.proto
Normal file
9
zellij-utils/src/plugin_api/file.proto
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package api.file;
|
||||||
|
|
||||||
|
message File {
|
||||||
|
string path = 1;
|
||||||
|
optional int32 line_number = 2;
|
||||||
|
optional string cwd = 3;
|
||||||
|
}
|
||||||
30
zellij-utils/src/plugin_api/file.rs
Normal file
30
zellij-utils/src/plugin_api/file.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
pub use super::generated_api::api::file::File as ProtobufFile;
|
||||||
|
use crate::data::FileToOpen;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufFile> for FileToOpen {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_file: ProtobufFile) -> Result<Self, &'static str> {
|
||||||
|
let path = PathBuf::from(protobuf_file.path);
|
||||||
|
let line_number = protobuf_file.line_number.map(|l| l as usize);
|
||||||
|
let cwd = protobuf_file.cwd.map(|c| PathBuf::from(c));
|
||||||
|
Ok(FileToOpen {
|
||||||
|
path,
|
||||||
|
line_number,
|
||||||
|
cwd,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<FileToOpen> for ProtobufFile {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(file_to_open: FileToOpen) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufFile {
|
||||||
|
path: file_to_open.path.display().to_string(),
|
||||||
|
line_number: file_to_open.line_number.map(|l| l as i32),
|
||||||
|
cwd: file_to_open.cwd.map(|c| c.display().to_string()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
40
zellij-utils/src/plugin_api/input_mode.proto
Normal file
40
zellij-utils/src/plugin_api/input_mode.proto
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package api.input_mode;
|
||||||
|
|
||||||
|
message InputModeMessage {
|
||||||
|
InputMode input_mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InputMode {
|
||||||
|
/// In `Normal` mode, input is always written to the terminal, except for the shortcuts leading
|
||||||
|
/// to other modes
|
||||||
|
Normal = 0;
|
||||||
|
/// In `Locked` mode, input is always written to the terminal and all shortcuts are disabled
|
||||||
|
/// except the one leading back to normal mode
|
||||||
|
Locked = 1;
|
||||||
|
/// `Resize` mode allows resizing the different existing panes.
|
||||||
|
Resize = 2;
|
||||||
|
/// `Pane` mode allows creating and closing panes, as well as moving between them.
|
||||||
|
Pane = 3;
|
||||||
|
/// `Tab` mode allows creating and closing tabs, as well as moving between them.
|
||||||
|
Tab = 4;
|
||||||
|
/// `Scroll` mode allows scrolling up and down within a pane.
|
||||||
|
Scroll = 5;
|
||||||
|
/// `EnterSearch` mode allows for typing in the needle for a search in the scroll buffer of a pane.
|
||||||
|
EnterSearch = 6;
|
||||||
|
/// `Search` mode allows for searching a term in a pane (superset of `Scroll`).
|
||||||
|
Search = 7;
|
||||||
|
/// `RenameTab` mode allows assigning a new name to a tab.
|
||||||
|
RenameTab = 8;
|
||||||
|
/// `RenamePane` mode allows assigning a new name to a pane.
|
||||||
|
RenamePane = 9;
|
||||||
|
/// `Session` mode allows detaching sessions
|
||||||
|
Session = 10;
|
||||||
|
/// `Move` mode allows moving the different existing panes within a tab
|
||||||
|
Move = 11;
|
||||||
|
/// `Prompt` mode allows interacting with active prompts.
|
||||||
|
Prompt = 12;
|
||||||
|
/// `Tmux` mode allows for basic tmux keybindings functionality
|
||||||
|
Tmux = 13;
|
||||||
|
}
|
||||||
69
zellij-utils/src/plugin_api/input_mode.rs
Normal file
69
zellij-utils/src/plugin_api/input_mode.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
pub use super::generated_api::api::input_mode::{
|
||||||
|
InputMode as ProtobufInputMode, InputModeMessage as ProtobufInputModeMessage,
|
||||||
|
};
|
||||||
|
use crate::data::InputMode;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufInputMode> for InputMode {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_input_mode: ProtobufInputMode) -> Result<Self, &'static str> {
|
||||||
|
match protobuf_input_mode {
|
||||||
|
ProtobufInputMode::Normal => Ok(InputMode::Normal),
|
||||||
|
ProtobufInputMode::Locked => Ok(InputMode::Locked),
|
||||||
|
ProtobufInputMode::Resize => Ok(InputMode::Resize),
|
||||||
|
ProtobufInputMode::Pane => Ok(InputMode::Pane),
|
||||||
|
ProtobufInputMode::Tab => Ok(InputMode::Tab),
|
||||||
|
ProtobufInputMode::Scroll => Ok(InputMode::Scroll),
|
||||||
|
ProtobufInputMode::EnterSearch => Ok(InputMode::EnterSearch),
|
||||||
|
ProtobufInputMode::Search => Ok(InputMode::Search),
|
||||||
|
ProtobufInputMode::RenameTab => Ok(InputMode::RenameTab),
|
||||||
|
ProtobufInputMode::RenamePane => Ok(InputMode::RenamePane),
|
||||||
|
ProtobufInputMode::Session => Ok(InputMode::Session),
|
||||||
|
ProtobufInputMode::Move => Ok(InputMode::Move),
|
||||||
|
ProtobufInputMode::Prompt => Ok(InputMode::Prompt),
|
||||||
|
ProtobufInputMode::Tmux => Ok(InputMode::Tmux),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<InputMode> for ProtobufInputMode {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(input_mode: InputMode) -> Result<Self, &'static str> {
|
||||||
|
Ok(match input_mode {
|
||||||
|
InputMode::Normal => ProtobufInputMode::Normal,
|
||||||
|
InputMode::Locked => ProtobufInputMode::Locked,
|
||||||
|
InputMode::Resize => ProtobufInputMode::Resize,
|
||||||
|
InputMode::Pane => ProtobufInputMode::Pane,
|
||||||
|
InputMode::Tab => ProtobufInputMode::Tab,
|
||||||
|
InputMode::Scroll => ProtobufInputMode::Scroll,
|
||||||
|
InputMode::EnterSearch => ProtobufInputMode::EnterSearch,
|
||||||
|
InputMode::Search => ProtobufInputMode::Search,
|
||||||
|
InputMode::RenameTab => ProtobufInputMode::RenameTab,
|
||||||
|
InputMode::RenamePane => ProtobufInputMode::RenamePane,
|
||||||
|
InputMode::Session => ProtobufInputMode::Session,
|
||||||
|
InputMode::Move => ProtobufInputMode::Move,
|
||||||
|
InputMode::Prompt => ProtobufInputMode::Prompt,
|
||||||
|
InputMode::Tmux => ProtobufInputMode::Tmux,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufInputModeMessage> for InputMode {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_input_mode: ProtobufInputModeMessage) -> Result<Self, &'static str> {
|
||||||
|
ProtobufInputMode::from_i32(protobuf_input_mode.input_mode)
|
||||||
|
.and_then(|p| p.try_into().ok())
|
||||||
|
.ok_or("Invalid input mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<InputMode> for ProtobufInputModeMessage {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(input_mode: InputMode) -> Result<Self, &'static str> {
|
||||||
|
let protobuf_input_mode: ProtobufInputMode = input_mode.try_into()?;
|
||||||
|
Ok(ProtobufInputModeMessage {
|
||||||
|
input_mode: protobuf_input_mode as i32,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
83
zellij-utils/src/plugin_api/key.proto
Normal file
83
zellij-utils/src/plugin_api/key.proto
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package api.key;
|
||||||
|
|
||||||
|
message Key {
|
||||||
|
enum KeyModifier {
|
||||||
|
CTRL = 0;
|
||||||
|
ALT = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NamedKey {
|
||||||
|
PageDown = 0;
|
||||||
|
PageUp = 1;
|
||||||
|
LeftArrow = 2;
|
||||||
|
DownArrow = 3;
|
||||||
|
UpArrow = 4;
|
||||||
|
RightArrow = 5;
|
||||||
|
Home = 6;
|
||||||
|
End = 7;
|
||||||
|
Backspace = 8;
|
||||||
|
Delete = 9;
|
||||||
|
Insert = 10;
|
||||||
|
F1 = 11;
|
||||||
|
F2 = 12;
|
||||||
|
F3 = 13;
|
||||||
|
F4 = 14;
|
||||||
|
F5 = 15;
|
||||||
|
F6 = 16;
|
||||||
|
F7 = 17;
|
||||||
|
F8 = 18;
|
||||||
|
F9 = 19;
|
||||||
|
F10 = 20;
|
||||||
|
F11 = 21;
|
||||||
|
F12 = 22;
|
||||||
|
Tab = 23;
|
||||||
|
Esc = 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Char {
|
||||||
|
a = 0;
|
||||||
|
b = 1;
|
||||||
|
c = 2;
|
||||||
|
d = 3;
|
||||||
|
e = 4;
|
||||||
|
f = 5;
|
||||||
|
g = 6;
|
||||||
|
h = 7;
|
||||||
|
i = 8;
|
||||||
|
j = 9;
|
||||||
|
k = 10;
|
||||||
|
l = 11;
|
||||||
|
m = 12;
|
||||||
|
n = 13;
|
||||||
|
o = 14;
|
||||||
|
p = 15;
|
||||||
|
q = 16;
|
||||||
|
r = 17;
|
||||||
|
s = 18;
|
||||||
|
t = 19;
|
||||||
|
u = 20;
|
||||||
|
v = 21;
|
||||||
|
w = 22;
|
||||||
|
x = 23;
|
||||||
|
y = 24;
|
||||||
|
z = 25;
|
||||||
|
zero = 26;
|
||||||
|
one = 27;
|
||||||
|
two = 28;
|
||||||
|
three = 29;
|
||||||
|
four = 30;
|
||||||
|
five = 31;
|
||||||
|
six = 32;
|
||||||
|
seven = 33;
|
||||||
|
eight = 34;
|
||||||
|
nine = 35;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional KeyModifier modifier = 1;
|
||||||
|
oneof main_key {
|
||||||
|
NamedKey key = 2;
|
||||||
|
Char char = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
222
zellij-utils/src/plugin_api/key.rs
Normal file
222
zellij-utils/src/plugin_api/key.rs
Normal file
|
|
@ -0,0 +1,222 @@
|
||||||
|
pub use super::generated_api::api::key::{
|
||||||
|
key::{KeyModifier, MainKey, NamedKey},
|
||||||
|
Key as ProtobufKey,
|
||||||
|
};
|
||||||
|
use crate::data::{CharOrArrow, Direction, Key};
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufKey> for Key {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_key: ProtobufKey) -> Result<Self, &'static str> {
|
||||||
|
let key_modifier = parse_optional_modifier(&protobuf_key);
|
||||||
|
match key_modifier {
|
||||||
|
Some(KeyModifier::Ctrl) => {
|
||||||
|
let character = char_from_main_key(protobuf_key.main_key)?;
|
||||||
|
Ok(Key::Ctrl(character))
|
||||||
|
},
|
||||||
|
Some(KeyModifier::Alt) => {
|
||||||
|
let char_or_arrow = CharOrArrow::from_main_key(protobuf_key.main_key)?;
|
||||||
|
Ok(Key::Alt(char_or_arrow))
|
||||||
|
},
|
||||||
|
None => match protobuf_key.main_key.as_ref().ok_or("invalid key")? {
|
||||||
|
MainKey::Char(_key_index) => {
|
||||||
|
let character = char_from_main_key(protobuf_key.main_key)?;
|
||||||
|
Ok(Key::Char(character))
|
||||||
|
},
|
||||||
|
MainKey::Key(key_index) => {
|
||||||
|
let key = NamedKey::from_i32(*key_index).ok_or("invalid_key")?;
|
||||||
|
Ok(named_key_to_key(key))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Key> for ProtobufKey {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(key: Key) -> Result<Self, &'static str> {
|
||||||
|
match key {
|
||||||
|
Key::PageDown => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::PageDown as i32)),
|
||||||
|
}),
|
||||||
|
Key::PageUp => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::PageUp as i32)),
|
||||||
|
}),
|
||||||
|
Key::Left => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::LeftArrow as i32)),
|
||||||
|
}),
|
||||||
|
Key::Down => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::DownArrow as i32)),
|
||||||
|
}),
|
||||||
|
Key::Up => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::UpArrow as i32)),
|
||||||
|
}),
|
||||||
|
Key::Right => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::RightArrow as i32)),
|
||||||
|
}),
|
||||||
|
Key::Home => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::Home as i32)),
|
||||||
|
}),
|
||||||
|
Key::End => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::End as i32)),
|
||||||
|
}),
|
||||||
|
Key::Backspace => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::Backspace as i32)),
|
||||||
|
}),
|
||||||
|
Key::Delete => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::Delete as i32)),
|
||||||
|
}),
|
||||||
|
Key::Insert => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::Insert as i32)),
|
||||||
|
}),
|
||||||
|
Key::F(index) => {
|
||||||
|
let main_key = match index {
|
||||||
|
1 => Some(MainKey::Key(NamedKey::F1 as i32)),
|
||||||
|
2 => Some(MainKey::Key(NamedKey::F2 as i32)),
|
||||||
|
3 => Some(MainKey::Key(NamedKey::F3 as i32)),
|
||||||
|
4 => Some(MainKey::Key(NamedKey::F4 as i32)),
|
||||||
|
5 => Some(MainKey::Key(NamedKey::F5 as i32)),
|
||||||
|
6 => Some(MainKey::Key(NamedKey::F6 as i32)),
|
||||||
|
7 => Some(MainKey::Key(NamedKey::F7 as i32)),
|
||||||
|
8 => Some(MainKey::Key(NamedKey::F8 as i32)),
|
||||||
|
9 => Some(MainKey::Key(NamedKey::F9 as i32)),
|
||||||
|
10 => Some(MainKey::Key(NamedKey::F10 as i32)),
|
||||||
|
11 => Some(MainKey::Key(NamedKey::F11 as i32)),
|
||||||
|
12 => Some(MainKey::Key(NamedKey::F12 as i32)),
|
||||||
|
_ => return Err("Invalid key"),
|
||||||
|
};
|
||||||
|
Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Key::Char(character) => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Char((character as u8) as i32)),
|
||||||
|
}),
|
||||||
|
Key::Alt(char_or_arrow) => {
|
||||||
|
let main_key = match char_or_arrow {
|
||||||
|
CharOrArrow::Char(character) => MainKey::Char((character as u8) as i32),
|
||||||
|
CharOrArrow::Direction(Direction::Left) => {
|
||||||
|
MainKey::Key(NamedKey::LeftArrow as i32)
|
||||||
|
},
|
||||||
|
CharOrArrow::Direction(Direction::Right) => {
|
||||||
|
MainKey::Key(NamedKey::RightArrow as i32)
|
||||||
|
},
|
||||||
|
CharOrArrow::Direction(Direction::Up) => MainKey::Key(NamedKey::UpArrow as i32),
|
||||||
|
CharOrArrow::Direction(Direction::Down) => {
|
||||||
|
MainKey::Key(NamedKey::DownArrow as i32)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Ok(ProtobufKey {
|
||||||
|
modifier: Some(KeyModifier::Alt as i32),
|
||||||
|
main_key: Some(main_key),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Key::Ctrl(character) => Ok(ProtobufKey {
|
||||||
|
modifier: Some(KeyModifier::Ctrl as i32),
|
||||||
|
main_key: Some(MainKey::Char((character as u8) as i32)),
|
||||||
|
}),
|
||||||
|
Key::BackTab => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::Tab as i32)),
|
||||||
|
}),
|
||||||
|
Key::Null => {
|
||||||
|
Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: None, // TODO: does this break deserialization?
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Key::Esc => Ok(ProtobufKey {
|
||||||
|
modifier: None,
|
||||||
|
main_key: Some(MainKey::Key(NamedKey::Esc as i32)),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CharOrArrow {
|
||||||
|
pub fn from_main_key(
|
||||||
|
main_key: std::option::Option<MainKey>,
|
||||||
|
) -> Result<CharOrArrow, &'static str> {
|
||||||
|
match main_key {
|
||||||
|
Some(MainKey::Char(encoded_key)) => {
|
||||||
|
Ok(CharOrArrow::Char(char_index_to_char(encoded_key)))
|
||||||
|
},
|
||||||
|
Some(MainKey::Key(key_index)) => match NamedKey::from_i32(key_index) {
|
||||||
|
Some(NamedKey::LeftArrow) => Ok(CharOrArrow::Direction(Direction::Left)),
|
||||||
|
Some(NamedKey::RightArrow) => Ok(CharOrArrow::Direction(Direction::Right)),
|
||||||
|
Some(NamedKey::UpArrow) => Ok(CharOrArrow::Direction(Direction::Up)),
|
||||||
|
Some(NamedKey::DownArrow) => Ok(CharOrArrow::Direction(Direction::Down)),
|
||||||
|
_ => Err("Unsupported key"),
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return Err("Unsupported key");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_optional_modifier(m: &ProtobufKey) -> Option<KeyModifier> {
|
||||||
|
match m.modifier {
|
||||||
|
Some(modifier) => KeyModifier::from_i32(modifier),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn char_index_to_char(char_index: i32) -> char {
|
||||||
|
char_index as u8 as char
|
||||||
|
}
|
||||||
|
|
||||||
|
fn char_from_main_key(main_key: Option<MainKey>) -> Result<char, &'static str> {
|
||||||
|
match main_key {
|
||||||
|
Some(MainKey::Char(encoded_key)) => {
|
||||||
|
return Ok(char_index_to_char(encoded_key));
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return Err("Unsupported key");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn named_key_to_key(named_key: NamedKey) -> Key {
|
||||||
|
match named_key {
|
||||||
|
NamedKey::PageDown => Key::PageDown,
|
||||||
|
NamedKey::PageUp => Key::PageUp,
|
||||||
|
NamedKey::LeftArrow => Key::Left,
|
||||||
|
NamedKey::DownArrow => Key::Down,
|
||||||
|
NamedKey::UpArrow => Key::Up,
|
||||||
|
NamedKey::RightArrow => Key::Right,
|
||||||
|
NamedKey::Home => Key::Home,
|
||||||
|
NamedKey::End => Key::End,
|
||||||
|
NamedKey::Backspace => Key::Backspace,
|
||||||
|
NamedKey::Delete => Key::Delete,
|
||||||
|
NamedKey::Insert => Key::Insert,
|
||||||
|
NamedKey::F1 => Key::F(1),
|
||||||
|
NamedKey::F2 => Key::F(2),
|
||||||
|
NamedKey::F3 => Key::F(3),
|
||||||
|
NamedKey::F4 => Key::F(4),
|
||||||
|
NamedKey::F5 => Key::F(5),
|
||||||
|
NamedKey::F6 => Key::F(6),
|
||||||
|
NamedKey::F7 => Key::F(7),
|
||||||
|
NamedKey::F8 => Key::F(8),
|
||||||
|
NamedKey::F9 => Key::F(9),
|
||||||
|
NamedKey::F10 => Key::F(10),
|
||||||
|
NamedKey::F11 => Key::F(11),
|
||||||
|
NamedKey::F12 => Key::F(12),
|
||||||
|
NamedKey::Tab => Key::BackTab,
|
||||||
|
NamedKey::Esc => Key::Esc,
|
||||||
|
}
|
||||||
|
}
|
||||||
9
zellij-utils/src/plugin_api/message.proto
Normal file
9
zellij-utils/src/plugin_api/message.proto
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package api.message;
|
||||||
|
|
||||||
|
message Message {
|
||||||
|
string name = 1;
|
||||||
|
string payload = 2;
|
||||||
|
optional string worker_name = 3;
|
||||||
|
}
|
||||||
29
zellij-utils/src/plugin_api/message.rs
Normal file
29
zellij-utils/src/plugin_api/message.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
pub use super::generated_api::api::message::Message as ProtobufMessage;
|
||||||
|
use crate::data::PluginMessage;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufMessage> for PluginMessage {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_message: ProtobufMessage) -> Result<Self, &'static str> {
|
||||||
|
let name = protobuf_message.name;
|
||||||
|
let payload = protobuf_message.payload;
|
||||||
|
let worker_name = protobuf_message.worker_name;
|
||||||
|
Ok(PluginMessage {
|
||||||
|
name,
|
||||||
|
payload,
|
||||||
|
worker_name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PluginMessage> for ProtobufMessage {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(plugin_message: PluginMessage) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufMessage {
|
||||||
|
name: plugin_message.name,
|
||||||
|
payload: plugin_message.payload,
|
||||||
|
worker_name: plugin_message.worker_name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
14
zellij-utils/src/plugin_api/mod.rs
Normal file
14
zellij-utils/src/plugin_api/mod.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
pub mod action;
|
||||||
|
pub mod command;
|
||||||
|
pub mod event;
|
||||||
|
pub mod file;
|
||||||
|
pub mod input_mode;
|
||||||
|
pub mod key;
|
||||||
|
pub mod message;
|
||||||
|
pub mod plugin_command;
|
||||||
|
pub mod plugin_ids;
|
||||||
|
pub mod resize;
|
||||||
|
pub mod style;
|
||||||
|
pub mod generated_api {
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/generated_plugin_api.rs"));
|
||||||
|
}
|
||||||
175
zellij-utils/src/plugin_api/plugin_command.proto
Normal file
175
zellij-utils/src/plugin_api/plugin_command.proto
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "event.proto";
|
||||||
|
import "file.proto";
|
||||||
|
import "command.proto";
|
||||||
|
import "message.proto";
|
||||||
|
import "input_mode.proto";
|
||||||
|
import "resize.proto";
|
||||||
|
|
||||||
|
package api.plugin_command;
|
||||||
|
|
||||||
|
enum CommandName {
|
||||||
|
Subscribe = 0;
|
||||||
|
Unsubscribe = 1;
|
||||||
|
SetSelectable = 2;
|
||||||
|
GetPluginIds = 3;
|
||||||
|
GetZellijVersion = 4;
|
||||||
|
OpenFile = 5;
|
||||||
|
OpenFileFloating = 6;
|
||||||
|
OpenTerminal = 7;
|
||||||
|
OpenTerminalFloating = 8;
|
||||||
|
OpenCommandPane = 9;
|
||||||
|
OpenCommandPaneFloating = 10;
|
||||||
|
SwitchTabTo = 11;
|
||||||
|
SetTimeout = 12;
|
||||||
|
ExecCmd = 13;
|
||||||
|
PostMessageTo = 14;
|
||||||
|
PostMessageToPlugin = 15;
|
||||||
|
HideSelf = 16;
|
||||||
|
ShowSelf = 17;
|
||||||
|
SwitchToMode = 18;
|
||||||
|
NewTabsWithLayout = 19;
|
||||||
|
NewTab = 20;
|
||||||
|
GoToNextTab = 21;
|
||||||
|
GoToPreviousTab = 22;
|
||||||
|
Resize = 23;
|
||||||
|
ResizeWithDirection = 24;
|
||||||
|
FocusNextPane = 25;
|
||||||
|
FocusPreviousPane = 26;
|
||||||
|
MoveFocus = 27;
|
||||||
|
MoveFocusOrTab = 28;
|
||||||
|
Detach = 29;
|
||||||
|
EditScrollback = 30;
|
||||||
|
Write = 31;
|
||||||
|
WriteChars = 32;
|
||||||
|
ToggleTab = 33;
|
||||||
|
MovePane = 34;
|
||||||
|
MovePaneWithDirection = 35;
|
||||||
|
ClearScreen = 36;
|
||||||
|
ScrollUp = 37;
|
||||||
|
ScrollDown = 38;
|
||||||
|
ScrollToTop = 39;
|
||||||
|
ScrollToBottom = 40;
|
||||||
|
PageScrollUp = 41;
|
||||||
|
PageScrollDown = 42;
|
||||||
|
ToggleFocusFullscreen = 43;
|
||||||
|
TogglePaneFrames = 44;
|
||||||
|
TogglePaneEmbedOrEject = 45;
|
||||||
|
UndoRenamePane = 46;
|
||||||
|
CloseFocus = 47;
|
||||||
|
ToggleActiveTabSync = 48;
|
||||||
|
CloseFocusedTab = 49;
|
||||||
|
UndoRenameTab = 50;
|
||||||
|
QuitZellij = 51;
|
||||||
|
PreviousSwapLayout = 52;
|
||||||
|
NextSwapLayout = 53;
|
||||||
|
GoToTabName = 54;
|
||||||
|
FocusOrCreateTab = 55;
|
||||||
|
GoToTab = 56;
|
||||||
|
StartOrReloadPlugin = 57;
|
||||||
|
CloseTerminalPane = 58;
|
||||||
|
ClosePluginPane = 59;
|
||||||
|
FocusTerminalPane = 60;
|
||||||
|
FocusPluginPane = 61;
|
||||||
|
RenameTerminalPane = 62;
|
||||||
|
RenamePluginPane = 63;
|
||||||
|
RenameTab = 64;
|
||||||
|
ReportCrash = 65;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PluginCommand {
|
||||||
|
CommandName name = 1;
|
||||||
|
oneof payload {
|
||||||
|
SubscribePayload subscribe_payload = 2;
|
||||||
|
UnsubscribePayload unsubscribe_payload = 3;
|
||||||
|
bool set_selectable_payload = 4;
|
||||||
|
OpenFilePayload open_file_payload = 5;
|
||||||
|
OpenFilePayload open_file_floating_payload = 6;
|
||||||
|
OpenFilePayload open_terminal_payload = 7;
|
||||||
|
OpenFilePayload open_terminal_floating_payload = 8;
|
||||||
|
OpenCommandPanePayload open_command_pane_payload = 9;
|
||||||
|
OpenCommandPanePayload open_command_pane_floating_payload = 10;
|
||||||
|
SwitchTabToPayload switch_tab_to_payload = 11;
|
||||||
|
SetTimeoutPayload set_timeout_payload = 12;
|
||||||
|
ExecCmdPayload exec_cmd_payload = 13;
|
||||||
|
PluginMessagePayload post_message_to_payload = 14;
|
||||||
|
PluginMessagePayload post_message_to_plugin_payload = 15;
|
||||||
|
bool show_self_payload = 16;
|
||||||
|
SwitchToModePayload switch_to_mode_payload = 17;
|
||||||
|
string new_tabs_with_layout_payload = 18;
|
||||||
|
ResizePayload resize_payload = 19;
|
||||||
|
ResizePayload resize_with_direction_payload = 20;
|
||||||
|
MovePayload move_focus_payload = 21;
|
||||||
|
MovePayload move_focus_or_tab_payload = 22;
|
||||||
|
bytes write_payload = 23;
|
||||||
|
string write_chars_payload = 24;
|
||||||
|
MovePayload move_pane_with_direction_payload = 25;
|
||||||
|
string go_to_tab_name_payload = 26;
|
||||||
|
string focus_or_create_tab_payload = 27;
|
||||||
|
int32 go_to_tab_payload = 28;
|
||||||
|
string start_or_reload_plugin_payload = 29;
|
||||||
|
int32 close_terminal_pane_payload = 30;
|
||||||
|
int32 close_plugin_pane_payload = 31;
|
||||||
|
PaneIdAndShouldFloat focus_terminal_pane_payload = 32;
|
||||||
|
PaneIdAndShouldFloat focus_plugin_pane_payload = 33;
|
||||||
|
IdAndNewName rename_terminal_pane_payload = 34;
|
||||||
|
IdAndNewName rename_plugin_pane_payload = 35;
|
||||||
|
IdAndNewName rename_tab_payload = 36;
|
||||||
|
string report_crash_payload = 37;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message SubscribePayload {
|
||||||
|
event.EventNameList subscriptions = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UnsubscribePayload {
|
||||||
|
event.EventNameList subscriptions = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OpenFilePayload {
|
||||||
|
file.File file_to_open = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OpenCommandPanePayload {
|
||||||
|
command.Command command_to_run = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchTabToPayload {
|
||||||
|
int32 tab_index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SetTimeoutPayload {
|
||||||
|
float seconds = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExecCmdPayload {
|
||||||
|
repeated string command_line = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PluginMessagePayload {
|
||||||
|
api.message.Message message = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchToModePayload {
|
||||||
|
input_mode.InputModeMessage input_mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResizePayload {
|
||||||
|
resize.Resize resize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MovePayload {
|
||||||
|
resize.MoveDirection direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PaneIdAndShouldFloat {
|
||||||
|
int32 pane_id = 1;
|
||||||
|
bool should_float = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message IdAndNewName {
|
||||||
|
int32 id = 1; // pane id or tab index
|
||||||
|
string new_name = 2;
|
||||||
|
}
|
||||||
825
zellij-utils/src/plugin_api/plugin_command.rs
Normal file
825
zellij-utils/src/plugin_api/plugin_command.rs
Normal file
|
|
@ -0,0 +1,825 @@
|
||||||
|
pub use super::generated_api::api::{
|
||||||
|
event::EventNameList as ProtobufEventNameList,
|
||||||
|
plugin_command::{
|
||||||
|
plugin_command::Payload, CommandName, ExecCmdPayload, IdAndNewName, MovePayload,
|
||||||
|
OpenCommandPanePayload, OpenFilePayload, PaneIdAndShouldFloat,
|
||||||
|
PluginCommand as ProtobufPluginCommand, PluginMessagePayload, ResizePayload,
|
||||||
|
SetTimeoutPayload, SubscribePayload, SwitchTabToPayload, SwitchToModePayload,
|
||||||
|
UnsubscribePayload,
|
||||||
|
},
|
||||||
|
resize::ResizeAction as ProtobufResizeAction,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::data::PluginCommand;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_plugin_command: ProtobufPluginCommand) -> Result<Self, &'static str> {
|
||||||
|
match CommandName::from_i32(protobuf_plugin_command.name) {
|
||||||
|
Some(CommandName::Subscribe) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::SubscribePayload(subscribe_payload)) => {
|
||||||
|
let protobuf_event_list = subscribe_payload.subscriptions;
|
||||||
|
match protobuf_event_list {
|
||||||
|
Some(protobuf_event_list) => {
|
||||||
|
Ok(PluginCommand::Subscribe(protobuf_event_list.try_into()?))
|
||||||
|
},
|
||||||
|
None => Err("malformed subscription event"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for Subscribe"),
|
||||||
|
},
|
||||||
|
Some(CommandName::Unsubscribe) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::UnsubscribePayload(unsubscribe_payload)) => {
|
||||||
|
let protobuf_event_list = unsubscribe_payload.subscriptions;
|
||||||
|
match protobuf_event_list {
|
||||||
|
Some(protobuf_event_list) => {
|
||||||
|
Ok(PluginCommand::Unsubscribe(protobuf_event_list.try_into()?))
|
||||||
|
},
|
||||||
|
None => Err("malformed unsubscription event"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for Unsubscribe"),
|
||||||
|
},
|
||||||
|
Some(CommandName::SetSelectable) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::SetSelectablePayload(should_be_selectable)) => {
|
||||||
|
Ok(PluginCommand::SetSelectable(should_be_selectable))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for SetSelectable"),
|
||||||
|
},
|
||||||
|
Some(CommandName::GetPluginIds) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
Err("GetPluginIds should not have a payload")
|
||||||
|
} else {
|
||||||
|
Ok(PluginCommand::GetPluginIds)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(CommandName::GetZellijVersion) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
Err("GetZellijVersion should not have a payload")
|
||||||
|
} else {
|
||||||
|
Ok(PluginCommand::GetZellijVersion)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(CommandName::OpenFile) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::OpenFilePayload(file_to_open_payload)) => {
|
||||||
|
match file_to_open_payload.file_to_open {
|
||||||
|
Some(file_to_open) => Ok(PluginCommand::OpenFile(file_to_open.try_into()?)),
|
||||||
|
None => Err("Malformed open file payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for OpenFile"),
|
||||||
|
},
|
||||||
|
Some(CommandName::OpenFileFloating) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::OpenFileFloatingPayload(file_to_open_payload)) => {
|
||||||
|
match file_to_open_payload.file_to_open {
|
||||||
|
Some(file_to_open) => {
|
||||||
|
Ok(PluginCommand::OpenFileFloating(file_to_open.try_into()?))
|
||||||
|
},
|
||||||
|
None => Err("Malformed open file payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for OpenFile"),
|
||||||
|
},
|
||||||
|
Some(CommandName::OpenTerminal) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::OpenTerminalPayload(file_to_open_payload)) => {
|
||||||
|
match file_to_open_payload.file_to_open {
|
||||||
|
Some(file_to_open) => {
|
||||||
|
Ok(PluginCommand::OpenTerminal(file_to_open.try_into()?))
|
||||||
|
},
|
||||||
|
None => Err("Malformed open terminal payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for OpenTerminal"),
|
||||||
|
},
|
||||||
|
Some(CommandName::OpenTerminalFloating) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::OpenTerminalFloatingPayload(file_to_open_payload)) => {
|
||||||
|
match file_to_open_payload.file_to_open {
|
||||||
|
Some(file_to_open) => Ok(PluginCommand::OpenTerminalFloating(
|
||||||
|
file_to_open.try_into()?,
|
||||||
|
)),
|
||||||
|
None => Err("Malformed open terminal floating payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for OpenTerminalFloating"),
|
||||||
|
},
|
||||||
|
Some(CommandName::OpenCommandPane) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::OpenCommandPanePayload(command_to_run_payload)) => {
|
||||||
|
match command_to_run_payload.command_to_run {
|
||||||
|
Some(command_to_run) => {
|
||||||
|
Ok(PluginCommand::OpenCommandPane(command_to_run.try_into()?))
|
||||||
|
},
|
||||||
|
None => Err("Malformed open open command pane payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for OpenCommandPane"),
|
||||||
|
},
|
||||||
|
Some(CommandName::OpenCommandPaneFloating) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::OpenCommandPaneFloatingPayload(command_to_run_payload)) => {
|
||||||
|
match command_to_run_payload.command_to_run {
|
||||||
|
Some(command_to_run) => Ok(PluginCommand::OpenCommandPaneFloating(
|
||||||
|
command_to_run.try_into()?,
|
||||||
|
)),
|
||||||
|
None => Err("Malformed open command pane floating payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for OpenCommandPaneFloating"),
|
||||||
|
},
|
||||||
|
Some(CommandName::SwitchTabTo) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::SwitchTabToPayload(switch_to_tab_payload)) => Ok(
|
||||||
|
PluginCommand::SwitchTabTo(switch_to_tab_payload.tab_index as u32),
|
||||||
|
),
|
||||||
|
_ => Err("Mismatched payload for SwitchToTab"),
|
||||||
|
},
|
||||||
|
Some(CommandName::SetTimeout) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::SetTimeoutPayload(set_timeout_payload)) => {
|
||||||
|
Ok(PluginCommand::SetTimeout(set_timeout_payload.seconds))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for SetTimeout"),
|
||||||
|
},
|
||||||
|
Some(CommandName::ExecCmd) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::ExecCmdPayload(exec_cmd_payload)) => {
|
||||||
|
Ok(PluginCommand::ExecCmd(exec_cmd_payload.command_line))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for ExecCmd"),
|
||||||
|
},
|
||||||
|
Some(CommandName::PostMessageTo) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::PostMessageToPayload(post_message_to_payload)) => {
|
||||||
|
match post_message_to_payload.message {
|
||||||
|
Some(message) => Ok(PluginCommand::PostMessageTo(message.try_into()?)),
|
||||||
|
None => Err("Malformed post message to payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for PostMessageTo"),
|
||||||
|
},
|
||||||
|
Some(CommandName::PostMessageToPlugin) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::PostMessageToPluginPayload(post_message_to_payload)) => {
|
||||||
|
match post_message_to_payload.message {
|
||||||
|
Some(message) => {
|
||||||
|
Ok(PluginCommand::PostMessageToPlugin(message.try_into()?))
|
||||||
|
},
|
||||||
|
None => Err("Malformed post message to plugin payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for PostMessageToPlugin"),
|
||||||
|
},
|
||||||
|
Some(CommandName::HideSelf) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("HideSelf should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::HideSelf)
|
||||||
|
},
|
||||||
|
Some(CommandName::ShowSelf) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::ShowSelfPayload(should_float_if_hidden)) => {
|
||||||
|
Ok(PluginCommand::ShowSelf(should_float_if_hidden))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for ShowSelf"),
|
||||||
|
},
|
||||||
|
Some(CommandName::SwitchToMode) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::SwitchToModePayload(switch_to_mode_payload)) => {
|
||||||
|
match switch_to_mode_payload.input_mode {
|
||||||
|
Some(input_mode) => Ok(PluginCommand::SwitchToMode(input_mode.try_into()?)),
|
||||||
|
None => Err("Malformed switch to mode payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for SwitchToMode"),
|
||||||
|
},
|
||||||
|
Some(CommandName::NewTabsWithLayout) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::NewTabsWithLayoutPayload(raw_layout)) => {
|
||||||
|
Ok(PluginCommand::NewTabsWithLayout(raw_layout))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for NewTabsWithLayout"),
|
||||||
|
},
|
||||||
|
Some(CommandName::NewTab) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("NewTab should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::NewTab)
|
||||||
|
},
|
||||||
|
Some(CommandName::GoToNextTab) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("GoToNextTab should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::GoToNextTab)
|
||||||
|
},
|
||||||
|
Some(CommandName::GoToPreviousTab) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("GoToPreviousTab should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::GoToPreviousTab)
|
||||||
|
},
|
||||||
|
Some(CommandName::Resize) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::ResizePayload(resize_payload)) => match resize_payload.resize {
|
||||||
|
Some(resize) => Ok(PluginCommand::Resize(resize.try_into()?)),
|
||||||
|
None => Err("Malformed switch resize payload"),
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for Resize"),
|
||||||
|
},
|
||||||
|
Some(CommandName::ResizeWithDirection) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::ResizeWithDirectionPayload(resize_with_direction_payload)) => {
|
||||||
|
match resize_with_direction_payload.resize {
|
||||||
|
Some(resize) => Ok(PluginCommand::ResizeWithDirection(resize.try_into()?)),
|
||||||
|
None => Err("Malformed switch resize payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for Resize"),
|
||||||
|
},
|
||||||
|
Some(CommandName::FocusNextPane) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("FocusNextPane should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::FocusNextPane)
|
||||||
|
},
|
||||||
|
Some(CommandName::FocusPreviousPane) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("FocusPreviousPane should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::FocusPreviousPane)
|
||||||
|
},
|
||||||
|
Some(CommandName::MoveFocus) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::MoveFocusPayload(move_payload)) => match move_payload.direction {
|
||||||
|
Some(direction) => Ok(PluginCommand::MoveFocus(direction.try_into()?)),
|
||||||
|
None => Err("Malformed move focus payload"),
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for MoveFocus"),
|
||||||
|
},
|
||||||
|
Some(CommandName::MoveFocusOrTab) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::MoveFocusOrTabPayload(move_payload)) => {
|
||||||
|
match move_payload.direction {
|
||||||
|
Some(direction) => Ok(PluginCommand::MoveFocusOrTab(direction.try_into()?)),
|
||||||
|
None => Err("Malformed move focus or tab payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for MoveFocusOrTab"),
|
||||||
|
},
|
||||||
|
Some(CommandName::Detach) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("Detach should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::Detach)
|
||||||
|
},
|
||||||
|
Some(CommandName::EditScrollback) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("EditScrollback should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::EditScrollback)
|
||||||
|
},
|
||||||
|
Some(CommandName::Write) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::WritePayload(bytes)) => Ok(PluginCommand::Write(bytes)),
|
||||||
|
_ => Err("Mismatched payload for Write"),
|
||||||
|
},
|
||||||
|
Some(CommandName::WriteChars) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::WriteCharsPayload(chars)) => Ok(PluginCommand::WriteChars(chars)),
|
||||||
|
_ => Err("Mismatched payload for WriteChars"),
|
||||||
|
},
|
||||||
|
Some(CommandName::ToggleTab) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("ToggleTab should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::ToggleTab)
|
||||||
|
},
|
||||||
|
Some(CommandName::MovePane) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("MovePane should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::MovePane)
|
||||||
|
},
|
||||||
|
Some(CommandName::MovePaneWithDirection) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::MovePaneWithDirectionPayload(move_payload)) => {
|
||||||
|
match move_payload.direction {
|
||||||
|
Some(direction) => {
|
||||||
|
Ok(PluginCommand::MovePaneWithDirection(direction.try_into()?))
|
||||||
|
},
|
||||||
|
None => Err("Malformed MovePaneWithDirection payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for MovePaneWithDirection"),
|
||||||
|
},
|
||||||
|
Some(CommandName::ClearScreen) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("ClearScreen should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::ClearScreen)
|
||||||
|
},
|
||||||
|
Some(CommandName::ScrollUp) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("ScrollUp should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::ScrollUp)
|
||||||
|
},
|
||||||
|
Some(CommandName::ScrollDown) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("ScrollDown should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::ScrollDown)
|
||||||
|
},
|
||||||
|
Some(CommandName::ScrollToTop) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("ScrollToTop should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::ScrollToTop)
|
||||||
|
},
|
||||||
|
Some(CommandName::ScrollToBottom) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("ScrollToBottom should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::ScrollToBottom)
|
||||||
|
},
|
||||||
|
Some(CommandName::PageScrollUp) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("PageScrollUp should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::PageScrollUp)
|
||||||
|
},
|
||||||
|
Some(CommandName::PageScrollDown) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("PageScrollDown should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::PageScrollDown)
|
||||||
|
},
|
||||||
|
Some(CommandName::ToggleFocusFullscreen) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("ToggleFocusFullscreen should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::ToggleFocusFullscreen)
|
||||||
|
},
|
||||||
|
Some(CommandName::TogglePaneFrames) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("TogglePaneFrames should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::TogglePaneFrames)
|
||||||
|
},
|
||||||
|
Some(CommandName::TogglePaneEmbedOrEject) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("TogglePaneEmbedOrEject should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::TogglePaneEmbedOrEject)
|
||||||
|
},
|
||||||
|
Some(CommandName::UndoRenamePane) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("UndoRenamePane should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::UndoRenamePane)
|
||||||
|
},
|
||||||
|
Some(CommandName::CloseFocus) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("CloseFocus should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::CloseFocus)
|
||||||
|
},
|
||||||
|
Some(CommandName::ToggleActiveTabSync) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("ToggleActiveTabSync should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::ToggleActiveTabSync)
|
||||||
|
},
|
||||||
|
Some(CommandName::CloseFocusedTab) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("CloseFocusedTab should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::CloseFocusedTab)
|
||||||
|
},
|
||||||
|
Some(CommandName::UndoRenameTab) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("UndoRenameTab should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::UndoRenameTab)
|
||||||
|
},
|
||||||
|
Some(CommandName::QuitZellij) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("QuitZellij should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::QuitZellij)
|
||||||
|
},
|
||||||
|
Some(CommandName::PreviousSwapLayout) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("PreviousSwapLayout should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::PreviousSwapLayout)
|
||||||
|
},
|
||||||
|
Some(CommandName::NextSwapLayout) => {
|
||||||
|
if protobuf_plugin_command.payload.is_some() {
|
||||||
|
return Err("NextSwapLayout should not have a payload");
|
||||||
|
}
|
||||||
|
Ok(PluginCommand::NextSwapLayout)
|
||||||
|
},
|
||||||
|
Some(CommandName::GoToTabName) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::GoToTabNamePayload(tab_name)) => {
|
||||||
|
Ok(PluginCommand::GoToTabName(tab_name))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for GoToTabName"),
|
||||||
|
},
|
||||||
|
Some(CommandName::FocusOrCreateTab) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::FocusOrCreateTabPayload(tab_name)) => {
|
||||||
|
Ok(PluginCommand::FocusOrCreateTab(tab_name))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for FocusOrCreateTab"),
|
||||||
|
},
|
||||||
|
Some(CommandName::GoToTab) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::GoToTabPayload(tab_index)) => {
|
||||||
|
Ok(PluginCommand::GoToTab(tab_index as u32))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for GoToTab"),
|
||||||
|
},
|
||||||
|
Some(CommandName::StartOrReloadPlugin) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::StartOrReloadPluginPayload(url)) => {
|
||||||
|
Ok(PluginCommand::StartOrReloadPlugin(url))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for StartOrReloadPlugin"),
|
||||||
|
},
|
||||||
|
Some(CommandName::CloseTerminalPane) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::CloseTerminalPanePayload(pane_id)) => {
|
||||||
|
Ok(PluginCommand::CloseTerminalPane(pane_id as u32))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for CloseTerminalPane"),
|
||||||
|
},
|
||||||
|
Some(CommandName::ClosePluginPane) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::ClosePluginPanePayload(pane_id)) => {
|
||||||
|
Ok(PluginCommand::ClosePluginPane(pane_id as u32))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for ClosePluginPane"),
|
||||||
|
},
|
||||||
|
Some(CommandName::FocusTerminalPane) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::FocusTerminalPanePayload(payload)) => {
|
||||||
|
let pane_id = payload.pane_id as u32;
|
||||||
|
let should_float = payload.should_float;
|
||||||
|
Ok(PluginCommand::FocusTerminalPane(pane_id, should_float))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for ClosePluginPane"),
|
||||||
|
},
|
||||||
|
Some(CommandName::FocusPluginPane) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::FocusPluginPanePayload(payload)) => {
|
||||||
|
let pane_id = payload.pane_id as u32;
|
||||||
|
let should_float = payload.should_float;
|
||||||
|
Ok(PluginCommand::FocusPluginPane(pane_id, should_float))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for ClosePluginPane"),
|
||||||
|
},
|
||||||
|
Some(CommandName::RenameTerminalPane) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::RenameTerminalPanePayload(payload)) => {
|
||||||
|
let pane_id = payload.id as u32;
|
||||||
|
let new_name = payload.new_name;
|
||||||
|
Ok(PluginCommand::RenameTerminalPane(pane_id, new_name))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for RenameTerminalPane"),
|
||||||
|
},
|
||||||
|
Some(CommandName::RenamePluginPane) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::RenamePluginPanePayload(payload)) => {
|
||||||
|
let pane_id = payload.id as u32;
|
||||||
|
let new_name = payload.new_name;
|
||||||
|
Ok(PluginCommand::RenamePluginPane(pane_id, new_name))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for RenamePluginPane"),
|
||||||
|
},
|
||||||
|
Some(CommandName::RenameTab) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::RenameTabPayload(payload)) => {
|
||||||
|
let tab_index = payload.id as u32;
|
||||||
|
let name = payload.new_name;
|
||||||
|
Ok(PluginCommand::RenameTab(tab_index, name))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for RenameTab"),
|
||||||
|
},
|
||||||
|
Some(CommandName::ReportCrash) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::ReportCrashPayload(payload)) => {
|
||||||
|
Ok(PluginCommand::ReportPanic(payload))
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for ReportCrash"),
|
||||||
|
},
|
||||||
|
None => Err("Unrecognized plugin command"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(plugin_command: PluginCommand) -> Result<Self, &'static str> {
|
||||||
|
match plugin_command {
|
||||||
|
PluginCommand::Subscribe(subscriptions) => {
|
||||||
|
let subscriptions: ProtobufEventNameList = subscriptions.try_into()?;
|
||||||
|
Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::Subscribe as i32,
|
||||||
|
payload: Some(Payload::SubscribePayload(SubscribePayload {
|
||||||
|
subscriptions: Some(subscriptions),
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
PluginCommand::Unsubscribe(subscriptions) => {
|
||||||
|
let subscriptions: ProtobufEventNameList = subscriptions.try_into()?;
|
||||||
|
Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::Unsubscribe as i32,
|
||||||
|
payload: Some(Payload::UnsubscribePayload(UnsubscribePayload {
|
||||||
|
subscriptions: Some(subscriptions),
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
PluginCommand::SetSelectable(should_be_selectable) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::SetSelectable as i32,
|
||||||
|
payload: Some(Payload::SetSelectablePayload(should_be_selectable)),
|
||||||
|
}),
|
||||||
|
PluginCommand::GetPluginIds => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::GetPluginIds as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::GetZellijVersion => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::GetZellijVersion as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::OpenFile(file_to_open) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::OpenFile as i32,
|
||||||
|
payload: Some(Payload::OpenFilePayload(OpenFilePayload {
|
||||||
|
file_to_open: Some(file_to_open.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::OpenFileFloating(file_to_open) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::OpenFileFloating as i32,
|
||||||
|
payload: Some(Payload::OpenFileFloatingPayload(OpenFilePayload {
|
||||||
|
file_to_open: Some(file_to_open.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::OpenTerminal(cwd) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::OpenTerminal as i32,
|
||||||
|
payload: Some(Payload::OpenTerminalPayload(OpenFilePayload {
|
||||||
|
file_to_open: Some(cwd.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::OpenTerminalFloating(cwd) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::OpenTerminalFloating as i32,
|
||||||
|
payload: Some(Payload::OpenTerminalFloatingPayload(OpenFilePayload {
|
||||||
|
file_to_open: Some(cwd.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::OpenCommandPane(command_to_run) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::OpenCommandPane as i32,
|
||||||
|
payload: Some(Payload::OpenCommandPanePayload(OpenCommandPanePayload {
|
||||||
|
command_to_run: Some(command_to_run.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::OpenCommandPaneFloating(command_to_run) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::OpenCommandPaneFloating as i32,
|
||||||
|
payload: Some(Payload::OpenCommandPaneFloatingPayload(
|
||||||
|
OpenCommandPanePayload {
|
||||||
|
command_to_run: Some(command_to_run.try_into()?),
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
}),
|
||||||
|
PluginCommand::SwitchTabTo(tab_index) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::SwitchTabTo as i32,
|
||||||
|
payload: Some(Payload::SwitchTabToPayload(SwitchTabToPayload {
|
||||||
|
tab_index: tab_index as i32,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::SetTimeout(seconds) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::SetTimeout as i32,
|
||||||
|
payload: Some(Payload::SetTimeoutPayload(SetTimeoutPayload { seconds })),
|
||||||
|
}),
|
||||||
|
PluginCommand::ExecCmd(command_line) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ExecCmd as i32,
|
||||||
|
payload: Some(Payload::ExecCmdPayload(ExecCmdPayload { command_line })),
|
||||||
|
}),
|
||||||
|
PluginCommand::PostMessageTo(plugin_message) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::PostMessageTo as i32,
|
||||||
|
payload: Some(Payload::PostMessageToPayload(PluginMessagePayload {
|
||||||
|
message: Some(plugin_message.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::PostMessageToPlugin(plugin_message) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::PostMessageToPlugin as i32,
|
||||||
|
payload: Some(Payload::PostMessageToPluginPayload(PluginMessagePayload {
|
||||||
|
message: Some(plugin_message.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::HideSelf => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::HideSelf as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::ShowSelf(should_float_if_hidden) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ShowSelf as i32,
|
||||||
|
payload: Some(Payload::ShowSelfPayload(should_float_if_hidden)),
|
||||||
|
}),
|
||||||
|
PluginCommand::SwitchToMode(input_mode) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::SwitchToMode as i32,
|
||||||
|
payload: Some(Payload::SwitchToModePayload(SwitchToModePayload {
|
||||||
|
input_mode: Some(input_mode.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::NewTabsWithLayout(raw_layout) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::NewTabsWithLayout as i32,
|
||||||
|
payload: Some(Payload::NewTabsWithLayoutPayload(raw_layout)),
|
||||||
|
}),
|
||||||
|
PluginCommand::NewTab => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::NewTab as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::GoToNextTab => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::GoToNextTab as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::GoToPreviousTab => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::GoToPreviousTab as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::Resize(resize) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::Resize as i32,
|
||||||
|
payload: Some(Payload::ResizePayload(ResizePayload {
|
||||||
|
resize: Some(resize.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::ResizeWithDirection(resize) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ResizeWithDirection as i32,
|
||||||
|
payload: Some(Payload::ResizeWithDirectionPayload(ResizePayload {
|
||||||
|
resize: Some(resize.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::FocusNextPane => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::FocusNextPane as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::FocusPreviousPane => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::FocusPreviousPane as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::MoveFocus(direction) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::MoveFocus as i32,
|
||||||
|
payload: Some(Payload::MoveFocusPayload(MovePayload {
|
||||||
|
direction: Some(direction.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::MoveFocusOrTab(direction) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::MoveFocusOrTab as i32,
|
||||||
|
payload: Some(Payload::MoveFocusOrTabPayload(MovePayload {
|
||||||
|
direction: Some(direction.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::Detach => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::Detach as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::EditScrollback => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::EditScrollback as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::Write(bytes) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::Write as i32,
|
||||||
|
payload: Some(Payload::WritePayload(bytes)),
|
||||||
|
}),
|
||||||
|
PluginCommand::WriteChars(chars) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::WriteChars as i32,
|
||||||
|
payload: Some(Payload::WriteCharsPayload(chars)),
|
||||||
|
}),
|
||||||
|
PluginCommand::ToggleTab => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ToggleTab as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::MovePane => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::MovePane as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::MovePaneWithDirection(direction) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::MovePaneWithDirection as i32,
|
||||||
|
payload: Some(Payload::MovePaneWithDirectionPayload(MovePayload {
|
||||||
|
direction: Some(direction.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::ClearScreen => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ClearScreen as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::ScrollUp => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ScrollUp as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::ScrollDown => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ScrollDown as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::ScrollToTop => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ScrollToTop as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::ScrollToBottom => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ScrollToBottom as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::PageScrollUp => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::PageScrollUp as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::PageScrollDown => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::PageScrollDown as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::ToggleFocusFullscreen => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ToggleFocusFullscreen as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::TogglePaneFrames => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::TogglePaneFrames as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::TogglePaneEmbedOrEject => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::TogglePaneEmbedOrEject as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::UndoRenamePane => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::UndoRenamePane as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::CloseFocus => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::CloseFocus as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::ToggleActiveTabSync => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ToggleActiveTabSync as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::CloseFocusedTab => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::CloseFocusedTab as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::UndoRenameTab => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::UndoRenameTab as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::QuitZellij => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::QuitZellij as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::PreviousSwapLayout => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::PreviousSwapLayout as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::NextSwapLayout => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::NextSwapLayout as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
|
PluginCommand::GoToTabName(tab_name) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::GoToTabName as i32,
|
||||||
|
payload: Some(Payload::GoToTabNamePayload(tab_name)),
|
||||||
|
}),
|
||||||
|
PluginCommand::FocusOrCreateTab(tab_name) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::FocusOrCreateTab as i32,
|
||||||
|
payload: Some(Payload::FocusOrCreateTabPayload(tab_name)),
|
||||||
|
}),
|
||||||
|
PluginCommand::GoToTab(tab_index) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::GoToTab as i32,
|
||||||
|
payload: Some(Payload::GoToTabPayload(tab_index as i32)),
|
||||||
|
}),
|
||||||
|
PluginCommand::StartOrReloadPlugin(url) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::StartOrReloadPlugin as i32,
|
||||||
|
payload: Some(Payload::StartOrReloadPluginPayload(url)),
|
||||||
|
}),
|
||||||
|
PluginCommand::CloseTerminalPane(pane_id) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::CloseTerminalPane as i32,
|
||||||
|
payload: Some(Payload::CloseTerminalPanePayload(pane_id as i32)),
|
||||||
|
}),
|
||||||
|
PluginCommand::ClosePluginPane(pane_id) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ClosePluginPane as i32,
|
||||||
|
payload: Some(Payload::ClosePluginPanePayload(pane_id as i32)),
|
||||||
|
}),
|
||||||
|
PluginCommand::FocusTerminalPane(pane_id, should_float_if_hidden) => {
|
||||||
|
Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::FocusTerminalPane as i32,
|
||||||
|
payload: Some(Payload::FocusTerminalPanePayload(PaneIdAndShouldFloat {
|
||||||
|
pane_id: pane_id as i32,
|
||||||
|
should_float: should_float_if_hidden,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
PluginCommand::FocusPluginPane(pane_id, should_float_if_hidden) => {
|
||||||
|
Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::FocusPluginPane as i32,
|
||||||
|
payload: Some(Payload::FocusPluginPanePayload(PaneIdAndShouldFloat {
|
||||||
|
pane_id: pane_id as i32,
|
||||||
|
should_float: should_float_if_hidden,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
PluginCommand::RenameTerminalPane(pane_id, new_name) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::RenameTerminalPane as i32,
|
||||||
|
payload: Some(Payload::RenameTerminalPanePayload(IdAndNewName {
|
||||||
|
id: pane_id as i32,
|
||||||
|
new_name,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::RenamePluginPane(pane_id, new_name) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::RenamePluginPane as i32,
|
||||||
|
payload: Some(Payload::RenamePluginPanePayload(IdAndNewName {
|
||||||
|
id: pane_id as i32,
|
||||||
|
new_name,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::RenameTab(tab_index, new_name) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::RenameTab as i32,
|
||||||
|
payload: Some(Payload::RenameTabPayload(IdAndNewName {
|
||||||
|
id: tab_index as i32,
|
||||||
|
new_name,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
PluginCommand::ReportPanic(payload) => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::ReportCrash as i32,
|
||||||
|
payload: Some(Payload::ReportCrashPayload(payload)),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
zellij-utils/src/plugin_api/plugin_ids.proto
Normal file
12
zellij-utils/src/plugin_api/plugin_ids.proto
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package api.plugin_ids;
|
||||||
|
|
||||||
|
message PluginIds {
|
||||||
|
int32 plugin_id = 1;
|
||||||
|
int32 zellij_pid = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ZellijVersion {
|
||||||
|
string version = 1;
|
||||||
|
}
|
||||||
35
zellij-utils/src/plugin_api/plugin_ids.rs
Normal file
35
zellij-utils/src/plugin_api/plugin_ids.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
pub use super::generated_api::api::plugin_ids::{
|
||||||
|
PluginIds as ProtobufPluginIds, ZellijVersion as ProtobufZellijVersion,
|
||||||
|
};
|
||||||
|
use crate::data::PluginIds;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufPluginIds> for PluginIds {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_plugin_ids: ProtobufPluginIds) -> Result<Self, &'static str> {
|
||||||
|
Ok(PluginIds {
|
||||||
|
plugin_id: protobuf_plugin_ids.plugin_id as u32,
|
||||||
|
zellij_pid: protobuf_plugin_ids.zellij_pid as u32,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PluginIds> for ProtobufPluginIds {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(plugin_ids: PluginIds) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufPluginIds {
|
||||||
|
plugin_id: plugin_ids.plugin_id as i32,
|
||||||
|
zellij_pid: plugin_ids.zellij_pid as i32,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for ProtobufZellijVersion {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(zellij_version: &str) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufZellijVersion {
|
||||||
|
version: zellij_version.to_owned(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
24
zellij-utils/src/plugin_api/resize.proto
Normal file
24
zellij-utils/src/plugin_api/resize.proto
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package api.resize;
|
||||||
|
|
||||||
|
enum ResizeAction {
|
||||||
|
Increase = 0;
|
||||||
|
Decrease = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ResizeDirection {
|
||||||
|
Left = 0;
|
||||||
|
Right = 1;
|
||||||
|
Up = 2;
|
||||||
|
Down = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Resize {
|
||||||
|
ResizeAction resize_action = 1;
|
||||||
|
optional ResizeDirection direction = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MoveDirection {
|
||||||
|
ResizeDirection direction = 1;
|
||||||
|
}
|
||||||
130
zellij-utils/src/plugin_api/resize.rs
Normal file
130
zellij-utils/src/plugin_api/resize.rs
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
pub use super::generated_api::api::resize::{
|
||||||
|
MoveDirection as ProtobufMoveDirection, Resize as ProtobufResize, ResizeAction,
|
||||||
|
ResizeDirection, ResizeDirection as ProtobufResizeDirection,
|
||||||
|
};
|
||||||
|
use crate::data::{Direction, Resize, ResizeStrategy};
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufResize> for Resize {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_resize: ProtobufResize) -> Result<Self, &'static str> {
|
||||||
|
if protobuf_resize.direction.is_some() {
|
||||||
|
return Err("Resize cannot have a direction");
|
||||||
|
}
|
||||||
|
match ResizeAction::from_i32(protobuf_resize.resize_action) {
|
||||||
|
Some(ResizeAction::Increase) => Ok(Resize::Increase),
|
||||||
|
Some(ResizeAction::Decrease) => Ok(Resize::Decrease),
|
||||||
|
None => Err("No resize action for the given index"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Resize> for ProtobufResize {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(resize: Resize) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufResize {
|
||||||
|
resize_action: match resize {
|
||||||
|
Resize::Increase => ResizeAction::Increase as i32,
|
||||||
|
Resize::Decrease => ResizeAction::Decrease as i32,
|
||||||
|
},
|
||||||
|
direction: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufResize> for ResizeStrategy {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_resize: ProtobufResize) -> Result<Self, &'static str> {
|
||||||
|
let direction = match protobuf_resize
|
||||||
|
.direction
|
||||||
|
.and_then(|r| ResizeDirection::from_i32(r))
|
||||||
|
{
|
||||||
|
Some(ResizeDirection::Left) => Some(Direction::Left),
|
||||||
|
Some(ResizeDirection::Right) => Some(Direction::Right),
|
||||||
|
Some(ResizeDirection::Up) => Some(Direction::Up),
|
||||||
|
Some(ResizeDirection::Down) => Some(Direction::Down),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let resize = match ResizeAction::from_i32(protobuf_resize.resize_action) {
|
||||||
|
Some(ResizeAction::Increase) => Resize::Increase,
|
||||||
|
Some(ResizeAction::Decrease) => Resize::Decrease,
|
||||||
|
None => return Err("No resize action for the given index"),
|
||||||
|
};
|
||||||
|
Ok(ResizeStrategy {
|
||||||
|
direction,
|
||||||
|
resize,
|
||||||
|
invert_on_boundaries: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ResizeStrategy> for ProtobufResize {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(resize_strategy: ResizeStrategy) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufResize {
|
||||||
|
resize_action: match resize_strategy.resize {
|
||||||
|
Resize::Increase => ResizeAction::Increase as i32,
|
||||||
|
Resize::Decrease => ResizeAction::Decrease as i32,
|
||||||
|
},
|
||||||
|
direction: match resize_strategy.direction {
|
||||||
|
Some(Direction::Left) => Some(ResizeDirection::Left as i32),
|
||||||
|
Some(Direction::Right) => Some(ResizeDirection::Right as i32),
|
||||||
|
Some(Direction::Up) => Some(ResizeDirection::Up as i32),
|
||||||
|
Some(Direction::Down) => Some(ResizeDirection::Down as i32),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufMoveDirection> for Direction {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_move_direction: ProtobufMoveDirection) -> Result<Self, &'static str> {
|
||||||
|
match ResizeDirection::from_i32(protobuf_move_direction.direction) {
|
||||||
|
Some(ResizeDirection::Left) => Ok(Direction::Left),
|
||||||
|
Some(ResizeDirection::Right) => Ok(Direction::Right),
|
||||||
|
Some(ResizeDirection::Up) => Ok(Direction::Up),
|
||||||
|
Some(ResizeDirection::Down) => Ok(Direction::Down),
|
||||||
|
None => Err("No direction for the given index"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Direction> for ProtobufMoveDirection {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(direction: Direction) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufMoveDirection {
|
||||||
|
direction: match direction {
|
||||||
|
Direction::Left => ResizeDirection::Left as i32,
|
||||||
|
Direction::Right => ResizeDirection::Right as i32,
|
||||||
|
Direction::Up => ResizeDirection::Up as i32,
|
||||||
|
Direction::Down => ResizeDirection::Down as i32,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufResizeDirection> for Direction {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_resize_direction: ProtobufResizeDirection) -> Result<Self, &'static str> {
|
||||||
|
match protobuf_resize_direction {
|
||||||
|
ProtobufResizeDirection::Left => Ok(Direction::Left),
|
||||||
|
ProtobufResizeDirection::Right => Ok(Direction::Right),
|
||||||
|
ProtobufResizeDirection::Up => Ok(Direction::Up),
|
||||||
|
ProtobufResizeDirection::Down => Ok(Direction::Down),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Direction> for ProtobufResizeDirection {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(direction: Direction) -> Result<Self, &'static str> {
|
||||||
|
Ok(match direction {
|
||||||
|
Direction::Left => ProtobufResizeDirection::Left,
|
||||||
|
Direction::Right => ProtobufResizeDirection::Right,
|
||||||
|
Direction::Up => ProtobufResizeDirection::Up,
|
||||||
|
Direction::Down => ProtobufResizeDirection::Down,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
54
zellij-utils/src/plugin_api/style.proto
Normal file
54
zellij-utils/src/plugin_api/style.proto
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package api.style;
|
||||||
|
|
||||||
|
message Style {
|
||||||
|
Palette palette = 1;
|
||||||
|
bool rounded_corners = 2;
|
||||||
|
bool hide_session_name = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Palette {
|
||||||
|
ThemeHue theme_hue = 1;
|
||||||
|
Color fg = 2;
|
||||||
|
Color bg = 3;
|
||||||
|
Color black = 4;
|
||||||
|
Color red = 5;
|
||||||
|
Color green = 6;
|
||||||
|
Color yellow = 7;
|
||||||
|
Color blue = 8;
|
||||||
|
Color magenta = 9;
|
||||||
|
Color cyan = 10;
|
||||||
|
Color white = 11;
|
||||||
|
Color orange = 12;
|
||||||
|
Color gray = 13;
|
||||||
|
Color purple = 14;
|
||||||
|
Color gold = 15;
|
||||||
|
Color silver = 16;
|
||||||
|
Color pink = 17;
|
||||||
|
Color brown = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Color {
|
||||||
|
ColorType color_type = 1;
|
||||||
|
oneof payload {
|
||||||
|
RgbColorPayload rgb_color_payload = 2;
|
||||||
|
uint32 eight_bit_color_payload = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message RgbColorPayload {
|
||||||
|
uint32 red = 1;
|
||||||
|
uint32 green = 2;
|
||||||
|
uint32 blue = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ColorType {
|
||||||
|
Rgb = 0;
|
||||||
|
EightBit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ThemeHue {
|
||||||
|
Dark = 0;
|
||||||
|
Light = 1;
|
||||||
|
}
|
||||||
213
zellij-utils/src/plugin_api/style.rs
Normal file
213
zellij-utils/src/plugin_api/style.rs
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
use super::generated_api::api::style::{
|
||||||
|
color::Payload as ProtobufColorPayload, Color as ProtobufColor, ColorType as ProtobufColorType,
|
||||||
|
Palette as ProtobufPalette, RgbColorPayload as ProtobufRgbColorPayload, Style as ProtobufStyle,
|
||||||
|
ThemeHue as ProtobufThemeHue,
|
||||||
|
};
|
||||||
|
use crate::data::{Palette, PaletteColor, Style, ThemeHue};
|
||||||
|
use crate::errors::prelude::*;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufStyle> for Style {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_style: ProtobufStyle) -> Result<Self, &'static str> {
|
||||||
|
Ok(Style {
|
||||||
|
colors: protobuf_style
|
||||||
|
.palette
|
||||||
|
.ok_or("malformed style payload")?
|
||||||
|
.try_into()?,
|
||||||
|
rounded_corners: protobuf_style.rounded_corners,
|
||||||
|
hide_session_name: protobuf_style.hide_session_name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Style> for ProtobufStyle {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(style: Style) -> Result<Self, &'static str> {
|
||||||
|
Ok(ProtobufStyle {
|
||||||
|
palette: Some(style.colors.try_into()?),
|
||||||
|
rounded_corners: style.rounded_corners,
|
||||||
|
hide_session_name: style.hide_session_name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufPalette> for Palette {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_palette: ProtobufPalette) -> Result<Self, &'static str> {
|
||||||
|
Ok(Palette {
|
||||||
|
theme_hue: ProtobufThemeHue::from_i32(protobuf_palette.theme_hue)
|
||||||
|
.ok_or("malformed theme_hue payload for Palette")?
|
||||||
|
.try_into()?,
|
||||||
|
fg: protobuf_palette
|
||||||
|
.fg
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
bg: protobuf_palette
|
||||||
|
.bg
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
black: protobuf_palette
|
||||||
|
.black
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
red: protobuf_palette
|
||||||
|
.red
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
green: protobuf_palette
|
||||||
|
.green
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
yellow: protobuf_palette
|
||||||
|
.yellow
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
blue: protobuf_palette
|
||||||
|
.blue
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
magenta: protobuf_palette
|
||||||
|
.magenta
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
cyan: protobuf_palette
|
||||||
|
.cyan
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
white: protobuf_palette
|
||||||
|
.white
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
orange: protobuf_palette
|
||||||
|
.orange
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
gray: protobuf_palette
|
||||||
|
.gray
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
purple: protobuf_palette
|
||||||
|
.purple
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
gold: protobuf_palette
|
||||||
|
.gold
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
silver: protobuf_palette
|
||||||
|
.silver
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
pink: protobuf_palette
|
||||||
|
.pink
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
brown: protobuf_palette
|
||||||
|
.brown
|
||||||
|
.ok_or("malformed palette payload")?
|
||||||
|
.try_into()?,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Palette> for ProtobufPalette {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(palette: Palette) -> Result<Self, &'static str> {
|
||||||
|
let theme_hue: ProtobufThemeHue = palette
|
||||||
|
.theme_hue
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| "malformed payload for palette")?;
|
||||||
|
Ok(ProtobufPalette {
|
||||||
|
theme_hue: theme_hue as i32,
|
||||||
|
fg: Some(palette.fg.try_into()?),
|
||||||
|
bg: Some(palette.bg.try_into()?),
|
||||||
|
black: Some(palette.black.try_into()?),
|
||||||
|
red: Some(palette.red.try_into()?),
|
||||||
|
green: Some(palette.green.try_into()?),
|
||||||
|
yellow: Some(palette.yellow.try_into()?),
|
||||||
|
blue: Some(palette.blue.try_into()?),
|
||||||
|
magenta: Some(palette.magenta.try_into()?),
|
||||||
|
cyan: Some(palette.cyan.try_into()?),
|
||||||
|
white: Some(palette.white.try_into()?),
|
||||||
|
orange: Some(palette.orange.try_into()?),
|
||||||
|
gray: Some(palette.gray.try_into()?),
|
||||||
|
purple: Some(palette.purple.try_into()?),
|
||||||
|
gold: Some(palette.gold.try_into()?),
|
||||||
|
silver: Some(palette.silver.try_into()?),
|
||||||
|
pink: Some(palette.pink.try_into()?),
|
||||||
|
brown: Some(palette.brown.try_into()?),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufColor> for PaletteColor {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_color: ProtobufColor) -> Result<Self, &'static str> {
|
||||||
|
match ProtobufColorType::from_i32(protobuf_color.color_type) {
|
||||||
|
Some(ProtobufColorType::Rgb) => match protobuf_color.payload {
|
||||||
|
Some(ProtobufColorPayload::RgbColorPayload(rgb_color_payload)) => {
|
||||||
|
Ok(PaletteColor::Rgb((
|
||||||
|
rgb_color_payload.red as u8,
|
||||||
|
rgb_color_payload.green as u8,
|
||||||
|
rgb_color_payload.blue as u8,
|
||||||
|
)))
|
||||||
|
},
|
||||||
|
_ => Err("malformed payload for Rgb color"),
|
||||||
|
},
|
||||||
|
Some(ProtobufColorType::EightBit) => match protobuf_color.payload {
|
||||||
|
Some(ProtobufColorPayload::EightBitColorPayload(eight_bit_payload)) => {
|
||||||
|
Ok(PaletteColor::EightBit(eight_bit_payload as u8))
|
||||||
|
},
|
||||||
|
_ => Err("malformed payload for 8bit color"),
|
||||||
|
},
|
||||||
|
None => Err("malformed payload for Color"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PaletteColor> for ProtobufColor {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(color: PaletteColor) -> Result<Self, &'static str> {
|
||||||
|
match color {
|
||||||
|
PaletteColor::Rgb((red, green, blue)) => {
|
||||||
|
let red = red as u32;
|
||||||
|
let green = green as u32;
|
||||||
|
let blue = blue as u32;
|
||||||
|
Ok(ProtobufColor {
|
||||||
|
color_type: ProtobufColorType::Rgb as i32,
|
||||||
|
payload: Some(ProtobufColorPayload::RgbColorPayload(
|
||||||
|
ProtobufRgbColorPayload { red, green, blue },
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
PaletteColor::EightBit(color) => Ok(ProtobufColor {
|
||||||
|
color_type: ProtobufColorType::EightBit as i32,
|
||||||
|
payload: Some(ProtobufColorPayload::EightBitColorPayload(color as u32)),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ThemeHue> for ProtobufThemeHue {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(theme_hue: ThemeHue) -> Result<Self, &'static str> {
|
||||||
|
match theme_hue {
|
||||||
|
ThemeHue::Light => Ok(ProtobufThemeHue::Light),
|
||||||
|
ThemeHue::Dark => Ok(ProtobufThemeHue::Dark),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ProtobufThemeHue> for ThemeHue {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_theme_hue: ProtobufThemeHue) -> Result<Self, &'static str> {
|
||||||
|
match protobuf_theme_hue {
|
||||||
|
ProtobufThemeHue::Light => Ok(ThemeHue::Light),
|
||||||
|
ProtobufThemeHue::Dark => Ok(ThemeHue::Dark),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue