Fix large env vars breaking the subprocess

Bug:
When you call some command in a directory with a large number of hosts,
xplr will fail setting the environment vars as the command will become
too large to handle.

Fix:
Port the value of multi-line variables from env vars to pipes and set
the name of the pipe as env var instead. And deprecate the variables
that doesn't make much sense.

In other words,

- `$XPLR_APP_YAML` has been removed.
- `$XPLR_RESULT` has been ported to `$XPLR_PIPE_RESULT_OUT`.
- `$XPLR_GLOBAL_HELP_MENU` has been ported to
  `$XPLR_PIPE_GLOBAL_HELP_MENU_OUT`.
- `$XPLR_DIRECTORY_NODES` has been ported to
  `$XPLR_PIPE_DIRECTORY_NODES_OUT`.
- `$XPLR_LOGS` has been ported to `$XPLR_PIPE_LOGS_OUT`.
- `$XPLR_PIPE_RESULT` has been ported to `$XPLR_PIPE_RESULT_OUT`.

Hence, instead of `<<< $VAR`, `< $VAR_PIPE_OUT` should be used.
pull/9/head v0.3.0
Arijit Basu 3 years ago committed by Arijit Basu
parent 9747c8667b
commit 981ead8c36

2
Cargo.lock generated

@ -1164,7 +1164,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "xplr"
version = "0.2.21"
version = "0.3.0"
dependencies = [
"anyhow",
"chrono",

@ -1,6 +1,6 @@
[package]
name = "xplr"
version = "0.2.21" # Update app.rs
version = "0.3.0" # Update app.rs
authors = ["Arijit Basu <sayanarijit@gmail.com>"]
edition = "2018"
description = "A hackable, minimal, fast TUI file explorer, stealing ideas from nnn and fzf"

@ -12,7 +12,7 @@ use std::fs;
use std::io;
use std::path::PathBuf;
pub const VERSION: &str = "v0.2.21"; // Update Cargo.toml
pub const VERSION: &str = "v0.3.0"; // Update Cargo.toml
pub const TEMPLATE_TABLE_ROW: &str = "TEMPLATE_TABLE_ROW";
@ -23,11 +23,15 @@ pub struct Pipe {
pub msg_in: String,
pub focus_out: String,
pub selection_out: String,
pub result_out: String,
pub mode_out: String,
pub directory_nodes_out: String,
pub global_help_menu_out: String,
pub logs_out: String,
}
impl Pipe {
fn from_session_path(path: &str) -> Self {
fn from_session_path(path: &str) -> Result<Self> {
let pipesdir = PathBuf::from(path).join("pipe");
fs::create_dir_all(&pipesdir).unwrap();
@ -38,19 +42,41 @@ impl Pipe {
let selection_out = pipesdir.join("selection_out").to_string_lossy().to_string();
let result_out = pipesdir.join("result_out").to_string_lossy().to_string();
let mode_out = pipesdir.join("mode_out").to_string_lossy().to_string();
fs::write(&msg_in, "").unwrap();
fs::write(&focus_out, "").unwrap();
fs::write(&selection_out, "").unwrap();
fs::write(&mode_out, "").unwrap();
let directory_nodes_out = pipesdir
.join("directory_nodes_out")
.to_string_lossy()
.to_string();
Self {
let global_help_menu_out = pipesdir
.join("global_help_menu_out")
.to_string_lossy()
.to_string();
let logs_out = pipesdir.join("logs_out").to_string_lossy().to_string();
fs::write(&msg_in, "")?;
fs::write(&focus_out, "")?;
fs::write(&selection_out, "")?;
fs::write(&mode_out, "")?;
fs::write(&directory_nodes_out, "")?;
fs::write(&global_help_menu_out, "")?;
fs::write(&result_out, "")?;
fs::write(&logs_out, "")?;
Ok(Self {
msg_in,
focus_out,
selection_out,
result_out,
mode_out,
}
directory_nodes_out,
global_help_menu_out,
logs_out,
})
}
}
@ -387,7 +413,7 @@ pub struct ExplorerConfig {
}
impl ExplorerConfig {
pub fn apply(&self, node: &Node) -> bool {
pub fn filter(&self, node: &Node) -> bool {
self.filters.iter().all(|f| f.apply(node))
}
}
@ -545,17 +571,17 @@ pub enum ExternalMsg {
/// Reset the node filters back to the default configuration.
ResetNodeFilters,
/// Log information message. Stored in `$XPLR_LOGS`.
/// Log information message.
///
/// Example: `LogInfo: launching satellite`
LogInfo(String),
/// Log a success message. Stored in `$XPLR_LOGS`.
/// Log a success message.
///
/// Example: `LogSuccess: satellite reached destination`. Stored in `$XPLR_LOGS`
/// Example: `LogSuccess: satellite reached destination`.
LogSuccess(String),
/// Log an error message, Stoted in `$XPLR_LOGS`
/// Log an error message.
///
/// Example: `LogError: satellite crashed`
LogError(String),
@ -754,7 +780,7 @@ impl App {
input_buffer: Default::default(),
pid,
session_path: session_path.clone(),
pipe: Pipe::from_session_path(&session_path),
pipe: Pipe::from_session_path(&session_path)?,
explorer_config,
logs: Default::default(),
})
@ -1281,12 +1307,40 @@ impl App {
}
}
pub fn directory_nodes_str(&self) -> String {
self.directory_buffer()
.map(|d| {
d.nodes
.iter()
.map(|n| format!("{}\n", n.absolute_path))
.collect::<Vec<String>>()
.join("")
})
.unwrap_or_default()
}
pub fn logs_str(&self) -> String {
self.logs()
.iter()
.map(|l| format!("{}\n", l))
.collect::<Vec<String>>()
.join("")
}
pub fn selection_str(&self) -> String {
self.selection
.iter()
.map(|n| format!("{}\n", n.absolute_path))
.collect::<Vec<String>>()
.join("")
}
pub fn result_str(&self) -> String {
self.result()
.into_iter()
.map(|n| n.absolute_path.clone())
.map(|n| format!("{}\n", n.absolute_path))
.collect::<Vec<String>>()
.join("\n")
.join("")
}
/// Get a reference to the app's explorer config.
@ -1298,4 +1352,30 @@ impl App {
pub fn logs(&self) -> &Vec<Log> {
&self.logs
}
pub fn global_help_menu_str(&self) -> String {
self.config()
.modes
.iter()
.map(|(name, mode)| {
let help = mode
.help_menu()
.iter()
.map(|l| match l {
HelpMenuLine::Paragraph(p) => format!("\t{}\n", p),
HelpMenuLine::KeyMap(k, h) => {
format!(" {:15} | {}\n", k, h)
}
})
.collect::<Vec<String>>()
.join("");
format!(
"### {}\n\n key | action\n --------------- | ------\n{}\n",
name, help
)
})
.collect::<Vec<String>>()
.join("\n")
}
}

@ -354,7 +354,7 @@ impl Default for KeyBindings {
help: global help menu
messages:
- BashExec: |
echo -e "${XPLR_GLOBAL_HELP_MENU}"
cat "${XPLR_PIPE_GLOBAL_HELP_MENU_OUT}"
echo
read -p "[enter to continue]"
@ -627,7 +627,7 @@ impl Default for Config {
help: logs
messages:
- BashExec: |
echo -e "$XPLR_LOGS"
cat "${XPLR_PIPE_LOGS_OUT}"
read -p "[enter to continue]"
- SwitchMode: default
@ -662,7 +662,7 @@ impl Default for Config {
else
echo "LogError: failed to copy $line to $PWD" >> "${XPLR_PIPE_MSG_IN:?}"
fi
done <<< "${XPLR_SELECTION:?}")
done < "${XPLR_PIPE_SELECTION_OUT:?}")
echo Explore >> "${XPLR_PIPE_MSG_IN:?}"
echo ClearSelection >> "${XPLR_PIPE_MSG_IN:?}"
read -p "[enter to continue]"
@ -678,7 +678,7 @@ impl Default for Config {
else
echo "LogError: failed to move $line to $PWD" >> "${XPLR_PIPE_MSG_IN:?}"
fi
done <<< "${XPLR_SELECTION:?}")
done < "${XPLR_PIPE_SELECTION_OUT:?}")
echo Explore >> "${XPLR_PIPE_MSG_IN:?}"
read -p "[enter to continue]"
- SwitchMode: default
@ -929,7 +929,7 @@ impl Default for Config {
echo "LogError: failed to delete $line" >> "${XPLR_PIPE_MSG_IN:?}"
fi
fi
done <<< "${XPLR_RESULT:?}")
done < "${XPLR_PIPE_RESULT_OUT:?}")
echo Explore >> "${XPLR_PIPE_MSG_IN:?}"
read -p "[enter to continue]"
- SwitchMode: default
@ -944,7 +944,7 @@ impl Default for Config {
else
echo "LogError: failed to delete $line" >> "${XPLR_PIPE_MSG_IN:?}"
fi
done <<< "${XPLR_RESULT:?}")
done < "${XPLR_PIPE_RESULT_OUT:?}")
echo Explore >> "${XPLR_PIPE_MSG_IN:?}"
read -p "[enter to continue]"
- SwitchMode: default

@ -27,7 +27,7 @@ pub fn explore(
})
})
.map(|name| Node::new(parent.clone(), name))
.filter(|n| config.apply(n))
.filter(|n| config.filter(n))
.collect::<Vec<Node>>()
})
.map(|nodes| {

@ -111,6 +111,7 @@ fn main() -> Result<()> {
}
app::MsgOut::Refresh => {
app = app.refresh_selection()?;
if app.pwd() != &last_pwd {
explorer::explore(
app.explorer_config().clone(),
@ -131,19 +132,12 @@ fn main() -> Result<()> {
.unwrap_or_default();
fs::write(&app.pipe().focus_out, focused)?;
app = app.refresh_selection()?;
let selection = app
.selection()
.iter()
.map(|n| n.absolute_path.clone())
.collect::<Vec<String>>()
.join("\n");
fs::write(&app.pipe().selection_out, selection)?;
fs::write(&app.pipe().selection_out, app.selection_str())?;
fs::write(&app.pipe().mode_out, &app.mode().name)?;
fs::write(&app.pipe().directory_nodes_out, app.directory_nodes_str())?;
fs::write(&app.pipe().global_help_menu_out, app.global_help_menu_str())?;
fs::write(&app.pipe().logs_out, app.logs_str())?;
fs::write(&app.pipe().result_out, app.result_str())?;
}
app::MsgOut::Call(cmd) => {
@ -167,60 +161,14 @@ fn main() -> Result<()> {
.unwrap_or_default()
.to_string();
let selection = app
.selection()
.iter()
.map(|n| n.absolute_path.clone())
.collect::<Vec<String>>()
.join("\n");
let directory_nodes = app
.directory_buffer()
.map(|d| {
d.nodes
.iter()
.map(|n| n.absolute_path.clone())
.collect::<Vec<String>>()
.join("\n")
})
.unwrap_or_default();
let logs = app
.logs()
.iter()
.map(|l| l.to_string())
.collect::<Vec<String>>()
.join("\n");
let help_menu = app
.config()
.modes
.iter()
.map(|(name, mode)| {
let help = mode
.help_menu()
.iter()
.map(|l| match l {
app::HelpMenuLine::Paragraph(p) => format!("\t{}", p),
app::HelpMenuLine::KeyMap(k, h) => {
format!(" {:15} | {}", k, h)
}
})
.collect::<Vec<String>>()
.join("\n");
format!("### {}\n\n key | action\n --------------- | ------\n{}", name, help)
})
.collect::<Vec<String>>()
.join("\n\n\n");
let pipe_msg_in = app.pipe().msg_in.clone();
let pipe_focus_out = app.pipe().focus_out.clone();
let pipe_selection_out = app.pipe().selection_out.clone();
let app_yaml = serde_yaml::to_string(&app)?;
let pipe_result_out = app.pipe().result_out.clone();
let pipe_directory_nodes_out = app.pipe().directory_nodes_out.clone();
let pipe_global_help_menu_out = app.pipe().global_help_menu_out.clone();
let pipe_logs_out = app.pipe().logs_out.clone();
let session_path = app.session_path();
let result = app.result_str();
let status = std::process::Command::new(cmd.command.clone())
.current_dir(app.pwd())
@ -228,16 +176,14 @@ fn main() -> Result<()> {
.env("XPLR_INPUT_BUFFER", input_buffer)
.env("XPLR_FOCUS_PATH", focus_path)
.env("XPLR_FOCUS_INDEX", focus_index)
.env("XPLR_SELECTION", selection)
.env("XPLR_SESSION_PATH", session_path)
.env("XPLR_PIPE_MSG_IN", pipe_msg_in)
.env("XPLR_PIPE_SELECTION_OUT", pipe_selection_out)
.env("XPLR_PIPE_FOCUS_OUT", pipe_focus_out)
.env("XPLR_APP_YAML", app_yaml)
.env("XPLR_RESULT", result)
.env("XPLR_GLOBAL_HELP_MENU", help_menu)
.env("XPLR_DIRECTORY_NODES", directory_nodes)
.env("XPLR_LOGS", logs)
.env("XPLR_PIPE_RESULT_OUT", pipe_result_out)
.env("XPLR_PIPE_GLOBAL_HELP_MENU_OUT", pipe_global_help_menu_out)
.env("XPLR_PIPE_DIRECTORY_NODES_OUT", pipe_directory_nodes_out)
.env("XPLR_PIPE_LOGS_OUT", pipe_logs_out)
.args(cmd.args.clone())
.status()
.map(|s| {

Loading…
Cancel
Save