Nukesor / pueue

:stars: Manage your shell commands.
MIT License
4.69k stars 128 forks source link

add task reading from stdin via pipe #498

Closed ln4r3n closed 4 months ago

ln4r3n commented 4 months ago

A detailed description of the feature you would like to see added.

I would love to have the ability to add new tasks from stdin via pipe.

Explain your usecase of the requested feature

Assembling task command in a script and then passing it to pueue would be easier (fewer escapes needed):

Now: pueue add -g 'photo' -- magick convert -resize "${Xscreen}^x${Yscreen}^" "'${src_dir}/${file}'" "'${dst_dir/${file}'"

Desired feature: echo "magick convert -resize ${Xscreen}^x${Yscreen}^ '${src_dir}/${file}' '${dst_dir/${file}'" | pueue add -g 'photo' -

pueue could potentially also parse env vars starting with pueue, example (thats just an idea, don't know if its even useful): PUEUE_GROUP=photo PUEUE_STASHED=true etc.

Alternatives

No response

Additional context

No response

Nukesor commented 4 months ago

Hm. Wouldn't this work just fine as well?

pueue add -g 'photo' "magick convert -resize ${Xscreen}^x${Yscreen}^ '${src_dir}/${file}' '${dst_dir/${file}'"

This saves the pipe and echo call.

Nukesor commented 4 months ago

I'm planning to publish a new release soonish.

Is this topic still an issue or can this be closed :)

ln4r3n commented 4 months ago

Sorry, before writing this issue I have totally forgotten why I wanted to ask for this, but now I know.

I cases where same variable has a an ' or " or sometimes both in it (for example names: Mc'Laren) pueue cannot parse it properly (but that's maybe a shell limitation). One workaround is to escape it beforehand with sed. And now I'm not sure if piping it into pueue would solve the problem...

#!/usr/bin/bash
# vim syntax=sh

test=("Mc'Laren" 'Mc"Laren')
for i in "${test[@]}"; do
    pueue add -- "echo '${i}'"
    pueue add -- "echo \"${i}\""
done

test2=("Mc'Laren" 'Mc"Laren')
for i in "${test2[@]}"; do
    j="$(echo "${i}" | sed -e "s|'|'\\\\''|g" -e 's|"|"\\\""|g')"
    pueue add -- "echo '${j}'"
    pueue add -- "echo \"${j}\""
done

pueue output:

Group "default" (10 parallel): running
────────────────────────────────────────────────────────────────────────────
 Id   Status       Command              Path            Start      End      
════════════════════════════════════════════════════════════════════════════
 0    Failed (2)   echo 'Mc'Laren'      /data/storage   19:50:12   19:50:12 
────────────────────────────────────────────────────────────────────────────
 1    Success      echo "Mc'Laren"      /data/storage   19:50:12   19:50:12 
────────────────────────────────────────────────────────────────────────────
 2    Success      echo 'Mc"Laren'      /data/storage   19:50:12   19:50:12 
────────────────────────────────────────────────────────────────────────────
 3    Failed (2)   echo "Mc"Laren"      /data/storage   19:50:12   19:50:12 
────────────────────────────────────────────────────────────────────────────
 4    Success      echo 'Mc'\''Laren'   /data/storage   19:50:12   19:50:12 
────────────────────────────────────────────────────────────────────────────
 5    Success      echo "Mc'\''Laren"   /data/storage   19:50:12   19:50:12 
────────────────────────────────────────────────────────────────────────────
 6    Success      echo 'Mc"\""Laren'   /data/storage   19:50:12   19:50:12 
────────────────────────────────────────────────────────────────────────────
 7    Success      echo "Mc"\""Laren"   /data/storage   19:50:12   19:50:12 
────────────────────────────────────────────────────────────────────────────

I understand if its corner case

Nukesor commented 4 months ago

To be honest, It feels like piping doesn't necessarily solve the problem.

For one, there's the --escape flag, which works as long as you don't need other special bash syntax.

test=("Mc'Laren" 'Mc"Laren')
for i in "${test[@]}"; do
    pueue add --escape -- echo ${i}
done

However when using bash syntax, the user always has to make sure their escaping is correct.

If you're working with unknown strings and need to dynamically assemble commands with correct escaping for them, choosing a different scripting language feels like the less painful way to do this. Bash doesn't feel like the right pick for this kind of complexity :sweat_smile:

ln4r3n commented 4 months ago

Digging in shell features (and of Stack Overflow) I found these solutions:

bash:

# solution 1
esc_var="$(printf '%q' "${var}")"
pueue add -- echo "${esc_var}"

# solution 2
printf -v esc_var '%q' "${var}"
pueue add -- echo "${esc_var}"

# solution 3 - maybe the simplest
pueue add -- echo "${var%Q}"

with POSIX sh (dash), the idea is the variables value needs to look like this: 'value' and in-string single qoutes needs to be escaped with sed

esc_var="'$(echo "${var}" | sed -e "s|'|'\\\\''|g")'"
pueue add -- echo "${esc_var}"

Thanks for the help and for this amazing piece of software!