¿Un trazador de líneas en Ruby para mostrar un mensaje, obtener entradas y asignar una variable?

79

A menudo me encuentro haciendo lo siguiente:

print "Input text: "
input = gets.strip

¿Hay alguna forma elegante de hacer esto en una línea? Algo como:

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

El problema con esto es que espera la entrada antes de mostrar el mensaje. ¿Algunas ideas?

Jarsen
fuente
¿Convertirla en una función que tome el texto del mensaje y devuelva el texto de entrada? Si desea ser más sofisticado y necesita múltiples ciclos de solicitud / entrada, puede hacer que la función tome una serie de solicitudes y un Bloque, luego recorra las solicitudes y genere cada entrada.
asm

Respuestas:

77

Echa un vistazo a Highline :

require "highline/import"
input = ask "Input text: "
Marc-André Lafortune
fuente
76

Creo que ir con algo como lo que sugirió Marc-Andre será el camino a seguir, pero ¿por qué traer una tonelada de código cuando puede definir una función de dos líneas en la parte superior de cualquier script que vaya a usar? :

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

name = prompt "Input name: "
Bryn
fuente
2
De hecho, eso también funcionará bien. Hasta que desee agregar alguna verificación de entrada. O algún valor predeterminado. O no mostrar lo que ha escrito porque pide una contraseña ...
Marc-André Lafortune
4
Para un guión de 5 segundos, diría que este es el camino a seguir.
Will Richardson
1
Adjuntaría el .chompmétodo después de lo getscontrario, la variable contendría un \ncarácter de nueva línea al final.
Toma Nistor
32

Un truco seguro. Agraciado ... bueno, no exactamente.

input = [(print 'Name: '), gets.rstrip][1]
rbnewb
fuente
2
Creo que input = (print 'Name: '; gets.rstrip)es más legible. Pero ambas soluciones tienen problemas con los nilvalores. En Ruby 2.3 se pueden manejar con elegancia input = (print 'Name: '; gets&.rstrip).
Michau
14

Sé que esta pregunta es antigua, pero pensé que mostraría lo que uso como mi método estándar para obtener información.

require 'readline'

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

Esto es realmente bueno porque si el usuario agrega espacios extraños al final o al principio, los eliminará y mantendrá un historial de lo que ingresaron en el pasado (cambie truea falsepara que no haga eso). Y, si ARGVno está vacío, getsintentará leer desde un archivo ARGV, en lugar de obtener entrada. Además, Readlinees parte de la biblioteca estándar de Ruby, por lo que no tiene que instalar ninguna gema. Además, no puede mover el cursor cuando usa gets, pero puede hacerlo con Readline.

Y sé que el método no es una línea, pero es cuando lo llamas

name = input "What is your name? "
Addison
fuente
"NOTA: [Readline::readline ] finaliza el intérprete ruby ​​y no devuelve el estado del terminal después de que el usuario presiona '^ C' cuando espera ingresar la línea".
ma11hew28
Me gusta esto y la sugerencia de @Andrew Grimm como las mejores alternativas al usohighline/import
Chux Uzoeto
12

Siguiendo el ejemplo de @ Bryn:

def prompt(default, *args)
  print(*args)
  result = gets.strip
  return result.empty? ? default : result
end
Tiago Fernández
fuente
4

El problema con la solución propuesta es que la cadena que se va a imprimir no se puede construir hasta que la entrada se lea, elimine y asigne. Puede separar cada línea con un punto y coma:

$ ruby -e 'print "Input text: "; input=gets.strip; puts input'
Input text: foo
foo
maerics
fuente
5
Eso no es realmente una línea; está utilizando punto y coma y eso probablemente no encajaría en la parte elegante de su solicitud.
alternativa
1
$ ruby ​​-e 'print ("Texto de entrada:") || (entrada = gets.strip) && (pone entrada)'
Lars Haugseth
1

Encontré la gema Inquirer por casualidad y realmente me gusta, la encuentro mucho más ordenada y fácil de usar que Highline, aunque carece de validación de entrada por sí misma.
Tu ejemplo se puede escribir así

require 'inquirer'
inputs = Ask.input 'Input text'
Redition
fuente