Rename messages

pull/522/head
Arijit Basu 2 years ago committed by Arijit Basu
parent 7b8f38df5b
commit 91e3990df1

@ -547,54 +547,78 @@ Example:
#### Call #### Call
Like `Call0`, but it uses `\n` as the delimiter in input/output pipes,
hence it cannot handle files with `\n` in the name.
You may want to use `Call0` instead.
#### Call0
Call a shell command with the given arguments. Call a shell command with the given arguments.
Note that the arguments will be shell-escaped. Note that the arguments will be shell-escaped.
So to read the variables, the `-c` option of the shell So to read the variables, the `-c` option of the shell
can be used. can be used.
You may need to pass `ExplorePwd` depening on the expectation. You may need to pass `ExplorePwd` depending on the expectation.
Type: { Call = { command = string, args = { "list", "of", "string" } } Type: { Call0 = { command = "string", args = { "list", "of", "string" } }
Example: Example:
- Lua: `{ Call = { command = "bash", args = { "-c", "read -p test" } } }` - Lua: `{ Call0 = { command = "bash", args = { "-c", "read -p test" } } }`
- YAML: `Call: { command: bash, args: ["-c", "read -p test"] }` - YAML: `Call0: { command: bash, args: ["-c", "read -p test"] }`
#### CallSilently #### CallSilently
Like `Call` but without the flicker. The stdin, stdout Like `CallSilently0`, but it uses `\n` as the delimiter in input/output
pipes, hence it cannot handle files with `\n` in the name.
You may want to use `Call0Silently` instead.
#### CallSilently0
Like `Call0` but without the flicker. The stdin, stdout
stderr will be piped to null. So it's non-interactive. stderr will be piped to null. So it's non-interactive.
Type: { CallSilently = "string" } Type: { CallSilently0 = { command = "string", args = {"list", "of", "string"} } }
Example: Example:
- Lua: `{ CallSilently = { command = "tput", args = { "bell" } } }` - Lua: `{ CallSilently0 = { command = "tput", args = { "bell" } } }`
- YAML: `CallSilently: { command: tput, args: ["bell"] }` - YAML: `CallSilently0: { command: tput, args: ["bell"] }`
#### BashExec #### BashExec
Like `BashExec0`, but it uses `\n` as the delimiter in input/output
pipes, hence it cannot handle files with `\n` in the name.
You may want to use `BashExec0` instead.
#### BashExec0
An alias to `Call: {command: bash, args: ["-c", "{string}"], silent: false}` An alias to `Call: {command: bash, args: ["-c", "{string}"], silent: false}`
where `{string}` is the given value. where `{string}` is the given value.
Type: { BashExec = "string" } Type: { BashExec0 = "string" }
Example: Example:
- Lua: `{ BashExec = "read -p test" }` - Lua: `{ BashExec0 = "read -p test" }`
- YAML: `BashExec: "read -p test"` - YAML: `BashExec0: "read -p test"`
#### BashExecSilently #### BashExecSilently
Like `BashExec` but without the flicker. The stdin, stdout Like `BashExecSilently0`, but it uses `\n` as the delimiter in
input/output pipes, hence it cannot handle files with `\n` in the name.
You may want to use `BashExec0Silently` instead.
#### BashExecSilently0
Like `BashExec0` but without the flicker. The stdin, stdout
stderr will be piped to null. So it's non-interactive. stderr will be piped to null. So it's non-interactive.
Type: { BashExecSilently = "string" } Type: { BashExec0Silently = "string" }
Example: Example:
- Lua: `{ BashExecSilently = "tput bell" }` - Lua: `{ BashExecSilently0 = "tput bell" }`
- YAML: `BashExecSilently: "tput bell"` - YAML: `BashExecSilently0: "tput bell"`
### Calling Lua Functions ### Calling Lua Functions

@ -15,7 +15,6 @@ pub use crate::msg::in_::ExternalMsg;
pub use crate::msg::in_::InternalMsg; pub use crate::msg::in_::InternalMsg;
pub use crate::msg::in_::MsgIn; pub use crate::msg::in_::MsgIn;
pub use crate::msg::out::MsgOut; pub use crate::msg::out::MsgOut;
use crate::newlines::unescape_string;
pub use crate::node::Node; pub use crate::node::Node;
pub use crate::node::ResolvedNode; pub use crate::node::ResolvedNode;
pub use crate::pipe::Pipe; pub use crate::pipe::Pipe;
@ -175,7 +174,6 @@ pub struct App {
pub mode: Mode, pub mode: Mode,
pub layout: Layout, pub layout: Layout,
pub input: InputBuffer, pub input: InputBuffer,
pub input_unescaped: String,
pub pid: u32, pub pid: u32,
pub session_path: String, pub session_path: String,
pub pipe: Pipe, pub pipe: Pipe,
@ -310,7 +308,6 @@ impl App {
mode, mode,
layout, layout,
input, input,
input_unescaped: Default::default(),
pid, pid,
session_path: session_path.clone(), session_path: session_path.clone(),
pipe: Pipe::from_session_path(&session_path)?, pipe: Pipe::from_session_path(&session_path)?,
@ -452,9 +449,13 @@ impl App {
SwitchLayoutBuiltin(mode) => self.switch_layout_builtin(&mode), SwitchLayoutBuiltin(mode) => self.switch_layout_builtin(&mode),
SwitchLayoutCustom(mode) => self.switch_layout_custom(&mode), SwitchLayoutCustom(mode) => self.switch_layout_custom(&mode),
Call(cmd) => self.call(cmd), Call(cmd) => self.call(cmd),
Call0(cmd) => self.call0(cmd),
CallSilently(cmd) => self.call_silently(cmd), CallSilently(cmd) => self.call_silently(cmd),
CallSilently0(cmd) => self.call_silently0(cmd),
BashExec(cmd) => self.bash_exec(cmd), BashExec(cmd) => self.bash_exec(cmd),
BashExec0(cmd) => self.bash_exec0(cmd),
BashExecSilently(cmd) => self.bash_exec_silently(cmd), BashExecSilently(cmd) => self.bash_exec_silently(cmd),
BashExecSilently0(cmd) => self.bash_exec_silently0(cmd),
CallLua(func) => self.call_lua(func), CallLua(func) => self.call_lua(func),
CallLuaSilently(func) => self.call_lua_silently(func), CallLuaSilently(func) => self.call_lua_silently(func),
LuaEval(code) => self.lua_eval(code), LuaEval(code) => self.lua_eval(code),
@ -557,14 +558,6 @@ impl App {
} }
}); });
self.input_unescaped = unescape_string(
&self.input
.buffer
.as_ref()
.map(|i| i.value().to_string())
.unwrap_or_default(),
)?;
for msg in msgs { for msg in msgs {
self = self.enqueue(Task::new(MsgIn::External(msg), Some(key))); self = self.enqueue(Task::new(MsgIn::External(msg), Some(key)));
} }
@ -1108,12 +1101,24 @@ impl App {
Ok(self) Ok(self)
} }
fn call0(mut self, command: Command) -> Result<Self> {
self.logs_hidden = true;
self.msg_out.push_back(MsgOut::Call0(command));
Ok(self)
}
fn call_silently(mut self, command: Command) -> Result<Self> { fn call_silently(mut self, command: Command) -> Result<Self> {
self.logs_hidden = true; self.logs_hidden = true;
self.msg_out.push_back(MsgOut::CallSilently(command)); self.msg_out.push_back(MsgOut::CallSilently(command));
Ok(self) Ok(self)
} }
fn call_silently0(mut self, command: Command) -> Result<Self> {
self.logs_hidden = true;
self.msg_out.push_back(MsgOut::CallSilently0(command));
Ok(self)
}
fn bash_exec(self, script: String) -> Result<Self> { fn bash_exec(self, script: String) -> Result<Self> {
self.call(Command { self.call(Command {
command: "bash".into(), command: "bash".into(),
@ -1121,6 +1126,13 @@ impl App {
}) })
} }
fn bash_exec0(self, script: String) -> Result<Self> {
self.call0(Command {
command: "bash".into(),
args: vec!["-c".into(), script],
})
}
fn bash_exec_silently(self, script: String) -> Result<Self> { fn bash_exec_silently(self, script: String) -> Result<Self> {
self.call_silently(Command { self.call_silently(Command {
command: "bash".into(), command: "bash".into(),
@ -1128,6 +1140,13 @@ impl App {
}) })
} }
fn bash_exec_silently0(self, script: String) -> Result<Self> {
self.call_silently0(Command {
command: "bash".into(),
args: vec!["-c".into(), script],
})
}
fn call_lua(mut self, func: String) -> Result<Self> { fn call_lua(mut self, func: String) -> Result<Self> {
self.logs_hidden = true; self.logs_hidden = true;
self.msg_out.push_back(MsgOut::CallLua(func)); self.msg_out.push_back(MsgOut::CallLua(func));
@ -1560,48 +1579,48 @@ impl App {
} }
} }
pub fn directory_nodes_str(&self) -> String { pub fn directory_nodes_str(&self, delimiter: char) -> String {
self.directory_buffer self.directory_buffer
.as_ref() .as_ref()
.map(|d| { .map(|d| {
d.nodes d.nodes
.iter() .iter()
.map(|n| format!("{}\n", n.absolute_path)) .map(|n| format!("{}{}", n.absolute_path, delimiter))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("") .join("")
}) })
.unwrap_or_default() .unwrap_or_default()
} }
pub fn pwd_str(&self) -> String { pub fn pwd_str(&self, delimiter: char) -> String {
format!("{}\n", &self.pwd) format!("{}{}", &self.pwd, delimiter)
} }
pub fn selection_str(&self) -> String { pub fn selection_str(&self, delimiter: char) -> String {
self.selection self.selection
.iter() .iter()
.map(|n| format!("{}\n", n.absolute_path)) .map(|n| format!("{}{}", n.absolute_path, delimiter))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("") .join("")
} }
pub fn result_str(&self) -> String { pub fn result_str(&self, delimiter: char) -> String {
self.result() self.result()
.into_iter() .into_iter()
.map(|n| format!("{}\n", n.absolute_path)) .map(|n| format!("{}{}", n.absolute_path, delimiter))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("") .join("")
} }
pub fn logs_str(&self) -> String { pub fn logs_str(&self, delimiter: char) -> String {
self.logs self.logs
.iter() .iter()
.map(|l| format!("{}\n", l)) .map(|l| format!("{}{}", l, delimiter))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("") .join("")
} }
pub fn global_help_menu_str(&self) -> String { pub fn global_help_menu_str(&self, delimiter: char) -> String {
let builtin = self.config.modes.builtin.clone(); let builtin = self.config.modes.builtin.clone();
let custom = self.config.modes.custom.clone(); let custom = self.config.modes.custom.clone();
let read_only = self.config.general.read_only; let read_only = self.config.general.read_only;
@ -1617,53 +1636,53 @@ impl App {
.help_menu() .help_menu()
.iter() .iter()
.map(|l| match l { .map(|l| match l {
HelpMenuLine::Paragraph(p) => format!("\t{}\n", p), HelpMenuLine::Paragraph(p) => format!("\t{}{}", p, delimiter),
HelpMenuLine::KeyMap(k, remaps, h) => { HelpMenuLine::KeyMap(k, remaps, h) => {
let remaps = remaps.join(", "); let remaps = remaps.join(", ");
format!(" {:15} | {:25} | {}\n", k, remaps, h) format!(" {:15} | {:25} | {}{}", k, remaps, h , delimiter)
} }
}) })
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(""); .join("");
format!( format!(
"### {}\n\n key | remaps | action\n --------------- | ------------------------- | ------\n{}\n", "### {}{d}{d} key | remaps | action\n --------------- | ------------------------- | ------{d}{}{d}",
name, help name, help, d = delimiter
) )
}) })
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("\n") .join(&delimiter.to_string())
} }
pub fn history_str(&self) -> String { pub fn history_str(&self, delimiter: char) -> String {
self.history self.history
.paths .paths
.iter() .iter()
.map(|p| format!("{}\n", &p)) .map(|p| format!("{}{}", &p, delimiter))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("") .join("")
} }
pub fn write_pipes(&self) -> Result<()> { pub fn write_pipes(&self, delimiter: char) -> Result<()> {
fs::create_dir_all(self.pipe.path.clone())?; fs::create_dir_all(self.pipe.path.clone())?;
fs::write(&self.pipe.msg_in, "")?; fs::write(&self.pipe.msg_in, "")?;
let selection_str = self.selection_str(); let selection_str = self.selection_str(delimiter);
fs::write(&self.pipe.selection_out, selection_str)?; fs::write(&self.pipe.selection_out, selection_str)?;
let history_str = self.history_str(); let history_str = self.history_str(delimiter);
fs::write(&self.pipe.history_out, history_str)?; fs::write(&self.pipe.history_out, history_str)?;
let directory_nodes_str = self.directory_nodes_str(); let directory_nodes_str = self.directory_nodes_str(delimiter);
fs::write(&self.pipe.directory_nodes_out, directory_nodes_str)?; fs::write(&self.pipe.directory_nodes_out, directory_nodes_str)?;
let logs_str = self.logs_str(); let logs_str = self.logs_str(delimiter);
fs::write(&self.pipe.logs_out, logs_str)?; fs::write(&self.pipe.logs_out, logs_str)?;
let result_str = self.result_str(); let result_str = self.result_str(delimiter);
fs::write(&self.pipe.result_out, result_str)?; fs::write(&self.pipe.result_out, result_str)?;
let global_help_menu_str = self.global_help_menu_str(); let global_help_menu_str = self.global_help_menu_str(delimiter);
fs::write(&self.pipe.global_help_menu_out, global_help_menu_str)?; fs::write(&self.pipe.global_help_menu_out, global_help_menu_str)?;
Ok(()) Ok(())

@ -1045,9 +1045,9 @@ xplr.config.modes.builtin.default = {
help = "global help menu", help = "global help menu",
messages = { messages = {
{ {
BashExec = [===[ BashExec0 = [===[
[ -z "$PAGER" ] && PAGER="less -+F" [ -z "$PAGER" ] && PAGER="less -+F"
cat -- "${XPLR_PIPE_GLOBAL_HELP_MENU_OUT}" | ${PAGER:?} cat -- "${XPLR_PIPE_GLOBAL_HELP_MENU_OUT}" | tr '\0' '\n' | ${PAGER:?}
]===], ]===],
}, },
}, },
@ -1154,9 +1154,10 @@ xplr.config.modes.builtin.default = {
"PopMode", "PopMode",
{ SwitchModeBuiltin = "rename" }, { SwitchModeBuiltin = "rename" },
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
NAME=$(basename "${XPLR_FOCUS_PATH:?}") NAME=$(basename "${XPLR_FOCUS_PATH:?}")
printf "SetInputBuffer: %s\0" "${NAME:?}" >> "${XPLR_PIPE_MSG_IN:?}" NAME_ESC=${NAME//\"/\\\"}
printf 'SetInputBuffer: "%s"\0' "${NAME_ESC:?}" >> "${XPLR_PIPE_MSG_IN:?}"
]===], ]===],
}, },
}, },
@ -1167,9 +1168,10 @@ xplr.config.modes.builtin.default = {
"PopMode", "PopMode",
{ SwitchModeBuiltin = "duplicate_as" }, { SwitchModeBuiltin = "duplicate_as" },
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
NAME=$(basename "${XPLR_FOCUS_PATH:?}") NAME=$(basename "${XPLR_FOCUS_PATH:?}")
printf "SetInputBuffer: %s\0" "${NAME:?}" >> "${XPLR_PIPE_MSG_IN:?}" NAME_ESC=${NAME//\"/\\\"}
printf 'SetInputBuffer: "%s"\0' "${NAME_ESC:?}" >> "${XPLR_PIPE_MSG_IN:?}"
]===], ]===],
}, },
}, },
@ -1204,8 +1206,9 @@ xplr.config.modes.builtin.default = {
help = "go home", help = "go home",
messages = { messages = {
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
printf "ChangeDirectory: %s\0" "${HOME:?}" >> "${XPLR_PIPE_MSG_IN:?}" HOME_ESC=${HOME//\"/\\\"}
printf 'ChangeDirectory: "%s"\0' "${HOME_ESC:?}" >> "${XPLR_PIPE_MSG_IN:?}"
]===], ]===],
}, },
}, },
@ -1301,8 +1304,8 @@ xplr.config.modes.builtin.debug_error = {
help = "open logs in editor", help = "open logs in editor",
messages = { messages = {
{ {
BashExec = [===[ BashExec0 = [===[
cat "${XPLR_PIPE_LOGS_OUT:?}" | ${EDITOR:-vi} - cat "${XPLR_PIPE_LOGS_OUT:?}" | tr '\0' '\n' | ${EDITOR:-vi} -
]===], ]===],
}, },
}, },
@ -1362,11 +1365,15 @@ xplr.config.modes.builtin.go_to_path = {
help = "submit", help = "submit",
messages = { messages = {
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
if [ -d "$XPLR_INPUT_BUFFER" ]; then PTH=${XPLR_INPUT_BUFFER}
printf "ChangeDirectory: %s\0" "$XPLR_INPUT_BUFFER" >> "${XPLR_PIPE_MSG_IN:?}" PTH_ESC=${XPLR_INPUT_BUFFER//\"/\\\"}
elif [ -e "$XPLR_INPUT_BUFFER" ]; then if [ -d "$PTH" ]; then
printf "FocusPath: %s\0" "$XPLR_INPUT_BUFFER" >> "${XPLR_PIPE_MSG_IN:?}" printf 'ChangeDirectory: "%s"\0' "$PTH_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
elif [ -e "$PTH" ]; then
printf 'FocusPath: "%s"\0' "$PTH_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
else
printf 'LogError: "Could not find %s"\0' "$PTH_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
fi fi
]===], ]===],
}, },
@ -1399,16 +1406,17 @@ xplr.config.modes.builtin.selection_ops = {
help = "copy here", help = "copy here",
messages = { messages = {
{ {
BashExec = [===[ BashExec0 = [===[
(while IFS= read -r -d '' line; do (while IFS= read -r -d '' LINE; do
if cp -vr -- "${line:?}" ./; then LINE_ESC=${LINE//\"/\\\"}
printf "LogSuccess: %s\0" "$line copied to $PWD" >> "${XPLR_PIPE_MSG_IN:?}" if cp -vr -- "${LINE:?}" ./; then
else printf 'LogSuccess: "%s"\0' "$LINE_ESC copied to ." >> "${XPLR_PIPE_MSG_IN:?}"
printf "LogError: %s\0" "Failed to copy $line to $PWD" >> "${XPLR_PIPE_MSG_IN:?}" else
fi printf 'LogError: "%s"\0' "Failed to copy $LINE_ESC to ." >> "${XPLR_PIPE_MSG_IN:?}"
fi
done < "${XPLR_PIPE_SELECTION_OUT:?}") done < "${XPLR_PIPE_SELECTION_OUT:?}")
printf "ExplorePwdAsync\0" >> "${XPLR_PIPE_MSG_IN:?}" printf 'ExplorePwdAsync\0' >> "${XPLR_PIPE_MSG_IN:?}"
printf "ClearSelection\0" >> "${XPLR_PIPE_MSG_IN:?}" printf 'ClearSelection\0' >> "${XPLR_PIPE_MSG_IN:?}"
read -p "[enter to continue]" read -p "[enter to continue]"
]===], ]===],
}, },
@ -1419,15 +1427,16 @@ xplr.config.modes.builtin.selection_ops = {
help = "move here", help = "move here",
messages = { messages = {
{ {
BashExec = [===[ BashExec0 = [===[
(while IFS= read -r -d '' line; do (while IFS= read -r -d '' LINE; do
if mv -v -- "${line:?}" ./; then LINE_ESC=${LINE//\"/\\\"}
printf "LogSuccess: %s\0" "$line moved to $PWD" >> "${XPLR_PIPE_MSG_IN:?}" if mv -v -- "${LINE:?}" ./; then
else printf 'LogSuccess: "%s"\0' "$LINE_ESC moved to ." >> "${XPLR_PIPE_MSG_IN:?}"
printf "LogError: %s\0" "Failed to move $line to $PWD" >> "${XPLR_PIPE_MSG_IN:?}" else
fi printf 'LogError: "%s"\0' "Failed to move $LINE_ESC to ." >> "${XPLR_PIPE_MSG_IN:?}"
fi
done < "${XPLR_PIPE_SELECTION_OUT:?}") done < "${XPLR_PIPE_SELECTION_OUT:?}")
printf "ExplorePwdAsync\0" >> "${XPLR_PIPE_MSG_IN:?}" printf 'ExplorePwdAsync\0' >> "${XPLR_PIPE_MSG_IN:?}"
read -p "[enter to continue]" read -p "[enter to continue]"
]===], ]===],
}, },
@ -1441,30 +1450,6 @@ xplr.config.modes.builtin.selection_ops = {
"PopMode", "PopMode",
}, },
}, },
["x"] = {
help = "open in gui",
messages = {
{
BashExecSilently = [===[
if [ -z "$OPENER" ]; then
if command -v xdg-open; then
OPENER=xdg-open
elif command -v open; then
OPENER=open
else
printf "LogError: %s\0" "$OPENER not found" >> "${XPLR_PIPE_MSG_IN:?}"
exit 1
fi
fi
(while IFS= read -r -d '' line; do
$OPENER "${line:?}" > /dev/null 2>&1
done < "${XPLR_PIPE_RESULT_OUT:?}")
]===],
},
"ClearScreen",
"PopMode",
},
},
}, },
}, },
} }
@ -1514,16 +1499,17 @@ xplr.config.modes.builtin.create_directory = {
help = "submit", help = "submit",
messages = { messages = {
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
PTH="$XPLR_INPUT_BUFFER" PTH="$XPLR_INPUT_BUFFER"
if [ "${PTH}" ]; then PTH_ESC=${PTH//\"/\\\"}
mkdir -p -- "${PTH:?}" \ if [ "$PTH" ]; then
&& printf "SetInputBuffer: ''\0" >> "${XPLR_PIPE_MSG_IN:?}" \ mkdir -p -- "$PTH" \
&& printf "ExplorePwd\0" >> "${XPLR_PIPE_MSG_IN:?}" \ && printf 'SetInputBuffer: ""\0' >> "${XPLR_PIPE_MSG_IN:?}" \
&& printf "LogSuccess: %s\0" "$PTH created" >> "${XPLR_PIPE_MSG_IN:?}" \ && printf 'ExplorePwd\0' >> "${XPLR_PIPE_MSG_IN:?}" \
&& printf "FocusPath: %s\0" "$PTH" >> "${XPLR_PIPE_MSG_IN:?}" && printf 'LogSuccess: "%s"\0' "$PTH_ESC created" >> "${XPLR_PIPE_MSG_IN:?}" \
&& printf 'FocusPath: "%s"\0' "$PTH_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
else else
printf "PopMode\0" >> "${XPLR_PIPE_MSG_IN:?}" printf 'PopMode\0' >> "${XPLR_PIPE_MSG_IN:?}"
fi fi
]===], ]===],
}, },
@ -1556,8 +1542,9 @@ xplr.config.modes.builtin.create_file = {
help = "submit", help = "submit",
messages = { messages = {
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
PTH="$XPLR_INPUT_BUFFER" PTH="$XPLR_INPUT_BUFFER"
PTH_ESC=${PTH//\"/\\\"}
if [ "$PTH" ]; then if [ "$PTH" ]; then
mkdir -p -- "$(dirname $PTH)" \ mkdir -p -- "$(dirname $PTH)" \
&& touch -- "$PTH" \ && touch -- "$PTH" \
@ -1566,7 +1553,7 @@ xplr.config.modes.builtin.create_file = {
&& printf 'ExplorePwd\0' >> "${XPLR_PIPE_MSG_IN:?}" \ && printf 'ExplorePwd\0' >> "${XPLR_PIPE_MSG_IN:?}" \
&& printf 'FocusPath: "%s"\0' "$PTH_ESC" >> "${XPLR_PIPE_MSG_IN:?}" && printf 'FocusPath: "%s"\0' "$PTH_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
else else
printf "PopMode\0" >> "${XPLR_PIPE_MSG_IN:?}" printf 'PopMode\0' >> "${XPLR_PIPE_MSG_IN:?}"
fi fi
]===], ]===],
}, },
@ -1657,22 +1644,25 @@ xplr.config.modes.builtin.go_to = {
{ SetInputBuffer = "" }, { SetInputBuffer = "" },
}, },
}, },
["x"] = { ["x"] = {
help = "open in gui", help = "open in gui",
messages = { messages = {
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
if [ -z "$OPENER" ]; then if [ -z "$OPENER" ]; then
if command -v xdg-open; then if command -v xdg-open; then
OPENER=xdg-open OPENER=xdg-open
elif command -v open; then elif command -v open; then
OPENER=open OPENER=open
else else
printf "LogError: %s\0" "$OPENER not found" >> "${XPLR_PIPE_MSG_IN:?}" printf 'LogError: "$OPENER not found"\0' >> "${XPLR_PIPE_MSG_IN:?}"
exit 1 exit 1
fi fi
fi fi
$OPENER "${XPLR_FOCUS_PATH:?}" > /dev/null 2>&1 (while IFS= read -r -d '' LINE; do
$OPENER "${LINE:?}" > /dev/null 2>&1
done < "${XPLR_PIPE_RESULT_OUT:?}")
]===], ]===],
}, },
"ClearScreen", "ClearScreen",
@ -1700,16 +1690,18 @@ xplr.config.modes.builtin.rename = {
help = "submit", help = "submit",
messages = { messages = {
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
SRC="${XPLR_FOCUS_PATH:?}" SRC="${XPLR_FOCUS_PATH:?}"
SRC_ESC=${SRC//\"/\\\"}
TARGET="${XPLR_INPUT_BUFFER:?}" TARGET="${XPLR_INPUT_BUFFER:?}"
TARGET_ESC=${TARGET//\"/\\\"}
if [ -e "${TARGET:?}" ]; then if [ -e "${TARGET:?}" ]; then
printf "LogError: %s\0" "$TARGET already exists" >> "${XPLR_PIPE_MSG_IN:?}" printf 'LogError: "%s"\0' "$TARGET_ESC already exists" >> "${XPLR_PIPE_MSG_IN:?}"
else else
mv -- "${SRC:?}" "${TARGET:?}" \ mv -- "${SRC:?}" "${TARGET:?}" \
&& printf "ExplorePwd\0" >> "${XPLR_PIPE_MSG_IN:?}" \ && printf 'ExplorePwd\0' >> "${XPLR_PIPE_MSG_IN:?}" \
&& printf "FocusPath: %s\0" "$TARGET" >> "${XPLR_PIPE_MSG_IN:?}" \ && printf 'FocusPath: "%s"\0' "$TARGET_ESC" >> "${XPLR_PIPE_MSG_IN:?}" \
&& printf "LogSuccess: %s\0" "$SRC renamed to $TARGET" >> "${XPLR_PIPE_MSG_IN:?}" && printf 'LogSuccess: "%s"\0' "$SRC_ESC renamed to $TARGET_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
fi fi
]===], ]===],
}, },
@ -1742,16 +1734,18 @@ xplr.config.modes.builtin.duplicate_as = {
help = "submit", help = "submit",
messages = { messages = {
{ {
BashExecSilently = [===[ BashExecSilently0 = [===[
SRC="${XPLR_FOCUS_PATH:?}" SRC="${XPLR_FOCUS_PATH:?}"
SRC_ESC=${SRC//\"/\\\"}
TARGET="${XPLR_INPUT_BUFFER:?}" TARGET="${XPLR_INPUT_BUFFER:?}"
TARGET_ESC=${TARGET//\"/\\\"}
if [ -e "${TARGET:?}" ]; then if [ -e "${TARGET:?}" ]; then
printf "LogError: %s\0" "$TARGET already exists" >> "${XPLR_PIPE_MSG_IN:?}" printf 'LogError: "%s"\0' "$TARGET_ESC already exists" >> "${XPLR_PIPE_MSG_IN:?}"
else else
cp -r -- "${SRC:?}" "${TARGET:?}" \ cp -r -- "${SRC:?}" "${TARGET:?}" \
&& printf "ExplorePwd\0" >> "${XPLR_PIPE_MSG_IN:?}" \ && printf 'ExplorePwd\0' >> "${XPLR_PIPE_MSG_IN:?}" \
&& printf "FocusPath: %s\0" "$TARGET" >> "${XPLR_PIPE_MSG_IN:?}" \ && printf 'FocusPath: "%s"\0' "$TARGET_ESC" >> "${XPLR_PIPE_MSG_IN:?}" \
&& printf "LogSuccess: %s\0" "$SRC duplicated as $TARGET" >> "${XPLR_PIPE_MSG_IN:?}" && printf 'LogSuccess: "%s"\0' "$SRC_ESC duplicated as $TARGET_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
fi fi
]===], ]===],
}, },
@ -1778,15 +1772,16 @@ xplr.config.modes.builtin.delete = {
help = "force delete", help = "force delete",
messages = { messages = {
{ {
BashExec = [===[ BashExec0 = [===[
(while IFS= read -r -d '' line; do (while IFS= read -r -d '' LINE; do
if rm -rfv -- "${line:?}"; then LINE_ESC=${LINE//\"/\\\"}
printf "LogSuccess: %s\0" "$line deleted" >> "${XPLR_PIPE_MSG_IN:?}" if rm -rfv -- "${LINE:?}"; then
else printf 'LogSuccess: "%s"\0' "$LINE_ESC deleted" >> "${XPLR_PIPE_MSG_IN:?}"
printf "LogError: %s\0" "Failed to delete $line" >> "${XPLR_PIPE_MSG_IN:?}" else
fi printf 'LogError: "%s"\0' "Failed to delete $LINE_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
fi
done < "${XPLR_PIPE_RESULT_OUT:?}") done < "${XPLR_PIPE_RESULT_OUT:?}")
printf "ExplorePwdAsync\0" >> "${XPLR_PIPE_MSG_IN:?}" printf 'ExplorePwdAsync\0' >> "${XPLR_PIPE_MSG_IN:?}"
read -p "[enter to continue]" read -p "[enter to continue]"
]===], ]===],
}, },
@ -1797,23 +1792,24 @@ xplr.config.modes.builtin.delete = {
help = "delete", help = "delete",
messages = { messages = {
{ {
BashExec = [===[ BashExec0 = [===[
(while IFS= read -r -d '' line; do (while IFS= read -r -d '' LINE; do
if [ -d "$line" ] && [ ! -L "$line" ]; then LINE_ESC=${LINE//\"/\\\"}
if rmdir -v -- "${line:?}"; then if [ -d "$LINE" ] && [ ! -L "$LINE" ]; then
printf "LogSuccess: %s\0" "$line deleted" >> "${XPLR_PIPE_MSG_IN:?}" if rmdir -v -- "${LINE:?}"; then
printf 'LogSuccess: "%s"\0' "$LINE_ESC deleted" >> "${XPLR_PIPE_MSG_IN:?}"
else
printf 'LogError: "%s"\0' "Failed to delete $LINE_ESC" >> "${XPLR_PIPE_MSG_IN:?}"
fi
else else
printf "LogError: %s\0" "Failed to delete $line" >> "${XPLR_PIPE_MSG_IN:?}" if rm -v -- "${LINE:?}"; then
printf 'LogSuccess: "%s"\0' "$line deleted" >> "${XPLR_PIPE_MSG_IN:?}"
else
printf 'LogError: "%s"\0' "Failed to delete $line" >> "${XPLR_PIPE_MSG_IN:?}"
fi
fi fi
else
if rm -v -- "${line:?}"; then
printf "LogSuccess: %s\0" "$line deleted" >> "${XPLR_PIPE_MSG_IN:?}"
else
printf "LogError: %s\0" "Failed to delete $line" >> "${XPLR_PIPE_MSG_IN:?}"
fi
fi
done < "${XPLR_PIPE_RESULT_OUT:?}") done < "${XPLR_PIPE_RESULT_OUT:?}")
printf "ExplorePwdAsync\0" >> "${XPLR_PIPE_MSG_IN:?}" printf 'ExplorePwdAsync\0' >> "${XPLR_PIPE_MSG_IN:?}"
read -p "[enter to continue]" read -p "[enter to continue]"
]===], ]===],
}, },
@ -1834,7 +1830,7 @@ xplr.config.modes.builtin.action = {
["!"] = { ["!"] = {
help = "shell", help = "shell",
messages = { messages = {
{ Call = { command = "bash", args = { "-i" } } }, { Call0 = { command = "bash", args = { "-i" } } },
"ExplorePwdAsync", "ExplorePwdAsync",
"PopMode", "PopMode",
}, },
@ -1850,7 +1846,7 @@ xplr.config.modes.builtin.action = {
help = "open in editor", help = "open in editor",
messages = { messages = {
{ {
BashExec = [===[ BashExec0 = [===[
${EDITOR:-vi} "${XPLR_FOCUS_PATH:?}" ${EDITOR:-vi} "${XPLR_FOCUS_PATH:?}"
]===], ]===],
}, },
@ -1861,9 +1857,9 @@ xplr.config.modes.builtin.action = {
help = "logs", help = "logs",
messages = { messages = {
{ {
BashExec = [===[ BashExec0 = [===[
[ -z "$PAGER" ] && PAGER="less -+F" [ -z "$PAGER" ] && PAGER="less -+F"
cat -- "${XPLR_PIPE_LOGS_OUT}" | ${PAGER:?} cat -- "${XPLR_PIPE_LOGS_OUT}" | tr '\0' '\n' | ${PAGER:?}
]===], ]===],
}, },
"PopMode", "PopMode",
@ -2570,3 +2566,4 @@ end
-- You can also use nested tables such as -- You can also use nested tables such as
-- `xplr.fn.custom.my_plugin.my_function` to define custom functions. -- `xplr.fn.custom.my_plugin.my_function` to define custom functions.
xplr.fn.custom = {} xplr.fn.custom = {}

@ -3,7 +3,6 @@ use indexmap::IndexSet;
use regex::Regex; use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::cmp::Ordering; use std::cmp::Ordering;
use crate::newlines::escape_string;
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum ExternalMsg { pub enum ExternalMsg {
@ -483,52 +482,72 @@ pub enum ExternalMsg {
/// ### Executing Commands ------------------------------------------------ /// ### Executing Commands ------------------------------------------------
/// Like `Call0`, but it uses `\n` as the delimiter in input/output pipes,
/// hence it cannot handle files with `\n` in the name.
/// You may want to use `Call0` instead.
Call(Command),
/// Call a shell command with the given arguments. /// Call a shell command with the given arguments.
/// Note that the arguments will be shell-escaped. /// Note that the arguments will be shell-escaped.
/// So to read the variables, the `-c` option of the shell /// So to read the variables, the `-c` option of the shell
/// can be used. /// can be used.
/// You may need to pass `ExplorePwd` depening on the expectation. /// You may need to pass `ExplorePwd` depending on the expectation.
/// ///
/// Type: { Call = { command = string, args = { "list", "of", "string" } } /// Type: { Call0 = { command = "string", args = { "list", "of", "string" } }
/// ///
/// Example: /// Example:
/// ///
/// - Lua: `{ Call = { command = "bash", args = { "-c", "read -p test" } } }` /// - Lua: `{ Call0 = { command = "bash", args = { "-c", "read -p test" } } }`
/// - YAML: `Call: { command: bash, args: ["-c", "read -p test"] }` /// - YAML: `Call0: { command: bash, args: ["-c", "read -p test"] }`
Call(Command), Call0(Command),
/// Like `Call` but without the flicker. The stdin, stdout /// Like `CallSilently0`, but it uses `\n` as the delimiter in input/output
/// pipes, hence it cannot handle files with `\n` in the name.
/// You may want to use `Call0Silently` instead.
CallSilently(Command),
/// Like `Call0` but without the flicker. The stdin, stdout
/// stderr will be piped to null. So it's non-interactive. /// stderr will be piped to null. So it's non-interactive.
/// ///
/// Type: { CallSilently = "string" } /// Type: { CallSilently0 = { command = "string", args = {"list", "of", "string"} } }
/// ///
/// Example: /// Example:
/// ///
/// - Lua: `{ CallSilently = { command = "tput", args = { "bell" } } }` /// - Lua: `{ CallSilently0 = { command = "tput", args = { "bell" } } }`
/// - YAML: `CallSilently: { command: tput, args: ["bell"] }` /// - YAML: `CallSilently0: { command: tput, args: ["bell"] }`
CallSilently(Command), CallSilently0(Command),
/// Like `BashExec0`, but it uses `\n` as the delimiter in input/output
/// pipes, hence it cannot handle files with `\n` in the name.
/// You may want to use `BashExec0` instead.
BashExec(String),
/// An alias to `Call: {command: bash, args: ["-c", "{string}"], silent: false}` /// An alias to `Call: {command: bash, args: ["-c", "{string}"], silent: false}`
/// where `{string}` is the given value. /// where `{string}` is the given value.
/// ///
/// Type: { BashExec = "string" } /// Type: { BashExec0 = "string" }
/// ///
/// Example: /// Example:
/// ///
/// - Lua: `{ BashExec = "read -p test" }` /// - Lua: `{ BashExec0 = "read -p test" }`
/// - YAML: `BashExec: "read -p test"` /// - YAML: `BashExec0: "read -p test"`
BashExec(String), BashExec0(String),
/// Like `BashExec` but without the flicker. The stdin, stdout /// Like `BashExecSilently0`, but it uses `\n` as the delimiter in
/// input/output pipes, hence it cannot handle files with `\n` in the name.
/// You may want to use `BashExec0Silently` instead.
BashExecSilently(String),
/// Like `BashExec0` but without the flicker. The stdin, stdout
/// stderr will be piped to null. So it's non-interactive. /// stderr will be piped to null. So it's non-interactive.
/// ///
/// Type: { BashExecSilently = "string" } /// Type: { BashExec0Silently = "string" }
/// ///
/// Example: /// Example:
/// ///
/// - Lua: `{ BashExecSilently = "tput bell" }` /// - Lua: `{ BashExecSilently0 = "tput bell" }`
/// - YAML: `BashExecSilently: "tput bell"` /// - YAML: `BashExecSilently0: "tput bell"`
BashExecSilently(String), BashExecSilently0(String),
/// ### Calling Lua Functions ---------------------------------------------- /// ### Calling Lua Functions ----------------------------------------------
@ -1071,7 +1090,7 @@ impl TryFrom<&str> for ExternalMsg {
if value.starts_with('!') { if value.starts_with('!') {
serde_yaml::from_str(value) serde_yaml::from_str(value)
} else if let Some((msg, args)) = value.split_once(' ') { } else if let Some((msg, args)) = value.split_once(' ') {
let msg = format!("!{} {}", msg.trim_end_matches(':'), escape_string(args)); let msg = format!("!{} {}", msg.trim_end_matches(':'), args);
serde_yaml::from_str(&msg) serde_yaml::from_str(&msg)
} else { } else {
serde_yaml::from_str(value) serde_yaml::from_str(value)
@ -1086,11 +1105,11 @@ impl ExternalMsg {
Self::Call(_) Self::Call(_)
| Self::Call0(_) | Self::Call0(_)
| Self::CallSilently(_) | Self::CallSilently(_)
| Self::Call0Silently(_) | Self::CallSilently0(_)
| Self::BashExec(_) | Self::BashExec(_)
| Self::BashExec0(_) | Self::BashExec0(_)
| Self::BashExecSilently(_) | Self::BashExecSilently(_)
| Self::BashExec0Silently(_) | Self::BashExecSilently0(_)
| Self::CallLua(_) | Self::CallLua(_)
| Self::CallLuaSilently(_) | Self::CallLuaSilently(_)
| Self::LuaEval(_) | Self::LuaEval(_)

@ -10,7 +10,9 @@ pub enum MsgOut {
ClearScreen, ClearScreen,
Debug(String), Debug(String),
Call(Command), Call(Command),
Call0(Command),
CallSilently(Command), CallSilently(Command),
CallSilently0(Command),
CallLua(String), CallLua(String),
CallLuaSilently(String), CallLuaSilently(String),
LuaEval(String), LuaEval(String),

@ -16,12 +16,14 @@ use crossterm::terminal as term;
use mlua::LuaSerdeExt; use mlua::LuaSerdeExt;
use mlua::Value; use mlua::Value;
use std::fs; use std::fs;
use std::fs::File;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::{Command, ExitStatus, Stdio}; use std::process::{Command, Stdio};
use std::sync::mpsc; use std::sync::mpsc;
use tui::backend::CrosstermBackend; use tui::backend::CrosstermBackend;
use tui::Terminal; use tui::Terminal;
use tui_input::Input;
pub fn get_tty() -> Result<fs::File> { pub fn get_tty() -> Result<fs::File> {
let tty = "/dev/tty"; let tty = "/dev/tty";
@ -60,7 +62,30 @@ fn call_lua_heavy(
lua::call(lua, func, arg) lua::call(lua, func, arg)
} }
fn call(app: &app::App, cmd: app::Command, silent: bool) -> Result<ExitStatus> { fn call(
mut app: app::App,
cmd: app::Command,
silent: bool,
terminal: &mut Terminal<CrosstermBackend<File>>,
event_reader: &mut EventReader,
mouse_enabled: &mut bool,
delimiter: char,
) -> Result<app::App> {
if !silent {
if *mouse_enabled {
execute!(terminal.backend_mut(), event::DisableMouseCapture)
.unwrap_or_default();
}
event_reader.stop();
terminal.clear()?;
terminal.set_cursor(0, 0)?;
term::disable_raw_mode()?;
terminal.show_cursor()?;
}
app.write_pipes(delimiter)?;
let focus_index = app let focus_index = app
.directory_buffer .directory_buffer
.as_ref() .as_ref()
@ -74,10 +99,17 @@ fn call(app: &app::App, cmd: app::Command, silent: bool) -> Result<ExitStatus> {
(get_tty()?.into(), get_tty()?.into(), get_tty()?.into()) (get_tty()?.into(), get_tty()?.into(), get_tty()?.into())
}; };
Command::new(cmd.command.clone()) let input_buffer = app
.input
.buffer
.as_ref()
.map(Input::to_string)
.unwrap_or_default();
let status = Command::new(cmd.command.clone())
.env("XPLR_APP_VERSION", app.version.clone()) .env("XPLR_APP_VERSION", app.version.clone())
.env("XPLR_PID", &app.pid.to_string()) .env("XPLR_PID", &app.pid.to_string())
.env("XPLR_INPUT_BUFFER", &app.input_unescaped) .env("XPLR_INPUT_BUFFER", input_buffer)
.env("XPLR_FOCUS_PATH", app.focused_node_str()) .env("XPLR_FOCUS_PATH", app.focused_node_str())
.env("XPLR_FOCUS_INDEX", focus_index) .env("XPLR_FOCUS_INDEX", focus_index)
.env("XPLR_SESSION_PATH", &app.session_path) .env("XPLR_SESSION_PATH", &app.session_path)
@ -100,7 +132,49 @@ fn call(app: &app::App, cmd: app::Command, silent: bool) -> Result<ExitStatus> {
.stderr(stderr) .stderr(stderr)
.args(cmd.args) .args(cmd.args)
.status() .status()
.map_err(Error::new) .map(|s| {
if s.success() {
Ok(())
} else {
Err(format!("process exited with code {}", &s))
}
})
.unwrap_or_else(|e| Err(e.to_string()));
match pipe::read_all(&app.pipe.msg_in, delimiter) {
Ok(msgs) => {
app = app.handle_batch_external_msgs(msgs)?;
}
Err(err) => {
app = app.log_error(err.to_string())?;
}
};
app.cleanup_pipes()?;
if let Err(e) = status {
app = app.log_error(e)?;
};
if !silent {
terminal.clear()?;
term::enable_raw_mode()?;
terminal.hide_cursor()?;
event_reader.start();
if *mouse_enabled {
match execute!(terminal.backend_mut(), event::EnableMouseCapture) {
Ok(_) => {
*mouse_enabled = true;
}
Err(e) => {
app = app.log_error(e.to_string())?;
}
}
}
}
Ok(app)
} }
fn start_fifo(path: &str, focus_path: &str) -> Result<fs::File> { fn start_fifo(path: &str, focus_path: &str) -> Result<fs::File> {
@ -122,6 +196,7 @@ pub struct Runner {
read_only: bool, read_only: bool,
print_pwd_as_result: bool, print_pwd_as_result: bool,
selection: Vec<PathBuf>, selection: Vec<PathBuf>,
delimiter: char,
} }
impl Runner { impl Runner {
@ -158,6 +233,7 @@ impl Runner {
read_only: cli.read_only, read_only: cli.read_only,
print_pwd_as_result: cli.print_pwd_as_result, print_pwd_as_result: cli.print_pwd_as_result,
selection: paths.collect(), selection: paths.collect(),
delimiter: if cli.write0 { '\0' } else { '\n' },
}) })
} }
@ -275,27 +351,27 @@ impl Runner {
} }
PrintPwdAndQuit => { PrintPwdAndQuit => {
result = Ok(Some(format!("{}\n", app.pwd))); result = Ok(Some(app.pwd_str(self.delimiter)));
break 'outer; break 'outer;
} }
PrintFocusPathAndQuit => { PrintFocusPathAndQuit => {
result = Ok(app result = Ok(app.focused_node().map(|n| {
.focused_node() format!("{}{}", n.absolute_path, self.delimiter)
.map(|n| format!("{}\n", n.absolute_path))); }));
break 'outer; break 'outer;
} }
PrintSelectionAndQuit => { PrintSelectionAndQuit => {
result = Ok(Some(app.selection_str())); result = Ok(Some(app.selection_str(self.delimiter)));
break 'outer; break 'outer;
} }
PrintResultAndQuit => { PrintResultAndQuit => {
result = if self.print_pwd_as_result { result = if self.print_pwd_as_result {
Ok(Some(app.pwd_str())) Ok(Some(app.pwd_str(self.delimiter)))
} else { } else {
Ok(Some(app.result_str())) Ok(Some(app.result_str(self.delimiter)))
}; };
break 'outer; break 'outer;
@ -490,37 +566,6 @@ impl Runner {
}; };
} }
CallSilently(cmd) => {
app.write_pipes()?;
let status = call(&app, cmd, true)
.map(|s| {
if s.success() {
Ok(())
} else {
Err(format!(
"process exited with code {}",
&s
))
}
})
.unwrap_or_else(|e| Err(e.to_string()));
match pipe::read_all(&app.pipe.msg_in) {
Ok(msgs) => {
app = app.handle_batch_external_msgs(msgs)?;
}
Err(err) => {
app = app.log_error(err.to_string())?;
}
};
app.cleanup_pipes()?;
if let Err(e) = status {
app = app.log_error(e.to_string())?;
};
}
CallLua(func) => { CallLua(func) => {
execute!( execute!(
terminal.backend_mut(), terminal.backend_mut(),
@ -684,67 +729,51 @@ impl Runner {
} }
Call(cmd) => { Call(cmd) => {
execute!( app = call(
terminal.backend_mut(), app,
event::DisableMouseCapture cmd,
) false,
.unwrap_or_default(); &mut terminal,
&mut event_reader,
event_reader.stop(); &mut mouse_enabled,
'\n',
terminal.clear()?; )?;
terminal.set_cursor(0, 0)?; }
term::disable_raw_mode()?;
terminal.show_cursor()?;
app.write_pipes()?;
let status = call(&app, cmd, false)
.map(|s| {
if s.success() {
Ok(())
} else {
Err(format!(
"process exited with code {}",
&s
))
}
})
.unwrap_or_else(|e| Err(e.to_string()));
// TODO remove duplicate segment
match pipe::read_all(&app.pipe.msg_in) {
Ok(msgs) => {
app = app.handle_batch_external_msgs(msgs)?;
}
Err(err) => {
app = app.log_error(err.to_string())?;
}
};
app.cleanup_pipes()?;
if let Err(e) = status { Call0(cmd) => {
app = app.log_error(e.to_string())?; app = call(
}; app,
cmd,
false,
&mut terminal,
&mut event_reader,
&mut mouse_enabled,
'\0',
)?;
}
terminal.clear()?; CallSilently(cmd) => {
term::enable_raw_mode()?; app = call(
terminal.hide_cursor()?; app,
event_reader.start(); cmd,
true,
&mut terminal,
&mut event_reader,
&mut mouse_enabled,
'\n',
)?;
}
if mouse_enabled { CallSilently0(cmd) => {
match execute!( app = call(
terminal.backend_mut(), app,
event::EnableMouseCapture cmd,
) { true,
Ok(_) => { &mut terminal,
mouse_enabled = true; &mut event_reader,
} &mut mouse_enabled,
Err(e) => { '\0',
app = app.log_error(e.to_string())?; )?;
}
}
}
} }
}; };
} }

Loading…
Cancel
Save