24

I'm trying to gather user input in a fish shellscript, particularly of the following oft-seen form:

This command will delete some files. Proceed (y/N)?

After some searching around, I am still not sure how to do this cleanly.

Is these a special way of doing this in fish?

Barett
  • 5,826
  • 6
  • 51
  • 55
user456584
  • 86,427
  • 15
  • 75
  • 107

4 Answers4

36

The best way I know of is to use the builtin read. If you are using this in multiple places you could create this helper function:

function read_confirm
  while true
    read -l -P 'Do you want to continue? [y/N] ' confirm

    switch $confirm
      case Y y
        return 0
      case '' N n
        return 1
    end
  end
end

and use it like this in your scripts/functions:

if read_confirm
  echo 'Do stuff'
end

See documentation for more options: https://fishshell.com/docs/current/commands.html#read

Xavier
  • 1,536
  • 2
  • 16
  • 29
terje
  • 4,164
  • 2
  • 28
  • 28
  • 3
    Actually, the argument to `-p` can be any shell command, which will get tokenized as you might expect at spaces, e.g. `echo "Delete Files? [Y/n]: "'` From the doc you linked: "-p PROMPT_CMD or --prompt=PROMPT_CMD uses the output of the shell command PROMPT_CMD as the prompt for the interactive mode. The default prompt command is `set_color green; echo read; set_color normal; echo "> "` – Ionoclast Brigham Jul 17 '14 at 23:51
  • This worked for me however the prompt implies that Yes is default however the switch statement will interpret empty as No. – JonoCoetzee Oct 20 '16 at 10:15
  • 3
    read can now take a string instead of a function using `read -P "prompt: " ...` or `read --prompt-str="prompt: " ...` – Brett Y Oct 25 '17 at 03:28
7

This does the same as the chosen answer but with only one function, seems cleaner to me:

function read_confirm
  while true
    read -p 'echo "Confirm? (y/n):"' -l confirm

    switch $confirm
      case Y y
        return 0
      case '' N n
        return 1
    end
  end
end

The prompt function can be inlined as such.

Pysis
  • 1,452
  • 2
  • 17
  • 31
Fyrn
  • 116
  • 1
  • 8
4

Here's a version with optional, defaulted prompt:

function read_confirm --description 'Ask the user for confirmation' --argument prompt
    if test -z "$prompt"
        set prompt "Continue?"
    end 

    while true
        read -p 'set_color green; echo -n "$prompt [y/N]: "; set_color normal' -l confirm

        switch $confirm
            case Y y 
                return 0
            case '' N n 
                return 1
        end 
    end 
end
sbrandt
  • 87
  • 1
  • 7
1

With the help of some fish plugins fisherman and get

To install both, simply in your fish shell

curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs https://git.io/fisher
. ~/.config/fish/config.fish
fisher get

then you can write something like this in your fish function/script

get --prompt="Are you sure  [yY]?:" --rule="[yY]" | read confirm
switch $confirm
  case Y y
    # DELETE COMMAND GOES HERE
end
bigsolom
  • 2,309
  • 1
  • 19
  • 15
  • 1
    fisherman is [fisher](https://github.com/jorgebucaran/fisher) now. Unfortunately, I couldn't find where `get` went. – Raphael Nov 05 '19 at 01:07
  • The get package has moved to https://github.com/fishpkg/fish-get. As much as I like fisherman and appreciate the work of its maintainers, it's not a tool I can recommend anymore. Its ecosystem is much too unstable, frequent breaking changes from stuff moving around and being rewritten in its unending pursuit of perfection. – Dennis Oct 11 '20 at 14:21
  • 1
    fish-get seems to have gone from there. – Steve Bennett Dec 08 '21 at 00:41