Предварительно заполненное приглашение в Ruby [дубликат]

This question already has an answer here:

What will give me something like ruby readline with a default value? 5 answers

Я использую Ruby для написания небольшой утилиты командной строки для поиска в Pubmed. Прямо сейчас я запрашиваю у пользователя запрос и отображаю результаты, и у пользователя есть возможность добавить запрос или ввести совершенно новый запрос. Я хотел бы добавить возможность редактировать текущий запрос; то есть приглашение должно быть предварительно заполнено редактируемой версией предыдущего запроса, например так:

Enter query: <PREVIOUS QUERY HERE>

Достаточно легко напечатать предыдущий запрос рядом с подсказкой, но как мне сделать этот вывод редактируемым, как если бы пользователь сам его набрал?

@casper: Спасибо за ответ Каспер. Я попробовал код, который вы предоставили ниже, и он действительно работает сам по себе. Как ни странно, это не работает, когда я пытаюсь использовать его в драгоценном камне. Мой драгоценный камень называется db_hippo. Я добавил rb-readline в качестве зависимости в моем gemspec и добавил расширение для RbReadline в lib / db_hippo / rb-readline.rb

module DbHippo
  module RbReadline
    <CASPER'S EXTENSION HERE>
  end
end

Я хочу использовать функциональность в другом подмодуле DbHippo, DbHippo :: Source. В DbHippo :: Source я добавил вверху:

require 'rb-readline'
require 'db_hippo/rb-readline'

Затем в одном из методов DbHippo :: Source я имею:

RbReadline.prefill_prompt(query)
query = Readline.readline("Query: ", true)

Переменная запроса определенно не пуста, но по какой-то причине в этом контексте приглашение не заполняется предварительно. Я также замечаю, что если я помещаю расширение в тот же файл (lib / db_hippo / rb-readline), не делая его подмодулем DbHippo, я получаю ошибку:uninitialized constant DbHippo::Source::Readline (NameError) на линии:

query = Readline.readline("Query: ", true)

Похоже, что все это связано с правильным именованием модулей, операторов операторов и гемов. Это первая жемчужина, которую я пытался собрать. Есть идеи, что здесь не так?

 Sean Mackesey18 июн. 2012 г., 08:49
Отличное объяснение, у меня все работает сейчас. Спасибо за помощь!
 Casper18 июн. 2012 г., 07:32
Я обычно создаю папку в моемlib Дир называетсяextensions или что-то подобное, и поместите туда все обезьяньи заплатки. Тогда ты простоrequire 'db-hippo/extensions/rb-readline'и для любого читающего код будет совершенно очевидно, что происходит.
 Casper18 июн. 2012 г., 07:48
Также обратите внимание, что вы должныrequire 'rb-readline' ДО того, как вам потребуется код расширения. Убедитесь, что он идет в правильном порядке, иначе он не будет работать. Если вы не уверены, переименуйте файл расширения в другоеreadline-patch.rb чтобы убедиться, что вы включаетеrb-readline драгоценный камень до того, как вы добавите код патча (возможно спутать rubygems, когда у вас есть файл с тем же именем, что и у глобального драгоценного камня).
 Casper18 июн. 2012 г., 07:29
Да. Вы не можете поместить мой код расширения вDbHippo модуль. Это потому, что мой код расширения - это патч обезьяныRbReadline, который является модулем верхнего уровня. Если вы положите код патча внутрьDbHippo вы создадите новый модульDbHippo::RbReadlineи оригинальный непропатченный код все еще будет существовать на верхнем уровнеRbReadline модуль. В дополнение к этому у вас теперь есть дваRbReadline Модули и Ruby будут иметь проблемы с их дифференциацией .. поэтому все работает очень плохо: - / Так что просто держите мой патч обезьяны на верхнем уровне, и у вас все будет в порядке.

Ответы на вопрос(2)

С равнинойReadline на Ruby 2.1 вы можете использовать:

def ask(prompt, default=nil)

  if default
    Readline.pre_input_hook = -> {
      Readline.insert_text(default)
      Readline.redisplay
    }
  end
  data = Readline.readline("#{prompt}: ")
  return data.chomp
end

ask("MOAR...?", "COMPUTARS!") # displays: MOAR...? COMPUTARS!

По подсказке текстCOMPUTARS! будет редактируемым

 09 июн. 2016 г., 00:35
После нескольких часов поиска, поиска в Google и поиска различных способов работы с терминалом в ruby, чтобы решить эту проблему, я, наконец, нашел действительно чистое решение благодаря Вам !! Благодарю вас!
 10 сент. 2018 г., 06:57
Однако было бы очень разумно очиститьReadline.pre_input_hook внутри обработчик крюка. Если вы этого не сделаете, он будет продолжать срабатывать на каждой readline (включаяirb подскажите: D)
Решение Вопроса

RbReadline:

require 'rubygems'
require 'rb-readline'

module RbReadline
  def self.prefill_prompt(str)
    @rl_prefill = str
    @rl_startup_hook = :rl_prefill_hook
  end

  def self.rl_prefill_hook
    rl_insert_text @rl_prefill if @rl_prefill
    @rl_startup_hook = nil
  end
end

RbReadline.prefill_prompt("Previous query")
str = Readline.readline("Enter query: ", true)

puts "You entered: #{str}"

Ваш ответ на вопрос