mirror of
https://github.com/jarun/nnn.git
synced 2024-11-24 11:51:27 +00:00
Plugin fzdirs: fuzzy search multiple directories
This commit is contained in:
parent
831287c92e
commit
462531b8c7
|
@ -26,6 +26,7 @@ Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or bina
|
||||||
| [finder](finder) | Run custom find command and list | sh | - |
|
| [finder](finder) | Run custom find command and list | sh | - |
|
||||||
| [fixname](fixname) | Clean filename to be more shell-friendly [✓] | bash | sed |
|
| [fixname](fixname) | Clean filename to be more shell-friendly [✓] | bash | sed |
|
||||||
| [fzcd](fzcd) | Change to the directory of a fuzzy-selected file/dir | sh | fzf |
|
| [fzcd](fzcd) | Change to the directory of a fuzzy-selected file/dir | sh | fzf |
|
||||||
|
| [fzdirs](fzdirs) | Fuzzy search multiple directories [✓] | sh | fzf, fd |
|
||||||
| [fzhist](fzhist) | Fuzzy-select a cmd from history, edit in `$EDITOR` and run | sh | fzf, mktemp |
|
| [fzhist](fzhist) | Fuzzy-select a cmd from history, edit in `$EDITOR` and run | sh | fzf, mktemp |
|
||||||
| [fzopen](fzopen) | Fuzzy find file(s) in subtree to edit/open/pick | sh | fzf, xdg-open |
|
| [fzopen](fzopen) | Fuzzy find file(s) in subtree to edit/open/pick | sh | fzf, xdg-open |
|
||||||
| [fzplug](fzplug) | Fuzzy find, preview and run other plugins | sh | fzf |
|
| [fzplug](fzplug) | Fuzzy find, preview and run other plugins | sh | fzf |
|
||||||
|
@ -189,9 +190,9 @@ Notes:
|
||||||
When `nnn` executes a plugin, it does the following:
|
When `nnn` executes a plugin, it does the following:
|
||||||
- Changes to the directory where the plugin is to be run (`$PWD` pointing to the active directory)
|
- Changes to the directory where the plugin is to be run (`$PWD` pointing to the active directory)
|
||||||
- Passes three arguments to the script:
|
- Passes three arguments to the script:
|
||||||
1. The hovered file's name.
|
1. `$1`: The hovered file's name.
|
||||||
2. The working directory (might differ from `$PWD` in case of symlinked paths; non-canonical).
|
2. `$2`: The working directory (might differ from `$PWD` in case of symlinked paths; non-canonical).
|
||||||
3. The picker mode output file (`-` for stdout) if `nnn` is executed as a file picker.
|
3. `$3`: The picker mode output file (`-` for stdout) if `nnn` is executed as a file picker.
|
||||||
- Sets the environment variable `NNN_PIPE` used to control `nnn` active directory.
|
- Sets the environment variable `NNN_PIPE` used to control `nnn` active directory.
|
||||||
|
|
||||||
Plugins can also read the `.selection` file in the config directory.
|
Plugins can also read the `.selection` file in the config directory.
|
||||||
|
@ -200,21 +201,24 @@ Plugins can also read the `.selection` file in the config directory.
|
||||||
|
|
||||||
Plugins can be written in any scripting language. However, POSIX-compliant shell scripts runnable in `sh` are preferred.
|
Plugins can be written in any scripting language. However, POSIX-compliant shell scripts runnable in `sh` are preferred.
|
||||||
|
|
||||||
Drop the plugin in `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins` and make it executable. Optionally add a hotkey in `$NNN_PLUG` for frequent usage.
|
Make the file executable and drop it in the plugin install directory. Optionally add a hotkey in `$NNN_PLUG` for frequent usage.
|
||||||
|
|
||||||
#### Send data to `nnn`
|
#### Send data to `nnn`
|
||||||
`nnn` provides a mechanism for plugins to send data to `nnn` to control its active directory or invoke the list mode.
|
`nnn` provides a mechanism for plugins to send data to `nnn` to control its active directory or invoke the list mode.
|
||||||
The way to do so is by writing to the pipe pointed by the environment variable `NNN_PIPE`.
|
The way to do so is by writing to the pipe pointed by the environment variable `NNN_PIPE`.
|
||||||
The plugin should write a single string in the format `<ctxcode><opcode><data>` without a newline at the end. For example, `1c/etc`.
|
The plugin should write a single string in the format `(<->)<ctxcode><opcode><data>` without a newline at the end. For example, `1c/etc`.
|
||||||
|
|
||||||
|
The optional `-` at the **beginning of the stream** instructs `nnn` to clear the selection.
|
||||||
|
In cases where the data transfer to `nnn` has to happen while the selection file is being read (e.g. in a loop), the plugin should
|
||||||
|
create a tmp copy of the selection file, inform `nnn` to clear the selection and then do the subsequent processing with the tmp file.
|
||||||
|
|
||||||
The `ctxcode` indicates the context to change the active directory of.
|
The `ctxcode` indicates the context to change the active directory of.
|
||||||
|
|
||||||
| Context code | Meaning |
|
| Context code | Meaning |
|
||||||
|:---:| --- |
|
|:---:| --- |
|
||||||
| `1`-`4` | context number |
|
|
||||||
| `0` | current context |
|
|
||||||
| `+` | smart context (next inactive else current) |
|
| `+` | smart context (next inactive else current) |
|
||||||
| `-` | clear the selection |
|
| `0` | current context |
|
||||||
|
| `1`-`4` | context number |
|
||||||
|
|
||||||
The `opcode` indicates the operation type.
|
The `opcode` indicates the operation type.
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
if [ "$(cmd_exists fzf)" -eq "0" ]; then
|
if [ "$(cmd_exists fzf)" -eq "0" ]; then
|
||||||
sel=$(fzf)
|
sel=$(fzf)
|
||||||
# Show only the file ane parent dir
|
# Show only the file and parent dir
|
||||||
# sel=$(fzf --delimiter / --with-nth=-2,-1 --tiebreak=begin --info=hidden)
|
# sel=$(fzf --delimiter / --with-nth=-2,-1 --tiebreak=begin --info=hidden)
|
||||||
else
|
else
|
||||||
exit 1
|
exit 1
|
||||||
|
|
70
plugins/fzdirs
Executable file
70
plugins/fzdirs
Executable file
|
@ -0,0 +1,70 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Description: Fuzzy search multiple locations read-in from a path-list
|
||||||
|
# file and open the selected file's directory in a smart context.
|
||||||
|
# Dependencies: fzf, fd
|
||||||
|
#
|
||||||
|
# Details: Paths in list file should be newline-separated absolute paths.
|
||||||
|
# Paths can be file paths; the script will scan the parent dirs.
|
||||||
|
#
|
||||||
|
# The path-list file can be generated easily:
|
||||||
|
# - pick the (file)paths in picker mode to path-list file
|
||||||
|
# - OR, edit selection in nnn and save as path-list file
|
||||||
|
#
|
||||||
|
# The plugin clears nnn selection as the user can be tempted to delete
|
||||||
|
# duplicate files after finding copies and remove selection by mistake.
|
||||||
|
#
|
||||||
|
# Shell: POSIX compliant
|
||||||
|
# Author: Arun Prakash Jana
|
||||||
|
|
||||||
|
IFS="$(printf '\n\r')"
|
||||||
|
|
||||||
|
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||||
|
|
||||||
|
CTX=+
|
||||||
|
|
||||||
|
if [ "$(cmd_exists fzf)" -eq "0" ] && [ -s "$1" ]; then
|
||||||
|
|
||||||
|
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
|
||||||
|
|
||||||
|
for entry in $(tr '\0' '\n' < "$1")
|
||||||
|
do
|
||||||
|
if [ -d "$entry" ]; then
|
||||||
|
printf "%s\n" "$entry" >> "$tmpfile"
|
||||||
|
elif [ -f "$entry" ]; then
|
||||||
|
printf "%s\n" "$(dirname "$entry")" >> "$tmpfile"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Clear selection
|
||||||
|
if [ -p "$NNN_PIPE" ]; then
|
||||||
|
printf "-" >"$NNN_PIPE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sel=$(xargs -d '\n' -a "$tmpfile" fd -H . | fzf --delimiter / --tiebreak=begin --info=hidden)
|
||||||
|
|
||||||
|
rm "$tmpfile"
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$sel" ]; then
|
||||||
|
if [ "$sel" = "." ] || { ! [ -d "$sel" ] && ! [ -f "$sel" ]; }; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if selected path returned
|
||||||
|
# by fzf command is absolute
|
||||||
|
case $sel in
|
||||||
|
/*) nnn_cd "$sel" "$CTX" ;;
|
||||||
|
*)
|
||||||
|
# Remove "./" prefix if it exists
|
||||||
|
sel="${sel#./}"
|
||||||
|
|
||||||
|
if [ "$PWD" = "/" ]; then
|
||||||
|
nnn_cd "/$sel" "$CTX"
|
||||||
|
else
|
||||||
|
nnn_cd "$PWD/$sel" "$CTX"
|
||||||
|
fi;;
|
||||||
|
esac
|
||||||
|
fi
|
20
src/nnn.c
20
src/nnn.c
|
@ -4758,17 +4758,19 @@ static void readpipe(int fd, char **path, char **lastname, char **lastdir)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
char ctx, *nextpath = NULL;
|
char ctx, *nextpath = NULL;
|
||||||
ssize_t len = read_nointr(fd, g_buf, 1);
|
|
||||||
|
|
||||||
if (len != 1)
|
if (read_nointr(fd, g_buf, 1) != 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (g_buf[0] == '-') { /* Clear selection on '-' */
|
||||||
|
clearselection();
|
||||||
|
if (read_nointr(fd, g_buf, 1) != 1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_buf[0] == '+')
|
if (g_buf[0] == '+')
|
||||||
ctx = (char)(get_free_ctx() + 1);
|
ctx = (char)(get_free_ctx() + 1);
|
||||||
else if (g_buf[0] == '-') { /* Clear selection on '-' */
|
else if (g_buf[0] < '0')
|
||||||
clearselection();
|
|
||||||
return;
|
|
||||||
} else if (g_buf[0] < '0')
|
|
||||||
return;
|
return;
|
||||||
else {
|
else {
|
||||||
ctx = g_buf[0] - '0';
|
ctx = g_buf[0] - '0';
|
||||||
|
@ -4776,14 +4778,14 @@ static void readpipe(int fd, char **path, char **lastname, char **lastdir)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = read_nointr(fd, g_buf, 1);
|
if (read_nointr(fd, g_buf, 1) != 1)
|
||||||
if (len != 1)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char op = g_buf[0];
|
char op = g_buf[0];
|
||||||
|
|
||||||
if (op == 'c') {
|
if (op == 'c') {
|
||||||
len = read_nointr(fd, g_buf, PATH_MAX);
|
ssize_t len = read_nointr(fd, g_buf, PATH_MAX);
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue