@ -253,8 +253,7 @@ advantages and limitations.</p>
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.< / p >
< p > One way to keep an eye on the releases is to
< a href = "https://github.com/sayanarijit/xplr/watchers" > watch the repository< / a > .< / p >
< p > One way to keep an eye on the releases is to < a href = "https://github.com/sayanarijit/xplr/watchers" > watch the repository< / a > .< / p >
< h2 id = "community-maintained-repositories" > < a class = "header" href = "#community-maintained-repositories" > Community Maintained Repositories< / a > < / h2 >
< p > xplr can be installed from one of the following community maintained
repositories:< / p >
@ -403,11 +402,9 @@ mkdir -p "$XDG_CONFIG_HOME" "$XDG_RUNTIME_DIR"
< h2 id = "create-the-customizable-config-file" > < a class = "header" href = "#create-the-customizable-config-file" > Create the customizable config file< / a > < / h2 >
< pre > < code class = "language-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
< / code > < / pre >
< p > Then
< strong > < a href = "https://github.com/sayanarijit/xplr/blob/main/src/init.lua" > copy from here< / a > < / strong >
@ -1161,12 +1158,12 @@ directory.</p>
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" ,
@ -1184,12 +1181,10 @@ directory.</p>
< p > As you can see, the key < code > F< / code > in mode < code > fzxplr< / code > (the name can be anything)
executes a script in < code > bash< / code > .< / p >
< p > < code > BashExec< / code > , < code > PopMode< / code > , < code > SwitchModeBuiltin< / code > , < code > ChangeDirectory< / code > and < code > FocusPath< / code >
are < a href = "message.html#message" > messages< / a > , < code > $XPLR_PIPE_MSG_IN< / code > ,
< code > $XPLR_PIPE_DIRECTORY_NODES_OUT< / code > are
< a href = "environment-variables-and-pipes.html#environment-variables" > environment variables< / a > exported by < code > xplr< / code >
before executing the command. They contain the path to the
< a href = "environment-variables-and-pipes.html#input-pipe" > input< / a > and < a href = "environment-variables-and-pipes.html#output-pipes" > output< / a > pipes that
allows external tools to interact with < code > xplr< / code > .< / p >
are < a href = "message.html#message" > messages< / a > , < code > $XPLR< / code > , < code > $XPLR_PIPE_DIRECTORY_NODES_OUT< / code > are
< a href = "environment-variables-and-pipes.html#environment-variables" > environment variables< / a > exported by < code > xplr< / code > before executing the command.
They contain the path to the < a href = "environment-variables-and-pipes.html#input-pipe" > input< / a > and < a href = "environment-variables-and-pipes.html#output-pipes" > output< / a > pipes that allows
external tools to interact with < code > xplr< / code > .< / p >
< p > Now that we have our new mode ready, let's add an entry point to this mode via
the < code > default< / code > mode.< / p >
< pre > < code class = "language-lua" > xplr.config.modes.builtin.default.key_bindings.on_key[" F" ] = {
@ -2308,43 +2303,59 @@ It keeps the input buffer.</p>
< / ul >
< h3 id = "executing-commands" > < a class = "header" href = "#executing-commands" > Executing Commands< / a > < / h3 >
< h4 id = "call" > < a class = "header" href = "#call" > Call< / a > < / h4 >
< p > Like < code > Call0< / code > , but it uses < code > \n< / code > as the delimiter in input/output pipes,
hence it cannot handle files with < code > \n< / code > in the name.
You may want to use < code > Call0< / code > instead.< / p >
< h4 id = "call0" > < a class = "header" href = "#call0" > Call0< / a > < / h4 >
< p > Call a shell command with the given arguments.
Note that the arguments will be shell-escaped.
So to read the variables, the < code > -c< / code > option of the shell
can be used.
You may need to pass < code > ExplorePwd< / code > depening on the expectation.< / p >
< p > Type: { Call = { command = string, args = { " list" , " of" , " string" } }< / p >
You may need to pass < code > ExplorePwd< / code > depend ing on the expectation.< / p >
< p > Type: { Call0 = { command = " string" , args = { " list" , " of" , " string" } }< / p >
< p > Example:< / p >
< ul >
< li > Lua: < code > { Call = { command = " bash" , args = { " -c" , " read -p test" } } }< / code > < / li >
< li > YAML: < code > Call: { command: bash, args: [" -c" , " read -p test" ] }< / code > < / li >
< li > Lua: < code > { Call0 = { command = " bash" , args = { " -c" , " read -p test" } } }< / code > < / li >
< li > YAML: < code > Call0 : { command: bash, args: [" -c" , " read -p test" ] }< / code > < / li >
< / ul >
< h4 id = "callsilently" > < a class = "header" href = "#callsilently" > CallSilently< / a > < / h4 >
< p > Like < code > Call< / code > but without the flicker. The stdin, stdout
< p > Like < code > CallSilently0< / code > , but it uses < code > \n< / code > as the delimiter in input/output
pipes, hence it cannot handle files with < code > \n< / code > in the name.
You may want to use < code > CallSilently0< / code > instead.< / p >
< h4 id = "callsilently0" > < a class = "header" href = "#callsilently0" > CallSilently0< / a > < / h4 >
< p > Like < code > Call0< / code > but without the flicker. The stdin, stdout
stderr will be piped to null. So it's non-interactive.< / p >
< p > Type: { CallSilently = " string" }< / p >
< p > Type: { CallSilently0 = { command = " string" , args = {" list" , " of" , " string" } } }< / p >
< p > Example:< / p >
< ul >
< li > Lua: < code > { CallSilently = { command = " tput" , args = { " bell" } } }< / code > < / li >
< li > YAML: < code > CallSilently: { command: tput, args: [" bell" ] }< / code > < / li >
< li > Lua: < code > { CallSilently0 = { command = " tput" , args = { " bell" } } }< / code > < / li >
< li > YAML: < code > CallSilently0 : { command: tput, args: [" bell" ] }< / code > < / li >
< / ul >
< h4 id = "bashexec" > < a class = "header" href = "#bashexec" > BashExec< / a > < / h4 >
< p > Like < code > BashExec0< / code > , but it uses < code > \n< / code > as the delimiter in input/output
pipes, hence it cannot handle files with < code > \n< / code > in the name.
You may want to use < code > BashExec0< / code > instead.< / p >
< h4 id = "bashexec0" > < a class = "header" href = "#bashexec0" > BashExec0< / a > < / h4 >
< p > An alias to < code > Call: {command: bash, args: [" -c" , " {string}" ], silent: false}< / code >
where < code > {string}< / code > is the given value.< / p >
< p > Type: { BashExec = " string" }< / p >
< p > Type: { BashExec0 = " string" }< / p >
< p > Example:< / p >
< ul >
< li > Lua: < code > { BashExec = " read -p test" }< / code > < / li >
< li > YAML: < code > BashExec: " read -p test" < / code > < / li >
< li > Lua: < code > { BashExec0 = " read -p test" }< / code > < / li >
< li > YAML: < code > BashExec0 : " read -p test" < / code > < / li >
< / ul >
< h4 id = "bashexecsilently" > < a class = "header" href = "#bashexecsilently" > BashExecSilently< / a > < / h4 >
< p > Like < code > BashExec< / code > but without the flicker. The stdin, stdout
< p > Like < code > BashExecSilently0< / code > , but it uses < code > \n< / code > as the delimiter in
input/output pipes, hence it cannot handle files with < code > \n< / code > in the name.
You may want to use < code > BashExecSilently0< / code > instead.< / p >
< h4 id = "bashexecsilently0" > < a class = "header" href = "#bashexecsilently0" > BashExecSilently0< / a > < / h4 >
< p > Like < code > BashExec0< / code > but without the flicker. The stdin, stdout
stderr will be piped to null. So it's non-interactive.< / p >
< p > Type: { BashExecSilently = " string" }< / p >
< p > Type: { BashExecSilently0 = " string" }< / p >
< p > Example:< / p >
< ul >
< li > Lua: < code > { BashExecSilently = " tput bell" }< / code > < / li >
< li > YAML: < code > BashExecSilently: " tput bell" < / code > < / li >
< li > Lua: < code > { BashExecSilently0 = " tput bell" }< / code > < / li >
< li > YAML: < code > BashExecSilently0 : " tput bell" < / code > < / li >
< / ul >
< h3 id = "calling-lua-functions" > < a class = "header" href = "#calling-lua-functions" > Calling Lua Functions< / a > < / h3 >
< h4 id = "calllua" > < a class = "header" href = "#calllua" > CallLua< / a > < / h4 >
@ -3447,7 +3458,7 @@ xplr.config.modes.builtin.default.key_bindings.on_key.space = {
< / code > < / pre >
< div style = "break-before: page; page-break-before: always;" > < / div > < h1 id = "environment-variables-and-pipes" > < a class = "header" href = "#environment-variables-and-pipes" > Environment Variables and Pipes< / a > < / h1 >
< p > Alternative to < code > CallLua< / code > , < code > CallLuaSilently< / code > messages that call Lua functions,
there are < code > Call< / code > , < code > CallSilently< / code > , < code > BashExec< / code > , < code > BashExecSilently< / code > messages
there are < code > Call0 < / code > , < code > CallSilently0 < / code > , < code > BashExec0 < / code > , < code > BashExecSilently0 < / code > messages
that call shell commands.< / p >
< p > However, unlike the Lua functions, these shell commands have to read the useful
information and send messages via environment variables and temporary files
@ -3457,10 +3468,11 @@ a command is being executed.</p>
for example.< / p >
< p > To see the environment variables and pipes, invoke the shell by typing < code > :!< / code > in default
mode and run the following command:< / p >
< pre > < code > env | grep ^XPLR_
< pre > < code > env | grep ^XPLR
< / code > < / pre >
< p > You will see something like:< / p >
< pre > < code > XPLR_FOCUS_INDEX=0
< pre > < code > XPLR=xplr
XPLR_FOCUS_INDEX=0
XPLR_MODE=action to
XPLR_PIPE_SELECTION_OUT=/run/user/1000/xplr/session/122278/pipe/selection_out
XPLR_INPUT_BUFFER=
@ -3479,6 +3491,7 @@ XPLR_PIPE_DIRECTORY_NODES_OUT=/run/user/1000/xplr/session/122278/pipe/directory_
called < a href = "environment-variables-and-pipes.html#pipes" > " pipe" s< / a > .< / p >
< p > The other variables are single-line variables containing simple information:< / p >
< ul >
< li > < a href = "environment-variables-and-pipes.html#xplr" > XPLR< / a > < / li >
< li > < a href = "environment-variables-and-pipes.html#xplr_app_version" > XPLR_APP_VERSION< / a > < / li >
< li > < a href = "environment-variables-and-pipes.html#xplr_focus_index" > XPLR_FOCUS_INDEX< / a > < / li >
< li > < a href = "environment-variables-and-pipes.html#xplr_focus_path" > XPLR_FOCUS_PATH< / a > < / li >
@ -3488,20 +3501,25 @@ called <a href="environment-variables-and-pipes.html#pipes">"pipe"s</a
< li > < a href = "environment-variables-and-pipes.html#xplr_session_path" > XPLR_SESSION_PATH< / a > < / li >
< / ul >
< h3 id = "environment-variables" > < a class = "header" href = "#environment-variables" > Environment variables< / a > < / h3 >
< h4 id = "xplr" > < a class = "header" href = "#xplr" > XPLR< / a > < / h4 >
< p > The binary path of xplr command.< / p >
< h4 id = "xplr_app_version" > < a class = "header" href = "#xplr_app_version" > XPLR_APP_VERSION< / a > < / h4 >
< p > Self-explanatory.< / p >
< h4 id = "xplr_focus_index" > < a class = "header" href = "#xplr_focus_index" > XPLR_FOCUS_INDEX< / a > < / h4 >
< p > Contains the index of the currently focused item, as seen in < a href = "column-renderer.html#index" > column-renderer/index< / a > .< / p >
< p > Contains the index of the currently focused item, as seen in
< a href = "column-renderer.html#index" > column-renderer/index< / a > .< / p >
< h4 id = "xplr_focus_path" > < a class = "header" href = "#xplr_focus_path" > XPLR_FOCUS_PATH< / a > < / h4 >
< p > Contains the full path of the currently focused node.< / p >
< h4 id = "xplr_input_buffer" > < a class = "header" href = "#xplr_input_buffer" > XPLR_INPUT_BUFFER< / a > < / h4 >
< p > The line currently in displaying in the xplr input buffer. For e.g. the search input while searching. See < a href = "messages.html#reading-input" > Reading Input< / a > .< / p >
< p > The line currently in displaying in the xplr input buffer. For e.g. the search
input while searching. See < a href = "messages.html#reading-input" > Reading Input< / a > .< / p >
< h4 id = "xplr_mode" > < a class = "header" href = "#xplr_mode" > XPLR_MODE< / a > < / h4 >
< p > Contains the mode xplr is currently in, see < a href = "modes.html#modes" > modes< / a > .< / p >
< h4 id = "xplr_pid" > < a class = "header" href = "#xplr_pid" > XPLR_PID< / a > < / h4 >
< p > Contains the process ID of the current xplr process.< / p >
< h4 id = "xplr_session_path" > < a class = "header" href = "#xplr_session_path" > XPLR_SESSION_PATH< / a > < / h4 >
< p > Contains the current session path, like /tmp/runtime-" $USER" /xplr/session/" $XPLR_PID" /, you can find temporary files here, such as pipes.< / p >
< p > Contains the current session path, like /tmp/runtime-" $USER" /xplr/session/" $XPLR_PID" /,
you can find temporary files here, such as pipes.< / p >
< h3 id = "pipes" > < a class = "header" href = "#pipes" > Pipes< / a > < / h3 >
< h4 id = "input-pipe" > < a class = "header" href = "#input-pipe" > Input pipe< / a > < / h4 >
< p > Currently there is only one input pipe.< / p >
@ -3511,7 +3529,9 @@ called <a href="environment-variables-and-pipes.html#pipes">"pipe"s</a
< h4 id = "output-pipes" > < a class = "header" href = "#output-pipes" > Output pipes< / a > < / h4 >
< p > < code > XPLR_PIPE_*_OUT< / code > are the output pipes that contain data which cannot be
exposed directly via environment variables, like multi-line strings.
These pipes can be accessed as plaintext files located in $XPLR_SESSION_PATH.< / p >
These pipes can be accessed as plain text files located in $XPLR_SESSION_PATH.< / p >
< p > Depending on the message (e.g. < code > Call< / code > or < code > Call0< / code > ), each line will be separated
by newline or null character (< code > \n< / code > or < code > \0< / code > ).< / p >
< ul >
< li > < a href = "environment-variables-and-pipes.html#xplr_pipe_selection_out" > XPLR_PIPE_SELECTION_OUT< / a > < / li >
< li > < a href = "environment-variables-and-pipes.html#xplr_pipe_global_help_menu_out" > XPLR_PIPE_GLOBAL_HELP_MENU_OUT< / a > < / li >
@ -3521,35 +3541,41 @@ These pipes can be accessed as plaintext files located in $XPLR_SESSION_PATH.</p
< li > < a href = "environment-variables-and-pipes.html#xplr_pipe_directory_nodes_out" > XPLR_PIPE_DIRECTORY_NODES_OUT< / a > < / li >
< / ul >
< h4 id = "xplr_pipe_msg_in" > < a class = "header" href = "#xplr_pipe_msg_in" > XPLR_PIPE_MSG_IN< / a > < / h4 >
< p > Append new-line delimited messages to this pipe in < a href = "https://www.yaml.org" > YAML< / a >
(or < a href = "https://www.json.org" > JSON< / a > ) syntax. These messages will be read and
handled by xplr after the command execution.< / p >
< p > Append new messages to this pipe in < a href = "https://www.yaml.org" > YAML< / a > (or < a href = "https://www.json.org" > JSON< / a > ) syntax. These
messages will be read and handled by xplr after the command execution.< / p >
< p > Depending on the message (e.g. < code > Call< / code > or < code > Call0< / code > ) you need to separate each
message using newline or null character (< code > \n< / code > or < code > \0< / code > ).< / p >
< blockquote >
< p > < strong > < em > NOTE:< / em > < / strong > Since version < code > v0.20.0< / code > , it's recommended to avoid writing
directly to this file, as safely escaping YAML strings is a lot of work. Use
< code > xplr -m< / code > / < code > xplr --pipe-msg-in< / code > to pass messages to xplr in a safer way.< / p >
< p > Example: < code > " $XPLR" -m 'ChangeDirectory: %q' " ${HOME:?}" < / code > < / p >
< / blockquote >
< h4 id = "xplr_pipe_selection_out" > < a class = "header" href = "#xplr_pipe_selection_out" > XPLR_PIPE_SELECTION_OUT< / a > < / h4 >
< p > New-line delimited list of selected paths.< / p >
< p > L ist of selected paths.< / p >
< h4 id = "xplr_pipe_global_help_menu_out" > < a class = "header" href = "#xplr_pipe_global_help_menu_out" > XPLR_PIPE_GLOBAL_HELP_MENU_OUT< / a > < / h4 >
< p > The full help menu.< / p >
< h4 id = "xplr_pipe_logs_out" > < a class = "header" href = "#xplr_pipe_logs_out" > XPLR_PIPE_LOGS_OUT< / a > < / h4 >
< p > New-line delimited list of logs.< / p >
< p > L ist of logs.< / p >
< h4 id = "xplr_pipe_result_out" > < a class = "header" href = "#xplr_pipe_result_out" > XPLR_PIPE_RESULT_OUT< / a > < / h4 >
< p > New-line delimited r esult (selected paths if any, else the focused path)< / p >
< p > R esult (selected paths if any, else the focused path)< / p >
< h4 id = "xplr_pipe_history_out" > < a class = "header" href = "#xplr_pipe_history_out" > XPLR_PIPE_HISTORY_OUT< / a > < / h4 >
< p > New-line delimited l ist of last visited paths (similar to jump list in vim).< / p >
< p > L ist of last visited paths (similar to jump list in vim).< / p >
< h4 id = "xplr_pipe_directory_nodes_out" > < a class = "header" href = "#xplr_pipe_directory_nodes_out" > XPLR_PIPE_DIRECTORY_NODES_OUT< / a > < / h4 >
< p > New-line delimited list of paths, filtered and sorted as displayed in the
< a href = "layout.html#table" > files table< / a > .< / p >
< p > List of paths, filtered and sorted as displayed in the < a href = "layout.html#table" > files table< / a > .< / p >
< h3 id = "example-using-environment-variables-and-pipes" > < a class = "header" href = "#example-using-environment-variables-and-pipes" > Example: Using Environment Variables and Pipes< / a > < / h3 >
< pre > < code class = "language-lua" > xplr.config.modes.builtin.default.key_bindings.on_key.space = {
help = " ask name and greet" ,
messages = {
{
BashExec = [===[
echo " What's your name?"
BashExec0 = [===[
echo " What's your name?"
read name
greeting=" Hello $name!"
message=" $greeting You are inside $PWD"
read name
greeting=" Hello $name!"
message=" $greeting You are inside $PWD"
echo LogSuccess: '" '$message'" ' > > " ${XPLR_PIPE_MSG_IN:?} "
" $XPLR" -m 'LogSuccess: %q' " $message "
]===]
}
}
@ -3563,8 +3589,8 @@ handled by xplr after the command execution.</p>
help = " open" ,
messages = {
{
BashExecSilently = [===[
xdg-open " ${XPLR_FOCUS_PATH:?}"
BashExecSilently0 = [===[
xdg-open " ${XPLR_FOCUS_PATH:?}"
]===],
},
},
@ -3636,12 +3662,13 @@ gracefully cancel "cd on quit".</p>
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
]===],
},
@ -3652,10 +3679,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
]===],
},
@ -3682,17 +3710,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
]]
},
@ -3702,10 +3731,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
]===]
},
@ -3714,7 +3743,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:?}"
]]
@ -3745,7 +3774,7 @@ xplr.config.modes.custom.bookmark = {
help = " bookmark jump" ,
messages = {
" PopMode" ,
{ BashExec = [===[
{ BashExec0 = [===[
field='\(\S\+\s*\)'
esc=$(printf '\033')
N=" ${esc}[0m"
@ -3762,7 +3791,7 @@ xplr.config.modes.custom.bookmark = {
--preview-window=" right:50%" \
| sed 's#.*-> ##')
if [ " $PTH" ]; then
echo ChangeDirectory: " '" ${PTH:?}" '" > > " ${XPLR_PIPE_MSG_IN:?} "
" $XPLR" -m 'ChangeDirectory: %q' " $PTH"
fi
]===]
},
@ -3784,10 +3813,10 @@ xplr.config.modes.custom.bookmark = {
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
]===],
},
@ -3814,7 +3843,7 @@ xplr.config.modes.custom.bookmark = {
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
]===],
},
@ -3835,7 +3864,7 @@ xplr.config.modes.custom.bookmark = {
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
@ -3862,16 +3891,16 @@ xplr.config.modes.custom.bookmark = {
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
]===],
},
@ -3917,27 +3946,33 @@ imv-msg "$IMV_PID" quit
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 = {
@ -3990,7 +4025,7 @@ end
< pre > < code class = "language-lua" > 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) " ]] },
},
}
< / code > < / pre >
@ -4072,8 +4107,7 @@ integers. They will be plugged using the <code>require()</code> function in Lua.
├── README.md
└── init.lua
< / code > < / pre >
< p > You can also use
< a href = "https://github.com/sayanarijit/plugin-template1.xplr" > this template< / a > .< / p >
< p > You can also use < a href = "https://github.com/sayanarijit/plugin-template1.xplr" > this template< / a > .< / p >
< h3 id = "readmemd" > < a class = "header" href = "#readmemd" > README.md< / a > < / h3 >
< p > This is where you document what the plugin does, how to use it, etc.< / p >
< h3 id = "initlua" > < a class = "header" href = "#initlua" > init.lua< / a > < / h3 >
@ -4093,6 +4127,18 @@ to append <code>.xplr</code> to the name to make them distinguishable. Similar t
< code > *.nvim< / code > naming convention for < a href = "https://neovim.io" > Neovim< / a > plugins.< / p >
< p > Finally, after publishing, don't hesitate to
< a href = "https://github.com/sayanarijit/xplr/discussions/categories/show-and-tell" > let us know< / a > .< / p >
< h2 id = "best-practices" > < a class = "header" href = "#best-practices" > Best practices< / a > < / h2 >
< ul >
< li > Try not to execute a lot of commands at startup, it may make xplr slow to
start.< / li >
< li > When executing commands, prefer < code > Call0< / code > over < code > Call< / code > , < code > BashExec0< / code > over
< code > BashExec< / code > and so on. File names may contain newline characters
(e.g. < code > foo$'\n'bar< / code > ).< / li >
< li > File names may also contain quotes. Avoid writing directly to
< code > $XPLR_PIPE_MSG_IN< / code > . Use < code > xplr -m< / code > / < code > xplr --pipe-msg-in< / code > instead.< / li >
< li > Check for empty variables using the syntax < code > ${FOO:?}< / code > or use a default value
< code > ${FOO:-defaultvalue}< / code > .< / li >
< / ul >
< h2 id = "examples" > < a class = "header" href = "#examples" > Examples< / a > < / h2 >
< p > Visit < a href = "awesome-plugins.html" > Awesome Plugins< / a > for xplr plugin examples.< / p >
< h2 id = "also-see-7" > < a class = "header" href = "#also-see-7" > Also See< / a > < / h2 >
@ -4298,6 +4344,30 @@ e.g. <code>app-1.0.0</code> with <code>config-1.1.0</code>. But vice versa is fi
compatibility.< / p >
< / details >
< h3 id = "instructions" > < a class = "header" href = "#instructions" > Instructions< / a > < / h3 >
< h4 id = "v0194---v0200-beta0" > < a class = "header" href = "#v0194---v0200-beta0" > < a href = "https://github.com/sayanarijit/xplr/releases/tag/v0.19.4" > v0.19.4< / a > -> v0.20.0-beta.0< / a > < / h4 >
< ul >
< li > BREAKING: xplr shell (< code > :!< / code > ) will default to null (< code > \0< / code > ) delimited pipes, as
opposed to newline (< code > \n< / code > ) delimited ones (i.e. will use < code > Call0< / code > instead of
< code > Call< / code > ).< / li >
< li > Use new messages for safer file path handling (< code > \0< / code > delimited):
< ul >
< li > Call0< / li >
< li > CallSilently0< / li >
< li > BashExec0< / li >
< li > BashExecSilently0< / li >
< / ul >
< / li >
< li > Use new sub-commands for safer message passing:
< ul >
< li > < code > -m FORMAT [ARGUMENT]...< / code > / < code > --pipe-msg-in FORMAT [ARGUMENT]...< / code > < / li >
< li > < code > -M FORMAT [ARGUMENT]...< / code > / < code > --print-msg-in FORMAT [ARGUMENT]...< / code >
Where FORMAT is a YAML string that may contain < code > %s< / code > , < code > %q< / code > and < code > %%< / code >
placeholders and ARGUMENT is the value per placeholder. See < code > init.lua< / code > .< / li >
< / ul >
< / li >
< li > Handling and displaying file paths with newline (< code > \n< / code > ) characters are now
supported.< / li >
< / ul >
< h4 id = "v0180---v0194" > < a class = "header" href = "#v0180---v0194" > < a href = "https://github.com/sayanarijit/xplr/releases/tag/v0.18.0" > v0.18.0< / a > -> < a href = "https://github.com/sayanarijit/xplr/releases/tag/v0.19.4" > v0.19.4< / a > < / a > < / h4 >
< ul >
< li > BREAKING: The builtin modes cannot be accessed using space separated names