Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: gets.chomp with default value

Is there some simple way how to ask for a user input in Ruby WHILE providing a default value?

Consider this code in bash:

function ask_q {
    local PROMPT="$1"
    local DEF_V="$2"
    read -e -p "$PROMPT" -i "$DEF_V" REPLY
    echo $REPLY
}

TEST=$(ask_q "Are you hungry?" "Yes")
echo "Answer was \"$TEST\"."

Can you achieve similar behaviour with Ruby's gets.chomp?

function ask_q(prompt, default="")
    puts prompt
    reply = gets.chomp() # ???
    return reply
def

reply = ask_q("Are you hungry?", "Yes")

I understand I can sort replicate the functionality in Ruby this way ...

def ask_q(prompt, default="")
    default_msg = (default.to_s.empty?) ? "" : "[default: \"#{default}\"]"
    puts "${prompt} ${default}"
    reply = gets.chomp()
    reply = (default.to_s.empty?) ? default : reply
    return reply
end

... but it does not seem very pretty. I also need to show the default value manually and the user needs to retype it in the prompt line, if he wants to use modified version of it (say yes! instead of yes).

I'm starting with Ruby now, so there may be a lot of syntax mistakes and I also may be missing something obvious ... Also, I googled a lot but surprisingly found no clue.

TL; DR

To make the question clearer, this is what you should see in terminal and what I am able to achieve in bash (and not in Ruby, so far):

### Terminal output of `reply=ask_q("Are you hungry?" "Yes")`

$ Are you hungry?
$ Yes # default editable value

### Terminal output of `reply=ask_q("What do you want to eat?")`

$ What do you want to eat?
$ # blank line waiting for user input, since there is no second parameter

And the actual situation: I am building bootstrap script for my web apps. I need to provide users with existing configuration data, that they can change if needed.

### Terminal output of `reply=ask_q("Define name of database." "CURR_DB_NAME")` 

I don't think it's that fancy functionality, that would require switch to GUI app world.

And as I've said before, this is quite easily achievable in bash. Problem is, that other things are pure pain (associative arrays, no return values from functions, passing parameters, ...). I guess I just need to decide what sucks the least in my case ...

like image 931
Petr Cibulka Avatar asked Nov 01 '22 18:11

Petr Cibulka


1 Answers

You need to do one of two things:

1) Create a gui program.

2) Use curses.

Personally, I think it's a waste of time to spend any time learning curses. Curses has even been removed from the Ruby Standard Library.

A GUI program:

Here is what a gui app looks like using the Tkinter GUI Framework:

def ask_q(prompt, default="")
  require 'tk'

  root = TkRoot.new
  root.title = "Your Info"

  #Display the prompt:
  TkLabel.new(root) do
    text "#{prompt}: " 
    pack("side" => "left")
  end

  #Create a textbox that displays the default value:
  results_var = TkVariable.new
  results_var.value = default

  TkEntry.new(root) do
    textvariable results_var
    pack("side" => "left")
  end

  user_input = nil

  #Create a button for the user to click to send the input to your program:
  TkButton.new(root) do
    text "OK"
    command(Proc.new do 
      user_input = results_var.value 
      root.destroy
    end)

    pack("side" => "right",  "padx"=> "50", "pady"=> "10")
  end

  Tk.mainloop
  user_input
end

puts ask_q("What is your name", "Petr Cibulka")

Calling a function in a bash script from ruby:

.../bash_programs/ask_q.sh:

#!/usr/bin/env bash

function ask_q {

    local QUESTION="$1"
    local DEFAULT_ANSWER="$2"

    local PROMPT="$QUESTION"

    read -p "$PROMPT $DEFAULT_ANSWER" USERS_ANSWER #I left out the -i stuff, because it doesn't work for my version of bash
    echo $USERS_ANSWER
}

ruby_prog.rb:

answer = %x{
  source ../bash_programs/ask_q.sh;  #When ask_q.sh is not in a directory in your $PATH, this allows the file to be seen.
  ask_q 'Are you Hungry?' 'Yes'  #Now you can call functions defined inside ask_q.sh
}

p answer.chomp  #=> "Maybe"

Using curses:

require 'rbcurse/core/util/app'

def help_text
<<-eos
Enter as much help text
here as you want
eos
end

user_answer = "error"

App.new do  #Ctrl+Q to terminate curses, or F10(some terminals don't process function keys)
  @form.help_manager.help_text = help_text()  #User can hit F1 to get help text (some terminals do not process function keys)

  question = "Are You Hungry?"
  default_answer = "Yes"

  row_position = 1
  column_position = 10

  text_field = Field.new(@form).
              name("textfield1").
              label(question).
              text(default_answer).
              display_length(20).
              bgcolor(:white).
              color(:black).
              row(row_position).
              col(column_position)

  text_field.cursor_end

  text_field.bind_key(13, 'return') do 
    user_answer = text_field.text
    throw :close
  end

end 

puts user_answer
like image 63
7stud Avatar answered Nov 15 '22 05:11

7stud