How the parent tool can ask for an Inter tree to be indexed.
§1. Public API. This is a large and complex module of code, but it really only does one thing, and so it is simple to control. Other modules or tools should do this only by calling the functions below.
To produce one or more index products (see below), first open a session; then set its localisation — essentially, choose what language it should be written in; then call functions to make the actual products; and finally close the session. Note that:
- (1) If you want to index the same tree of code to two different languages, you will need to do this as two sessions. However, an Index website and an EPS map which are in the same language can both be made in the same session, and this is more efficient than using two.
- (2) The index module probably works fine if multiple sessions are open at once (and indeed is probably threadsafe), but it hasn't been tested for that or written with that in mind: a safer way to make multiple indexes simultaneously is probably to run multiple independent inter processes, each making one index.
index_session *Indexing::open_session(inter_tree *I) { return Indexing::new_session(I); }
§3. Now localising. You can either set an existing dictionary which you happen to have to hand, or else ask to read definitions from a file. See Localisation (in html) for how all of this works.
void Indexing::set_localisation_dictionary(index_session *session, localisation_dictionary *LD) { Check this is an open session3.5; session->localisation = LD; } void Indexing::localise(index_session *session, filename *F) { Check this is an open session3.5; Localisation::stock_from_file(F, session->localisation); }
§3.1. Now for the productive part. You can make an entire index mini-website with the following function, which may generate several hundred HTML files. This is what is used in the Inform GUI apps on every compilation.
void Indexing::generate_index_website(index_session *session, text_stream *structure) { Check this is an open session3.5; InterpretIndex::generate(structure, session); }
§3.2. This is a one-off function for generating the content of an index element (without its heading, or any HTML surround): it's used for unit-testing those elements, but is never used by the Inform GUI app.
void Indexing::generate_one_element(index_session *session, text_stream *OUT, wording elt) { Check this is an open session3.5; Elements::test_card(OUT, elt, session); }
§3.3. This is used by the Inform GUI apps to "release along with an EPS file". Essentially it makes a print-suitable version of the Map element of the index, though there are also many bells and whistles for customising the appearance of this. This is written to the stream F_alt if that is non-null, and otherwise into a text file at F (which is created in the process).
void Indexing::generate_EPS_map(index_session *session, filename *F, text_stream *F_alt) { Check this is an open session3.5; RenderEPSMap::render_map_as_EPS(F, F_alt, session); }
§3.4. And lastly closing. The only thing this now does is to enable a new session to be opened afterwards, in fact, but that might change in future.
void Indexing::close_session(index_session *session) { Check this is an open session3.5; session->session_closed = TRUE; }
§3.5. Check this is an open session3.5 =
if (session == NULL) internal_error("no indexing session"); if (session->session_closed) internal_error("closed indexing session");
- This code is used in §3 (twice), §3.1, §3.2, §3.3, §3.4, §6 (three times), §7 (8 times), §8 (three times).
§4. Sessions. This is a miscellany, plain and simple, but it contains all of the workspace and caches needed to index an Inter tree.
typedef struct index_session { struct inter_tree *tree; struct tree_inventory *inv; struct inter_lexicon *lexicon; struct faux_instance_set *set_of_instances; struct linked_list *list_of_scenes; of simplified_scene struct localisation_dictionary *localisation; struct linked_list *list_of_EPS_map_levels; of EPS_map_level struct linked_list *list_of_submaps; of connected_submap struct linked_list *list_of_pages; of index_page struct map_parameter_scope global_map_scope; int changed_global_room_colour; struct index_page_data page; struct map_calculation_data calc; int story_dir_to_page_dir[MAX_DIRECTIONS]; int session_closed; CLASS_DEFINITION } index_session;
- The structure index_session is accessed in 1/is, 2/iu, 2/fi, 2/fs, 4/mc, 4/sm, 4/rhm, 4/rem and here.
index_session *Indexing::new_session(inter_tree *I) { if (I == NULL) internal_error("no tree to index"); index_session *session = CREATE(index_session); session->tree = I; session->inv = MakeSynopticModuleStage::take_inventory(I); session->lexicon = NULL; session->set_of_instances = NULL; session->list_of_scenes = NULL; session->list_of_EPS_map_levels = NEW_LINKED_LIST(EPS_map_level); session->list_of_submaps = NEW_LINKED_LIST(connected_submap); session->list_of_pages = NEW_LINKED_LIST(index_page); session->localisation = Localisation::new(); session->global_map_scope = ConfigureIndexMap::global_settings(); session->changed_global_room_colour = FALSE; session->calc = SpatialMap::fresh_data(); session->session_closed = FALSE; for (int i=0; i<MAX_DIRECTIONS; i++) session->story_dir_to_page_dir[i] = i; return session; }
§6. Private API. The remaining functions in this section are for use only within the index module.
inter_tree *Indexing::get_tree(index_session *session) { Check this is an open session3.5; return session->tree; } localisation_dictionary *Indexing::get_localisation(index_session *session) { Check this is an open session3.5; return session->localisation; } tree_inventory *Indexing::get_inventory(index_session *session) { Check this is an open session3.5; return session->inv; } map_parameter_scope *Indexing::get_global_map_scope(index_session *session) { return &(session->global_map_scope); }
linked_list *Indexing::get_list_of_EPS_map_levels(index_session *session) { Check this is an open session3.5; return session->list_of_EPS_map_levels; } void Indexing::add_EPS_map_levels(index_session *session, EPS_map_level *eml) { Check this is an open session3.5; ADD_TO_LINKED_LIST(eml, EPS_map_level, session->list_of_EPS_map_levels); } linked_list *Indexing::get_list_of_submaps(index_session *session) { Check this is an open session3.5; return session->list_of_submaps; } void Indexing::add_submap(index_session *session, connected_submap *sub) { Check this is an open session3.5; ADD_TO_LINKED_LIST(sub, connected_submap, session->list_of_submaps); } void Indexing::empty_list_of_pages(index_session *session) { Check this is an open session3.5; LinkedLists::empty(session->list_of_pages); } linked_list *Indexing::get_list_of_pages(index_session *session) { Check this is an open session3.5; return session->list_of_pages; } void Indexing::add_page(index_session *session, index_page *page) { Check this is an open session3.5; ADD_TO_LINKED_LIST(page, index_page, session->list_of_pages); } index_page *Indexing::latest_page(index_session *session) { Check this is an open session3.5; if (LinkedLists::len(session->list_of_pages) == 0) return NULL; return LAST_IN_LINKED_LIST(index_page, session->list_of_pages); }
§8. These more substantial resources are calculated all in one go, but only on demand:
inter_lexicon *Indexing::get_lexicon(index_session *session) { Check this is an open session3.5; if (session->lexicon == NULL) session->lexicon = IndexLexicon::stock(session->tree, session->inv); return session->lexicon; } faux_instance_set *Indexing::get_set_of_instances(index_session *session) { Check this is an open session3.5; if (session->set_of_instances == NULL) FauxInstances::make_faux(session); return session->set_of_instances; } linked_list *Indexing::get_list_of_scenes(index_session *session) { Check this is an open session3.5; if (session->list_of_scenes == NULL) FauxScenes::list_of_faux_scenes(session); return session->list_of_scenes; }