Indexer für Apple Guide

Das Problem

Die Sprache zur Spezifikation von Apple Guides hat einige unschöne Eigenschaften, die einem das Leben unnötig schwer machen. Wenn man z.B. auf seine Hilfeseiten über einen Index zugreifen möchte, so muß man große Teile der Zugriffsstruktur doppelt schreiben. Die doppelte Pflege von Informationen führt aber fast immer irgendwann einmal dazu, daß etwas vergessen wird. Deshalb stelle ich hier einen halbautomatischen Weg vor, die Indexstruktur für ein Apple Guide Dokument zu erzeugen:

Der Zugriff über Themen

Der Zugriff auf eine Hilfeseite (oder Hilfeseitensequenz) wird in Apple Guide folgendermassen definiert:

<Topic Area> "mein Themenbereich"
    <Header> "Wie"
        <Topic> "erstelle ich mein Lieblingsobjekt?" , "SequenceLieblingsobjekt"
        <Topic> "erstelle ich Zonenreferenzen?",...
    <Header> "Warum"
         ......
<Topic Area> "nächster Bereich"

An anderer Stelle ist dann die Hilfeseitensequenz mit den Namen "SequenceLieblingsobjekt" definiert.

Der Zugriff über Indexe

ist nun für jedes Indexwort folgendermassen definiert:

<Index> "Lieblingsobjekt"
    <Header> "Wie"
         <Topic> "erstelle ich mein Lieblingsobjekt?", "SequenceLieblingsobjekt"
         <Topic> ....
    <Header> "Warum"
         ...
<Index> "Zonenrefernzen"
    <Header> "Wie"
        <Topic> "erstelle ich Zonenreferenzen?",...

Wie man sieht, ist das Erstellen des Indexes mit Arbeit verbunden, die zum größten Teil aus stupiden aber fehlerträchtigen Copy&Paste besteht. Das schreit gerade zu nach Computerunterstützung.

Die veränderte Spezifikation

Ich definiere die Indizes in der Definition der Themenbereiche und lasse dann die Indexspezifikation von einen Perl Skript erzeugen:

<Topic Area> "mein Themenbereich"
    <Header> "Wie"
        <Topic> "erstelle ich mein Lieblingsobjekt?" , "SequenceLieblingsobjekt"
			       #<Index> "Lieblingsobjekt"
			       #<Index> "Generierung"
			       #<Index> "..."
        <Topic> "..."
	

Warum Perl ?

Das Problem ist komplexer als es auf den ersten Blick scheint: Ein Indexeintrag kann in verschiedenen Topicareas mit verschiedenen Headern definiert werden, zu jeden Indexeintrag müssen wir uns Topic und Sequence merken, und alles muss zum Schluss in der richtigen Reihenfolge ausgegeben werden. Hätte ich dieses in C schreiben sollen, hätte ich vermutlich das Ergebnis ist den Aufwand nicht wert. In Perl werde ich für solche Aufgaben dagegen fast optimal unterstützt:

Das Perl Program

Die Eingabezeilen werden zunächst analysiert und es wird eine Struktur aufgebaut, deren oberster Zugriffspunkt die Variable %TopicOfIndex ist. Die Struktur sieht folgendermassen aus:

Lieblingsobjekt
Headerzeile Topiczeile Topiczeile Headerzeile Topiczeile
Zonenreferenz
Headerzeile Topiczeile Topiczeile ...
... ...

Ein Problem liegt darin, das die Werte des Hashes jeweils Listen sind, man muss deshalb mit Referenzen hantieren, wobei man aufpassen muß, das man die Syntax wirklich richtig hinkriegt.

 

#!/usr/local/bin/perl
# Apple Guide source file indexer
# extracting indexlines from Apple Guide source files
#------------------------------------------------
# Configuration
$InputFile			= "Topics.src";
$ResultFile 		= "result.src";
$currentHeader;
$currentTopic;	
%TopicOfIndex;		# Hash with stores Indices with Topic Infos
#%sumarize;
#------------------------------------------------

&analyse($InputFile);
&writeOut("-");				# stdout, can be changed to ResultFile
MacPerl::Answer("Fertig");
#---------------------------------
sub analyse{
	my($filepath) = @_;
 	open(SPEC, $filepath) || print "can't open spec file $filepath\n";
	while(){
	  s/[ \t]*$//g;				# kill trailing spaces
	  &analyseHeader($1) 	   if /^[ \t]*\[ \t]*(.*)$/;
	  &analyseHeader($1) 	   if /^[ \t]*\[ \t]*(.*)$/;
	  &analyseTopic($1)		   if /^[ \t]*\[ \t]*(.*)$/;
      &analyseIndex($1) 	   if /^[ \t]*\#[ \t]*(.*)$/;
	}
	close(SPEC);
}
#--------------------------------------
# if we got Header entry: remeber it
sub analyseHeader{
	my($Line) = @_;
	$currentHeader = "
$Line"; } #--------------------------------- # if we got Topic entry: remeber it sub analyseTopic{ my($Line) = @_; $currentTopic = "\t $Line"; } #--------------------------------- # if we got Index entry: # stored it with the last header and # Topic Entry in the Hash %TopicOfIndex sub analyseIndex{ my($Line) = @_; # if no entry for this index yet: make empty list if( !$TopicOfIndex{$Line}){ $TopicOfIndex{$Line} = [ ]; #Refenenz to empty List } # if this header not element yet: store it # $TopicOfIndex{$Line} is normaly a scalar, # must be dereferneced with @{...} # BUGBUG: same Header may come in several occurences # (Topicareas), we are not handling this case correct if( ! grep(/$currentHeader/, @{ $TopicOfIndex{$Line} } ) ){ push ( @{ $TopicOfIndex{$Line} }, $currentHeader); } # store Topic with Index push ( @{ $TopicOfIndex{$Line} }, $currentTopic); } #--------------------------------------------------------- # write out Index Entry # followed by header and topics for this index sub writeOut { local ($filepath)=@_; open(RESULT, ">$filepath") || print "can't open spec file $filepath\n"; foreach $key (sort keys %TopicOfIndex){ print " $key\n"; foreach $entry ( @{$TopicOfIndex{$key}}){ print "\t" . $entry . "\n"; } } close RESULT; }#endsub writeOut

 


		
		
home 
- contact
- q-zone
- dev-zone
Copyright © 1997 by Karsten Meier. All Rights reserved.