• 21.1. Система RubyGems
  • 21.2. Программа Rake
  • 21.3. Оболочка irb
  • 21.4. Утилита ri
  • 21.5. Поддержка со стороны редакторов
  • 21.6. Интегрированные среды разработки
  • 21.7. Заключение
  • Глава 21. Инструменты разработки для Ruby

    Человек — это животное, создающее инструменты.

    (Бенджамин Франклин)

    Среда разработки включает не только интерпретатор. У каждого хорошего разработчика под рукой всегда есть целый набор средств, облегчающих жизнь. Некоторые из них зависят от языка, другие — нет.

    Самый важный инструмент — редактор. Основная работа программиста — манипулирование текстом, поэтому выбор редактора (и ваше умение им пользоваться) оказывает огромное влияние на производительность труда. Немаловажно также наличие в нем поддержки конкретного языка или средств настройки. Мы дадим очень краткий обзор распространенных редакторов.

    Другие инструменты помогают в составлении документации, установке библиотек, отладке и т.д. Мы уже познакомились с библиотекой отладки (не являющейся автономным приложением) в главе 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
    и других аналогичных системах, то есть у каждой команды есть подкоманды, а у каждой подкоманды — специфичные для нее параметры. Ниже приведена информация о порядке запуска[18]:

    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
    ). Флаг
    --remot
    e существует, но пока не реализован.

    Кроме того, имеется команда деинсталляции

    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

    => #<IRB::Irb: @scanner=#<RubyLex:0xb7ee8394>,

    @signal_status=:IN_EVAL, @context=#<IRB::Context:0xb7ee86f0>>

    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. Это и есть тема следующей (и последней) главы.


    Примечания:



    1

    Огромное спасибо (яп.)



    18

    Программа печатает эту информацию на английском языке. Для удобства читателей приводим русский перевод. — Прим. перев.









    Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх