From c2275fa99d3b46e05e84f6cd6c81fc254996f4f8 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Tue, 16 Jul 2024 21:50:52 +0200 Subject: [PATCH 1/2] cloned Tutor documentation from deprecated rascal-tutor project to here --- courses/Tutor/API/API.md | 49 ++++ courses/Tutor/Architecture/Architecture.md | 62 +++++ courses/Tutor/Authoring/Authoring.md | 48 ++++ courses/Tutor/Compilation/Compilation.md | 122 +++++++++ courses/Tutor/Concept/Benefits/Benefits.md | 32 +++ courses/Tutor/Concept/Concept.md | 61 +++++ .../Tutor/Concept/Description/Description.md | 41 +++ courses/Tutor/Concept/Details/Details.md | 65 +++++ courses/Tutor/Concept/Examples/Examples.md | 54 ++++ courses/Tutor/Concept/Function/Function.md | 42 ++++ courses/Tutor/Concept/Keywords/Keywords.md | 23 ++ courses/Tutor/Concept/Pitfalls/Pitfalls.md | 32 +++ courses/Tutor/Concept/Synopsis/Synopsis.md | 33 +++ courses/Tutor/Concept/Syntax/Syntax.md | 44 ++++ courses/Tutor/Concept/Title/Title.md | 42 ++++ courses/Tutor/Concept/Types/Types.md | 68 +++++ courses/Tutor/Maintenance/Adding/Adding.md | 46 ++++ courses/Tutor/Maintenance/Maintenance.md | 28 +++ .../Tutor/Maintenance/Removing/Removing.md | 31 +++ .../Tutor/Maintenance/Renaming/Renaming.md | 33 +++ .../Tutor/Markup/InlineMarkup/Bold/Bold.md | 28 +++ .../Tutor/Markup/InlineMarkup/Code/Code.md | 34 +++ .../Tutor/Markup/InlineMarkup/Image/Image.md | 65 +++++ .../Markup/InlineMarkup/Image/dandelion.jpg | Bin 0 -> 89000 bytes .../InlineMarkup/Image/example-image.odg | Bin 0 -> 8763 bytes .../InlineMarkup/Image/example-image.png | Bin 0 -> 6874 bytes .../Tutor/Markup/InlineMarkup/InlineMarkup.md | 26 ++ .../Markup/InlineMarkup/Italic/Italic.md | 28 +++ .../LinkingConcepts/LinkingConcepts.md | 74 ++++++ .../Markup/InlineMarkup/Listing/Listing.md | 235 ++++++++++++++++++ .../Listing/Screenshots/Screenshots.md | 60 +++++ .../Markup/InlineMarkup/Variable/Variable.md | 38 +++ courses/Tutor/Markup/Markup.md | 33 +++ .../Markup/QuestionMarkup/Choice/Choice.md | 51 ++++ .../Markup/QuestionMarkup/Choice/Choice.quest | 1 + .../Tutor/Markup/QuestionMarkup/Question.odg | Bin 0 -> 8999 bytes .../Tutor/Markup/QuestionMarkup/Question.png | Bin 0 -> 5699 bytes .../Markup/QuestionMarkup/QuestionMarkup.md | 68 +++++ .../Tutor/Markup/QuestionMarkup/Text/Text.md | 44 ++++ .../Markup/QuestionMarkup/Text/Text.quest | 1 + .../Tutor/Markup/QuestionMarkup/Type/Type.md | 53 ++++ .../Markup/QuestionMarkup/Type/Type.quest | 1 + .../TypeDescriptor/TypeDescriptor.md | 72 ++++++ .../Markup/QuestionMarkup/Value/Value.md | 107 ++++++++ .../Markup/QuestionMarkup/Value/Value.quest | 1 + .../SourceCodeMarkup/SourceCodeMarkup.md | 160 ++++++++++++ .../StructureMarkup/Admonition/Admonition.md | 91 +++++++ .../BulletLists/BulletLists.md | 72 ++++++ .../NamedParagraph/NamedParagraph.md | 39 +++ .../NewParagraph/NewParagraph.md | 41 +++ .../NumberedLists/NumberedLists.md | 67 +++++ .../Markup/StructureMarkup/StructureMarkup.md | 26 ++ .../Markup/StructureMarkup/Table/Table.md | 97 ++++++++ .../TableOfContents/TableOfContents.md | 35 +++ courses/Tutor/Tutor.md | 75 ++++++ 55 files changed, 2679 insertions(+) create mode 100644 courses/Tutor/API/API.md create mode 100644 courses/Tutor/Architecture/Architecture.md create mode 100644 courses/Tutor/Authoring/Authoring.md create mode 100644 courses/Tutor/Compilation/Compilation.md create mode 100644 courses/Tutor/Concept/Benefits/Benefits.md create mode 100644 courses/Tutor/Concept/Concept.md create mode 100644 courses/Tutor/Concept/Description/Description.md create mode 100644 courses/Tutor/Concept/Details/Details.md create mode 100644 courses/Tutor/Concept/Examples/Examples.md create mode 100644 courses/Tutor/Concept/Function/Function.md create mode 100644 courses/Tutor/Concept/Keywords/Keywords.md create mode 100644 courses/Tutor/Concept/Pitfalls/Pitfalls.md create mode 100644 courses/Tutor/Concept/Synopsis/Synopsis.md create mode 100644 courses/Tutor/Concept/Syntax/Syntax.md create mode 100644 courses/Tutor/Concept/Title/Title.md create mode 100644 courses/Tutor/Concept/Types/Types.md create mode 100644 courses/Tutor/Maintenance/Adding/Adding.md create mode 100644 courses/Tutor/Maintenance/Maintenance.md create mode 100644 courses/Tutor/Maintenance/Removing/Removing.md create mode 100644 courses/Tutor/Maintenance/Renaming/Renaming.md create mode 100644 courses/Tutor/Markup/InlineMarkup/Bold/Bold.md create mode 100644 courses/Tutor/Markup/InlineMarkup/Code/Code.md create mode 100644 courses/Tutor/Markup/InlineMarkup/Image/Image.md create mode 100644 courses/Tutor/Markup/InlineMarkup/Image/dandelion.jpg create mode 100644 courses/Tutor/Markup/InlineMarkup/Image/example-image.odg create mode 100644 courses/Tutor/Markup/InlineMarkup/Image/example-image.png create mode 100644 courses/Tutor/Markup/InlineMarkup/InlineMarkup.md create mode 100644 courses/Tutor/Markup/InlineMarkup/Italic/Italic.md create mode 100644 courses/Tutor/Markup/InlineMarkup/LinkingConcepts/LinkingConcepts.md create mode 100644 courses/Tutor/Markup/InlineMarkup/Listing/Listing.md create mode 100644 courses/Tutor/Markup/InlineMarkup/Listing/Screenshots/Screenshots.md create mode 100644 courses/Tutor/Markup/InlineMarkup/Variable/Variable.md create mode 100644 courses/Tutor/Markup/Markup.md create mode 100644 courses/Tutor/Markup/QuestionMarkup/Choice/Choice.md create mode 100644 courses/Tutor/Markup/QuestionMarkup/Choice/Choice.quest create mode 100644 courses/Tutor/Markup/QuestionMarkup/Question.odg create mode 100644 courses/Tutor/Markup/QuestionMarkup/Question.png create mode 100644 courses/Tutor/Markup/QuestionMarkup/QuestionMarkup.md create mode 100644 courses/Tutor/Markup/QuestionMarkup/Text/Text.md create mode 100644 courses/Tutor/Markup/QuestionMarkup/Text/Text.quest create mode 100644 courses/Tutor/Markup/QuestionMarkup/Type/Type.md create mode 100644 courses/Tutor/Markup/QuestionMarkup/Type/Type.quest create mode 100644 courses/Tutor/Markup/QuestionMarkup/TypeDescriptor/TypeDescriptor.md create mode 100644 courses/Tutor/Markup/QuestionMarkup/Value/Value.md create mode 100644 courses/Tutor/Markup/QuestionMarkup/Value/Value.quest create mode 100644 courses/Tutor/Markup/SourceCodeMarkup/SourceCodeMarkup.md create mode 100644 courses/Tutor/Markup/StructureMarkup/Admonition/Admonition.md create mode 100644 courses/Tutor/Markup/StructureMarkup/BulletLists/BulletLists.md create mode 100644 courses/Tutor/Markup/StructureMarkup/NamedParagraph/NamedParagraph.md create mode 100644 courses/Tutor/Markup/StructureMarkup/NewParagraph/NewParagraph.md create mode 100644 courses/Tutor/Markup/StructureMarkup/NumberedLists/NumberedLists.md create mode 100644 courses/Tutor/Markup/StructureMarkup/StructureMarkup.md create mode 100644 courses/Tutor/Markup/StructureMarkup/Table/Table.md create mode 100644 courses/Tutor/Markup/StructureMarkup/TableOfContents/TableOfContents.md create mode 100644 courses/Tutor/Tutor.md diff --git a/courses/Tutor/API/API.md b/courses/Tutor/API/API.md new file mode 100644 index 000000000..c3880749b --- /dev/null +++ b/courses/Tutor/API/API.md @@ -0,0 +1,49 @@ +--- +title: API documentation +--- + +#### Synopsis + +The Tutor compiler reads Rascal source files and produces ((Concept)) markdown files +for each Rascal module. + +#### Description + +The compiler generates for every `Module.rsc` a markdown file with the following structure: + +`````` +--- +title: +--- + +// for each declaration (function, data, syntax, alias, import, extend) +## {#fully-qualified-declaration-name} + +#### Synopsis + +... +#### Description +... + +// etc. +`````` + +So, for all standard ((Concept)) headers, like `Synopsis` and `Benefits` there is a place at every declaration. + +The content of the header paragraphs is either directly derived from source code (like function signature and data definitions), or it is taken from the following tag definitions on each declaration: +* `@doc` may contain literally the headers of a ((Concept)), like `#### Synopsis`. This notation is deprecated in favor of the tags below. +* `@synopsis` is a single line description of the definition. +* `@description` is a multi-line explanantion of the definition. +* `@benefits`, `@pitfalls`, `@examples`, `@types`, `@name` and `@function` each follow the intent of the standard ((Concept)) headers. + +The documentation written for features without an explicit synopsis is not rendered. In other words it is obligatory to use at least a `@synopsis` tag or start with a `#### Synopsis` header.. + +#### Benefits + +* A (small) part of documentation writing is automated. The information about the name of a function, data or annotation declaration, or its signature is always consistent. +* You can write examples of the usage of each definition using ((Listing)) markup that is run and checked at documentation compile-time. + +#### Pitfalls + +* This approach requires that functions with the same name are grouped together in the source file. +* You need to run the tutor compiler before errors in the documentation tags are detected. diff --git a/courses/Tutor/Architecture/Architecture.md b/courses/Tutor/Architecture/Architecture.md new file mode 100644 index 000000000..168aadae4 --- /dev/null +++ b/courses/Tutor/Architecture/Architecture.md @@ -0,0 +1,62 @@ +--- +title: Architecture +--- + +#### Synopsis + +The global architecture of the Rascal Tutor + +#### Description + +The Rascal Tutor is a Markdown and Rascal source file pre-processor. As input it takes [Docusaurus Markdown](https://docusaurus.io/docs/markdown-features/) files organized in hierarchical folders, and Rascal modules organized in hierarchical packages. One root folder is called a "course". As output the pre-processor produces per course +a folder hierarchy again, where each folder has its own `index.md` file (generated or written). After the tutor +compiler has generated such a consistent folder of interconnected markdown files, other downstream processors can turn them into (static) html websites, pdf files or otherwise. The standard way of processing is to use the [Docusaurus](https://docusaurus.io) static website generator. + +The important features of the pre-processor, "compiler", are: + +1. The compiler is configured via `util::Reflective::PathConfig`, where: + * each entry in the `srcs` list is a single _course_ + * each entry in the `libs` list, be it a jar file or not, is searched for an `index.value` file to augment the current index. +1. Concept hierarchy - each folder `/X` has its own index file, called either `X/X.md` or `X/index.md`. Nested folders equal nested concepts. +1. Indexing - to help in easy cross-linking between concepts: + * Each concept of course `A` stored in `X/Y/Z/Z.md` may be linked via `Z`, `Y-Z`, `X-Y-Z`, `A:Z`, `A:Y-Z`, `A:X-Y-Z` + * Each Rascal module of course `A` named `a::b::C` may be linked via `C`, `b-C`, `a::b::C`, `module:a::b::C`, `A:C`, `A:b-C`, `A:a::b::C`, `A:module:a::b::C` + * Each Rascal package of course `A` named `a::b` may be linked via `b`, `a::b`, `package:a::b`, `A:b`, `A:a::b`, `A:module:a::b` + * Each image `x.{png,svg,jpg,jpeg}` stored in `X/Y/Z` may be linked as though it were a concept file. + * The index is a `rel[str,str]` from the above described links to the `index.md` files in the generated hierarchy. + * The compiler reports missing links and ambiguous links as errors. + * A single `index.value` file is written in the output folder for future reference by depending projects. +1. Code execution ensures lively demonstrations which are checked for correctness. + * Code blocks marked `rascal-shell` are executed line-by-line on the REPL prompt. Each prompt starts with a fresh environment. All error and standard output is captured and printed back. The `Content` module that serves HTML or any other file is also inlined in the output Markdown file. + * Code blocks marked `rascal-shell,continue` are executed in the previously constructed environment (from top to bottom in the Markdown file) and behave the same otherwise. + * Code blocks marked `rascal-prepare` with or without `continue` behave the same as above, except that no output or input is printed back into the output file. +1. Links written between `((` and `))` are resolved using the previously described index. +1. Table of contents are generated for the word TOC between three `(((` brackets `)))`; the content of each concept is the concept nested under it in the hierarchy. +1. Each Rascal file is indexed to list the declarations it contains and information is extracted: + * data declarations with their `doc`, `synopsis`, `examples` etc. tags + * (overloaded) function declarations with their `doc`, `synopsis`, `examples` etc. tags + * alias declarations with their `doc`, `synopsis`, `examples` etc. tags +1. Screenshots of interactive ((Library:module:Content) visualizations can be made by configuring the compiler to use selenium and chrome. + +Features on the TODO list are: +1. Interactive Questions (have to be revived) + + +To implement these features the following components are relevant: +* `lang::rascal::tutor::Indexer` implements indexing and lookup +* `lang::rascal::tutor::Compiler` implements linking, code execution, toc, and the generation of index files. +* `lang::rascal::tutor::apidoc::ExtractInfo` parses Rascal code and generates an intermediate overview +* `lang::rascal::tutor::apidoc::GenerateMarkdown` generates a single Markdown file for each Rascal module, and also reuses `Compiler` to process embedded markdown with code examples, links, etc. +* `lang::rascal::tutor::repl::TutorCommandExecutor` encapsulates a Rascal REPL as a set of closures (`eval`, `reset`, and `prompt`) + * for efficiency's sake a single executor is shared among all Markdown and Rascal files that are compiled in a single run. Between every file the executor is reset for a new environment, but previously loaded modules remain in the heap available for reuse. + +#### Benefits + +* Index creation is modular: an index is created per course and these indices are combined at runtime. +* Code execution is reasonably time efficient, although it may require quite some memory because eventually an entire course will be loaded. + +#### Pitfalls + +* Courses are compiled on a per-course basis. Support for incremental courses compilation is not yet available. +* Badly balanced code block quotes are not detected by this pre-processor but will fail HTML compilation downstream. +* Manual links are not checked at compile-time by this pre-processor but fill fail HTML compilation downstream. diff --git a/courses/Tutor/Authoring/Authoring.md b/courses/Tutor/Authoring/Authoring.md new file mode 100644 index 000000000..839f78f54 --- /dev/null +++ b/courses/Tutor/Authoring/Authoring.md @@ -0,0 +1,48 @@ +--- +title: Authoring +--- + +#### Synopsis + +Creating and writing a course for the Rascal Tutor. + +#### Syntax + +#### Types + +#### Function + +#### Description + +The life cycle of a course consists of the following steps: + +* A new course, say `MyCourse`, is created. This is achieved by: + * Creating a subdirectory named `MyCourse` in the `courses` directory of the current Rascal project. + * Creating a file `MyCourse/MyCourse.md`. This is the root concept of the new course. +* The contents of the course are created by populating the course with subconcepts of the root concept. +* A subconcept, say `CoolIdea` is created by: + * Creating a subdirectory `CoolIdea` of its parent concept. + * Creating a file `CoolIdea/CoolIdea.md` that describes the concept. + * Alternatively, a file `CoolIdea/index.md` works too. + * Renaming/moving/deleting concepts is done at the directory/file level. + +Concepts are represented as directories for the following reasons: + +* To represent subconcepts as subdirectories. +* To contain all figures and other files that are included in the concept. In this way: + * A complete concept can be easily moved or renamed as a single unit. + * Name clashes between included files per concept are avoided. + +#### Examples + +#### Benefits + +* You can use your favourite Markdown editor and standard system commands to author a course. +* The output of the Tutor compiler is Markdown/HTML that you can process further with any tool you like +* Links to other concepts are all _relative_ to a root directory with all the courses. So `../../Course/A/index.md` would be a link generated from a link to `A` in `/Course/Z/index.md`. This makes it easy to include courses in a website at any subfolder. +* The index that is generated for every project with several courses can be reused by other projects to generate consistent cross-referencing. For example a project `flybytes` which depends on the `rascal` project which contains the `Library` course, could use `Library:IO` to refer to the documentation about the `IO` module in the standard library of Rascal. + +#### Pitfalls + +* Special features like code execution and cross-referencing concepts are not implemented by generic Markdown editors, so you have to wait and see what happens until you compile the course. +* All images are referenced from `/assets/` so images have to be installed there on any website you want to include the documentation in. \ No newline at end of file diff --git a/courses/Tutor/Compilation/Compilation.md b/courses/Tutor/Compilation/Compilation.md new file mode 100644 index 000000000..999edb82d --- /dev/null +++ b/courses/Tutor/Compilation/Compilation.md @@ -0,0 +1,122 @@ +--- +title: Tutor Compilation +keywords: + - compilation + - compiler + - configuration + - maven + - deployment + - incremental + - dependency + - dependencies +--- + +After ((Authoring)) tutor files, they have to compiled down to plain docusaurus. The compiler implements features such as linking, screenshots, and executing code fragments. +Most importantly, when there are linking errors (missing or ambiguous) or code execution errors, the compiler reports them such that they can be fixed before releasing the documentation. + +## Configuration + +The way to execute the rascal tutor compiler is via [rascal-maven-plugin](http://github.com/usethesource/rascal-maven-plugin). First it +has to be configured for your project. + +Do configure the tutor, add the plugin to the pom.xml like so: + +```xml + + + org.rascalmpl + rascal-maven-plugin + 0.16.0 + + + default-cli + compile + + tutor + + + false + false + true + ${project.build.outputDirectory} + + ${project.basedir}/doc/Course1 + ${project.basedir}/doc/Course2 + ${project.basedir}/src/main/rascal + + + ${project.basedir}/src/main/rascal/experimental + + + + + + +``` + +1. `enableStandardLibrary` defines which library the links to standard library documentation refer to. Either the version of rascal that the rascal-maven-plugin depends on (`true`), or the version of rascal that the current project depends on (`false`). Also this defines which version of the library the code examples are executed against. +2. `errorsAsWarnings` and `warningsAsError` define failure modes for the compiler. Maven will not fail if `errorsAsWarnings` is set to `true` even if there are errors. +3. `isPackageCourse`, when set to `true` will nest all target documentation in `docs/Packages/projectName`, and rename `src/main/rascal` or `src` to `API`. All links will also be re-routed to these locations. Otherwise, when set to `false` all documentation ends up in `docs/Course1` and `docs/Course2`, etc. +4. `bin` points to the place that defines the root of the resulting `jar` file. All generated files will endup in `bin/docs` and `bin/docs/assets`. This has to be the outputDirectory and if you forget to configure this, it will be set automatically anyway. The compiler also writes `bin/index.value` file after it is done, to store the entire linking index for future usage. This future use can be either the next run of the compiler, or a depending project downstream. +5. `srcs` define root courses, some of which will be pure Concept hierarchies, and others could be the _root_ of Rascal source folders. Note that this also defines the search path for modules during code execution of `rascal-shell` blocks. +6. `ignores` defines files or folders which are to be ignore. These could be folder names inside of Rascal source folders, or files of Rascal modules, or course concept folders, or course concept files. When a folder is ignored, this works transitively for the contents of that folder. + +## Dependencies + +If the current Maven project has dependencies then the `index.value` files in these jar files are located +and imported in the current link index of the project. This allows you to refer to concepts in one of the +projects you depend on, provided that project was also using the `rascal-maven-plugin` to run the tutor compiler. + +The dependency feature depends on the assumption that the `/docs` folders in the jar of the current project and the jars of the +project it depends on are extracted into the `docs` folder of a Docusaurus project later, and that everything +under `/docs/assets` in the same jars is copied to `static/assets`. The `rascal-website` project +achieves this using the `resources` plugin `copy` commands. If you are running your own docusaurus site, +then this should be re-implemented. + +## Execution + +Simply run the maven `compile` or `package` or `install` command to trigger the rascal tutor compiler: + +```bash +$ mvn install +``` + +However, to exclusively run the tutor you can try this: + +```bash +$ mvn rascal:tutor +``` + +If there are screenshots in the documentation, then selenium must be configured with the location of `chrome` and `chromedriver`: + +```bash +$ mvn rascal:tutor -Dwebdriver.chrome.driver=`which chromedriver` -Dwebdriver.chrome.browser=`which chrome` +``` + +Here we have used the bash feature to splice in the location of chromedrive and chrome using the `which` command. This requires both to +be found on the system `PATH`. If this is not the case, provide the absolute path to the binaries of these two programs. Both on Mac +and Windows the path to `Google Chrome`, for example, may contain many spaces and it is wise to wrap the path in double quotes. + +The tutor compiler is **incremental** in a certain way. Running the compile twice in a row, only the markdown files and Rascal modules that have been modified will be compiled again. The compiler +reuses the output of the previous run, including error messages. All error messages and warnings, including those of unmodified files are +always presented at the end. + +Simple run the tutor twice to recompile only what has changed: + +```bash +mvn rascal:tutor +mvn rascal:tutor +``` + +:::warning +When folders or files are renamed, the old output files remain in the `bin` folder as well as the old links to those in the link index file. +This can lead to: +* spurious link ambiguity; for example when `A/B.md` has moved to `C/B.md` both versions of `B` will be present in the link administration. +* unreported missing links; for example when `A/B.md` has moved to A/C.md`, `B` will still be linked even though it is not present anymore. + +It is therefore always prudent to `mvn clean` such that the output directory including the `index.value` has been removed, when files or folder change name or location. +::: + +## Deployment of documentation + +* When `mvn install` or `mvn package` is run with the correct configuration for the `bin` folder, then all markdown files and other assets (screenshots) end up in the `jar` file of the current project. diff --git a/courses/Tutor/Concept/Benefits/Benefits.md b/courses/Tutor/Concept/Benefits/Benefits.md new file mode 100644 index 000000000..b93e111a5 --- /dev/null +++ b/courses/Tutor/Concept/Benefits/Benefits.md @@ -0,0 +1,32 @@ +--- +title: Benefits +--- + +#### Synopsis + +Briefly lists known advantages of the concept. + +#### Syntax + +``` +#### Benefits + +_MarkedText_ +``` + +#### Types + +#### Function + +#### Description + +#### Examples + +#### Benefits + +* Benefits allow a description of the, subjectively, positive aspects of a concept which is clearly delineated. This allows other sections to remain more factual and neutral. +* Benefits alert newcomers to possibilities they would not have thought of otherwise. + +#### Pitfalls + +* Benefits sections may grow into bragging lists. \ No newline at end of file diff --git a/courses/Tutor/Concept/Concept.md b/courses/Tutor/Concept/Concept.md new file mode 100644 index 000000000..e0b6dd1da --- /dev/null +++ b/courses/Tutor/Concept/Concept.md @@ -0,0 +1,61 @@ +--- +title: Concept +details: + - Title + - Keywords + - Synopsis + - Syntax + - Types + - Function + - Details + - Description + - Examples + - Benefits + - Pitfalls +--- + +#### Synopsis + +A _concept_ is the basic building block of a course. + +#### Syntax + +* `module a/b/Concept` in `a/b/Concept.rsc` +* Or a file `a/b/Concept/Concept.md`, `a/b/Concept/index.md`: + `````` + --- + title: Concept Title + keywords: + - keyword1 + - keyword2 + --- + + #### Synopsis + + This is the synopsis. + + #### Description + + #### Types + + #### Function + + #### Examples + + #### Benefits + + #### Pitfalls + `````` + +All sections are optional, but not the title header. It is always recommended to have at least a Synopsis and some Examples. Empty sections are removed by the preprocessor. + +#### Description + +A concept describes a separate entity (idea, artefact, function, rule) that is relevant in the scope of the course in which it appears. +It consists of the named sections above that are described separately. +Each section starts with a keyword that should appear at the begin of a line. + +Here is a brief summary of the sections of a concept: +(((TOC))) + + diff --git a/courses/Tutor/Concept/Description/Description.md b/courses/Tutor/Concept/Description/Description.md new file mode 100644 index 000000000..caa2e3786 --- /dev/null +++ b/courses/Tutor/Concept/Description/Description.md @@ -0,0 +1,41 @@ +--- +title: Description +--- + +#### Synopsis + +Gives a clear and concise explanation of a concept. + +#### Syntax + +``` +#### Description + +_MarkedText_ +``` + +#### Types + +#### Function + +#### Description + +The `Description` section gives a concise explanation of a concept. + +#### Examples + +The `Description` section of the concept `Description` (= the previous section) reads as follows: + +``` +#### Description + +The `Description` section gives a concise explanation of a concept. +``` + +#### Benefits + +#### Pitfalls + +* Avoid giving examples in the `Description` section but reserve these for the `Examples` section. +* Do not give explicit lists of subconcepts (details) since they are already included automatically in the `Details` section in the generated page. + diff --git a/courses/Tutor/Concept/Details/Details.md b/courses/Tutor/Concept/Details/Details.md new file mode 100644 index 000000000..e854e21fa --- /dev/null +++ b/courses/Tutor/Concept/Details/Details.md @@ -0,0 +1,65 @@ +--- +title: Details +--- + +#### Synopsis + +Explicitly list and _order_ the subconcepts of the current concept. + +#### Syntax + +Details are provided in the YAML header of the markdown file. + +``` +--- +details: + - Detail~1~ + - Detail~2~ + - ... +--- +``` + +#### Description + +To fully describe a concept, subconcepts (or details) are needed. +When the `details` meta-data header is empty, subconcepts will be listed +alphabetically in the (derived) outline of the documentation. + +This alphabetical order can be influenced by explicitly stating concepts in the details meta-data header.. +The effect is that the concepts listed there will be shown first, followed by the unmentioned subconcepts +in alphabetical order. + +The details declaration also influences the order and contents of the ((TableOfContents)) markup. + +#### Examples + +In ((Concept)) we want to order the details in the order as they appear in the concept description. +Its `Details` meta-data is therefore: + +`````` +--- +title: Concept +details: + - Name + - Details + - Syntax + - Types + - Function + - Synopsis + - Description + - Examples + - Benefits + - Pitfalls + - Questions +--- +`````` + +#### Benefits + +* With details you can choose an order for the subconcepts +* The Tutor compiler will warn about missing or additional elements in the details list. + +#### Pitfalls + +* You can forget to add a new concept to the list, or remove an old one from it. + diff --git a/courses/Tutor/Concept/Examples/Examples.md b/courses/Tutor/Concept/Examples/Examples.md new file mode 100644 index 000000000..e5e0a171f --- /dev/null +++ b/courses/Tutor/Concept/Examples/Examples.md @@ -0,0 +1,54 @@ +--- +title: Examples +--- + +#### Synopsis + +Examples to illustrate the concept. + +#### Syntax + +``` +#### Examples + +_MarkedText_ +``` + +#### Types + +#### Function + +#### Description + +Gives a number of simple but complete examples to illustrate the concepts and its variations. +Running examples are preferred. + +#### Examples + +Typically, examples would included executed code: + +`````` +```rascal-shell +import IO; +println("Hello World!") +``` +`````` + +to show this: + +```rascal-shell +import IO; +println("Hello World!") +``` + + +#### Benefits + +* Examples make documentation concrete and to the point. +* Examples can be copied by users and adapted for further exploratory learning. +* Code examples are checked by the tutor compiler for correctness (no exceptions or errors) + +#### Pitfalls + +* Code examples have to be maintained + diff --git a/courses/Tutor/Concept/Function/Function.md b/courses/Tutor/Concept/Function/Function.md new file mode 100644 index 000000000..617eb619e --- /dev/null +++ b/courses/Tutor/Concept/Function/Function.md @@ -0,0 +1,42 @@ +--- +title: Function +--- + +#### Synopsis + +Part of the synopsis that describes function signatures introduced by this concept. + +#### Syntax + +``` +#### Function + +_MarkedText_ +``` + +#### Types + +#### Function + +#### Description + +#### Examples + +Here is an example for the `readFile` function: + + +#### Syntax + +``` +#### Function + +str readFile(loc file) throws UnsupportedScheme(loc file), PathNotFound(loc file), IOError(str msg) +``` + +#### Benefits + +* These sections are usually generated from Rascal source code + +#### Pitfalls + +* The function signatures are not linked yet. diff --git a/courses/Tutor/Concept/Keywords/Keywords.md b/courses/Tutor/Concept/Keywords/Keywords.md new file mode 100644 index 000000000..605da7578 --- /dev/null +++ b/courses/Tutor/Concept/Keywords/Keywords.md @@ -0,0 +1,23 @@ +--- +title: Keywords +--- + +#### Synopsis + +Keywords are header meta-data to help search engines + +#### Syntax + +`````` +--- +title: Examples +keywords: + - '&' + - word + - "===" +--- +`````` + +#### Description + +A list of keywords is optional, but useful, for each concept. The list translates eventually to HTML meta-data that search engines may pick up. Also IDE features may use this to implement effective help facilities. \ No newline at end of file diff --git a/courses/Tutor/Concept/Pitfalls/Pitfalls.md b/courses/Tutor/Concept/Pitfalls/Pitfalls.md new file mode 100644 index 000000000..105129583 --- /dev/null +++ b/courses/Tutor/Concept/Pitfalls/Pitfalls.md @@ -0,0 +1,32 @@ +--- +title: Pitfalls +--- + +#### Synopsis + +Comprehensive list of known shortcomings or usage problems of the concept. + +#### Syntax + +``` +#### Pitfalls + +_MarkedText_ +``` + +#### Types + +#### Function + +#### Description + +#### Examples + +#### Benefits + +* Pitfalls allow a description of the, subjectively, negative aspects of a concept which is clearly delineated. This allows other sections to remain more factual and neutral. +* Pitfalls when described clearly can help newcomers to avoid the damage of well-known mistakes. + +#### Pitfalls + +* Too many pitfalls can scare newcomers away. If this happens a re-design should be considered. diff --git a/courses/Tutor/Concept/Synopsis/Synopsis.md b/courses/Tutor/Concept/Synopsis/Synopsis.md new file mode 100644 index 000000000..c72f1e4e4 --- /dev/null +++ b/courses/Tutor/Concept/Synopsis/Synopsis.md @@ -0,0 +1,33 @@ +--- +title: Synopsis +--- + +#### Synopsis + +One-line summary of the concept that is usable as a tool tip or table of contents entry + +#### Syntax + +``` +#### Synopsis + +_MarkedText_ +``` + +#### Types + +#### Function + +#### Description + +The full summary of a concept consists of the Synopsis and the optional elements +((Syntax)), ((Types)) and ((Function)). + +Synopsis is *mandatory* (this is not yet enforced). + +#### Examples + +#### Benefits + +#### Pitfalls + diff --git a/courses/Tutor/Concept/Syntax/Syntax.md b/courses/Tutor/Concept/Syntax/Syntax.md new file mode 100644 index 000000000..dd06bbef1 --- /dev/null +++ b/courses/Tutor/Concept/Syntax/Syntax.md @@ -0,0 +1,44 @@ +--- +title: Syntax +--- + +#### Synopsis + +Part of the synopsis that summarizes syntax introduced by this concept. + +#### Syntax + +``` +#### Syntax + +_MarkedText_ +``` + +#### Types + +#### Function + +#### Description + +The syntax section is intended to describe syntactic aspects of language constructs. +The contents of this section are arbitrary text. + + +#### Examples + +The syntax section for an if-then statement can be written as: + +``` +#### Syntax + +`if ( Exp ) Statement;` +``` + +#### Benefits + +* Syntax elements are usually "by example" such that you can immediately read what to write. + +#### Pitfalls + +* Syntax elements are not yet generated from actual syntax definitions + diff --git a/courses/Tutor/Concept/Title/Title.md b/courses/Tutor/Concept/Title/Title.md new file mode 100644 index 000000000..86b75490e --- /dev/null +++ b/courses/Tutor/Concept/Title/Title.md @@ -0,0 +1,42 @@ +--- +title: Title +--- + +#### Synopsis + +The display (presentation) name of a concept. + +#### Syntax + +`````` +--- +title: _ConceptName_ +--- +`````` + +#### Description + +A concept has actually three names: + +* Its file name, i.e., the name of the `.md` file in which the concept is described. +* Its _full_ name, the path name from the root concept to the current concept file. +* Its displayed title, its name as its appears as section heading and in the table of contents. + +The title metadata in the file header defines the presentation name of a concept and may be an arbitrary text. + +Concept names are used to refer to other concepts: when unambiguous its file name or display name can be used to refer to another concept, otherwise a sufficient part of its full name has to be given to make it unambiguous. + +The title is *mandatory* for every concept file. + +#### Examples + +The first line of this concept is: + +`````` +--- +title: What a title +--- +`````` + + + diff --git a/courses/Tutor/Concept/Types/Types.md b/courses/Tutor/Concept/Types/Types.md new file mode 100644 index 000000000..17424836c --- /dev/null +++ b/courses/Tutor/Concept/Types/Types.md @@ -0,0 +1,68 @@ +--- +title: Types +--- + +#### Synopsis + +Part of the synopsis that describes any types or typing rules introduced by this concept. + +#### Syntax + +``` +#### Types + +_MarkedText_ +``` + +#### Types + +#### Function + +#### Description + +The `Types` section describes any types that are involved in the concept that is described. +The description can be just text, but in many cases a table is useful to describe types. + + +#### Examples + +Here is a type description of an if-then-else statement: + +``` +#### Types + +| `Exp` | `if ( Exp ) Statement;` | +``` | +| `bool` | `void` | + + + +| `Exp` | `Statement~1~` | `Statement~2~` | `if ( Exp ) Statement~1~ else Statement~2~;` | +| --- | --- | --- | --- | +| `bool` | T~1~ | T~2~ | `lub(T~1~, T~2~)` | + +---- + +The result will be displayed as: + +#### Types + +| `Exp` | `if ( Exp ) Statement;` | +| --- | --- | +| `bool` | `void` | + + + +| `Exp` | `Statement~1~` | `Statement~2~` | `if ( Exp ) Statement~1~ else Statement~2~;` | +| --- | --- | --- | --- | +| `bool` | T~1~ | T~2~ | `lub(T~1~, T~2~)` | + + +#### Benefits + +* The reader gets an immediate overview of how to use an expression or a function + +#### Pitfalls + +* There may be many different ways of using an operator, combinatorially many, which can not be explored visually in a list or a table. +* These type signatures are written manually and not generated from source (yet) diff --git a/courses/Tutor/Maintenance/Adding/Adding.md b/courses/Tutor/Maintenance/Adding/Adding.md new file mode 100644 index 000000000..18f87b163 --- /dev/null +++ b/courses/Tutor/Maintenance/Adding/Adding.md @@ -0,0 +1,46 @@ +--- +title: Adding +--- + +#### Synopsis + +Add a concept to a course + +#### Syntax + +#### Types + +#### Function + +#### Usage + +#### Description + +There are basically two scenarios for adding a new concept, depending on where its contents come from. + +If the concept is part of a "course": + +* Select a concept that is suitable as parent for the new concept. +* Create a subdirectory, say `SubConcept` for the new subconcept. +* Create the file `SubConcept/SubConcept.md` or `SubConcept/index.md` using your favourite editor. +* Add the name and other information about the new concept. +* Save the file. + +If a concept is a Rascal source module: + +* Simply write the Rascal module in `folder/MyModule.rsc` +* Add @synopsis, @description, @examples, etc. tags to every notable declaration in the module +* Save the file. + +If a concept is a ((Concept)) or Rascal module container only: + +* Create the folder `MyConcept` +* Add new `SubConcept`s as above or new Rascal modules, as above. +* an `index.md` file will be generated for the folder + +#### Examples + +#### Benefits + +#### Pitfalls + diff --git a/courses/Tutor/Maintenance/Maintenance.md b/courses/Tutor/Maintenance/Maintenance.md new file mode 100644 index 000000000..e52ae2bdb --- /dev/null +++ b/courses/Tutor/Maintenance/Maintenance.md @@ -0,0 +1,28 @@ +--- +title: Maintenance +--- + +#### Synopsis + +How to maintain a course. + +#### Syntax + +#### Types + +#### Function + +#### Usage + +#### Description + +The following topics are discussed: + +(((TOC))) + +#### Examples + +#### Benefits + +#### Pitfalls + diff --git a/courses/Tutor/Maintenance/Removing/Removing.md b/courses/Tutor/Maintenance/Removing/Removing.md new file mode 100644 index 000000000..f6b080f4b --- /dev/null +++ b/courses/Tutor/Maintenance/Removing/Removing.md @@ -0,0 +1,31 @@ +--- +title: Removing +--- + +#### Synopsis + +Remove a concept from a course. + +#### Syntax + +#### Types + +#### Function + +#### Usage + +#### Description + +To remove a concept _C_: + +* Remove subdirectory _C_ (and its subdirectories) using standard commands. +* Recompile the course. + +#### Examples + +#### Benefits + +* If there are dangling links to the course, the compiler will produce an exact error for each reference. + +#### Pitfalls + diff --git a/courses/Tutor/Maintenance/Renaming/Renaming.md b/courses/Tutor/Maintenance/Renaming/Renaming.md new file mode 100644 index 000000000..1e3e46994 --- /dev/null +++ b/courses/Tutor/Maintenance/Renaming/Renaming.md @@ -0,0 +1,33 @@ +--- +title: Renaming +--- + +#### Synopsis + +How to rename a concept. + +#### Syntax + +#### Types + +#### Function + +#### Usage + +#### Description + +To rename a concept _C_ to _D_: + +* Rename _C_ to _D_ using the commands of the version control system. +* Rename `D/C.md` to `D/D.md` using the version control system, or keep `D/index.md` +* Open `D/D.md` in a text editor and change the title `title: Old Display Name` to `title: New Display Name`. +* Recompile the course. + +#### Examples + +#### Benefits + +* If there are dangling links to the course, the compiler will produce an exact error for each reference. + +#### Pitfalls + diff --git a/courses/Tutor/Markup/InlineMarkup/Bold/Bold.md b/courses/Tutor/Markup/InlineMarkup/Bold/Bold.md new file mode 100644 index 000000000..585e51b0c --- /dev/null +++ b/courses/Tutor/Markup/InlineMarkup/Bold/Bold.md @@ -0,0 +1,28 @@ +--- +title: Bold +--- + +#### Synopsis + +Create *bold* text. + +#### Syntax + +`````` +*Text* +`````` + +#### Types + +#### Function + +#### Description + +#### Examples + +`*bold*` gives *bold*. + +#### Benefits + +#### Pitfalls + diff --git a/courses/Tutor/Markup/InlineMarkup/Code/Code.md b/courses/Tutor/Markup/InlineMarkup/Code/Code.md new file mode 100644 index 000000000..907e993ec --- /dev/null +++ b/courses/Tutor/Markup/InlineMarkup/Code/Code.md @@ -0,0 +1,34 @@ +--- +title: Code +--- + +#### Synopsis + +Create inline code fragments. + +#### Syntax + +#### Syntax + +`````` +`MarkedText` +`````` + +#### Types + +#### Function + +#### Description + +Creates inline fragments of text that represent code. +Inside the _MarkedText_, other markup can be used. + +#### Examples + +* `` `if` `` gives `if`. +* to escape backquotes surround by more: ``` `` `if` `` ``` + +#### Benefits + +#### Pitfalls + diff --git a/courses/Tutor/Markup/InlineMarkup/Image/Image.md b/courses/Tutor/Markup/InlineMarkup/Image/Image.md new file mode 100644 index 000000000..556f322ca --- /dev/null +++ b/courses/Tutor/Markup/InlineMarkup/Image/Image.md @@ -0,0 +1,65 @@ +--- +title: Image +--- + +#### Synopsis + +Include an image. + +#### Syntax + +This is the general Markdown syntax: +`````` +![alt text](url) +`````` + +With the double brackets you can search for an image in the tutor index: +`````` +![alt text]((Link)) +`````` + +Or, if you need more configurability, like dimensions: +`````` + +`````` + + + +#### Types + +#### Function + +#### Description + +Tutor offers the simple Markdown image syntax plus referencing images in a course. +If you need more flexibility, use the HTML `` tag. + +#### Examples + +`````` +![alt]((dandelion.jpg)) +`````` + +will produce: + +![alt]((dandelion.jpg)) + +or we could use an `img` tag with a full path to the file in the assets folder: +`````` + +`````` + +which produces this: + + + + +(((TODO: uncomment the next link after bootstrapping +))) + +#### Benefits + +#### Pitfalls + +* Don't forget a sensible alt text. It makes the documentation much more accessible. diff --git a/courses/Tutor/Markup/InlineMarkup/Image/dandelion.jpg b/courses/Tutor/Markup/InlineMarkup/Image/dandelion.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5dbe2e76bb2dbb0699222d403d23b264599aaa4e GIT binary patch literal 89000 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

