Статьи

Руби Интерфейс командной строки Gems

Компьютерный монитор

Итак, вы написали эту удивительную библиотеку, но чего-то не хватает … интерфейс командной строки! Руби идеально подходит для такого рода вещей. Хотя есть базовый подход 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 !). Есть также так много других, которые я не упомянул в этой статье, но я надеюсь, что это даст вам общий обзор некоторых замечательных вариантов.