summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2023-06-14 13:44:46 +0200
committerGitHub <noreply@github.com>2023-06-14 13:44:46 +0200
commitf19334754cf1f8e6bd48bb9cdd905a2d5147e30e (patch)
tree6d29a1a05518c109bfc734edf34f3d178051196b
parent59239cc1133179e2825d98b5c2be7c6c3bfdcc9c (diff)
fix(plugins): allow loading relative urls (#2539)
* fix(plugins): allow loading relative urls * style(fmt): rustfmt
-rw-r--r--zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap11
-rw-r--r--zellij-server/src/plugins/zellij_exports.rs13
-rw-r--r--zellij-server/src/route.rs11
-rw-r--r--zellij-server/src/screen.rs8
-rw-r--r--zellij-utils/src/cli.rs2
-rw-r--r--zellij-utils/src/input/actions.rs29
-rw-r--r--zellij-utils/src/input/layout.rs23
-rw-r--r--zellij-utils/src/kdl/kdl_layout_parser.rs15
-rw-r--r--zellij-utils/src/kdl/mod.rs7
9 files changed, 73 insertions, 46 deletions
diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap
index 173b0ce46..72364a88e 100644
--- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap
+++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap
@@ -1,13 +1,16 @@
---
source: zellij-server/src/plugins/./unit/plugin_tests.rs
-assertion_line: 2496
+assertion_line: 2889
expression: "format!(\"{:#?}\", new_tab_event)"
---
Some(
StartOrReloadPluginPane(
- File(
- "/path/to/my/plugin.wasm",
- ),
+ RunPlugin {
+ _allow_exec_host_cmd: false,
+ location: File(
+ "/path/to/my/plugin.wasm",
+ ),
+ },
None,
),
)
diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs
index d4153ec8a..08d54c848 100644
--- a/zellij-server/src/plugins/zellij_exports.rs
+++ b/zellij-server/src/plugins/zellij_exports.rs
@@ -26,7 +26,7 @@ use zellij_utils::{
input::{
actions::Action,
command::{RunCommand, RunCommandAction, TerminalAction},
- layout::Layout,
+ layout::{Layout, RunPlugin, RunPluginLocation},
plugins::PluginType,
},
serde,
@@ -946,10 +946,19 @@ fn host_start_or_reload_plugin(env: &ForeignFunctionEnv) {
env.plugin_env.name()
)
};
+ let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
wasi_read_string(&env.plugin_env.wasi_env)
.and_then(|url| Url::parse(&url).map_err(|e| anyhow!("Failed to parse url: {}", e)))
.and_then(|url| {
- let action = Action::StartOrReloadPlugin(url);
+ RunPluginLocation::parse(url.as_str(), Some(cwd))
+ .map_err(|e| anyhow!("Failed to parse plugin location: {}", e))
+ })
+ .and_then(|run_plugin_location| {
+ let run_plugin = RunPlugin {
+ location: run_plugin_location,
+ _allow_exec_host_cmd: false,
+ };
+ let action = Action::StartOrReloadPlugin(run_plugin);
apply_action!(action, error_msg, env);
Ok(())
})
diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs
index 2d78ae745..7ff859462 100644
--- a/zellij-server/src/route.rs
+++ b/zellij-server/src/route.rs
@@ -17,7 +17,7 @@ use zellij_utils::{
actions::{Action, SearchDirection, SearchOption},
command::TerminalAction,
get_mode_info,
- layout::{Layout, RunPluginLocation},
+ layout::Layout,
},
ipc::{
ClientAttributes, ClientToServerMsg, ExitReason, IpcReceiverWithContext, ServerToClientMsg,
@@ -615,14 +615,9 @@ pub(crate) fn route_action(
))
.with_context(err_context)?;
},
- Action::StartOrReloadPlugin(url) => {
- let run_plugin_location =
- RunPluginLocation::parse(url.as_str()).with_context(err_context)?;
+ Action::StartOrReloadPlugin(run_plugin) => {
senders
- .send_to_screen(ScreenInstruction::StartOrReloadPluginPane(
- run_plugin_location,
- None,
- ))
+ .send_to_screen(ScreenInstruction::StartOrReloadPluginPane(run_plugin, None))
.with_context(err_context)?;
},
Action::LaunchOrFocusPlugin(run_plugin, should_float) => {
diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs
index 7401d9d77..811777481 100644
--- a/zellij-server/src/screen.rs
+++ b/zellij-server/src/screen.rs
@@ -260,7 +260,7 @@ pub enum ScreenInstruction {
NewTiledPluginPane(RunPluginLocation, Option<String>, ClientId), // Option<String> is
// optional pane title
NewFloatingPluginPane(RunPluginLocation, Option<String>, ClientId), // Option<String> is an
- StartOrReloadPluginPane(RunPluginLocation, Option<String>),
+ StartOrReloadPluginPane(RunPlugin, Option<String>),
// optional pane title
AddPlugin(
Option<bool>, // should_float
@@ -2573,14 +2573,10 @@ pub(crate) fn screen_thread_main(
size,
))?;
},
- ScreenInstruction::StartOrReloadPluginPane(run_plugin_location, pane_title) => {
+ ScreenInstruction::StartOrReloadPluginPane(run_plugin, pane_title) => {
let tab_index = screen.active_tab_indices.values().next().unwrap_or(&1);
let size = Size::default();
let should_float = Some(false);
- let run_plugin = RunPlugin {
- _allow_exec_host_cmd: false,
- location: run_plugin_location,
- };
screen
.bus
.senders
diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs
index b222af004..6639f810b 100644
--- a/zellij-utils/src/cli.rs
+++ b/zellij-utils/src/cli.rs
@@ -375,7 +375,7 @@ pub enum CliAction {
/// Query all tab names
QueryTabNames,
StartOrReloadPlugin {
- url: Url,
+ url: String,
},
LaunchOrFocusPlugin {
#[clap(short, long, value_parser)]
diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs
index 36d59dde6..f6e080d80 100644
--- a/zellij-utils/src/input/actions.rs
+++ b/zellij-utils/src/input/actions.rs
@@ -16,7 +16,6 @@ use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::str::FromStr;
-use url::Url;
use crate::position::Position;
@@ -233,7 +232,7 @@ pub enum Action {
/// Open a new tiled (embedded, non-floating) plugin pane
NewTiledPluginPane(RunPluginLocation, Option<String>), // String is an optional name
NewFloatingPluginPane(RunPluginLocation, Option<String>), // String is an optional name
- StartOrReloadPlugin(Url),
+ StartOrReloadPlugin(RunPlugin),
}
impl Action {
@@ -287,14 +286,18 @@ impl Action {
close_on_exit,
start_suspended,
} => {
+ let current_dir = get_current_dir();
+ let cwd = cwd
+ .map(|cwd| current_dir.join(cwd))
+ .or_else(|| Some(current_dir));
if let Some(plugin) = plugin {
if floating {
- let plugin = RunPluginLocation::parse(&plugin).map_err(|e| {
+ let plugin = RunPluginLocation::parse(&plugin, cwd).map_err(|e| {
format!("Failed to parse plugin loction {plugin}: {}", e)
})?;
Ok(vec![Action::NewFloatingPluginPane(plugin, name)])
} else {
- let plugin = RunPluginLocation::parse(&plugin).map_err(|e| {
+ let plugin = RunPluginLocation::parse(&plugin, cwd).map_err(|e| {
format!("Failed to parse plugin location {plugin}: {}", e)
})?;
// it is intentional that a new tiled plugin pane cannot include a
@@ -310,10 +313,6 @@ impl Action {
} else if !command.is_empty() {
let mut command = command.clone();
let (command, args) = (PathBuf::from(command.remove(0)), command);
- let current_dir = get_current_dir();
- let cwd = cwd
- .map(|cwd| current_dir.join(cwd))
- .or_else(|| Some(current_dir));
let hold_on_start = start_suspended;
let hold_on_close = !close_on_exit;
let run_command_action = RunCommandAction {
@@ -474,9 +473,19 @@ impl Action {
CliAction::PreviousSwapLayout => Ok(vec![Action::PreviousSwapLayout]),
CliAction::NextSwapLayout => Ok(vec![Action::NextSwapLayout]),
CliAction::QueryTabNames => Ok(vec![Action::QueryTabNames]),
- CliAction::StartOrReloadPlugin { url } => Ok(vec![Action::StartOrReloadPlugin(url)]),
+ CliAction::StartOrReloadPlugin { url } => {
+ let current_dir = get_current_dir();
+ let run_plugin_location = RunPluginLocation::parse(&url, Some(current_dir))
+ .map_err(|e| format!("Failed to parse plugin location: {}", e))?;
+ let run_plugin = RunPlugin {
+ location: run_plugin_location,
+ _allow_exec_host_cmd: false,
+ };
+ Ok(vec![Action::StartOrReloadPlugin(run_plugin)])
+ },
CliAction::LaunchOrFocusPlugin { url, floating } => {
- let run_plugin_location = RunPluginLocation::parse(url.as_str())
+ let current_dir = get_current_dir();
+ let run_plugin_location = RunPluginLocation::parse(url.as_str(), Some(current_dir))
.map_err(|e| format!("Failed to parse plugin location: {}", e))?;
let run_plugin = RunPlugin {
location: run_plugin_location,
diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs
index b4fcbe2c5..c1d95a125 100644
--- a/zellij-utils/src/input/layout.rs
+++ b/zellij-utils/src/input/layout.rs
@@ -221,7 +221,7 @@ pub enum RunPluginLocation {
}
impl RunPluginLocation {
- pub fn parse(location: &str) -> Result<Self, PluginsConfigError> {
+ pub fn parse(location: &str, cwd: Option<PathBuf>) -> Result<Self, PluginsConfigError> {
let url = Url::parse(location)?;
let decoded_path = percent_encoding::percent_decode_str(url.path()).decode_utf8_lossy();
@@ -233,16 +233,29 @@ impl RunPluginLocation {
// Path is absolute, its safe to use URL path.
//
// This is the case if the scheme and : delimiter are followed by a / slash
- decoded_path
+ PathBuf::from(decoded_path.as_ref())
+ } else if location.starts_with("file:~") {
+ // Unwrap is safe here since location is a valid URL
+ PathBuf::from(location.strip_prefix("file:").unwrap())
} else {
// URL dep doesn't handle relative paths with `file` schema properly,
// it always makes them absolute. Use raw location string instead.
//
// Unwrap is safe here since location is a valid URL
- location.strip_prefix("file:").unwrap().into()
+ let stripped = location.strip_prefix("file:").unwrap();
+ match cwd {
+ Some(cwd) => cwd.join(stripped),
+ None => PathBuf::from(stripped),
+ }
};
-
- Ok(Self::File(PathBuf::from(path.as_ref())))
+ let path = match shellexpand::full(&path.to_string_lossy().to_string()) {
+ Ok(s) => PathBuf::from(s.as_ref()),
+ Err(e) => {
+ log::error!("Failed to shell expand plugin path: {}", e);
+ path
+ },
+ };
+ Ok(Self::File(path))
},
_ => Err(PluginsConfigError::InvalidUrlScheme(url)),
}
diff --git a/zellij-utils/src/kdl/kdl_layout_parser.rs b/zellij-utils/src/kdl/kdl_layout_parser.rs
index 21441cf17..a5cab4b1b 100644
--- a/zellij-utils/src/kdl/kdl_layout_parser.rs
+++ b/zellij-utils/src/kdl/kdl_layout_parser.rs
@@ -297,13 +297,14 @@ impl<'a> KdlLayoutParser<'a> {
plugin_block.span().len(),
),
)?;
- let location = RunPluginLocation::parse(&string_url).map_err(|e| {
- ConfigError::new_layout_kdl_error(
- e.to_string(),
- url_node.span().offset(),
- url_node.span().len(),
- )
- })?;
+ let location =
+ RunPluginLocation::parse(&string_url, self.cwd_prefix(None)?).map_err(|e| {
+ ConfigError::new_layout_kdl_error(
+ e.to_string(),
+ url_node.span().offset(),
+ url_node.span().len(),
+ )
+ })?;
Ok(Some(Run::Plugin(RunPlugin {
_allow_exec_host_cmd,
location,
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index 58dda9c86..dde484968 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -892,7 +892,8 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
let should_float = command_metadata
.and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "floating"))
.unwrap_or(false);
- let location = RunPluginLocation::parse(&plugin_path)?;
+ let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
+ let location = RunPluginLocation::parse(&plugin_path, Some(current_dir))?;
let run_plugin = RunPlugin {
location,
_allow_exec_host_cmd: false,
@@ -1402,7 +1403,7 @@ impl Options {
}
impl RunPlugin {
- pub fn from_kdl(kdl_node: &KdlNode) -> Result<Self, ConfigError> {
+ pub fn from_kdl(kdl_node: &KdlNode, cwd: Option<PathBuf>) -> Result<Self, ConfigError> {
let _allow_exec_host_cmd =
kdl_get_child_entry_bool_value!(kdl_node, "_allow_exec_host_cmd").unwrap_or(false);
let string_url = kdl_get_child_entry_string_value!(kdl_node, "location").ok_or(
@@ -1412,7 +1413,7 @@ impl RunPlugin {
kdl_node.span().len(),
),
)?;
- let location = RunPluginLocation::parse(string_url).map_err(|e| {
+ let location = RunPluginLocation::parse(string_url, cwd).map_err(|e| {
ConfigError::new_layout_kdl_error(
e.to_string(),
kdl_node.span().offset(),