Biont / sway-launcher-desktop

TUI Application launcher with Desktop Entry support. Made for SwayWM, but runs anywhere
GNU General Public License v3.0
606 stars 28 forks source link

Read input from pipe #64

Closed RayZ0rr closed 2 years ago

RayZ0rr commented 2 years ago

What would be a good way to implement reading from STDIN and using it with sway-launcher-desktop just like dmenu does?

I think the following two methods might work :

1) Make sway-launcher-desktop accept an argument similar to list-entries like dmenu or stdin which makes it call a function that reads from stdin 2) use a PROVIDERS_FILE with the script that reads from stdin and present it to list_cmd

I think the latter might be a better choice given the flexibility that provider files provide.

RayZ0rr commented 2 years ago

Ok, I came up with a solution for this. @Biont it would be great if you could take a look at this

There are two necessary files for this. One is sway-dmenu-launcher which can be used to take input from pipes and then write it to /tmp/sway-dmenu-launcher_catfile in the correct format required. Another is ~/.config/sway-desktop-launcher/stdin.conf providers file which reads from /tmp/sway-dmenu-launcher_catfile.

sway-dmenu-launcher

#!/usr/bin/env bash

export PROVIDERS_FILE="stdin.conf"

SWAY_LAUNCHER_PATH="$HOME/.local/bin"
SWAY_LAUNCER_CMD="alacritty -e ${SWAY_LAUNCHER_PATH}/sway-launcher-desktop"

cleanup() {
  rm -f /tmp/sway-dmenu-launcher_catfile
}
# trap cleanup EXIT

# If a named pipe for term-dmenu doesn't exist, create it
# [ -p /tmp/sway-dmenu-launcher_catfile ] || mkfifo /tmp/sway-dmenu-launcher_catfile &

# Export stdin, separated by newlines, so the terminal process can
# access it
IFS=$(printf '\n')
input=$(cat)
export input

# This function implements the `list_cmd` sway-launcher-desktop provider entry.
#
# For every newline separated entry from STDIN, it prints its 1-based index and the
# first line, followed by an ellipsis if there is more than one line.
list_cmd() {
    echo "$input" | awk '
        BEGIN {
            # RS = "\n";
            # FS = "\n";
            # This is the sway-launcher-desktop `list_cmd` field separator.
            # This way we can print a `list_cmd` line by passing each field as
            # a separate print argument
            OFS = "\034";
        }
        {
            # Fields are lines, hence NF is the number of lines
            LINE = NF > 1 ? $1"..." : $1;
            print NR,"stdin",LINE;
        }' > /tmp/sway-dmenu-launcher_catfile
}
list_cmd

# Send the value from the named pipe to stdout
# cat </tmp/sway-dmenu-launcher_catfile

eval "${SWAY_LAUNCER_CMD}"

# vi:ft=bash

~/.config/sway-desktop-launcher/stdin.conf

[stdin]
list_cmd=cat /tmp/sway-dmenu-launcher_catfile
preview_cmd=echo -e 'This is the preview of {1}'
launch_cmd=echo '{1}'
Biont commented 2 years ago

I like the idea and appreciate the solution. As you have found out, there is no clear way to do this directly with sway-launcher-desktop itself as it is mostly a consumer/wrapper of fzf with some added QoL features. History support -for example- does not work well with a feature like this. Until I get around to merge the purging branch #58 that means there will be zombie entries.

Anyway you found a nice workaround and can probably live with the tradeoffs involved. Great.

If you are adventurous, I would not be opposed to merging a PR that introduces an optional stdin_cmd for providers that allows any provider to process STDIN in some way (probably do some checks and then pipe to a tempfile). It's basically the same as your solution that way.

RayZ0rr commented 2 years ago

I think it's better to leave it here as an extra plugin as it's something that can be achieved with the existing capabilities of sway-launcher-desktop