mirror of
https://github.com/ganelson/inform.git
synced 2024-07-18 06:54:26 +03:00
203 lines
7.3 KiB
OpenEdge ABL
203 lines
7.3 KiB
OpenEdge ABL
[InterpretIndex::] Index Interpreter.
|
|
|
|
An index is generated by interpreting an index structure file.
|
|
|
|
@ The index is generated by a bare-bones structure file. These are identified
|
|
by name: in particular |Basic| is the barer version, for Basic Inform projects,
|
|
while |Standard| is the index as generated to suit typical IF uses of the Standard
|
|
Rules -- so, in other words, that's the index which most Inform users know.
|
|
These names have to correspond to |.indext| structure files stored in the
|
|
Inform distribution.
|
|
|
|
The structure file really just shows which index elements to include on which
|
|
pages. For example:
|
|
= (text)
|
|
page Kinds e9cf08
|
|
element Ch
|
|
element Ar
|
|
element Vl
|
|
=
|
|
declares a new index page with leafname |Kinds.html|, and with the highlight
|
|
colour (in CSS hexadecimal style) |e9cf08|; and then declzres that it contains
|
|
the three elements |Ch|, |Ar| and |Vl|, in that order. Note that this file does
|
|
not contain any user-facing text: all of that comes from //html: Localisation//.
|
|
|
|
The file also doesn't contain instructions for what goes into those elements.
|
|
All of that is hardwired into this module's code: for example, |Ar| is generated
|
|
by the function //ArithmeticElement::render// in //Arithmetic Element//.
|
|
|
|
The method here is basically to read all the declarations, generating a set
|
|
of //index_page// and //index_element// objects to represent them, and only to
|
|
begin writing some HTML when this scanning is done, i.e., when the whole structure
|
|
file has been read.
|
|
|
|
=
|
|
void InterpretIndex::generate(text_stream *structure, index_session *session) {
|
|
localisation_dictionary *D = Indexing::get_localisation(session);
|
|
Indexing::empty_list_of_pages(session);
|
|
filename *index_structure = InstalledFiles::index_structure_file(structure);
|
|
@<Read the structure file line by line@>;
|
|
@<Actually generate the index files@>;
|
|
}
|
|
|
|
@<Read the structure file line by line@> =
|
|
TextFiles::read(index_structure, FALSE, "unable to read index structure file", TRUE,
|
|
&InterpretIndex::read_structure, NULL, (void *) session);
|
|
|
|
@ |contents| is currently implemented identically to |pages|, but it is supposed to
|
|
represent the home page of the index. The declaration for it should come
|
|
last in the structure file, like so:
|
|
= (text)
|
|
contents Welcome 111111
|
|
=
|
|
It has no elements, because its only content will be a menu of links to the other
|
|
pages.
|
|
|
|
=
|
|
void InterpretIndex::read_structure(text_stream *text, text_file_position *tfp, void *state) {
|
|
index_session *session = (index_session *) state;
|
|
localisation_dictionary *D = Indexing::get_localisation(session);
|
|
match_results mr = Regexp::create_mr();
|
|
if (Regexp::match(&mr, text, L"page (%C+) (%C+)")) {
|
|
@<Register a new index page@>;
|
|
} else if (Regexp::match(&mr, text, L"contents (%C+) (%C+)")) {
|
|
@<Register a new index page@>;
|
|
} else if (Regexp::match(&mr, text, L"element (%C+)")) {
|
|
@<Register a new index element@>;
|
|
}
|
|
Regexp::dispose_of(&mr);
|
|
}
|
|
|
|
@ Note that the heading written on |Kinds.html|, say, is drawn from the
|
|
localisation file under the key |%Title| in the context |%%Kinds|. In English,
|
|
that will be "Kinds", but if the index is being generated with a Dutch localisation
|
|
dictionary then perhaps it would be "Soorten". Under the hood, though, the filename
|
|
will be |Kinds.html| either way.
|
|
|
|
@<Register a new index page@> =
|
|
text_stream *col = mr.exp[1];
|
|
text_stream *key = mr.exp[0];
|
|
TEMPORARY_TEXT(path)
|
|
WRITE_TO(path, "Index.Pages.%S.Title", key);
|
|
text_stream *heading = Localisation::read(D, path);
|
|
Str::clear(path);
|
|
WRITE_TO(path, "Index.Pages.%S.Caption", key);
|
|
text_stream *explanation = Localisation::read(D, path);
|
|
DISCARD_TEXT(path)
|
|
InterpretIndex::register_page(col, heading, explanation, key, session);
|
|
|
|
@<Register a new index element@> =
|
|
index_page *latest = Indexing::latest_page(session);
|
|
if (latest == NULL) internal_error("element without page");
|
|
text_stream *elt = mr.exp[0];
|
|
TEMPORARY_TEXT(tkey)
|
|
TEMPORARY_TEXT(hkey)
|
|
WRITE_TO(tkey, "Index.Elements.%S.Title", elt);
|
|
WRITE_TO(hkey, "Index.Elements.%S.Heading", elt);
|
|
InterpretIndex::register_element(elt, latest, Localisation::read(D, tkey), hkey);
|
|
DISCARD_TEXT(tkey)
|
|
DISCARD_TEXT(hkey)
|
|
|
|
@<Actually generate the index files@> =
|
|
index_page *page;
|
|
linked_list *L = Indexing::get_list_of_pages(session);
|
|
LOOP_OVER_LINKED_LIST(page, index_page, L) {
|
|
TEMPORARY_TEXT(leafname)
|
|
WRITE_TO(leafname, "%S.html", page->page_leafname);
|
|
TEMPORARY_TEXT(key)
|
|
WRITE_TO(key, "Index.Pages.%S.Title", page->page_leafname);
|
|
text_stream index_file_struct; text_stream *OUT = &index_file_struct;
|
|
InterpretIndex::open_file(OUT, page, leafname, Localisation::read(D, key),
|
|
-1, session);
|
|
Elements::periodic_table(OUT, page, leafname, session);
|
|
InterpretIndex::close_index_file(OUT);
|
|
DISCARD_TEXT(key)
|
|
DISCARD_TEXT(leafname)
|
|
}
|
|
GroupedElement::detail_pages(session);
|
|
|
|
@h Registering.
|
|
So, then, here are the objects representing the index pages and their elements
|
|
of content:
|
|
|
|
=
|
|
typedef struct index_page {
|
|
int no_elements;
|
|
struct text_stream *key_colour;
|
|
struct text_stream *page_title;
|
|
struct text_stream *page_explanation;
|
|
struct text_stream *page_leafname;
|
|
struct linked_list *elements; /* of |index_element| */
|
|
struct index_session *for_session;
|
|
CLASS_DEFINITION
|
|
} index_page;
|
|
|
|
index_page *InterpretIndex::register_page(text_stream *col, text_stream *title,
|
|
text_stream *exp, text_stream *leaf, index_session *session) {
|
|
index_page *new_page = CREATE(index_page);
|
|
new_page->no_elements = 0;
|
|
new_page->key_colour = Str::duplicate(col);
|
|
new_page->page_title = Str::duplicate(title);
|
|
new_page->page_explanation = Str::duplicate(exp);
|
|
new_page->page_leafname = Str::duplicate(leaf);
|
|
new_page->elements = NEW_LINKED_LIST(index_element);
|
|
new_page->for_session = session;
|
|
Indexing::add_page(session, new_page);
|
|
return new_page;
|
|
}
|
|
|
|
@ =
|
|
typedef struct index_element {
|
|
int atomic_number; /* 1, 2, 3, ..., within its page */
|
|
struct text_stream *chemical_symbol;
|
|
struct text_stream *element_name;
|
|
struct text_stream *explanation_key;
|
|
struct index_page *owning_page;
|
|
CLASS_DEFINITION
|
|
} index_element;
|
|
|
|
index_element *InterpretIndex::register_element(text_stream *abb, index_page *owner,
|
|
text_stream *title, text_stream *explanation) {
|
|
if (owner == NULL)
|
|
internal_error("template creates index elements improperly");
|
|
if (Str::len(abb) > 2)
|
|
internal_error("abbreviation for index element too long");
|
|
index_element *ie = CREATE(index_element);
|
|
ie->owning_page = owner;
|
|
ie->atomic_number = ++(owner->no_elements);
|
|
ie->chemical_symbol = Str::duplicate(abb);
|
|
ie->element_name = Str::duplicate(title);
|
|
ie->explanation_key = Str::duplicate(explanation);
|
|
ADD_TO_LINKED_LIST(ie, index_element, owner->elements);
|
|
return ie;
|
|
}
|
|
|
|
@h Opening and closing HTML files.
|
|
|
|
=
|
|
text_stream *InterpretIndex::open_file(text_stream *IF,
|
|
index_page *page, text_stream *index_leaf,
|
|
text_stream *title, int sub, index_session *session) {
|
|
filename *F = IndexLocations::filename(index_leaf, sub);
|
|
if (STREAM_OPEN_TO_FILE(IF, F, UTF8_ENC) == FALSE) {
|
|
#ifdef CORE_MODULE
|
|
Problems::fatal_on_file("Can't open index file", F);
|
|
#endif
|
|
#ifndef CORE_MODULE
|
|
Errors::fatal_with_file("can't open index file", F);
|
|
#endif
|
|
}
|
|
HTML::header(IF, title,
|
|
InstalledFiles::filename(CSS_FOR_STANDARD_PAGES_IRES),
|
|
InstalledFiles::filename(JAVASCRIPT_FOR_STANDARD_PAGES_IRES),
|
|
(void *) page);
|
|
IndexUtilities::clear_page_data(session);
|
|
return IF;
|
|
}
|
|
|
|
@ =
|
|
void InterpretIndex::close_index_file(text_stream *ifl) {
|
|
HTML::footer(ifl);
|
|
STREAM_CLOSE(ifl);
|
|
}
|