diff --git a/packages/preview/acrostiche/0.4.0/.gitignore b/packages/preview/acrostiche/0.4.0/.gitignore new file mode 100644 index 000000000..a13633799 --- /dev/null +++ b/packages/preview/acrostiche/0.4.0/.gitignore @@ -0,0 +1 @@ +*.pdf diff --git a/packages/preview/acrostiche/0.4.0/LICENSE b/packages/preview/acrostiche/0.4.0/LICENSE new file mode 100644 index 000000000..b291d1380 --- /dev/null +++ b/packages/preview/acrostiche/0.4.0/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2023 Arthur Grisel-Davy +Copyright (c) 2023 Aurel Weinhold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/preview/acrostiche/0.4.0/README.md b/packages/preview/acrostiche/0.4.0/README.md new file mode 100644 index 000000000..e11224476 --- /dev/null +++ b/packages/preview/acrostiche/0.4.0/README.md @@ -0,0 +1,122 @@ +# Acrostiche (0.4.0) + +Manages acronyms so you don't have to. + +## Quick Start + +``` +#import "@preview/acrostiche:0.4.0": * + +#init-acronyms(( + "WTP": ("Wonderful Typst Package","Wonderful Typst Packages"), +)) + +Acrostiche is a #acr("WTP")! This #acr("WTP") enables easy acronyms manipulation. + +Its main features are auto-expansion of the first occurence, global or selective expansion reset #reset-all-acronyms(), implicit or manual plural form support (there may be multiple #acrpl("WTP")), and customizable index printing. Have Fun! +``` + + +## Usage + +The main goal of Acrostiche is to keep track of which acronyms to define. + +### Define acronyms +First, define the acronyms in a dictionary, with the keys being the acronyms and the values being arrays of their definitions. +If there is only a singular version of the definition, the array contains only one value. +If there are both singular and plural versions, define the definition as an array where the first item is the singular definition and the second item is the plural. +Then, initialize Arostiche with the acronyms you just defined with the `#init-acronyms(...)` function: + +Here is a sample of the `acronyms.typ` file: +``` +#import "@preview/acrostiche:0.4.0": * + +#init-acronyms(( + "NN": ("Neural Network"), + "OS": ("Operating System",), + "BIOS": ("Basic Input/Output System", "Basic Input/Output Systems"), +)) +``` + +### Call Acrostiche functions +Once the acronyms are defined, you can use them in the text with the `#acr(...)` function. +The argument is the acronym as a string (for example, "BIOS"). On the first call of the function, it prints the acronym with its definition (for example, "Basic Input/Output System (BIOS)"). +On the next calls, it prints only the acronym. + +To get the plural version of the acronym, you can use the `#acrpl(...)` function that adds an 's' after the acronym. +If a plural version of the definition is provided, it will be used if the first use of the acronym is plural. +Otherwise, the singular version is used, and a trailing 's' is added. + +To intentionally print the full version of the acronym (definition + acronym, as for the first instance), without affecting the state, you can use the `#acrfull(...)` function. For the plural version, use the `#acrfullpl(...)` function. +Both functions have shortcuts with `#acrf(...)` and `#acrfpl(...)`. + +At any point in the document, you can reset acronyms with the functions `#reset-acronym(...)` (for a single acronym) or `reset-all-acronyms()` (to reset all acronyms). After a reset, the next use of the acronym is expanded. +Both functions have shortcuts with `#racr(...)` and `#raacr(...)`. + +You can also print an index of all acronyms used in the document with the `#print-index()` function. +The index is printed as a section for which you can choose the heading level, the numbering, and the outline parameters (with respectively the `level: int`, `numbering: none | string | function`, and `outlined: bool` parameters). +You can also choose their order with the `sorted: string` parameter that accepts either an empty string (print in the order they are defined), "up" (print in ascending alphabetical order), or "down" (print in descending alphabetical order). +By default, the index contains all the acronyms you defined. You can choose to only display acronyms that are actually used in the document by passing `used-only: true` to the function. Warning, the detection of used acronym uses the states at the end of the document. Thus, if you reset an acronym and do not use it again until the end, it will not appear in the index. + You can use the `title: string` parameter to change the name of the heading for the index section. +The default value is "Acronyms Index". Passing an empty string for `title` results in the index having no heading (i.e., no section for the index). +You can customize the string displayed after the acronym in the list with the `delimiter: ":"` parameter. +To adjust the spacing between the acronyms adjust the `row-gutter: auto | int | relative | fraction | array` parameter, the default is `2pt`. + +Finally, you can call the `#display-def(...)` function to display the definition of an acronym. Set the `plural` parameter to true to get the plural version. + +### Functions Summary: + +| **Function** | **Description** | +|-------------------------------|---------------------------------------------------------------------------------------------------------------------| +| **#init-acronyms(...)** | Initializes the acronyms by defining them in a dictionary where the keys are acronyms and the values are definitions. | +| **#acr(...)** | Prints the acronym with its definition on the first call, then just the acronym in subsequent calls. | +| **#acrpl(...)** | Prints the plural version of the acronym. Uses plural definition if available, otherwise adds an 's' to the acronym. | +| **#acrfull(...)** | Displays the full (long) version of the acronym without affecting the state or tracking its usage. | +| **#acrfullpl(...)** | Displays the full plural version of the acronym without affecting the state or tracking its usage. | +| **#reset-acronym(...)** | Resets a single acronym so the next usage will include its definition again. | +| **#reset-all-acronyms()** | Resets all acronyms so the next usage will include their definitions again. | +| **#print-index(...)** | Prints an index of all acronyms used, with customizable heading level, order, and display parameters. | +| **#display-def(...)** | Displays the definition of an acronym. Use `plural: true` to display the plural version of the definition. | +| **racr, raacr, acrf, acrfpl** | Shortcuts names for respectively `reset-acronym`, `reset-all-acronyms`, `acrfull`, and `acrfullpl`. | + +## Advanced Definitions +This is a bit of a hacky feature coming from pure serendipity. +There is no enforcement of the type of the definitions. +Most users would naturally use strings as definitions, but any other content is acceptable. +For example, you set your definition to a content block with rainbow-fille text, or even an image. +The rainbow text is kinda cool because the gradient depend on the position in the page so depending on the position of first use the acronym will have a pseudo-random color. + +If you use anything else than string for the definition, do not forget the trailing comma to force the definition to be an array (an array of a single element is not an array in Typst at the time of writing this). +I cannot guarantee that arbitrary content will remain available in future versions but I will do my best to keep it as it is kinda cool. +If you find cool uses, please reach out to show me! + + +PS: For the smart trouble-maker in the back that are thinking about nesting an acronym call in the definition of an acronym, I am way ahead of you and yes it is (kinda) possible. +If you point to another acronym, it all works fine. +If you point to the same acronym, you obviously create a recursive situation, and it fails. +It will not converge, and the compiler will warn you and will panic. +Be nice to the compiler, don't throw recursive traps. + + +Here is a minimal working example of funky acronyms: + +``` +#import "@preview/acrostiche:0.4.0": * +#init-acronyms(( + "RFA": ([#text(fill: gradient.linear(..color.map.rainbow))[Rainbow Filled Acronym]],), + "NA": ([Nested #acr("RFA") Acronym],) +)) +#acr("NA") +``` + +## Possible Errors: + + * If an acronym is not defined, an error will tell you which one is causing the error. Simply add it to the dictionary or check the spelling. + * `display-def` leverages the state `display` function and only works if the return value is actually printed in the document. For more information on states, see the Typst documentation on states. + * Acrostiche uses a state named `acronyms` to keep track of the definitions and usage. If you redefined this state or use it manually in your document, unexpacted behaviour might happen. + +# Acknowledgments + +Thank you to the contributors: **caemor**, **AurelWeinhold**, **daniel-eder**, **iostapyshyn**. + +If you notice any bug or want to contribute a new feature, please open an issue or a merge request on the fork [Grisely/packages](https://github.com/Grisely/packages) diff --git a/packages/preview/acrostiche/0.4.0/acrostiche.typ b/packages/preview/acrostiche/0.4.0/acrostiche.typ new file mode 100644 index 000000000..7f20c700b --- /dev/null +++ b/packages/preview/acrostiche/0.4.0/acrostiche.typ @@ -0,0 +1,177 @@ +// Acrostiche package for Typst +// Author: Grizzly + + +#let acros = state("acronyms",none) +#let init-acronyms(acronyms) = { + let states = (:) + for (acr, defs) in acronyms{ + let data = (defs, false) + states.insert(acr,data) + } + acros.update(states) +} + +#let display-def(plural: false, acr) = { + // Display the definition of an acronym by fetching it in the "acronyms" state's value (should be a dictionary). + + // First, grab the dictionary of definitions of acronyms from the "acronyms" state + context{ + let acronyms = acros.get() + if acr in acronyms{ + let defs = acronyms.at(acr).at(0) + if type(defs) == "string"{ // If user defined only one version and forgot the trailing comma the type is string + if plural{panic("You requested the plural version of the acronym but it seems like you only provided the singular version in #init-acronyms(dict)")} + else{defs} // All is good, we return the definition found as the singular version + } + else if type(defs) == "array"{ + if defs.len() == 0{ // The user could have provided an empty array, unlikely but possible. + panic("No definitions found for acronym "+acr+". Make sure it is defined in the dictionary passed to #init-acronyms(dict)") + }else if defs.len() == 1{ // User provided only one version, we make the plural by adding an "s" at the end. + if plural{defs.at(0)+"s"} + else{defs.at(0)} + }else{ // User provided more than one version. We assume the first is singular and the second is plural. All other are useless. + if plural{defs.at(1)} + else{defs.at(0)} + } + }else{ + panic("Definitions should be arrays of one or two strings. Definition of "+acr+ " is "+defs+" of type: "+type(defs)) + } + }else{ + panic(acr+" is not a key in the acronyms dictionary.") + } + } + +} + +#let acr(acr, plural:false) = { + // Display an acronym in the singular form by default. Expands it if used for the first time. + + // Generate the key associated with this acronym + let state-key = "acronym-state-" + acr + // Test if the state for this acronym already exists and if the acronym was already used + // to choose what to display. + context{ + let data = acros.get() + if acr in data{ + let short = if plural{[#acr\s]}else{acr} + if data.at(acr).at(1){ + short + }else{ + [#display-def(plural: plural, acr)~(#short)] + } + data.at(acr).at(1) = true + }else{ + panic("You requested the acronym "+acr+" that you did not define first.") + } + acros.update(data) + } +} + +#let acrpl(acronym) = {acr(acronym,plural:true)} // argument renamed acronym to differentiate with function acr + +#let acrfull(acr) = { + //Intentionally display an acronym in its full form. Do not update state. + [#display-def(plural: false, acr) (#acr)] +} + +#let acrfullpl(acr) = { + //Intentionally display an acronym in its full form in plural. Do not update state. + [#display-def(plural: true, acr) (#acr\s)] +} + +// define shortcuts + + +#let reset-acronym(acr) = { + // Reset a specific acronym. It will be expanded on next use. + context{ + let data = acros.get() + if acr in data{ + data.at(acr).at(1) = false + }else{ + panic("You requested the acronym "+acr+" that you did not define first.") + } + acros.update(data) + } +} + +#let reset-all-acronyms() = { + // Reset all acronyms. They will all be expanded on the next use. + context{ + let acronyms = acros.get() + for acr in acronyms.keys(){ + reset-acronym(acr) + } + } +} + +// Define shortcuts +#let acrf(acr) = {acrfull(acr)} +#let acrfpl(acr) = {acrfullpl(acr)} +#let racr(acr) = {reset-acronym(acr)} +#let raacr() = reset-all-acronyms() + + +#let print-index(level: 1, numbering: none, outlined: false, sorted:"", + title:"Acronyms Index", delimiter:":", row-gutter: 2pt, used-only: false) = { + //Print an index of all the acronyms and their definitions. + // Args: + // level: level of the heading. Default to 1. + // outlined: make the index section outlined. Default to false + // sorted: define if and how to sort the acronyms: "up" for alphabetical order, "down" for reverse alphabetical order, "" for no sort (print in the order they are defined). Default to "". + // title: set the title of the heading. Default to "Acronyms Index". Passing an empty string will result in removing the heading. + // delimiter: String to place after the acronym in the list. Defaults to ":" + // used-only: if true, only include in the index the acronyms that are used in the document. Warning, if you reset acronyms and don't used them after, they may not appear. + + // assert on input values to avoid cryptic error messages + assert(sorted in ("","up","down"), message:"Sorted must be a string either \"\", \"up\" or \"down\"") + + if title != ""{ + heading(level: level, numbering: numbering, outlined: outlined)[#title] + } + + context{ + let acronyms = acros.get() + + // Updated + // Build acronym list + let acr-list = acronyms.keys() + + if used-only{ + // Select only acronyms where state is true at the end of the document. + // TODO Ideally, the code would check if the acronym is used anywhere in the document, + // but I don't know how to do that yet. Feel free to propose changes. + let used-acr-list = () + for acr in acr-list{ + if acros.final().at(acr).at(1) { + used-acr-list.push(acr) + } + } + acr-list = used-acr-list + } + + // FEATURE: allow ordering by occurences position in the document. Not sure if possible yet. + + // order list depending on the sorted argument + if sorted=="down"{ + acr-list = acr-list.sorted().rev() + }else if sorted=="up"{ + acr-list = acr-list.sorted() + } + + // print the acronyms + table( + columns: (20%,80%), + stroke: none, + row-gutter: row-gutter, + ..for acr in acr-list{ + let desc = if type(acronyms.at(acr).at(0)) == array { + acronyms.at(acr).at(0).at(0) + } else {acronyms.at(acr).at(0)} + ([*#acr#delimiter*], desc) + } + ) + } +} + diff --git a/packages/preview/acrostiche/0.4.0/test.typ b/packages/preview/acrostiche/0.4.0/test.typ new file mode 100644 index 000000000..cbaebdadc --- /dev/null +++ b/packages/preview/acrostiche/0.4.0/test.typ @@ -0,0 +1,61 @@ +#import "@preview/acrostiche:0.4.0": * + +#init-acronyms(( + "PFT": ("Package For Typst","Packages For Typst"), + "AJT": ("Amicale des Joyeux Typistes"), + "TEA": ("The Extra Acronym",), +)) + +#let ref(str) = [#text(fill:green)[#str]] + +== Acronym with Two Definitions. + +First use of #acr("PFT") and second use of #acr("PFT").\ +#ref("First use of Package For Typst (PFT) and second use of PFT.") + +Reset acronyms. #reset-acronym("PFT") + +First use of plural #acrpl("PFT") and second use of plural #acrpl("PFT").\ +#ref("First use of plural Packages For Typst (PFTs) and second use of plural PFTs.") + +Reset acronyms. #racr("PFT") + +Full definition of #acrfull("PFT") and full plural definition of #acrfullpl("PFT"). +Full definition of #acrf("PFT") and full plural definition of #acrfpl("PFT"). +#ref("Full definition of Package For Typst (PFT) and full plural definition of Packages For Typst (PFTs).") + +== Acronym with a Single Definition. + +First use of #acr("AJT") and second use of #acr("AJT").\ +#ref("First use of Amicale des Joyeux Typistes (AJT) and second use of AJT.") + + +Reset acronyms. #racr("AJT") + +Full definition of #acrfull("AJT").\ +Full definition of #acrf("AJT").\ +#ref("Full definition of Amicale des Joyeux Typistes (AJT)") + +== Reset All Acronyms + +Use #acr("PFT") and #acr("AJT").\ +Reset.#reset-all-acronyms()\ +Use again #acr("PFT") and #acr("AJT"). + +#ref(" +Use Package For Typst (PFT) and Amicale des Joyeux Typistes (AJT). +Reset. +Use again Package For Typst (PFT) and Amicale des Joyeux Typistes (AJT). +") + +== Print Index Variations + +#print-index() + +#print-index(title:"Sorted Empty",sorted:"") +#print-index(title:"Sorted up", sorted:"up") +#print-index(title:"Sorted down", sorted:"down") + +#print-index(title:"Used only up", sorted: "up", used-only:true) +#print-index(title:"Used only down", sorted: "down", used-only:true) + diff --git a/packages/preview/acrostiche/0.4.0/typst.toml b/packages/preview/acrostiche/0.4.0/typst.toml new file mode 100644 index 000000000..f62b55fb1 --- /dev/null +++ b/packages/preview/acrostiche/0.4.0/typst.toml @@ -0,0 +1,11 @@ +[package] +name = "acrostiche" +version = "0.4.0" +entrypoint = "acrostiche.typ" +repository = "https://github.com/Grisely/packages" +authors = ["Grizzly"] +license = "MIT" +keywords = ["acronyms"] +categories = ["utility","model"] +exclude = ["test.typ"] +description = "Manage acronyms and their definitions in Typst."