Programmierung in Ruby

Der Leitfaden der Pragmatischen Programmierer

Interactive Ruby Shell



Weiter vorne auf Seite 126 haben wir irb vorgestellt, ein Ruby-Modul, mit dem man Ruby-Programme interaktiv eingeben und die Ergebnisse direkt sehen kann. Dieser Anhang geht mehr in die Details, wie man irb benutzt und einrichtet.

Komandozeile

irb läuft von der Komandozeile aus.

irb [irb-options][ruby_script][options]

Die Kommandozeilen-Optionen für irb sind in der Tabelle B.1 auf Seite 524 aufgeführt. Normalerweise führt man irb ohne Optionen aus, aber wenn man ein Script laufen lassen und dazu die Beschreibung Zeile für Zeile sehen will, kann man den Namen der Ruby-Scripts und die nötigen Optionen dafür mitgeben.
Kommandozeilen-Optionen für irb
Option Beschreibung
-f Unterdrücke das Lesen von ~/.irbrc.
-m Mathematischer Modus (es gibt Unterstützung für Brüche und Matrizen).
-d Setzt $DEBUG auf true (dasselbe wie ``ruby -d'').
-r load-module Dasselbe wie ``ruby -r''.
--inspect Benutze ``inspect'' für den Output (Defaulteinstellung, außer im mathematischen Modus).
--noinspect Benutze nicht inspect für den Output.
--readline Benutze das Readline-Erweiterungs-Modul.
--noreadline Benutze nicht das Readline-Erweiterungs-Modul.
--promptprompt-mode Schalte den Pompt-Modus um. Vordefinierte Prompt-Modi sind ``default'', ``simple'', ``xmp'' und ``inf-ruby''.
--prompt-modeprompt-mode Dasselbe wie --prompt.
--inf-ruby-mode Stellt irb so ein, dass es im inf-ruby-mode-Modus unter Emacs läuft. Ändert den Prompt und unterdrückt --readline.
--simple-prompt Einfacher Prompt-Modus.
--noprompt Zeige keinen Prompt an.
--tracer Zeige den Trace bei der Ausführung von Kommandos an.
--back-trace-limit n Zeige Backtrace-Informationen an, benutze dabei die ersten n und die letzten n Einträge. Der Default-Wert ist 16.
--irb_debug n Setze den internen Debug-Level auf n (nur zur irb-Entwicklung).
-v, --version Zeige die Version von irb.

Initialisierungs-Datei

irb benutzt eine Initialisierungs-Datei, in der man oft benutzte Optionen setzen und eventuell benötigte Ruby-Anweisungen ausführen kann. Wenn irb gestartet wird, sucht es die Initialisierungs-Datei von folgenden Orten in dieser Reihenfolge: ~/.irbrc, .irbrc, irb.rc, _irbrc und $irbrc.

Innerhalb der Initialisierungs-Datei kann man jeglichen Ruby-Code laufen lassen. Man kann desweiteren jeden Konfigurierungs-Wert setzen, der in Tabelle B.2 auf Seite 524 angegeben ist.
irb Konfigurierung-Werte

IRB.conf[:IRB_NAME] = "irb" IRB.conf[:MATH_MODE] = false
IRB.conf[:USE_TRACER] = false IRB.conf[:USE_LOADER] = false
IRB.conf[:IGNORE_SIGINT] = true IRB.conf[:IGNORE_EOF] = false
IRB.conf[:INSPECT_MODE] = nil IRB.conf[:IRB_RC] = nil
IRB.conf[:BACK_TRACE_LIMIT] = 16 IRB.conf[:USE_LOADER] = false
IRB.conf[:USE_READLINE] = nil IRB.conf[:USE_TRACER] = false
IRB.conf[:IGNORE_SIGINT] = true IRB.conf[:IGNORE_EOF] = false
IRB.conf[:PROMPT_MODE] = :DEFAULT IRB.conf[:PROMPT] = { ... }
IRB.conf[:DEBUG_LEVEL] = 0 IRB.conf[:VERBOSE] = true

