Создание интерактивного рубинового консольного приложения
Я хочу создать интерактивное приложение, в котором пользователь запускает его и может выполнять различную задачу, набрав команды (некую оболочку)
Пример:
./myapp.rb
App says Hi
Commands:
help - display help about command
open - open task
do - do action
Start>help open
open <TaskName>
opens specified task
Start>open Something
Something>do SomeAction
Success!
Something> (blinking cursor here)
Я искал, но не смог найти никаких рубиновых камней, которые я мог бы использовать специально для взаимодействия с консолью, поэтому я собираюсь сделать свой собственный...
Я посмотрел Thor, но это не совсем так, как я хочу, возможно, я мог бы использовать его, но не уверен...
он может выглядеть примерно так:
class Tasks
attr_reader :opened_task
desc "open <TaskName>", "opens specified task"
def open(params)
end
desc "do <ActionName>", "do specified action"
def do(params)
end
end
tasks = Tasks.new
# theoretical Console class
console = Console.new
console.addCommand("open",tasks.method(:open),"open task")
console.addCommand("do",tasks.method(:do),"do action")
console.start("%s>",[*tasks.opened_task])
так что мой вопрос: какие камни я могу использовать для создания такого класса консоли? может, кто-то уже сделал что-то подобное?
Я планирую использовать HighLine для ввода/вывода, но любое другое предложение, что я могу использовать?
Ответы
Ответ 1
Вы хотите REPL - Read → Evaluate → Print Loop
.
IRB, например, реализует REPL для языка Ruby.
Здесь очень простая реализация вашего приложения REPL:
loop do
Application::Console.prompt.display
input = gets.chomp
command, *params = input.split /\s/
case command
when /\Ahelp\z/i
puts Application::Console.help_text
when /\Aopen\z/i
Application::Task.open params.first
when /\Ado\z/i
Application::Action.perform *params
else puts 'Invalid command'
end
end
\A
и \z
соответствуют началу строки и концу строки соответственно.
Ответ 2
Вы также можете попробовать ripl. (из документации):
Создание и запуск пользовательской оболочки так же просто, как:
require 'ripl'
# Define plugins, load files, etc...
Ripl.start
Существует полный список плагинов для ripl, а также список консольных приложений с использованием ripl на веб-сайте проектов.
Ответ 3
ok, поэтому я создал эту библиотеку для создания консольных приложений в ruby. На самом деле это было какое-то время назад, но только решило выпустить его. Он поддерживает автозаполнение, если используется с HighLine и Readline.
Когда я написал это, не было никакой документации и тестов/спецификаций, но теперь я сделал некоторые. Все еще не много, но для начала должно быть хорошо.
Итак, gem cli-console и
код находится в GitHub, здесь пример использования
Ответ 4
Взгляните на cliqr
рубиновый камень. Это похоже на то, что вам нужно. Вот ссылка github с описательным readme: https://github.com/anshulverma/cliqr
Он может выполнять команды напрямую или внутри встроенной оболочки.
Вот тестовый пример из git repo:
it 'can execute a sub action from shell' do
cli = Cliqr.interface do
name 'my-command'
handler do
puts 'base command executed'
end
action :foo do
handler do
puts 'foo executed'
end
action :bar do
handler do
puts 'bar executed'
end
end
end
end
with_input(['', 'my-command', 'foo', 'foo bar', 'foo bar help']) do
result = cli.execute %w(my-command shell), output: :buffer
expect(result[:stdout]).to eq <<-EOS
Starting shell for command "my-command"
my-command > .
base command executed
my-command > my-command.
base command executed
my-command > foo.
foo executed
my-command > foo bar.
bar executed
my-command > foo bar help.
my-command foo bar
USAGE:
my-command foo bar [actions] [options] [arguments]
Available options:
--help, -h : Get helpful information for action "my-command foo bar" along with its usage information.
Available actions:
[ Type "my-command foo bar help [action-name]" to get more information about that action ]
help -- The help action for command "my-command foo bar" which provides details and usage information on how to use the command.
my-command > exit.
shell exited with code 0
EOS
end
end
Ответ 5
TTY - действительно хороший камень для того, чтобы легко делать такие вещи. У вас есть множество инструментов, которые могут работать в одиночку или с полным набором инструментов. Вы можете использовать цвета, подсказки, запускать shell-туземцы, взаимодействовать с экраном, печатать таблицы, progressbars и многие другие полезные элементы командной строки с легкостью apip-goop.
В частности tty-prompt действительно полезно для запроса ввода пользователя.
Краткий пример для предложенного вами случая:
require 'tty-prompt'
require 'pastel'
prompt = TTY::Prompt.new
loop do
cmd, parms* = prompt.ask('[email protected]$ ').split /\s/
case cmd
when "hola"
puts "Hola amigo " parms
when "exit"
break if prompt.yes?('Do you really want to exit?')
end
end
Ответ 6
class MyAPI
def self.__is__(text)
@__is__ = text
end
def self.method_added(method)
@__help__ ||= {}
@__help__[method.to_s] = @__is__
@__is__ = nil
end
def self.help(of)
@__help__[of]
end
__is__ "open file <file>"
def open(file)
#...
end
__is__ "do X"
def do(*params)
#...
end
__is__ "calls help, use help <command>"
def help(*args, &block)
self.class.help(*args, &block)
end
end
MyAPI.new(...).pry
Или вы можете использовать команды pry, но это побеждает
Туринг-полнота. Помощь может быть реализована с использованием команд, так как я
не уверен, насколько хорошо мой подход работает. Эти методы должны быть
закодированная оборона. Я не помню, как использовать переменные класса: -/