mirror of
https://github.com/sayanarijit/xplr.git
synced 2024-09-11 11:05:39 +03:00
Implement -M, --print-msg-in
To help with creating safe arguments for --on-load. e.g. ``` xplr --on-load $(xplr -M 'ChangeDirectory: %q' "${HOME:?}") ```
This commit is contained in:
parent
7c730557f2
commit
1d829c36e6
@ -87,12 +87,13 @@ xplr.config.modes.builtin.default.key_bindings.on_key.m = {
|
||||
help = "bookmark",
|
||||
messages = {
|
||||
{
|
||||
BashExecSilently = [===[
|
||||
BashExecSilently0 = [===[
|
||||
PTH="${XPLR_FOCUS_PATH:?}"
|
||||
PTH_ESC=$(printf %q "$PTH")
|
||||
if echo "${PTH:?}" >> "${XPLR_SESSION_PATH:?}/bookmarks"; then
|
||||
echo "LogSuccess: ${PTH:?} added to bookmarks" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m 'LogSuccess: %q' "$PTH_ESC added to bookmarks"
|
||||
else
|
||||
echo "LogError: Failed to bookmark ${PTH:?}" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m 'LogError: %q' "Failed to bookmark $PTH_ESC"
|
||||
fi
|
||||
]===],
|
||||
},
|
||||
@ -103,10 +104,11 @@ xplr.config.modes.builtin.default.key_bindings.on_key["`"] = {
|
||||
help = "go to bookmark",
|
||||
messages = {
|
||||
{
|
||||
BashExec = [===[
|
||||
BashExec0 = [===[
|
||||
PTH=$(cat "${XPLR_SESSION_PATH:?}/bookmarks" | fzf --no-sort)
|
||||
PTH_ESC=$(printf %q "$PTH")
|
||||
if [ "$PTH" ]; then
|
||||
echo FocusPath: "'"${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m 'FocusPath: %q' "$PTH"
|
||||
fi
|
||||
]===],
|
||||
},
|
||||
@ -138,17 +140,18 @@ xplr.config.modes.custom.bookmark = {
|
||||
m = {
|
||||
help = "bookmark dir",
|
||||
messages = {
|
||||
{ BashExecSilently = [[
|
||||
{ BashExecSilently0 = [[
|
||||
PTH="${XPLR_FOCUS_PATH:?}"
|
||||
if [ -d "${PTH}" ]; then
|
||||
PTH="${PTH}"
|
||||
elif [ -f "${PTH}" ]; then
|
||||
PTH="$(dirname "${PTH}")"
|
||||
fi
|
||||
PTH_ESC=$(printf %q "$PTH")
|
||||
if echo "${PTH:?}" >> "${XPLR_BOOKMARK_FILE:?}"; then
|
||||
echo "LogSuccess: ${PTH:?} added to bookmarks" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m 'LogSuccess: %q' "$PTH_ESC added to bookmarks"
|
||||
else
|
||||
echo "LogError: Failed to bookmark ${PTH:?}" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m 'LogError: %q' "Failed to bookmark $PTH_ESC"
|
||||
fi
|
||||
]]
|
||||
},
|
||||
@ -158,10 +161,10 @@ xplr.config.modes.custom.bookmark = {
|
||||
help = "go to bookmark",
|
||||
messages = {
|
||||
{
|
||||
BashExec = [===[
|
||||
BashExec0 = [===[
|
||||
PTH=$(cat "${XPLR_BOOKMARK_FILE:?}" | fzf --no-sort)
|
||||
if [ "$PTH" ]; then
|
||||
echo FocusPath: "'"${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m 'FocusPath: %q' "$PTH"
|
||||
fi
|
||||
]===]
|
||||
},
|
||||
@ -170,7 +173,7 @@ xplr.config.modes.custom.bookmark = {
|
||||
d = {
|
||||
help = "delete bookmark",
|
||||
messages = {
|
||||
{ BashExec = [[
|
||||
{ BashExec0 = [[
|
||||
PTH=$(cat "${XPLR_BOOKMARK_FILE:?}" | fzf --no-sort)
|
||||
sd "$PTH\n" "" "${XPLR_BOOKMARK_FILE:?}"
|
||||
]]
|
||||
@ -206,7 +209,7 @@ xplr.config.modes.builtin.go_to.key_bindings.on_key.b = {
|
||||
help = "bookmark jump",
|
||||
messages = {
|
||||
"PopMode",
|
||||
{ BashExec = [===[
|
||||
{ BashExec0 = [===[
|
||||
field='\(\S\+\s*\)'
|
||||
esc=$(printf '\033')
|
||||
N="${esc}[0m"
|
||||
@ -223,7 +226,7 @@ xplr.config.modes.builtin.go_to.key_bindings.on_key.b = {
|
||||
--preview-window="right:50%" \
|
||||
| sed 's#.*-> ##')
|
||||
if [ "$PTH" ]; then
|
||||
echo ChangeDirectory: "'"${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m 'ChangeDirectory: %q' "$PTH"
|
||||
fi
|
||||
]===]
|
||||
},
|
||||
@ -250,10 +253,10 @@ xplr.config.modes.builtin.go_to.key_bindings.on_key.h = {
|
||||
messages = {
|
||||
"PopMode",
|
||||
{
|
||||
BashExec = [===[
|
||||
PTH=$(cat "${XPLR_PIPE_HISTORY_OUT:?}" | sort -u | fzf --no-sort)
|
||||
BashExec0 = [===[
|
||||
PTH=$(cat "${XPLR_PIPE_HISTORY_OUT:?}" | sort -z -u | fzf --read0)
|
||||
if [ "$PTH" ]; then
|
||||
echo ChangeDirectory: "'"${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m 'ChangeDirectory: %q' "$PTH"
|
||||
fi
|
||||
]===],
|
||||
},
|
||||
@ -286,7 +289,7 @@ xplr.config.modes.builtin.default.key_bindings.on_key.R = {
|
||||
NODES=${SELECTION:-$(cat "${XPLR_PIPE_DIRECTORY_NODES_OUT:?}")}
|
||||
if [ "$NODES" ]; then
|
||||
echo -e "$NODES" | renamer
|
||||
echo ExplorePwdAsync >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
"$XPLR" -m ExplorePwdAsync
|
||||
fi
|
||||
]===],
|
||||
},
|
||||
@ -312,7 +315,7 @@ xplr.config.modes.builtin.default.key_bindings.on_key.S = {
|
||||
help = "serve $PWD",
|
||||
messages = {
|
||||
{
|
||||
BashExec = [===[
|
||||
BashExec0 = [===[
|
||||
IP=$(ip addr | grep -w inet | cut -d/ -f1 | grep -Eo '[0-9]{1,3}\.[0-9]{ 1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | fzf --prompt 'Select IP > ')
|
||||
echo "IP: ${IP:?}"
|
||||
read -p "Port (default 5000): " PORT
|
||||
@ -344,16 +347,16 @@ xplr.config.modes.builtin.default.key_bindings.on_key.P = {
|
||||
help = "preview",
|
||||
messages = {
|
||||
{
|
||||
BashExecSilently = [===[
|
||||
BashExecSilently0 = [===[
|
||||
FIFO_PATH="/tmp/xplr.fifo"
|
||||
|
||||
if [ -e "$FIFO_PATH" ]; then
|
||||
echo StopFifo >> "$XPLR_PIPE_MSG_IN"
|
||||
"$XPLR" -m StopFifo
|
||||
rm -f -- "$FIFO_PATH"
|
||||
else
|
||||
mkfifo "$FIFO_PATH"
|
||||
"$HOME/.local/bin/imv-open.sh" "$FIFO_PATH" "$XPLR_FOCUS_PATH" &
|
||||
echo "StartFifo: '$FIFO_PATH'" >> "$XPLR_PIPE_MSG_IN"
|
||||
"$XPLR" -m 'StartFifo: %q' "$FIFO_PATH"
|
||||
fi
|
||||
]===],
|
||||
},
|
||||
@ -407,27 +410,33 @@ local function stat(node)
|
||||
return node.mime_essence
|
||||
end
|
||||
|
||||
local function read(path, lines)
|
||||
local out = ""
|
||||
local function read(path, height)
|
||||
local p = io.open(path)
|
||||
|
||||
if p == nil then
|
||||
return stat(path)
|
||||
return nil
|
||||
end
|
||||
|
||||
local i = 0
|
||||
local res = ""
|
||||
for line in p:lines() do
|
||||
out = out .. line .. "\n"
|
||||
if i == lines then
|
||||
if line:match("[^ -~\n\t]") then
|
||||
p:close()
|
||||
return
|
||||
end
|
||||
|
||||
res = res .. line .. "\n"
|
||||
if i == height then
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
p:close()
|
||||
|
||||
return out
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
xplr.config.layouts.builtin.default = {
|
||||
Horizontal = {
|
||||
config = {
|
||||
@ -485,7 +494,7 @@ Navigate using the [tere][19] file explorer (defaults to type-to-nav system).
|
||||
xplr.config.modes.builtin.default.key_bindings.on_key.T = {
|
||||
help = "tere nav",
|
||||
messages = {
|
||||
{ BashExec = [[echo ChangeDirectory: "'"$(tere)"'" >> "$XPLR_PIPE_MSG_IN"]] },
|
||||
{ BashExec0 = [[xplr -m 'ChangeDirectory: %q' "$(tere)"]] },
|
||||
},
|
||||
}
|
||||
```
|
||||
|
@ -155,12 +155,12 @@ xplr.config.modes.custom.fzxplr = {
|
||||
messages = {
|
||||
{
|
||||
BashExec = [===[
|
||||
PTH=$(cat "${XPLR_PIPE_DIRECTORY_NODES_OUT:?}" | awk -F/ '{print $NF}' | fzf)
|
||||
if [ -d "$PTH" ]; then
|
||||
echo ChangeDirectory: "'"${PWD:?}/${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
else
|
||||
echo FocusPath: "'"${PWD:?}/${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||
fi
|
||||
PTH=$(cat "${XPLR_PIPE_DIRECTORY_NODES_OUT:?}" | awk -F/ '{print $NF}' | fzf)
|
||||
if [ -d "$PTH" ]; then
|
||||
"$XPLR" -m 'ChangeDirectory: %q' "$PTH"
|
||||
else
|
||||
"$XPLR" -m 'FocusPath: %q' "$PTH"
|
||||
fi
|
||||
]===]
|
||||
},
|
||||
"PopMode",
|
||||
@ -180,12 +180,10 @@ As you can see, the key `F` in mode `fzxplr` (the name can be anything)
|
||||
executes a script in `bash`.
|
||||
|
||||
`BashExec`, `PopMode`, `SwitchModeBuiltin`, `ChangeDirectory` and `FocusPath`
|
||||
are [messages][18], `$XPLR_PIPE_MSG_IN`,
|
||||
`$XPLR_PIPE_DIRECTORY_NODES_OUT` are
|
||||
[environment variables][22] exported by `xplr`
|
||||
before executing the command. They contain the path to the
|
||||
[input][23] and [output][24] pipes that
|
||||
allows external tools to interact with `xplr`.
|
||||
are [messages][18], `$XPLR`, `$XPLR_PIPE_DIRECTORY_NODES_OUT` are
|
||||
[environment variables][22] exported by `xplr` before executing the command.
|
||||
They contain the path to the [input][23] and [output][24] pipes that allows
|
||||
external tools to interact with `xplr`.
|
||||
|
||||
Now that we have our new mode ready, let's add an entry point to this mode via
|
||||
the `default` mode.
|
||||
|
@ -24,8 +24,7 @@ version of xplr, but they have one common drawback - the user will need to keep
|
||||
an eye on the releases, and manually upgrade xplr when a new version is
|
||||
available.
|
||||
|
||||
One way to keep an eye on the releases is to
|
||||
[watch the repository][4].
|
||||
One way to keep an eye on the releases is to [watch the repository][4].
|
||||
|
||||
## Community Maintained Repositories
|
||||
|
||||
|
@ -7,11 +7,9 @@ Once [installed][1], use the following steps to setup and run xplr.
|
||||
```bash
|
||||
mkdir -p ~/.config/xplr
|
||||
|
||||
version="$(xplr | grep ^version: | cut -d' ' -f 2)"
|
||||
version="$(xplr --version | awk '{print $2}')"
|
||||
|
||||
# When the app loads, press `#`
|
||||
|
||||
echo version = '"'${version:?}'"' > ~/.config/xplr/init.lua
|
||||
echo "version = '${version:?}'" > ~/.config/xplr/init.lua
|
||||
```
|
||||
|
||||
Then
|
||||
|
@ -20,8 +20,11 @@ fn main() {
|
||||
-- Denotes the end of command-line flags and options
|
||||
--force-focus Focuses on the given <PATH>, even if it is a directory
|
||||
-h, --help Prints help information
|
||||
-m, --pipe-msg-in Helps passing messages to the active xplr session
|
||||
--print-pwd-as-result Prints the present working directory when quitting
|
||||
-m, --pipe-msg-in Helps safely passing messages to the active xplr
|
||||
session, use %%, %s and %q as the placeholders
|
||||
-M, --print-msg-in Like --pipe-msg-in, but prints the message instead of
|
||||
passing to the active xplr session
|
||||
--print-pwd-as-result Prints the present working directory when quitting
|
||||
with `PrintResultAndQuit`
|
||||
--read-only Enables read-only mode (config.general.read_only)
|
||||
--read0 Reads paths separated using the null character (\0)
|
||||
@ -59,6 +62,11 @@ fn main() {
|
||||
eprintln!("error: {}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
} else if !cli.print_msg_in.is_empty() {
|
||||
if let Err(err) = cli::print_msg_in(cli.print_msg_in) {
|
||||
eprintln!("error: {}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
} else {
|
||||
match runner::from_cli(cli).and_then(|a| a.run()) {
|
||||
Ok(Some(out)) => {
|
||||
|
63
src/cli.rs
63
src/cli.rs
@ -22,6 +22,7 @@ pub struct Cli {
|
||||
pub extra_config: Vec<PathBuf>,
|
||||
pub on_load: Vec<app::ExternalMsg>,
|
||||
pub pipe_msg_in: Vec<String>,
|
||||
pub print_msg_in: Vec<String>,
|
||||
pub paths: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
@ -120,9 +121,11 @@ impl Cli {
|
||||
}
|
||||
|
||||
"-m" | "--pipe-msg-in" => {
|
||||
for arg in args.by_ref() {
|
||||
cli.pipe_msg_in.push(arg);
|
||||
}
|
||||
cli.pipe_msg_in.extend(args.by_ref());
|
||||
}
|
||||
|
||||
"-M" | "--print-msg-in" => {
|
||||
cli.print_msg_in.extend(args.by_ref());
|
||||
}
|
||||
|
||||
// path
|
||||
@ -137,15 +140,39 @@ impl Cli {
|
||||
}
|
||||
|
||||
pub fn pipe_msg_in(args: Vec<String>) -> Result<()> {
|
||||
let mut msg = fmt_msg_in(args)?;
|
||||
|
||||
if let Ok(path) = std::env::var("XPLR_PIPE_MSG_IN") {
|
||||
let delimiter = fs::read(&path)?
|
||||
.first()
|
||||
.cloned()
|
||||
.context("failed to detect delimmiter")?;
|
||||
|
||||
msg.push(delimiter.try_into()?);
|
||||
File::options()
|
||||
.append(true)
|
||||
.open(&path)?
|
||||
.write_all(msg.as_bytes())?;
|
||||
} else {
|
||||
println!("{}", msg);
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_msg_in(args: Vec<String>) -> Result<()> {
|
||||
let msg = fmt_msg_in(args)?;
|
||||
print!("{}", msg);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fmt_msg_in(args: Vec<String>) -> Result<String> {
|
||||
let mut args = args.into_iter();
|
||||
|
||||
let format = args.next().context("usage: xplr -m FORMAT [ARGUMENT]...")?;
|
||||
let format = args.next().context("usage: FORMAT [ARGUMENT]...")?;
|
||||
let mut msg = "".to_string();
|
||||
|
||||
let mut last_char = None;
|
||||
let chars = format.chars();
|
||||
|
||||
for ch in chars {
|
||||
for ch in format.chars() {
|
||||
match (ch, last_char) {
|
||||
('%', Some('%')) => {
|
||||
msg.push(ch);
|
||||
@ -183,22 +210,6 @@ pub fn pipe_msg_in(args: Vec<String>) -> Result<()> {
|
||||
}
|
||||
|
||||
// Validate
|
||||
let mut msg = json::to_string(&ExternalMsg::try_from(msg.as_str())?)?;
|
||||
|
||||
if let Ok(path) = std::env::var("XPLR_PIPE_MSG_IN") {
|
||||
let delimiter = fs::read(&path)?
|
||||
.first()
|
||||
.cloned()
|
||||
.context("failed to detect delimmiter")?;
|
||||
|
||||
msg.push(delimiter.try_into()?);
|
||||
File::options()
|
||||
.append(true)
|
||||
.open(&path)?
|
||||
.write_all(msg.as_bytes())?;
|
||||
} else {
|
||||
println!("{}", msg);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
let msg = json::to_string(&ExternalMsg::try_from(msg.as_str())?)?;
|
||||
Ok(msg)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user