JEG2 / highline

A higher level command-line oriented interface.
Other
1.29k stars 137 forks source link

high like/agree default option? #275

Open satmandu opened 1 month ago

satmandu commented 1 month ago

Is there a way to set a default value when using agree such that enter would choose that default?

(If that's not currently possible... This is a feature request.)

abinoam commented 1 month ago

It completely makes sense for me to have such feature documented.

The current implementation of #agree is at this link https://github.com/JEG2/highline/blob/3de8af1ea83016ede666f33917233fb7a6854fb7/lib/highline.rb#L192C1-L202C6

I believe, #ask is so flexible that we can achieve this by simply messing with its arguments.

I think I can do it this week. 👍

abinoam commented 1 month ago

Meanwhile, you can try this.

I have changed the validate regexp to match an empty string (the result of an enter).

require "highline"

def agree_with_default(yes_or_no_question, character = nil, default:)
  answer_type = ->(yn) { yn.downcase[0] == "y" || (yn.empty? && default.downcase[0] == "y") }

  HighLine.ask(yes_or_no_question, answer_type) do |q|
    q.validate                 = /\A(?:y(?:es)?|no?|)\Z/i
    q.responses[:not_valid]    = 'Please enter "yes" or "no".'
    q.responses[:ask_on_error] = :question
    q.character                = character
    q.completion               = %w[yes no]

    yield q if block_given?
  end
end

# Using it
agree_with_default("Install lib xyz (yes/NO)?", true, default: "n")
satmandu commented 6 days ago

Have you considered using timeout with highline at all?

Something simple like this might work?

require 'timeout'
TIMEOUT_SECONDS = 10
begin
  Timeout::timeout(TIMEOUT_SECONDS) do
    <highline stuff with default>
  end
rescue Timeout::Error
  <do default>
end
abinoam commented 2 days ago

It would be a really nice addition. I use things like that in shell scripts like It would work like read -t <timeout> -p <prompt> <name> of Bash. It's nice for "unattended" installs or something like that. But then you would have the chance to give a window of time for the user to change something, otherwise, it would follow the defaults.

As soon as I get some free time I can try doing that. Thanks for the suggestion.

satmandu commented 2 days ago

I added an implementation here:

https://github.com/chromebrew/chromebrew/pull/10498

abinoam commented 2 days ago

Nice. Perhaps we could do that from inside the "answer gathering" workflow.