Ein interessatner Kniff bei der Konfigurierung von irb ist, IRB.conf[:IRB_RC] auf ein Proc-Objekt zu setzen. Dann wird diese Prozedur jedes Mal aufgerufen, wenn der irb-Kontext sich ändert und bekommt den neuen Kontext als Parametr mit. Man kann das nutzen, um die Konfiguration abhängig vom Kontext dynamisch zu ändern.

Kommandos

Am irb-Prompt kann man jeden gültigen Ruby-Ausdruck eingeben und sieht das Ergebnis. Außerdem kann man mit einem der folgenden Kommandos die irb-Session kontrollieren.

exit, quit, irb_exit
Beendet die irb-Session oder die Unter-Session. Wenn man mit cb die Bindungen verändert hat (siehe unten), wird dieser Bindungs-Modus verlassen.

conf, irb_context
Zeigt die aktuelle Konfiguration an. Verändern der Konfiguration kann man mit dem Aufruf von Methoden von conf bewirken.

conf.back_trace_limit n
Setzt die angezeigten Zeilen für Backtrace auf die ersten n und die letzen n. Der Default-Wert ist 16.

conf.debug_level = N
Setzt den Debug-Level von irb.

conf.ignore_eof = true/false
Gibt das Verhalten an, falls ein end-of-file vom Input empfangen wird. Bei true wird es ignoriert, ansonsten wird irb beendet.

conf.ignore_sigint= true/false
Gibt das Verhalten für ^C (Control-C) an. Bei false erzwingt ^C das Verlassen von irb. Bei true erzwingt ^C während der Eingabe den Abbruch der Eingabe und die Rückkehr auf den Top-Level; während der Ausführung den Abbruch der aktuellen Operation.

conf.inf_ruby_mode = true/false
Falls true, ändert den Prompt und schaltet den Readline-Support aus, womit Ruby im inf-ruby-mode arbeiten kann . [Im inf-ruby-mode kann man im Emacs beim Editieren mit Ruby interagieren. Siehe die Datei inf_ruby.el im misc-Verzeichnis der Distribution.] Der Default-Wert ist false.

conf.inspect_mode = true/false/nil
Gigbt den Inspect-Modus an nach den folgenden Werten:

true Zeige Inspect an (default).
false Zeige to_s an.
nil Inspect-Modus für Nicht-Math-Modus, Nicht-Inspect-Modus für Math-Modus.

conf.irb_level
Zeigt den aktuellen Level der Bindung an (siehe cb).

conf.math_mode
Zeigt an, ob Ruby im Math-Modus ist oder nicht.

conf.use_loader = true/false
Gibt an, ob irb's eigene Datei-Lese-Methode benutzt wird bei load/require.

conf.prompt_c
Der Prompt für eine zu ergänzende Anweisung (zum Beispiel direkt nach einem ``if'').

conf.prompt_i
Der Standard-, Top-Level-Prompt.

conf.prompt_s
Der Prompt für einen zu ergänzenden String.

conf.rc = true/false
Gibt an, ob die Initialisierungs-Datei ~/.irbrc benutzt werden soll.

conf.use_prompt = true/false
gibt an, ob Prompts angezeigt werden sollen.

conf.use_readline = true/false/nil
Gibt an, ob Readline benutzt werden soll nach den folgenden Werten:

true Benutze Readline.
false Benutze Readline nicht.
nil Benuzte Readline außer im inf-ruby-mode (default).

conf.verbose=true/false
Gibt an, ob ausführliche Meldungen gezeigt werden sollen.

cb, irb_change_binding [obj]
Erzeugt und benutzt eine neue Bindung, die ihren eigenen Bereich für lokale Variablen hat. Falls obj angegeben ist, wird es als self in der neuen Bindung benutzt.

irb [obj]
Startet eine irb-Unter-Session. Falls obj agegeben ist, wird es als self benutzt.

jobs, irb_jobs
Zeigt alle irb-Unter-Sessions an.

