diff options
author | Aram Drevekenin <aram@poor.dev> | 2023-06-14 13:44:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-14 13:44:46 +0200 |
commit | f19334754cf1f8e6bd48bb9cdd905a2d5147e30e (patch) | |
tree | 6d29a1a05518c109bfc734edf34f3d178051196b /zellij-utils | |
parent | 59239cc1133179e2825d98b5c2be7c6c3bfdcc9c (diff) |
fix(plugins): allow loading relative urls (#2539)
* fix(plugins): allow loading relative urls
* style(fmt): rustfmt
Diffstat (limited to 'zellij-utils')
-rw-r--r-- | zellij-utils/src/cli.rs | 2 | ||||
-rw-r--r-- | zellij-utils/src/input/actions.rs | 29 | ||||
-rw-r--r-- | zellij-utils/src/input/layout.rs | 23 | ||||
-rw-r--r-- | zellij-utils/src/kdl/kdl_layout_parser.rs | 15 | ||||
-rw-r--r-- | zellij-utils/src/kdl/mod.rs | 7 |
5 files changed, 50 insertions, 26 deletions
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(), |