【问题标题】:Ruby: gets.chomp with default valueRuby:gets.chomp 具有默认值
【发布时间】:2014-10-24 10:40:14
【问题描述】:

是否有一些简单的方法可以在提供默认值的同时在 Ruby 中请求用户输入?

在 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\"."

你能用 Ruby 的gets.chomp 实现类似的行为吗?

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

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

我知道我可以用这种方式排序复制 Ruby 中的功能......

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

...但它看起来不是很漂亮。我还需要手动显示默认值,如果用户想使用它的修改版本(比如yes! 而不是yes),他需要在提示行中重新键入它。

我现在开始使用 Ruby,所以可能有很多语法错误,而且我也可能遗漏了一些明显的东西......另外,我搜索了很多,但令人惊讶的是没有发现任何线索。

TL;博士

为了让问题更清楚,这是您应该在终端中看到的内容以及我在 bash 中能够实现的内容(到目前为止,在 Ruby 中还没有):

### 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

以及实际情况:我正在为我的网络应用程序构建引导脚本。我需要为用户提供现有的配置数据,他们可以根据需要进行更改。

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

我不认为这是需要切换到 GUI 应用程序世界的花哨功能。

正如我之前所说,这在 bash 中很容易实现。问题是,其他事情是纯粹的痛苦(关联数组,函数没有返回值,传递参数,......)。我想我只需要决定在我的情况下什么最不糟糕......

【问题讨论】:

  • 这似乎是一个类似的问题:stackoverflow.com/questions/2314105/… 大多数答案也建议使用外部库。
  • 我没有使用 bash,但这段代码应该适用于 TL;DR 部分:def ask prompt, default = nil; unless default; return gets.chomp; end; return default; end;,您可以像这样使用它:ask 'what is your name' 等待您的回复。 ask 'what is your name', 'darek' 这只是返回默认值。好吧,如果那是您正在寻找的代码,我会将其发布为答案并进行更多解释(因为评论部分有字符限制)。附言。或者有点骇人听闻的方式:def ask2 prompt, default = nil; default || gets.chomp; end;
  • Derek:再一次,你的解决方案只是(更)优雅的方式来做我自己的def ask_q,对吧?看我的问题。此外,默认答案应该只对用户建议,您的解决方案似乎强制它。我说的对吗?
  • 是的,你可以这样称呼它。此建议,您希望用户如何编辑您的建议?
  • Darek:查看函数的“bash 版本”或这个问题 - stackoverflow.com/questions/2642585/… - 它描述了 bash 中所需的确切行为。

标签: ruby bash default-value gets


【解决方案1】:

您需要做以下两件事之一:

1) 创建一个 gui 程序。

2) 使用诅咒。

就个人而言,我认为花时间学习诅咒是浪费时间。 Curses 甚至已从 Ruby 标准库中移除。

图形用户界面程序:

这是使用 Tkinter GUI 框架的 gui 应用程序的样子:

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")

从 ruby​​ 调用 bash 脚本中的函数:

.../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"

使用诅咒:

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

【讨论】:

  • 提供对使用默认值的支持对我来说似乎是一个非常基本的功能。让我感到很惊讶的是 Ruby 不提供这个(即使是 Bash 也提供)......
  • @PetrCibulka,Ruby 的默认设置不是问题。问题是控制终端窗口的工作方式。您必须控制终端窗口并更改其正常行为才能在输出上退格。你发布的 shell 脚本对我不起作用 read: -i: invalid option ,所以我什至不知道你的 shell 脚本是否允许你这样做。是吗?
  • 确实如此。请参阅此问题 - stackoverflow.com/questions/2642585/… - 以及最受好评的答案。但是,您确实需要 Bash 4 ...
  • @PetrCibulka,请注意,如果您执行echo -n "Enter stuff: "; read,您将无法在输出上回退空间。所以 -i 选项必须导致某些代码执行,从而改变终端窗口的正常行为。
  • @PetrCibulka,您还可以使用 system()、backticks/%x(捕获外部程序的输出)或 popen3()(更灵活)从 ruby​​ 运行 bash 脚本;因此,如果您想要在 ruby​​ 中编写其他代码,您可以使用 ruby​​ 执行 bash 脚本以获取用户的输入,然后继续使用 ruby​​。我将发布一个示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多