building the site feature list page

This commit is contained in:
Allen Webster 2016-11-22 13:26:58 -05:00
parent 8ff329ede7
commit 1049acbacc
6 changed files with 353 additions and 196 deletions

View File

@ -188,8 +188,7 @@ restore_state(Application_Links *app, App_Coroutine_State state){
} }
inline Coroutine* inline Coroutine*
app_launch_coroutine(System_Functions *system, Application_Links *app, Coroutine_Type type, app_launch_coroutine(System_Functions *system, Application_Links *app, Coroutine_Type type, Coroutine *co, void *in, void *out){
Coroutine *co, void *in, void *out){
Coroutine* result = 0; Coroutine* result = 0;
App_Coroutine_State prev_state = get_state(app); App_Coroutine_State prev_state = get_state(app);
@ -203,8 +202,7 @@ app_launch_coroutine(System_Functions *system, Application_Links *app, Coroutine
} }
inline Coroutine* inline Coroutine*
app_resume_coroutine(System_Functions *system, Application_Links *app, Coroutine_Type type, app_resume_coroutine(System_Functions *system, Application_Links *app, Coroutine_Type type, Coroutine *co, void *in, void *out){
Coroutine *co, void *in, void *out){
Coroutine* result = 0; Coroutine* result = 0;
App_Coroutine_State prev_state = get_state(app); App_Coroutine_State prev_state = get_state(app);

View File

@ -935,7 +935,7 @@ site_build(char *cdir, uint32_t flags){
linux_popd(temp); linux_popd(temp);
#endif #endif
END_TIME_SECTION("run metagen"); END_TIME_SECTION("run sitegen");
} }
} }

View File

