Итак, вы написали эту удивительную библиотеку, но чего-то не хватает … интерфейс командной строки! Руби идеально подходит для такого рода вещей. Хотя есть базовый подход ARGV
, есть несколько отличных RubyGems, которые помогают с легкостью создавать интерфейсы командной строки (CLI). В этой статье мы рассмотрим несколько гемов Ruby CLI.
Предпосылки
- Ruby (минимум 1.9.3, но рекомендуется более 2.0.0)
- В этой статье я упоминаю различные RubyGems. Ожидается, что вы можете без проблем запустить
$ gem install GEMNAME
.
подсказки
- Большинство проектов Ruby имеют каталог
bin
в котором хранится двоичный файл CLI. (да, я знаю, что технически это не настоящий «бинарный файл») - Если вы в конечном итоге используете этот код дословно, не забудьте сделать ваши файлы исполняемыми.
- Возможно, вам понадобится Ruby Shebang для вашего двоичного файла
#!/usr/bin/env ruby
. - Постарайтесь сохранить код в вашем двоичном файле как можно более кратким. Это не только поможет вам позже с исправлением ошибок, но также поможет соавторам.
- Приведенные ниже гемы CLI содержат блок кода, в который вы передаете код, который будет выполнен при выполнении команды. Постарайтесь свести это к простому вызову метода. Возможно передача параметров из командной строки в хэш параметров в вашем методе, где параметры фактически анализируются.
Встроенный ARGV
ARGV
— это встроенный в Ruby массив для анализа аргументов командной строки. Например, ARGV[0]
возвращает первый аргумент, переданный скрипту Ruby. Для простого анализа аргументов вы можете попробовать что-то вроде этого:
puts "Hello #{ARGV[0]}!"
$ ./my-app world Hello world!
Очень простой пример, но довольно мощный. Единственная проблема с этим типом чтения аргументов — обработка ошибок. В частности, когда обязательный аргумент не указан. Это легко исправить, используя простой Ruby (см. Array docs и ARGV docs ). Я не буду слишком ARGV
, но вы можете увидеть возможности. Просто помните, что ARGV
— это просто массив, поэтому вам следует обращаться с ним как к аргументам и опциям.
command = ARGV[0] name = ARGV[1] name = "world" unless name case command when "hello" puts "Hello #{name}!" when "goodbye" puts "Goodbye #{name}!" end # And so on...
Тор
Вы, наверное, слышали о Торе раньше. Если вы посмотрите на статистику RubyGems , вы увидите Тора наверху. Это также мой личный фаворит из-за его расширяемости. Вот некоторый основной синтаксис:
CLI обернут в класс, унаследованный от суперкласса Thor
.
require "thor" class MyApp < Thor end
Добавьте команду, добавив метод в класс.
require "thor" class MyApp < Thor def hello puts "Hello world!" end end
В нижней части файла (как правило), вызовите MyApp#start
чтобы позволить ему запустить CLI.
# ... (MyApp class code above) MyApp.start $ ./my-app hello Hello world!
Мы можем добавить аргументы к этому, просто добавив аргументы в метод.
require "thor" class MyApp < Thor desc "hello", "Say hello" def hello(name) puts "Hello #{name}" end end
$ ./my-app hello universe Hello universe!
Или мы могли бы сделать то же самое с опцией.
require "thor" class MyApp < Thor desc: "Say Hello" method_option :name, :aliases => "-n", :desc => "Specify a name" def hello puts "Hello #{options[:name]}" end end
Вы можете указать тип method_option
вас опции, добавив method_option
. Документация для этого может быть найдена здесь . Например, в приведенном выше примере кода мы создаем name
параметра с псевдонимом -n
и описанием "Specify a name"
.
Возможно, вы заметили, что мы использовали desc
несколько раз. Это еще одна крутая особенность Тора, это самодокументирование. Если бы вы запустили my-app help hello
, вы бы увидели немного документации об этом.
$ ./my-app help hello Usage: my-app hello Options: -n, [--name=NAME] # Specify a name Say hello
Это действительно крутая особенность многих жемчужин CLI, которые я исследовал. Thor делает это, используя опцию desc
, но, как вы увидите, другие драгоценные камни используют разные опции документирования.
В общем, Thor — отличный инструмент, я верю, что он также поддерживает интерфейс командной строки Rails. Встроенная самодокументирование — приятное прикосновение, и я лишь коснулся всех его особенностей. Вы должны действительно проверить его вики, если вы хотите увидеть полную документацию. Также на SitePoint есть очень хороший учебник .
командующий
Commander — это полноценный пакет для написания приложений CLI. Я написал CLI, и Джекилл также использует его. Он имеет аккуратный DSL и, как и Тор, самодокументируется. Он также имеет очень хорошую обработку ошибок и настолько прост, что вы можете создать приложение командной строки менее чем за 15 секунд.
Чтобы создать новый CLI, перейдите в каталог bin/
вашего приложения (или в любое другое место, где он вам нужен) и запустите $ commander init my-app
(синтаксис: $ commander init FILENAME
).
Вы получите несколько подсказок для информации:
$ commander init my-app Machine name of program: my-app Describe your program: Does so many things. List the commands you wish to create: hello goodbye # Notice no commas Initialized template in my-app
Это создает файл my-app
который имеет содержимое:
#!/usr/bin/env ruby require 'rubygems' require 'commander/import' program :version, '0.0.1' program :description, 'Does oh so many things.' command :hello do |c| c.syntax = 'my-app hello [options]' c.summary = '' c.description = '' c.example 'description', 'command example' c.option '--some-switch', 'Some switch that does something' c.action do |args, options| # Do something or c.when_called My-app::Commands::Hello end end command :goodbye do |c| c.syntax = 'my-app goodbye [options]' c.summary = '' c.description = '' c.example 'description', 'command example' c.option '--some-switch', 'Some switch that does something' c.action do |args, options| # Do something or c.when_called My-app::Commands::Goodbye end end
Если вы сразу войдете в свой терминал, у вас теперь есть CLI, который ничего не делает.
$ ./my-app --help NAME: my-app DESCRIPTION: Does oh so many things. COMMANDS: goodbye hello help Display global or [command] help documentation. GLOBAL OPTIONS: -h, --help Display help documentation -v, --version
Далее мы отредактируем этот файл, чтобы он имел следующие функциональные возможности:
$ ./my-app hello world Hello world! $ ./my-app goodbye -n universe Goodbye universe!
Для первой команды, hello
, мы принимаем аргумент в качестве имени. Вторая команда, goodbye
, принимает опцию для имени.
Вот так!
#!/usr/bin/env ruby require 'rubygems' require 'commander/import' program :version, '0.0.1' program :description, 'Does oh so many things.' command :hello do |c| c.syntax = 'my-app hello NAME [options]' c.summary = 'Says hello' c.description = c.summary # Because we're lazy c.example 'Says hello to "world"', 'my-app hello world' c.action do |args, options| name = args.shift # or args.first or args[0] if you wish puts "Hello #{name}!" # Or in a real app, you would call a method and pass command line arguments to it. end end command :goodbye do |c| c.syntax = 'my-app goodbye NAME [options]' c.summary = 'Says goodbye' c.description = c.summary c.example 'Say goodbye to world', 'my-app goodbye -n world' c.example 'Say goodbye to world', 'my-app goodbye --name world' c.option '-n', '--name NAME', String, 'Specify a name' # Option aliasing c.action do |args, options| puts "Hello #{options.name}!" end end
По умолчанию параметры имеют логическое значение. Поэтому, когда мы добавляем к нему тип String
, он позволяет вызывать опцию с аргументом. Вы также можете определить опцию так:
# ... c.option '--option', 'A boolean by default' # ...
Commander также имеет встроенную HighLine, так что вы можете делать классные вещи, как это:
ask_for_array "Commands: " # => Commands: hello goodbye # => ["hello", "goodbye"] say "Hello!" # => Hello! ask "Password: " { |char| char.echo = "*" } # => Password: *********** # => "supersecret"
И, конечно, вы можете делать бесчисленные вещи с Коммандером, как и с Тором. Вы можете
проверить это
здесь
помои
Slop — это еще один DSL для создания приложений CLI в Ruby. Вы, вероятно, уже получили его от некоторых других самоцветов (как, например, tor и, возможно, командир). Кажется, это очень популярно, так что давайте начнем!
Отстой очень минимален и мало что делает для вас, если вы не попросите об этом. Начнем с добавления команды версии. Это будет -v
и --version
.
require "slop" Slop.parse do on "-v", "--version" do puts "my-app v0.0.1" end end
Давайте создадим то же приложение, которое у нас было раньше, но с помоем.
require "slop" opts = Slop.parse do on "-v", "--version" do puts "my-app v0.0.2" end command 'hello' do run do |opts, args| puts "Hello #{args.shift}" end end command 'goodbye' do on 'n=', 'name=' run do |opts, args| puts "Goodbye #{opts[:name]}" end end end
Это крайне минимально. CLI даже не волнует, является ли аргумент опции пустым! Но в этом суть Slop: простой вариант разбора. Это одна из вещей, которые мне больше всего нравятся в Слопе. Если Commander — это Rails, то Слоп — это Синатра.
Я бы предложил Slop для простых CLI и Commander для сложных. Вы должны действительно проверить его README, чтобы увидеть полный список функций и опций.
Вывод
Есть много замечательных жемчужин для создания интерфейсов командной строки. Какой из них вы выбираете, полностью зависит от вашего стиля. В вашем распоряжении Ruby-подобные (Thor), минимальные (Slop) и полнофункциональные интегрированные (Commander) среды CLI. В конце концов, вам решать, какой тип библиотеки вы хотите использовать для создания CLI, если таковой имеется (Homebrew использует опцию ARGV
!). Есть также так много других, которые я не упомянул в этой статье, но я надеюсь, что это даст вам общий обзор некоторых замечательных вариантов.