deed02392
deed02392

Reputation: 5032

Enter a command for a user

I have written a ZSH function whose output is a command line which runs a program I need the user to be able to interact with.

At the moment I just echo the command line and instruct the user to copy-paste it so that they have the necessary access to its pipes, however is there a way I can just have the function finish by entering the command for the user as if they had copied and pasted it themselves?

I have looked into using zle but that seems to require a key binding, whereas I just want the user to be able to run: myzshfunction arg1 and the ultimate result to be their terminal attached to the program launched as a result of some processing of their arg1.

$ myzshfunction arg2*2
Run this command! foobar baz4
$ foobar baz4
  ...

The function looks something like this:

myzshfunction() {
  if [[ $# = 0 ]]
  then
    echo "usage: myzshfunction 1.2.3.4"
    return
  fi

  local creds=`curl "https://xxx/$1/latest" | jq -r 'x'`
  local cred_arr=("${(@s|/|)creds}")
  local pwd_pipe=$(mktemp -u)
  mkfifo $pwd_pipe
  exec 3<>$pwd_pipe
  rm $pwd_pipe
  echo $cred_arr[2] >&3
  echo "Run this: sshpass -d3 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$cred_arr[1]@$1"
  exec 3>&-
}

TIA

Upvotes: 0

Views: 228

Answers (2)

deed02392
deed02392

Reputation: 5032

The best solution I could come up with was to use zle - the Zsh Line Editor.

This lets you update the command the user is currently editing, which to me feels a bit hacky. I would prefer a solution that lets you call a function, hit return, and then cleanly run a function with STDIO attached to your terminal as if you had run the resulting command line.

Perhaps you could emulate this by bindkey'ing the return key and doing some sort of decision/routing from there to see if the user wants to call myfunc. For now, my solution requires the Esc+i sequence is entered after typing a target for $host.

zle-myfunc() {
  apikey=$(keychain-environment-variable api-key)
  if [ $? -ne 0 ]; then
    echo "Add your api-key to the keychain: "
    BUFFER='security add-generic-password -U -a ${USER} -D "environment variable" -s "api-key" -w'
    zle accept-line
    return 1
  fi
  local host=$BUFFER
  zle kill-buffer
  local creds=`curl ..." | jq -r ...`
  if [ -z creds ]; then
    echo "Couldn't get creds, check your network"
    return 1
  fi
  local creds_arr=("${(@s|/|)creds}")
  local pwd_pipe=$(mktemp -u)
  mkfifo $pwd_pipe
  exec 3<>$pwd_pipe
  # anonymise the pipe
  rm $pwd_pipe
  echo "$creds_arr[2]" >&3
  BUFFER="sshpass -d3 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $creds_arr[1]@$host"
  zle accept-line
  # exec 3>&-
}
zle -N zle-myfunc
bindkey '\ei' zle-myfunc

Upvotes: 0

chepner
chepner

Reputation: 532418

Use print -z to add text to the buffer. From the documentation:

-z     Push the arguments onto the editing buffer stack, separated by spaces.

Calling foo, defined below, will result in hi being placed on the command line as if the user had typed it. For example,

% foo () { print -z hi; }
% foo
% hi

Upvotes: 1

Related Questions