fg n, irb_fg n
Schaltet um in die angegebene irb-Unter-Session. n darf einer der folgenden Werte sein:

irb-Unter-Session-Nummer
thread id
irb-Objekt
self (das obj, das eine spezeille Unter-Session gestartet hat)

kill n, irb_kill n
Killt eine irb-Unter-Session. n darf einer der für irb_fg beschriebenen Werte sein.

Den Prompt konfigurieren

Es gibt eine große Fexibilität bei der Gestaltung der Prompts, die irb benutzt. Eine Anzahl von Prompts wird im Prompt-Hash gehalten:

IRB.conf[:PROMPT]

Will man etwa einen neuen Prompt-Modus namens ``MY_PROMPT'' einführen, so sollte man folgendes eingeben (entweder am irb-Prompt oder in der Datei .irbrc):

IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
  :PROMPT_I => "...",             # normal prompt
  :PROMPT_S => "...",             # prompt for continuing strings
  :PROMPT_C => "...",             # prompt for continuing statement
  :RETURN => "    ==>%s\n"        # format to return value
}

Danach ruft man irb in diesem Prompt-Modus auf mit

% irb --prompt my-prompt

Oder man setzt den folgenden Konfigurations-Wert:

IRB.conf[:PROMPT_MODE] = :MY_PROMPT

Die Konstanten PROMPT_I, PROMPT_S und PROMPT_C geben das Format für jeden dieser Prompt-Strings an. Innerhalb des Prompt-Formats kann es die folgenden Flags geben, die den angegebenen Text erzeugen:

Flag Beschreibung
%N Aktuelles Komando.
%m to_s des Haupt-Objekts (self).
%M inspect des Haupt-Objekts (self).
%l Begrenzungs-Zeichen. In Strings, die über eine Zeile hinausgehen, zeigt %l den Typ des Begrenzers am Anfang des Strings an, damit man weiß, wie man ihn beenden soll. Der Begrenzer ist einer von ", ', /, ] oder `.
%ni Level der Einrückung. Die optionale Zahl n gibt die Breite für printf an, wie beiprintf("%nd").
%nn Aktuelle Zeilen-Nummer (n wie beim Level der Einrückung).
%% Ein literales Prozent-Zeichen.

Zum Beispiel ist der Default-Modus für den Prompt folgendermaßen definiert:

IRB.conf[:PROMPT_MODE][:DEFAULT] = {
      :PROMPT_I => "%N(%m):%03n:%i> ",
      :PROMPT_S => "%N(%m):%03n:%i%l ",
      :PROMPT_C => "%N(%m):%03n:%i* ",
      :RETURN => "%s\n"
}

Beschränkungen

Durch die Art, wie irb arbeitet, gibt es kleinere Inkompatibilitäten zwischen irb und dem Standard-Ruby-Interpreter. Das Problem liegt in der Bestimmung der lokalen Variablen.

Normalerweise sucht Ruby nach einer Zuweisung, um zu bestimmen, ob etwas eine Variable ist --- wenn einem Namen nichts zugewiesen wurde, nimmt Ruby an, dass das ein Methodenaufruf ist.