Nr9X`HHrsEf&eKRDfs z?EX!oa?WmVw7ofBZakCHaAw%+)X7Gf3ho`Il|_MalTfVUc?m|`H#nuh!O=&W&Nfuw zaXBhnV*DLBurnPm73NW@*5Jrfz0LUg&Gjc|lYaZ2m#zmuaok!%WCFt(Cg> zYva~E9+yxxfm2v#3srz=m9l9>%v9@mI|1zSe-+KTMLh61H2XkV$>b5t(C+(}d8VD~ z8#3e6=hdbZ{4*vu(&5rJcRs1L*!Crnq3r5XZlg#xr`(nX362)u=bXBFl{llwbv~Pu zQrUGHe3rA+=yh1iV$$jsjB-P16H@OxSM@WqQjZcb>k3@IZr!iW*zuq*nh9Fn(dSQ1 z&Z3(iGr5%MSSsRgAHUy-&MK`-$zkue64<4=cC#Qk+2(Ugl4j+Rd|#9+^zB}->{YlE zE|&%4)eqFgF)d36&Pu&it%z@Dm?@uF(#)GR`n0@WeL17G)AYHt7<(anOgVC5b;pfc ziTVEk(k`WjXq2GFvL1W1LRx&uYg; z_I9%ewcX__a??n><6@<*WM@@134mx+-Hy^mk%(kYZf;KV13fb4R@=?jZ#XIjF;FvK z7Z=8Ul9enYN^o#g-)biZjOAR(mp8+{6yzWfrWIYQ>X>>y)Ape?SxunH;#WptfKe${ z^OHxJc`A3sDsnNiAJO1Vw2sm+_Ry&exs2tTroY;F^6@lF=cHOMB_l;+Tq&DfnM`3h zhL)90n39@vek0YwDd+Wzw&N?rOJ#0iJ6*$+T9Nk0CLEgVw*dVobjbc5ab8Smwxx>9 zz9Kt5`$J5`4LgMJp>B6b;nbdYc-Z|1zAD%^1GZV*eS|AdUf4d^DmyV@>LwMZ%vBDi z=WllmQl<|hhVKqyBCy>>Eo3kDNZ@^->3S}zgC^~*eSzW-Qp??&OCbGY