@ -90,6 +90,7 @@ static Document_Item null_document_item = {0};
struct Abstract_Document{ struct Abstract_Document{
// Document value members // Document value members
Document_Item *root_item; Document_Item *root_item;
char *name;
// Document building members // Document building members
Partition *part; Partition *part;
@ -127,6 +128,11 @@ begin_document_description(Abstract_Document *doc, Partition *part, char *title)
set_section_name(doc->part, doc->root_item, title); set_section_name(doc->part, doc->root_item, title);
} }
static void
set_document_name(Abstract_Document *doc, char *name){
doc->name = name;
}
static void static void
end_document_description(Abstract_Document *doc){ end_document_description(Abstract_Document *doc){
Assert(doc->section_top == 0); Assert(doc->section_top == 0);
@ -296,10 +302,10 @@ struct Section_Counter{
}; };
static void static void
append_section_number_reduced(String *out, Section_Counter section_counter, int32_t reduce){ append_section_number_reduced(String *out, Section_Counter *section_counter, int32_t reduce){
int32_t level = section_counter.nest_level-reduce; int32_t level = section_counter->nest_level-reduce;
for (int32_t i = 1; i <= level; ++i){ for (int32_t i = 1; i <= level; ++i){
append_int_to_str(out, section_counter.counter[i]); append_int_to_str(out, section_counter->counter[i]);
if (i != level){ if (i != level){
append_sc(out, "."); append_sc(out, ".");
} }
@ -307,7 +313,7 @@ append_section_number_reduced(String *out, Section_Counter section_counter, int3
} }
static void static void
append_section_number(String *out, Section_Counter section_counter){ append_section_number(String *out, Section_Counter *section_counter){
append_section_number_reduced(out, section_counter, 0); append_section_number_reduced(out, section_counter, 0);
} }
@ -360,7 +366,39 @@ extract_command_body(String *out, String l, int32_t *i_in_out, int32_t *body_sta
} }
static void static void
write_enriched_text_html(String *out, Enriched_Text *text){ html_render_section_header(String *out, String section_name, String section_id, Section_Counter *section_counter){
if (section_counter->nest_level <= 1){
if (section_id.size > 0){
append_sc(out, "\n<h2 id='section_");
append_ss(out, section_id);
append_sc(out, "'>&sect;");
}
else{
append_sc(out, "\n<h2>&sect;");
}
append_section_number(out, section_counter);
append_sc(out, " ");
append_ss(out, section_name);
append_sc(out, "</h2>");
}
else{
if (section_id.size > 0){
append_sc(out, "<h3 id='section_");
append_ss(out, section_id);
append_sc(out, "'>&sect;");
}
else{
append_sc(out, "<h3>&sect;");
}
append_section_number(out, section_counter);
append_sc(out, " ");
append_ss(out, section_name);
append_sc(out, "</h3>");
}
}
static void
write_enriched_text_html(String *out, Enriched_Text *text, Section_Counter *section_counter){
String source = text->source; String source = text->source;
append_sc(out, "<div>"); append_sc(out, "<div>");
@ -393,21 +431,42 @@ write_enriched_text_html(String *out, Enriched_Text *text){
String command_string = substr(l, command_start, command_end - command_start); String command_string = substr(l, command_start, command_end - command_start);
static String enriched_commands[] = { enum Command_Types{
make_lit_string("\\"), Cmd_BackSlash,
make_lit_string("VERSION"), Cmd_Version,
make_lit_string("CODE_STYLE"), Cmd_CodeStyle,
make_lit_string("DOC_LINK"), Cmd_DocLink,
Cmd_BeginList,
Cmd_EndList,
Cmd_BeginItem,
Cmd_EndItem,
Cmd_BoldFace,
Cmd_Section,
// never below this
Cmd_COUNT,
}; };
static String enriched_commands[Cmd_COUNT];
enriched_commands[Cmd_BackSlash] = make_lit_string("\\");
enriched_commands[Cmd_Version] = make_lit_string("VERSION");
enriched_commands[Cmd_CodeStyle] = make_lit_string("CODE_STYLE");
enriched_commands[Cmd_DocLink] = make_lit_string("DOC_LINK");
enriched_commands[Cmd_BeginList] = make_lit_string("BEGIN_LIST");
enriched_commands[Cmd_EndList] = make_lit_string("END_LIST");
enriched_commands[Cmd_BeginItem] = make_lit_string("BEGIN_ITEM");
enriched_commands[Cmd_EndItem] = make_lit_string("END_ITEM");
enriched_commands[Cmd_BoldFace] = make_lit_string("BOLD_FACE");
enriched_commands[Cmd_Section] = make_lit_string("SECTION");
i = command_end; i = command_end;
int32_t match_index = 0; int32_t match_index = 0;
if (string_set_match(enriched_commands, ArrayCount(enriched_commands), command_string, &match_index)){ if (string_set_match(enriched_commands, ArrayCount(enriched_commands), command_string, &match_index)){
switch (match_index){ switch (match_index){
case 0: append_sc(out, "\\"); break; case Cmd_BackSlash: append_sc(out, "\\"); break;
case 1: append_sc(out, VERSION); break; case Cmd_Version: append_sc(out, VERSION); break;
case 2: case Cmd_CodeStyle:
{ {
int32_t body_start = 0, body_end = 0; int32_t body_start = 0, body_end = 0;
int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string); int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string);
@ -419,7 +478,7 @@ write_enriched_text_html(String *out, Enriched_Text *text){
} }
}break; }break;
case 3: case Cmd_DocLink:
{ {
int32_t body_start = 0, body_end = 0; int32_t body_start = 0, body_end = 0;
int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string); int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string);
@ -432,6 +491,38 @@ write_enriched_text_html(String *out, Enriched_Text *text){
append_sc(out, "</a>"); append_sc(out, "</a>");
} }
}break; }break;
case Cmd_BeginList:
{
append_sc(out, "<ul style='margin-left: 5mm;'>");
}break;
case Cmd_EndList:
{
append_sc(out, "</ul>");
}break;
case Cmd_BeginItem:
{
append_sc(out, "<li>");
}break;
case Cmd_EndItem:
{
append_sc(out, "</li>");
}break;
case Cmd_Section:
{
int32_t body_start = 0, body_end = 0;
int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string);
if (has_body){
String body_text = substr(l, body_start, body_end - body_start);
html_render_section_header(out, body_text, null_string, section_counter);
++section_counter->counter[section_counter->nest_level];
}
}break;
} }
} }
else{ else{
@ -1060,7 +1151,7 @@ write_enriched_text_html(String *out, Enriched_Text *text){
} }
static void static void
doc_item_head_html(String *out, Partition *part, Used_Links *used_links, Document_Item *item, Section_Counter section_counter){ doc_item_head_html(String *out, Partition *part, Used_Links *used_links, Document_Item *item, Section_Counter *section_counter){
switch (item->type){ switch (item->type){
case Doc_Root: case Doc_Root:
{ {
@ -1131,34 +1222,7 @@ static void
case Doc_Section: case Doc_Section:
{ {
if (section_counter.nest_level <= 1){ html_render_section_header(out, item->section.name, item->section.id, section_counter);
if (item->section.id.size > 0){
append_sc(out, "\n<h2 id='section_");
append_ss(out, item->section.id);
append_sc(out, "'>&sect;");
}
else{
append_sc(out, "\n<h2>&sect;");
}
append_section_number(out, section_counter);
append_sc(out, " ");
append_ss(out, item->section.name);
append_sc(out, "</h2>");
}
else{
if (item->section.id.size > 0){
append_sc(out, "<h3 id='section_");
append_ss(out, item->section.id);
append_sc(out, "'>&sect;");
}
else{
append_sc(out, "<h3>&sect;");
}
append_section_number(out, section_counter);
append_sc(out, " ");
append_ss(out, item->section.name);
append_sc(out, "</h3>");
}
}break; }break;
case Doc_Todo: case Doc_Todo:
@ -1168,7 +1232,7 @@ static void
case Doc_Enriched_Text: case Doc_Enriched_Text:
{ {
write_enriched_text_html(out, item->text.text); write_enriched_text_html(out, item->text.text, section_counter);
}break; }break;
case Doc_Element_List: case Doc_Element_List:
@ -1261,7 +1325,7 @@ static void
} }
static void static void
doc_item_foot_html(String *out, Partition *part, Used_Links *used_links, Document_Item *item, Section_Counter section_counter){ doc_item_foot_html(String *out, Partition *part, Used_Links *used_links, Document_Item *item, Section_Counter *section_counter){
switch (item->type){ switch (item->type){
case Doc_Root: case Doc_Root:
{ {
@ -1276,8 +1340,7 @@ doc_item_foot_html(String *out, Partition *part, Used_Links *used_links, Documen
static void static void
generate_item_html(String *out, Partition *part, Used_Links *used_links, Document_Item *item, Section_Counter *section_counter){ generate_item_html(String *out, Partition *part, Used_Links *used_links, Document_Item *item, Section_Counter *section_counter){
Section_Counter sc = *section_counter; doc_item_head_html(out, part, used_links, item, section_counter);
doc_item_head_html(out, part, used_links, item, sc);
if (item->type == Doc_Root || item->type == Doc_Section){ if (item->type == Doc_Root || item->type == Doc_Section){
int32_t level = ++section_counter->nest_level; int32_t level = ++section_counter->nest_level;
@ -1291,7 +1354,7 @@ generate_item_html(String *out, Partition *part, Used_Links *used_links, Documen
++section_counter->counter[section_counter->nest_level]; ++section_counter->counter[section_counter->nest_level];
} }
doc_item_foot_html(out, part, used_links, item, sc); doc_item_foot_html(out, part, used_links, item, section_counter);
} }
static void static void

6
site/build.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
pushd ..
make clean
make site
popd

View File

@ -25,7 +25,7 @@
#define InvalidPath Assert(!"Invalid path of execution") #define InvalidPath Assert(!"Invalid path of execution")
////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// //
// Meta Parse Rules // Meta Parse Rules
@ -151,17 +151,10 @@ assert_files_are_equal(char *directory, char *filename1, char *filename2){
} }
} }
static void static Abstract_Document*
generate_site(char *code_directory, char *src_directory, char *dst_directory){ generate_4coder_API(Partition *part, char *code_directory, char *src_directory, char *dst_directory){
#define API_DOC "4coder_API.html" #define API_DOC "4coder_API.html"
int32_t size = (512 << 20);
void *mem = malloc(size);
memset(mem, 0, size);
Partition part_ = make_part(mem, size);
Partition *part = &part_;
static Meta_Keywords meta_keywords[] = { static Meta_Keywords meta_keywords[] = {
{make_lit_string("API_EXPORT") , Item_Function } , {make_lit_string("API_EXPORT") , Item_Function } ,
{make_lit_string("API_EXPORT_INLINE") , Item_Function } , {make_lit_string("API_EXPORT_INLINE") , Item_Function } ,
@ -175,14 +168,27 @@ generate_site(char *code_directory, char *src_directory, char *dst_directory){
#define ExpandArray(a) (a), (ArrayCount(a)) #define ExpandArray(a) (a), (ArrayCount(a))
Meta_Unit *custom_types_unit = push_struct(part, Meta_Unit);
Meta_Unit *lexer_funcs_unit = push_struct(part, Meta_Unit);
Meta_Unit *lexer_types_unit = push_struct(part, Meta_Unit);
Meta_Unit *string_unit = push_struct(part, Meta_Unit);
Meta_Unit *custom_funcs_unit = push_struct(part, Meta_Unit);
Alternate_Names_Array *custom_func_names = push_struct(part, Alternate_Names_Array);
Enriched_Text *introduction = push_struct(part, Enriched_Text);
Enriched_Text *lexer_introduction = push_struct(part, Enriched_Text);
Abstract_Document *doc = push_struct(part, Abstract_Document);
// NOTE(allen): Parse the important code. // NOTE(allen): Parse the important code.
Meta_Unit custom_types_unit = compile_meta_unit(part, code_directory, "4coder_types.h", ExpandArray(meta_keywords)); *custom_types_unit = compile_meta_unit(part, code_directory, "4coder_types.h", ExpandArray(meta_keywords));
Meta_Unit lexer_funcs_unit = compile_meta_unit(part, code_directory, "4cpp_lexer.h", ExpandArray(meta_keywords)); *lexer_funcs_unit = compile_meta_unit(part, code_directory, "4cpp_lexer.h", ExpandArray(meta_keywords));
Meta_Unit lexer_types_unit = compile_meta_unit(part, code_directory, "4cpp_lexer_types.h", ExpandArray(meta_keywords)); *lexer_types_unit = compile_meta_unit(part, code_directory, "4cpp_lexer_types.h", ExpandArray(meta_keywords));
Meta_Unit string_unit = compile_meta_unit(part, code_directory, "internal_4coder_string.cpp", ExpandArray(meta_keywords)); *string_unit = compile_meta_unit(part, code_directory, "internal_4coder_string.cpp", ExpandArray(meta_keywords));
static char *functions_files[] = { static char *functions_files[] = {
"4ed_api_implementation.cpp", "4ed_api_implementation.cpp",
@ -190,16 +196,16 @@ generate_site(char *code_directory, char *src_directory, char *dst_directory){
0 0
}; };
Meta_Unit custom_funcs_unit = compile_meta_unit(part, code_directory, functions_files, ExpandArray(meta_keywords)); *custom_funcs_unit = compile_meta_unit(part, code_directory, functions_files, ExpandArray(meta_keywords));
// NOTE(allen): Compute and store variations of the custom function names // NOTE(allen): Compute and store variations of the custom function names
Alternate_Names_Array custom_func_names = allocate_app_api(part, custom_funcs_unit.set.count); *custom_func_names = allocate_app_api(part, custom_funcs_unit->set.count);
for (int32_t i = 0; i < custom_funcs_unit.set.count; ++i){ for (int32_t i = 0; i < custom_funcs_unit->set.count; ++i){
String name_string = custom_funcs_unit.set.items[i].name; String name_string = custom_funcs_unit->set.items[i].name;
String *macro = &custom_func_names.names[i].macro; String *macro = &custom_func_names->names[i].macro;
String *public_name = &custom_func_names.names[i].public_name; String *public_name = &custom_func_names->names[i].public_name;
*macro = str_alloc(part, name_string.size+4); *macro = str_alloc(part, name_string.size+4);
to_upper_ss(macro, name_string); to_upper_ss(macro, name_string);
@ -212,89 +218,143 @@ generate_site(char *code_directory, char *src_directory, char *dst_directory){
} }
// NOTE(allen): Load enriched text materials // NOTE(allen): Load enriched text materials
Enriched_Text introduction = load_enriched_text(part, src_directory, "introduction.txt"); *introduction = load_enriched_text(part, src_directory, "introduction.txt");
Enriched_Text lexer_introduction = load_enriched_text(part, src_directory, "lexer_introduction.txt"); *lexer_introduction = load_enriched_text(part, src_directory, "lexer_introduction.txt");
// NOTE(allen): Put together the abstract document // NOTE(allen): Put together the abstract document
Abstract_Document doc = {0}; memset(doc, 0, sizeof(*doc));
begin_document_description(&doc, part, "4coder API Docs"); begin_document_description(doc, part, "4coder API Docs");
set_document_name(doc, API_DOC);
add_table_of_contents(&doc); add_table_of_contents(doc);
begin_section(&doc, "Introduction", "introduction"); begin_section(doc, "Introduction", "introduction");
add_enriched_text(&doc, &introduction); add_enriched_text(doc, introduction);
end_section(&doc); end_section(doc);
begin_section(&doc, "4coder Systems", "4coder_systems"); begin_section(doc, "4coder Systems", "4coder_systems");
add_todo(&doc); add_todo(doc);
end_section(&doc); end_section(doc);
begin_section(&doc, "Types and Functions", "types_and_functions"); begin_section(doc, "Types and Functions", "types_and_functions");
{ {
begin_section(&doc, "Function List", 0); begin_section(doc, "Function List", 0);
add_element_list(&doc, &custom_funcs_unit, &custom_func_names, AltName_Public_Name); add_element_list(doc, custom_funcs_unit, custom_func_names, AltName_Public_Name);
end_section(&doc); end_section(doc);
begin_section(&doc, "Type List", 0); begin_section(doc, "Type List", 0);
add_element_list(&doc, &custom_types_unit); add_element_list(doc, custom_types_unit);
end_section(&doc); end_section(doc);
begin_section(&doc, "Function Descriptions", 0); begin_section(doc, "Function Descriptions", 0);
add_full_elements(&doc, &custom_funcs_unit, &custom_func_names, AltName_Public_Name); add_full_elements(doc, custom_funcs_unit, custom_func_names, AltName_Public_Name);
end_section(&doc); end_section(doc);
begin_section(&doc, "Type Descriptions", 0); begin_section(doc, "Type Descriptions", 0);
add_full_elements(&doc, &custom_types_unit); add_full_elements(doc, custom_types_unit);
end_section(&doc); end_section(doc);
} }
end_section(&doc); end_section(doc);
begin_section(&doc, "String Library", "string_library"); begin_section(doc, "String Library", "string_library");
{ {
begin_section(&doc, "String Library Intro", 0); begin_section(doc, "String Library Intro", 0);
add_todo(&doc); add_todo(doc);
end_section(&doc); end_section(doc);
begin_section(&doc, "String Function List", 0); begin_section(doc, "String Function List", 0);
add_element_list(&doc, &string_unit); add_element_list(doc, string_unit);
end_section(&doc); end_section(doc);
begin_section(&doc, "String Function Descriptions", 0); begin_section(doc, "String Function Descriptions", 0);
add_full_elements(&doc, &string_unit); add_full_elements(doc, string_unit);
end_section(&doc); end_section(doc);
} }
end_section(&doc); end_section(doc);
begin_section(&doc, "Lexer Library", "lexer_library"); begin_section(doc, "Lexer Library", "lexer_library");
{ {
begin_section(&doc, "Lexer Intro", 0); begin_section(doc, "Lexer Intro", 0);
add_enriched_text(&doc, &lexer_introduction); add_enriched_text(doc, lexer_introduction);
end_section(&doc); end_section(doc);
begin_section(&doc, "Lexer Function List", 0); begin_section(doc, "Lexer Function List", 0);
add_element_list(&doc, &lexer_funcs_unit); add_element_list(doc, lexer_funcs_unit);
end_section(&doc); end_section(doc);
begin_section(&doc, "Lexer Type List", 0); begin_section(doc, "Lexer Type List", 0);
add_element_list(&doc, &lexer_types_unit); add_element_list(doc, lexer_types_unit);
end_section(&doc); end_section(doc);
begin_section(&doc, "Lexer Function Descriptions", 0); begin_section(doc, "Lexer Function Descriptions", 0);
add_full_elements(&doc, &lexer_funcs_unit); add_full_elements(doc, lexer_funcs_unit);
end_section(&doc); end_section(doc);
begin_section(&doc, "Lexer Type Descriptions", 0); begin_section(doc, "Lexer Type Descriptions", 0);
add_full_elements(&doc, &lexer_types_unit); add_full_elements(doc, lexer_types_unit);
end_section(&doc); end_section(doc);
} }
end_section(&doc); end_section(doc);
end_document_description(&doc); end_document_description(doc);
// NOTE(allen): Output // NOTE(allen): Output
Temp_Memory temp = begin_temp_memory(part);
String out = str_alloc(part, 10 << 20); String out = str_alloc(part, 10 << 20);
Out_Context context = {0}; Out_Context context = {0};
set_context_directory(&context, dst_directory); set_context_directory(&context, dst_directory);
// Output Docs // Output Docs
if (begin_file_out(&context, API_DOC, &out)){ if (begin_file_out(&context, doc->name, &out)){
generate_document_html(&out, part, &doc); generate_document_html(&out, part, doc);
end_file_out(context); end_file_out(context);
} }
else{ else{
fprintf(stderr, "Failed to open %s", API_DOC); fprintf(stderr, "Failed to open %s", doc->name);
} }
end_temp_memory(temp);
return(doc);
}
static Abstract_Document*
generate_feature_list(Partition *part, char *src_directory, char *dst_directory){
Enriched_Text *feature_list = push_struct(part, Enriched_Text);
Abstract_Document *doc = push_struct(part, Abstract_Document);
*feature_list = load_enriched_text(part, src_directory, "feature_list.txt");
// NOTE(allen): Put together the abstract document
memset(doc, 0, sizeof(*doc));
begin_document_description(doc, part, "4coder Feature List");
set_document_name(doc, "4coder_features.html");
add_enriched_text(doc, feature_list);
end_document_description(doc);
// NOTE(allen): Output
Temp_Memory temp = begin_temp_memory(part);
String out = str_alloc(part, 10 << 20);
Out_Context context = {0};
set_context_directory(&context, dst_directory);
// Output Docs
if (begin_file_out(&context, doc->name, &out)){
generate_document_html(&out, part, doc);
end_file_out(context);
}
else{
fprintf(stderr, "Failed to open %s", doc->name);
}
end_temp_memory(temp);
return(doc);
}
static void
generate_site(char *code_directory, char *src_directory, char *dst_directory){
int32_t size = (512 << 20);
void *mem = malloc(size);
memset(mem, 0, size);
Partition part_ = make_part(mem, size);
Partition *part = &part_;
Abstract_Document *api_document = generate_4coder_API(part, code_directory, src_directory, dst_directory);
Abstract_Document *feature_list = generate_feature_list(part, src_directory, dst_directory);
} }

View File

@ -0,0 +1,30 @@
\SECTION{Text Editing}
\BEGIN_LIST
\BEGIN_ITEM Cursor and mark editing paradigm \END_ITEM
\BEGIN_ITEM Navigation by characters, words, tokens, lines, and blank lines \END_ITEM
\BEGIN_ITEM Modern style undo and redo \END_ITEM
\BEGIN_ITEM Word complete with matching words in open files \END_ITEM
\BEGIN_ITEM Incremental word search \END_ITEM
\BEGIN_ITEM Word replace \END_ITEM
\BEGIN_ITEM List all occurences of words in open buffers \END_ITEM
\END_LIST
\SECTION{C/C++ Editing}
\BEGIN_LIST
\BEGIN_ITEM Code highlighting for C/C++ code \END_ITEM
\BEGIN_ITEM Code auto-layout rendering engine \END_ITEM
\BEGIN_ITEM Text level auto-indenting \END_ITEM
\BEGIN_ITEM Build in editor \END_ITEM
\BEGIN_ITEM Jump to error \END_ITEM
\END_LIST
\SECTION{The Customization API}
\BEGIN_LIST
\BEGIN_ITEM Easy key rebinding \END_ITEM
\BEGIN_ITEM Create custom commands \END_ITEM
\BEGIN_ITEM Buffer reading and editing \END_ITEM
\BEGIN_ITEM Buffer reading and editing \END_ITEM
\BEGIN_ITEM View opening, closing, positioning \END_ITEM
\END_LIST