Một lớp lót trong Ruby để hiển thị lời nhắc, nhận đầu vào và gán cho một biến?


79

Thường thì tôi thấy mình đang làm những điều sau:

print "Input text: "
input = gets.strip

Có cách nào duyên dáng để làm điều này trong một dòng không? Cái gì đó như:

puts "Input text: #{input = gets.strip}"

Vấn đề với điều này là nó đợi đầu vào trước khi hiển thị lời nhắc. Có ý kiến ​​gì không?


Biến nó thành một hàm nhận văn bản nhắc và trả về văn bản đầu vào? Nếu bạn muốn nhận được nhiều hơn và cần nhiều chu kỳ nhắc / nhập, bạn có thể làm cho hàm nhận một loạt các lời nhắc và một Khối, sau đó lặp lại các lời nhắc và đưa ra từng đầu vào.
asm

Câu trả lời:



76

Tôi nghĩ rằng đi theo những gì Marc-Andre đề xuất sẽ là con đường để đi, nhưng tại sao phải mang theo cả tấn mã khi bạn chỉ có thể xác định một hàm hai dòng ở đầu bất kỳ tập lệnh nào bạn sẽ sử dụng :

def prompt(*args)
    print(*args)
    gets
end

name = prompt "Input name: "

2
Thật vậy, điều đó cũng sẽ hoạt động tốt. Cho đến khi bạn muốn thêm một số kiểm tra đầu vào. Hoặc một số giá trị mặc định. Hoặc không hiển thị nội dung đã nhập vì bạn yêu cầu mật khẩu ...
Marc-André La xui xẻo

4
Đối với một kịch bản dài 5 giây, tôi sẽ nói rằng đây là cách để đi.
Will Richardson

1
Tôi sẽ đính kèm .chompphương thức sau getsnếu không biến sẽ chứa một \nký tự dòng mới ở cuối.
Toma Nistor

32

Một lần hack chắc chắn. Duyên dáng ... cũng không chính xác.

input = [(print 'Name: '), gets.rstrip][1]

2
Tôi nghĩ input = (print 'Name: '; gets.rstrip)là dễ đọc hơn. Nhưng cả hai giải pháp đều có vấn đề với nilcác giá trị. Trong Ruby 2.3, chúng có thể được xử lý một cách duyên dáng input = (print 'Name: '; gets&.rstrip).
michau

14

Tôi biết câu hỏi này đã cũ, nhưng tôi sẽ hiển thị những gì tôi sử dụng làm phương pháp tiêu chuẩn để nhận đầu vào.

require 'readline'

def input(prompt="", newline=false)
  prompt += "\n" if newline
  Readline.readline(prompt, true).squeeze(" ").strip
end

Điều này thực sự tuyệt vời vì nếu người dùng thêm các khoảng trắng lạ ở cuối hoặc ở đầu, nó sẽ xóa những khoảng trắng đó và lưu lại lịch sử những gì họ đã nhập trong quá khứ (Thay đổi truethành falseđể không làm điều đó.). Và, nếu ARGVkhông trống, sau đó getssẽ cố gắng đọc từ một tệp trong ARGV, thay vì nhận đầu vào. Thêm vào đó, Readlinelà một phần của thư viện chuẩn Ruby nên bạn không phải cài đặt bất kỳ viên ngọc nào. Ngoài ra, bạn không thể di chuyển con trỏ của mình khi sử dụng gets, nhưng bạn có thể với Readline.

Và, tôi biết phương pháp không phải là một dòng, mà là khi bạn gọi nó

name = input "What is your name? "

"LƯU Ý: [Readline::readline ] kết thúc trình thông dịch ruby ​​và không trả lại trạng thái đầu cuối sau khi người dùng nhấn '^ C' khi dòng nhập chờ."
ma11hew28

Tôi thích điều này và đề xuất của highline/import
@Andrew

12

Theo lời dẫn của @ Bryn:

def prompt(default, *args)
  print(*args)
  result = gets.strip
  return result.empty? ? default : result
end

4

Vấn đề với giải pháp được đề xuất của bạn là không thể tạo chuỗi được in cho đến khi đầu vào được đọc, loại bỏ và được gán. Bạn có thể phân tách từng dòng bằng dấu chấm phẩy:

$ ruby -e 'print "Input text: "; input=gets.strip; puts input'
Input text: foo
foo

5
Đó không thực sự là một dòng; bạn đang sử dụng dấu chấm phẩy và điều đó có thể không phù hợp với yêu cầu của anh ấy.
thay thế

1
$ ruby ​​-e 'print ("Văn bản đầu vào:") || (input = get.strip) && (đặt đầu vào)'
Lars Haugseth

1

Tôi đã tình cờ tìm thấy viên ngọc Inquirer và tôi thực sự thích nó, tôi thấy nó gọn gàng và dễ sử dụng hơn Highline, mặc dù nó thiếu xác thực đầu vào.
Ví dụ của bạn có thể được viết như thế này

require 'inquirer'
inputs = Ask.input 'Input text'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.