Среда разработки включает не только интерпретатор. У каждого хорошего разработчика под рукой всегда есть целый набор средств, облегчающих жизнь. Некоторые из них зависят от языка, другие — нет.
Самый важный инструмент — редактор. Основная работа программиста — манипулирование текстом, поэтому выбор редактора (и ваше умение им пользоваться) оказывает огромное влияние на производительность труда. Немаловажно также наличие в нем поддержки конкретного языка или средств настройки. Мы дадим очень краткий обзор распространенных редакторов.
Другие инструменты помогают в составлении документации, установке библиотек, отладке и т.д. Мы уже познакомились с библиотекой отладки (не являющейся автономным приложением) в главе 16, а в главе 17 рассказали о системе RDoc. Поэтому здесь мы их касаться не будем. Также в главе 17 шла речь о системе RubyGems с точки зрения разработчика, создающего пакет; теперь же мы станем на место программиста, который пользуется пакетами, созданными другими людьми.
Также в этой главе мы рассмотрим программы irb (интерактивный Ruby) и ri (инструмент для чтения документации). И завершим ее кратким обсуждением интегрированных сред разработки (IDE), которые хорошо работают с Ruby.
21.1. Система RubyGems
RubyGems — это не «официальная» система управления пакетами для Ruby, но одна из тех, что пользуются обширной поддержкой со стороны сообщества. В июле 2006 года она еще не входила в стандартный дистрибутив, но может стать его частью в будущем. Мы довольно подробно рассматривали процедуру создания gem- пакета в главе 17. А в этой главе расскажем, как пользоваться пакетами, созданными другими людьми.
RubyGems пытается решить несколько основных проблем, как то: простота установки, центральный репозиторий, управление версиями библиотек, управление зависимостями и т.д. Gem-пакеты предоставляют доступ к документации и позволяют легко контролировать, какие библиотеки установлены.
Если система RubyGems на вашем компьютере не установлена, зайдите на страницу http://rubyforge.org/projects/rubygems и выполните простые инструкции по загрузке и установке. В дальнейшем RubyGems будет обновляться автоматически.
Сам исполняемый файл называется gem. Структура команд похожа на применяемую в cvs и других аналогичных системах, то есть у каждой команды есть подкоманды, а у каждой подкоманды — специфичные для нее параметры. Ниже приведена информация о порядке запуска:
RubyGems - развитый менеджер пакетов для Ruby. Ниже приведена
краткая справка с указанием на источники дополнительной информации.
Порядок запуска:
gem -h/--help
gem -v/--version
gem command [аргументы...] [флаги...]
Примеры:
gem install rake
gem list —local
gem build package.gemspec
gem help install
Более подробные справки:
gem help commands показать все команды 'gem'
gem help examples показать примеры использования
gem help COMMAND вывести справку о команде COMMAND
(например, 'gem help install')
Дополнительная информация:
http://rubygems.ruby forge.org
Самые важные команды не вызывают затруднений. Например, чтобы установить библиотеку feedtools, нужно выполнить команду:
gem install feedtools
Сначала она будет искать gem-пакет локально, а если не найдет, то обратится к серверу Ruby Forge. По умолчанию устанавливается последняя версия (хотя в некоторых случаях вам задают вопрос, какой именно пакет вы хотите установить). Можно и явно указать версию с помощью флага -v или --version. Есть еще несколько флагов, управляющих установкой; подробную информацию дает команда gem help install.
Иногда gem-пакет зависит от других пакетов. В таком случае вас спросят, надо ли их устанавливать. Понятно, что, отказавшись от требуемых пакетов, вы не сможете установить и тот, что хотели изначально.
Как узнать имя нужного вам пакета? Если он находится на сайте RubyForge, то обычно называется так же, как проект. Например, программа rake находится на странице http://rubyforge.org/projects/rake или просто http://rake.rubyforge.org. поэтому для установки нужно выполнить команду gem install rake.
Если вы не располагаете даже такой информацией, попробуйте воспользоваться командой gem search. Если указать часть предполагаемого имени gem-пакета, то будут найдены все пакеты с похожими именами. По умолчанию поиск производится на локальном компьютере; чтобы искать в центральном репозитории, задайте флаг --remote. Например, команда gem search xml --remote нашла 12 пакетов.
Чтобы получить информацию об установленном пакете, введите команду gem specification — она напечатает все содержащиеся в пакете метаданные (в основном содержимое самого файла gemspec). Флаг --remote существует, но пока не реализован.
Кроме того, имеется команда деинсталляции uninstall, а также команды query и list, отчасти перекрывающие друг друга и команду search. Есть и еще много команд (дополнительную информацию вы найдете во встроенной справке или в онлайновой документации).
Полезно установить gem-сервер и на своей системе — не в качестве репозитория, из которого другие смогут дистанционно устанавливать пакеты, а как централизованный механизм, позволяющий просматривать в браузере все локально установленные пакеты вместе с документацией.
Для запуска gem-сервера просто наберите команду gem_server (обычно сервер работает в фоновом режиме). Указав в адресной строке браузера URL localhost:8808, вы увидите страницу «RubyGems Documentation Index», где в алфавитном порядке перечислены все установленные gem-пакеты со ссылками на документацию в формате rdoc и на домашнюю страницу проекта в Web.
О системе RubyGems можно еще многое сказать; к тому же она постоянно развивается. Самая актуальная информация представлена на сайте http://rubygems.rubyforge.org.
21.2. Программа Rake
Утилита rake — это вариация на тему давно известной в UNIX программы make. Но вместо «странного» синтаксиса make, который все мы знаем и терпеть не можем, в rake используется код на самом Ruby. Программу написал Джим Вайрих (Jim Weirich); это первый, насколько мне известно, пример формальной реализации языка DSL (domain-specific language — язык предметной области) на Ruby.
Есть два варианта написания названия: Rake и rake. Первый - это название инструмента, второй — имя самого исполняемого файла. На мой взгляд, различие несущественное.
Нет сомнения, что на дизайн Rake оказала большое влияние программа make, так что терминология одна и та же. Как и раньше, мы говорим о целях, действиях, зависимостях и правилах.
Применениям Rake нет числа. Вы можете пользоваться ею для сборки проектов, написанных на С, C++ или Java (или на любом другом языке). Годится она и для генерирования документации с помощью RDoc, развертывания программ, обновления проекта на сайте Ruby Forge и множества других задач.
Неудивительно, что на вход Rake подается командный файл (rake-файл), который по умолчанию называется rakefile или Rakefile. Если вы хотите назвать его иначе, укажите имя с помощью флага -f или --rakefile:
$ rake # Искать сначала 'rakefile', потом 'Rakefile'.
$ rake -f myfile # Использовать файл с именем 'myfile'.
Основная «единица работы» в Rake — задание; именуются задания посредством символов Ruby. Предполагается, что в каждом rake-файле есть задание по умолчанию :default — оно будет выполняться, если явно не указано другое имя.
$ rake # Выполнить задание по умолчанию.
$ rake mytask # Выполнить задание с именем 'mytask'.
Внутри rake-файла мы указываем задания с помощью метода task, передавая символ и блок:
task :mytask do
# ...
end
Содержимое блока в примере выше опущено. То, что в нем находится, называется действием.
В действии можно выполнять произвольный код на Ruby. Для типичных операций предусмотрены готовые методы. Так, метод sh (название которого напоминает об интерпретаторе команд в UNIX) запускает системную команду.
Методы cp, mv и rm предназначены соответственно для копирования, перемещения и удаления файлов. (Как и make, Rake беззастенчиво выдает свое происхождение от UNIX.) Есть и другие подобные команды; дополнительную информацию вы найдете в онлайновой документации на сайте http://docs.rubyrake.org.
При желании можете заключать блок в фигурные скобки, но обычно в этом случае интерпретатор Ruby ожидает, что параметры будут заключены в круглые скобки.
task(:mytask) { do_something }
Рассмотрим более конкретный пример. Предположим, что имеется программа myprog.с, написанная на С, и еще два связанных с ней исходных файла (каждый со своим заголовочным файлом). Иными словами, у нас есть пять исходных файлов:
myprog.с
sub1.с
sub1.h
sub2.с
sub2.h
Мы хотим собрать из них исполняемый файл myprog. Эта процедура состоит из нескольких шагов: откомпилировать все файлы с расширением .с, а затем скомпоновать получившиеся в результате файлы с расширением .о.
Начнем с метода file, который определяет зависимости файлов:
file "myprog.о" => ["myprog.с"]
file "sub1.о" => ["sub1.с", "sub1.h"]
file "sub2.o" => ["sub2.c", "sub2.h"]
file "myprog" => ["sub1.o", "sub2.o"]
Отметим, что метод file принимает хэш, который ассоциирует имя файла с массивом имен файлов, от которых он зависит.
Теперь перейдем к построению двоичных файлов. Расширим написанный выше код. Если после вызова метода file указать блок, то мы сможем ассоциировать с файлом набор действий, которые необходимо выполнить для создания этого файла:
file "myprog.о" => ["myprog.с"] do
sh "сс -с -о myprog.о myprog.с"
end
file "sub1.o" => ["sub1.с", "sub1.h"] do
sh "сс -с -o sub1.o sub1.c"
end
file "sub2.o" => ["sub2.c", "sub2.h"] do
sh "сс -с -o sub2.o sub2.c"
end
file "myprog" => ["sub1.o", "sub2.o"] do
sh "cc -o myprog myprog.о sub1.o sub2.o"
end
Здесь имеется некоторое дублирование, но от него можно избавиться. В Rake есть специальный механизм, который называется FileList; он понимает метасимволы (шаблоны) и позволяет работать сразу с несколькими файлами. В данном случае поместим все файлы с расширением .c в список SRC. Константа типа FileList ведет себя как массив:
SRC = FileList["*.с"]
Теперь можно определить действия в цикле, как показано ниже. И обратите внимание, что зависимости здесь не упоминаются — Rake самостоятельно учтет эту информацию, если она была задана в другом месте.
SRC.each do |src|
obj = src.sub(/.c$/,".о")
file(obj) { sh "cc -с -o #{obj} #{src}" }
end
Однако проще пользоваться правилами. Это еще один механизм Rake, естественно, позаимствованный у make:
rule '.о' => '.с' do |target|
sh "сс -с -о #{target.name} #{target.source}"
end
Тут мы наблюдаем небольшое волшебство. Rake устанавливает атрибут source, подставляя расширение имени файла из хэша (в данном случае .o заменяется на .c).
Продолжим сеанс магии. Если затребовать библиотеку rake/clean, то появляются константы clean и clobber (первоначально пустые) и задания :clean и :clobber. По сложившейся традиции clean удаляет временные файлы, a clobber — еще и собранный исполняемый файл.
Для этих напоминающих массив констант определен метод include, принимающий маску имени файлов; это неявное использование механизма FileList.
Теперь наш rake-файл принимает такой вид:
require 'rake/clean'
CLEAN.include("*.о")
CLOBBER.include("myprog")
SRC = FileList['*.с']
OBJ = SRC.ext('o')
rule '.o' => '.c' do |t|
sh "cc -с -o #{t.name} #{t.source}"
end
file "hello" => OBJ do
sh "cc -o hello #{OBJ}"
end
file "myprog.o" => ["myprog.c"]
file "sub1.o" => ["sub1.c", "sub1.h"]
file "sub2.o" => ["sub2.c", "sub2.h"]
task :default => ["myprog"]
Обратите внимание, что мы не задавали задания «clean» и «clobber» явно. Кроме того, отметим что «clobber» неявно включает операцию «clean». И наконец, мы определили задание default для удобства запуска rake-файла; теперь можно не указывать явно имя задания, осуществляющего компиляцию и сборку.
У программы rake есть несколько параметров командной строки. Иногда желательно протестировать rake-файл, не выполняя никаких (потенциально опасных) операций; для этого служит флаг -n или --dry-run. Флаг -T выводит список всех целей в rake-файле. Имеются также флаги, управляющие поиском библиотек, трассировкой, протоколированием и т.д.
Программа Rake сложнее, чем я описал в этом разделе (особенно это касается правил). И она продолжает развиваться. Как обычно, самую свежую информацию ищите в онлайновой документации (http://docs.rubyrake.org/).
21.3. Оболочка irb
Утилита irb (интерактивный Ruby) уже много лет как включена в дистрибутив Ruby. Можно считать, что это «испытательный стенд» или «площадка для игр», на которой вы опробуете новые приемы и идеи.
Работать с irb просто. После запуска вы получаете приглашение и можете вводить произвольные выражения Ruby. Выражение вычисляется, и печатается результат. Вот пример короткого сеанса:
$ irb
irb(main):001:0> "cell" + "о"
=> "cello"
irb(main):002:0> 3*79
=> 237
irb(main):003:0> Dir.entries(".").size
=> 17
irb(main):004:0> rand
=> 0.850757389880155
irb(main):005:0> rand
=> 0.679879756672551
irb(main):006:0> defined? Foo
=> nil
irb(main):007:0> defined? Object
=> "constant"
irb(main):008:0> quit
$
Конечно, это больше, чем калькулятор. При желании можно ввести произвольный код на Ruby:
[hal@localhost ch21]$ irb
irb(main):001:0> require 'mathn'
=> true
irb(main):002:0> gen = Prime.new
=> #
При установке флага -r выполняется require, поэтому можно включать код из внешнего файла. Предположим, что вы написали такой файл:
# File: foo.rb
class MyClass
attr_accessor :alpha, :beta
def initialize(a, b)
@alpha, @beta = a, b
end
end
obj1 = MyClass.new(23,34)
obj2 = MyClass.new("abc","xyz")
Тогда можно сделать следующее:
$ irb -rfoo
irb(main):001:0> obj = MyClass.new(88,99)
=> #
Отметим, что хотя обращаться к сущностям, определенным в файле (например, к константе MyClass) мы можем, это не относится к локальным переменным. Локальные переменные доступны только в самом файле, require (выполненное хоть внутри, хоть вне irb) доступа к ним не дает.
Новичков часто смущает информация, выводимая irb:
$ irb -rfoo
irb(main):001:0> puts "hello"
hello
=> nil
Позвольте, что тут делает nil? Разумеется, это значение, возвращенное методом puts.
Еще один источник недоразумений — метод eval. Взгляните на следующий сеанс:
$ irb
irb (main) : 001:0> eval("var = 567")
=> 567
irb(main) :002:0> eval("var")
=> 567
irb(main):003:0> var
=> 567
Вас ничего не удивляет? Но давайте запустим следующий сценарий и посмотрим, что произойдет:
р eval("var = 567")
р eval("var")
р var
# Results:
# 567
# 567
# temp.rb:3: undefined local variable or method 'var' for main:Object
# (NameError)
У Ruby есть такая особенность: когда вы выполняете eval, а вслед за ним еще один, они в некотором смысле разделяют «общую область видимости». Поэтому к переменной, определенной в первой строке, можно обратиться во второй (вне или внутри irb). Но различие проявляется, когда мы попытаемся обратиться к той же переменной без использования eval. В irb это работает, а в сценарии мы получаем ошибку. Что происходит?
Поведение сценария следует считать более правильным. Не забывайте, что сама программа irb написана на Ruby; здравый смысл подсказывает, что она, скорее всего, внутри вызывает eval. Но мы только что убедились, что результат применения eval может отличаться от того, что мы видим на верхнем уровне, поэтому исполнение кода внутри irb не всегда идентично исполнению такого же кода в сценарии. Об этом не следует забывать, особенно если вы ставите какие-нибудь экзотические эксперименты.
Имейте в виду, что irb настраивается в широких пределах. При запуске она читает все инициализационные файлы, которые может найти, в следующем порядке:
• файл ~/.irbrc;
• файл .irbrc;
• файл irb.rс;
• файл _irbrc;
• путь, указанный в переменной окружения $irbrc.
Инициализационные файлы пишутся на Ruby. В них можно настраивать текст приглашения и многое другое. Подробно эти файлы обсуждаются в книге «Programming Ruby». Ниже мы сделаем лишь несколько замечаний.
Если ваша версия Ruby собрана с поддержкой библиотеки GNU readline (обычно так и есть), то вы можете перемещаться по истории команд с помощью клавиш со стрелками вверх и вниз. Еще важнее, что работает механизм завершения по клавише Tab: когда вы набираете начало идентификатора, а затем нажимаете Tab, irb пытается дописать имя идентификатора за вас.
Чтобы включить механизм завершения, добавьте в файл .irbrc следующий фрагмент:
IRB.conf[:AUTO_INDENT] = true
IRB.сonf[:USE_READLINE] = true
IRB.conf[:LOAD_MODULES] ||= []
IRB.conf[:LOAD_MODULES] |= ['irb/completion']
В файле .irbrc может содержаться произвольный код. Например, я часто пользуюсь описанным ниже методом. Для краткости он назван sm (сокращение от «show methods»), а цель — вывести (в алфавитном порядке) список всех методов, которые можно вызывать для данного объекта, за исключением тех, которые он унаследовал от своих предков:
def sm(obj)
list = obj.methods
anc = obj.class.ancestors — [obj.class]
anc.each {|a| list -= a.instance_methods }
list.sort
end
Вот пример его использования:
irb(main):001:0> str = "hello"
=> "hello"
irb(main):002:0> sm str
=> ["%", "*", "+", "<<", "<=>", "[]", "[]=", "capitalize",
"capitalize!", "casecmp", "center", "chomp", "chomp!", "chop", "chop!",
"concat", "count", "crypt", "delete", "delete!", "downcase", "downcase!",
"dump", "each", "each_byte", "each_line", "empty?", "gsub", "gsub!", "hex",
"index", "insert", "intern", "length", "ljust", "lstrip", "lstrip!", "match",
"next", "next!", "oct", "replace", "reverse", "reverse!", "rindex", "rjust",
"rstrip", "rstrip!", "scan", "size", "slice", "slice!", "split", "squeeze",
"squeeze!", "strip", "strip!", "sub", "sub!", "succ", "succ!", "sum",
"swapcase", "swapcase!", "to_f", "to_i", "to_str", "to_sym", "tr", "tr!",
"tr_s", "tr_s!", "unpack", "upcase", "upcase!", "upto"]
irb(main):003:0> sm String
=> ["allocate", "new", "superclass"]
irb(main):004:0> sm 123 => ["%", "*", "**", "+", "-", "/", "<<", ">>", "[]", "^",
"id2name", "power!", "rdiv", "rpower", "size", "to_f", "to_sym, "|", "-"]
Программа irb позволяет запускать подсеансы внутри сеанса, хотя это используется и нечасто. Можно запустить несколько сеансов и переключаться между ними, у каждого сеанса собственный набор привязок.
Может быть, вам это и не кажется полезным, но можно, например, задать объект в сочетании с подкомандой irb. Тогда контекстом подсеанса станет этот объект, псевдопеременная self будет ссылаться на него, он же станет областью видимости и т.д.:
$ irb
irb(main):001:0> t0 = Time.now
=> Mon Jul 31 04:51:50 CDT 2006
irb(main):002:0> irb t0
irb#1(Mon Jul 31 04:51:50 CDT 2006):001:0> strftime("%a %b %c")
=> "Mon Jul Mon Jul 31 04:51:50 2006"
irb#1(Mon Jul 31 04:51:50 CDT 2006):002:0> to_i
=> 1154339510
irb#1(Mon Jul 31 04:51:50 CDT 2006):003:0> self + 1000
=> Mon Jul 31 05:08:30 CDT 2006
irb#1(Mon Jul 31 04:51:50 CDT 2006):004:0> wday
=> 1
irb#1(Mon Jul 31 04:51:50 CDT 2006):005:0> class
SyntaxError: compile error
(irb#1):5: syntax error, unexpected $end
from (irb#1):5
irb#1(Mon Jul 31 04:51:50 CDT 2006):006:0> self.class
=> Time
irb#1(Mon Jul 31 04:51:50 CDT 2006):007:0> quit
=> #
@signal_status=:IN_EVAL, @context=#
irb(main):003:0> quit
$
Мы уже убедились в полезности библиотеки ruby-breakpoint (см. главу 16). В сочетании с ней irb становится мощным средством отладки, поскольку вы можете установить точку прерывания и «оказаться» в сеансе irb. Конечно, это не настоящий отладчик, потому что не позволяет исполнять код в пошаговом режиме.
Иногда бывает полезна библиотека xmp. Она принимает предложения на Ruby, исполняет их и помещает возвращаемое значение в комментарий. В книге «Programming Ruby» рассматривается xmp, а также библиотека rtags (которая генерирует файл TAGS для редакторов emacs или vi).
У irb есть еще одна приятная особенность, о которой стоит знать. Понятно, что irb умеет анализировать написанный на Ruby код, но лексический анализатор несложно использовать и в других приложениях. Вот простой пример программы, которая открывает саму себя и анализирует собственный код, выводя отсортированный список всех идентификаторов и констант:
require 'irb/ruby-lex'
file = File.new(__FILE__)
parse = RubyLex.new # (file)
parse.set_input(file)
idents = []
loop do
token = parse.token
break if token.nil?
if token.is_a? RubyToken::TkIDENTIFIER or
token.is_a? RubyToken::TkCONSTANT
idents << token.name
end
end
p idents.uniq.sort
# Выводится:
# ["File", "RubyLex", "RubyToken", "TkCONSTANT", "TkIDENTIFIER", "file",
# "idents", "loop", "name", "new", "p", "parse", "require", "set_input",
# "sort", "token", "uniq"]
Насколько мне известно, этот механизм не документирован на английском языке. Но если вам необходим лексический анализатор Ruby, то можете изучить исходный текст и адаптировать его под свои нужды.
21.4. Утилита ri
Сокращение ri, вероятно, означает «Ruby index» или нечто подобное. Это командная утилита для чтения документации, предоставляющая информацию о классах, методах, модулях и т.д. Пример:
$ ri each_with_index
------------------------------------------------------------
enumObj.each_with_index {|obj, i| block } -> nil
------------------------------------------------------------
Calls block with two arguments, the item and its index,
for each item in enumObj.
hash = Hash.new
%w(cat dog wombat).each_with_index {|item, index|
hash[item] = index
}
hash #=> {"dog"=>1, "wombat" =>2, "cat"=>0}
Отметим, что в ней есть ошибки и странности. Можете сообщать о них (а равно об опечатках и других неточностях), если найдете человека, который сознается в авторстве.
Мартин Анкерл (Martin Ankerl) написал графическую утилиту fxri, которая работает устойчиво. Она получает данные от RDoc, как и ri. Кроме того, в ней есть панель, где запущена irb.
21.5. Поддержка со стороны редакторов
Любой современный редактор должен проявлять дружелюбие по отношению к программистам. Память о двадцатом веке уходит в прошлое, и мы принимаем как должное, что редакторы изменяют свое поведение в зависимости от типа редактируемого файла. Мы ожидаем синтаксической подсветки, автоматического формирования отступов и прочего в том же духе.
Программист, пишущий на Ruby, не будет разочарован имеющимся инструментарием. Многие возможности стандартно включены в редактор, другие приходится настраивать.
Два прекрасных редактора — это SciTe (на базе виджета редактирования Scintilla) и TextMate (имеется только для Mac OS X). Оба хорошо поддерживают Ruby, но больше я о них ничего сказать не могу.
Третий редактор — jEdit, написанный на Java редактор для программистов (www.jedit.com). Роб МакКиннон дополнил его модулем для Ruby (http://rubyjedit.org/). Но в этой книге я не могу задерживаться на его описании.
Среди программистов наиболее распространены редакторы vi (или vim) и emacs. Их мы кратко рассмотрим.
Исторически для пользователей vim было создано три разных пакета. К счастью, теперь они объединены в пакет vim-ruby. Это набор конфигурационных файлов, поддерживающий синтаксическую подсветку, автоматическое формирование отступов и завершение кода. Кроме того, он позволяет вызывать интерпретатор Ruby прямо из редактора.
Если вы работаете с vim версии 7 (как и положено), то этот пакет, вероятно, уже установлен. (Если же по какой-то неуважительной причине вы все еще используете версию 6.x, то самое время провести обновление.)
Но может оказаться, что пакет не активирован (возможно, в целях обратной совместимости). Тогда нужно его активировать, добавив в файл .vimrc следующие строки:
set nocompatible
syntax on
filetype on
filetype indent on
filetype plugin on
Есть также по меньшей мере две реализации сворачивания кода для Ruby. На мои взгляд, любая методика сворачивания, которая требует вставлять в код специальные комментарии или символы, не оптимальна. Хороший механизм сворачивания должен анализировать код и распознавать в нем классы, модули, методы и т.д. Такую реализацию для vim написал Маурицио Фернандес (http://eigenclass.nrg/hiki.rb?Usable+Ruby+folding+for+Vim).
В принципе есть много причин не любить редактор vim; одна из самых основательных — язык vimscript. Хорошая новость — теперь есть возможность программировать поведение vim на Ruby! И плохая… она неважно документирована. Если хотите узнать подробнее, рекомендую для начала набрать команду :help ruby в vim. Дополнительная информация имеется на странице http://wiki.rubygarden.org/Ruby/page/show/VimRubyInterface. Наконец, загляните на сайт http://vim/org; может быть, там появилось что-то новенькое.
Еще один популярнейший в мире редактор — emacs. Вообще-то называть его редактором не вполне правильно. Это, скорее, миниатюрная операционная система, которая заодно позволяет и редактировать тексты. Одно из главных достоинств emacs — поразительная расширяемость; пользователь программирует его поведение на диалекте языка Lisp (elisp). Язык elisp мощнее, чем vimscript, но читать написанные на нем программы не менее сложно (правда, по другой причине).
Я сам не работаю с emacs, но очень уважаю тех, кто им пользуется. Не могу почти ничего сказать о поддержке Ruby в emacs; отсылаю вас на wiki-страницу RubyGarden (http://wiki.rubygarden.org/Ruby/page/show/EmacsExtensions).
21.6. Интегрированные среды разработки
Можно спорить с тем, что компания Borland со своим языком Turbo Pascal (в середине 1980-х годов) стала праотцом всех современных интегрированных сред разработки (IDE), но без сомнения Borland сделала идею популярной. Кто бы ни стоял у ее истоков, идея IDE в обозримом будущем никуда не денется.
В центре IDE обычно стоит мощный редактор, знающий обо всех особенностях синтаксиса языка. Такие средства, как синтаксическая подсветка и автоматическое формирование отступов, стали стандартными. Обычно включают также отладчик и средства управления проектом. Все чаще в среду интегрируются механизмы тестирования и сопряжение с системой управления версиями.
Трудно проводить осмысленное сравнение IDE. Все они похожи и все в чем-то различаются. Выбор такой же личный и субъективный, как при покупке автомобиля. Я попытался провести небольшое исследование, чтобы помочь вам принять решение:
• Одна из самых важных для Ruby сред — FreeRIDE. Она «заточена» специально под Ruby и всецело контролируется разработчиками, входящими в сообщество пользователей этого языка. В число основных авторов входят Рич Килмер (Rich Kilmer), Курт Гиббс (Curt Hibbs) и Лоран Жуллиар (Laurent Julliard), но есть и много других. Как и в случае любого крупного проекта с открытыми исходными текстами, разработка ведется медленно. Получить самую свежую информацию и загрузить программу можно на сайте http://freeride.rubyforge.org.
• Одно из самых последних решений — программа Komodo производства компании ActiveState. Это мощная, полнофункциональная среда, но имейте в виду, что продукт коммерческий. Полную информацию можно найти на странице http://www.activestate.com/Products/Komodo/.
• Если вы поклонник Eclipse, то должны знать о существовании Ruby Development Tool (RDT). Это набор подключаемых модулей для поддержки Ruby на платформе Eclipse. Детали изложены на странице http://sourceforge.net/projects/rubyeclipse.
• ArachnoRuby — еще один коммерческий продукт; автор Лотар Шольц (Lothar Scholz). Набор функций достаточно полон, но в июле 2006 года он работал еще не так устойчиво, как другие IDE. Дополнительную информацию ищите на странице http://wwwruby-ide.com/ruby/ruby_ide_and_ruby_editor.php.
• Наконец, есть еще RDE, Ruby Development Environment. Работает неплохо, достаточно мощная и бесплатная. Но только на платформе Windows.
В таблице 21.1 перечислены характеристики различных IDE.
Таблица 21.1. Сравнение пяти IDE для Ruby
Характеристика | Free-RIDE | RDE | RDT | ArachnoRuby | Komodo |
Коммерческий | нет | нет | нет | да | да |
Платформы | все | Win32 | все | Linux, Win32 | все |
Синтаксическая подсветка | да | да | да | да | да |
Автоматическое формирование отступов | да | да | да | да | да |
Сворачивание кода | да | нет | нет | да | да |
Редактирование нескольких документов | да | да | да | да | да |
Поддержка других языков (Perl и т.д.) | ограниченная | да | да | да | да |
Настраиваемые привязки клавиш | да | нет | нет | да | да |
Макросы редактора | да | нет | нет | да | да |
Обзор кода | да | да | да | да | да |
Интеграция с системой управления версиями | нет | нет | да | нет | да |
Построитель графических интерфейсов | нет | нет | нет | нет | да |
Управление проектом | да | нет | да | да | да |
Интегрированное тестирование | да | нет | да | нет | нет |
Прочие замечания | чистый Ruby | - | - | включены инструменты для Web | построен на базе Mozilla |
Естественно, это лишь отправная точка для ваших собственных изысканий. Для настоящего сравнения потребовалась бы сотня страниц (а к моменту завершения работы данные уже устарели бы).
В таблице рассматриваются только три платформы: семейство Linux/UNIX, семейство Win32 и Mac OS X. Когда мы пишем «все», имеются в виду только эти платформы.
21.7. Заключение
В этой главе мы рассмотрели ряд инструментов, облегчающих жизнь программисту на Ruby. К числу общеупотребительных относятся интерактивная оболочка для Ruby irb, инсталлятор RubyGems и утилита чтения документации ri. Мы также дали обзор модулей для поддержки Ruby, которые подключаются к редакторам. Наконец, мы вкратце упомянули некоторые IDE с поддержкой Ruby. Но самый главный инструмент — это не программы, а люди, то есть все сообщество пользователей Ruby. Это и есть тема следующей (и последней) главы.