eval "a = 0"
a
erzeugt:
prog.rb:2: undefined local variable or method `a'
for #<Object:0x4019ac90> (NameError)

In diesem Fall ist die Zuweisung zwar vorhanden, aber innerhalb eines Strings, so dass Ruby sie nicht beachtet.

Andererseits führt irb die Anweisung aus, sowie sie auftaucht.

  irb(main):001:0> eval "a = 0"
  0
  irb(main):002:0> a
  0

In irb wurde die Zuweisung ausgeführt, bevor die zweite Zeile betrachtet wird, deshalb wird ``a'' zutreffend als lokale Variable erkannt.

Wenn man das Ruby-Verhalten genauer abbilden will, kann man diese Anweisungen in ein begin/end-Paar setzen.

  irb(main):001:0> begin
  irb(main):002:1*   eval "a = 0"
  irb(main):003:1>   a
  irb(main):004:1> end
  NameError: undefined local variable or method `a'
  (irb):3:in `irb_binding'

rtags, xmp nd die Frame-Klasse

Die Basis-Version von irb wird zusammen mit Ruby selber installiert. Es gibt aber eine erweiterte Version von irb in den Archiven, die ein paar Extra-Eigenschaften besitzt und erwähnt werden sollte.

rtags

rtags ist ein Kommando, mit dem eine TAGS-Datei für entweder den emacs- oder den vi-Editor erzeugt werden kann.

rtags [-vi][files]...

Dafautlmäßig wird eine TAGS-Datei passend für den emacs erzeugt (siehe etags.el). Die -vi-Option erzeugt eine TAGS-Datei für den vi.

rtags muss genauso installiert werden wie irb (das heißt, man muss irb im Bibliotheks-Pfad installieren und einen Link von irb/rtags.rb nach bin/rtags setzen).

xmp

irb's xmp ist ein ``Beispiel-Drucker'' --- das heißt ein Pretty-Printer, der den Wert jedes Ausdrucks während der Ausführung anzeigt (so ähnlich wie das Script, das wir geschrieben haben, um die Beispiele in diesem Buch zu formatieren). Es gibt auch einen anderen allein einsetzbaren xmp in den Archiven.

xmp kann folgendermaßen benutzt werden:

require "irb/xmp"

xmp <<END artist = "Doc Severinsen" artist END
erzeugt:
artist = "Doc Severinsen"
    ==>"Doc Severinsen"
artist
    ==>"Doc Severinsen"

Es kann auch als Objekt-Instanz benutzt werden. Dann behält das Objekt den Kontext auch zwischen den Aufrufen:

require "irb/xmp"

x = XMP.new x.puts <<END artist = "Louis Prima" END

x.puts <<END artist END
erzeugt:
artist = "Louis Prima"
    ==>"Louis Prima"
artist
    ==>"Louis Prima"

Man kann eine Bindung explizit angeben; ansonsten benutzt xmp die Umgebung des Aufrufers.

xmp code_string, abinding
XMP.new(abinding)

Beachte, dass xmp beim Multi-Threading nicht funktiniert.

Die Klasse Frame

Die IRB::Frame-Klasse repräsentiert den Stack des Interpreters und erlaubt den einfachen Zugriff auf die effektive Bindungs-Umgebung auf verschiedenen Stack-Leveln.

IRB::Frame.top(n = 0) Liefert ein Binding für den n-ten Kontext von oben. Der 0-te Kontext ist der oberste, zuletzt benutzte Frame.
IRB::Frame.bottom(n = 0) Liefert ein Binding für den n-ten Kontext von unten. Der 0-te Kontext ist der unterste, ursprünglich Frame.
IRB::Frame.sender Liefert das Objekt (den Absender), das die aktuelle Methode aufgerufen hat.

Man kann diese Fähigkeiten zum Beispiel nutzen, um die lokalen Variablen der Methode zu untersuchen, von der die aktuelle Methode aufgerufen wurde:

require 'irb/frame'

def outie   b = IRB::Frame.top(1)   eval "p my_local", b end

def innie   my_local = 102.7   outie end

innie
erzeugt:
102.7

Beachte, dass das nicht in Multi-Thread-Programmen funktioniert.


Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Übersetzung: Jürgen Katins
Für das englische Original:
© 2000 Addison Wesley Longman, Inc. Released under the terms of the Open Publication License V1.0. That reference is available for download.
Diese Lizenz sowie das Original vom Herbst 2001 bilden die Grundlage der Übersetzung
Es wird darauf hingewiesen, dass sich die Lizenz des englischen Originals inzwischen geändert hat.
Für die deutsche Übersetzung:
© 2002 Jürgen Katins
Der Copyright-Eigner stellt folgende Lizenzen zur Verfügung:
Nicht-freie Lizenz:
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/). Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.
Freie Lizenz:
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".