{"id":28432484,"url":"https://github.com/amari-calipso/univ","last_synced_at":"2025-07-01T08:31:47.605Z","repository":{"id":294041847,"uuid":"985826094","full_name":"amari-calipso/UniV","owner":"amari-calipso","description":"UniV - The unifying sorting visualization software","archived":false,"fork":false,"pushed_at":"2025-06-29T15:43:53.000Z","size":2277,"stargazers_count":5,"open_issues_count":28,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-29T16:38:09.202Z","etag":null,"topics":["array-manipulation","array-manipulations","array-visualizer","compiler","language-design","language-engineering","programming-language","python","python3","raylib","raylib-rs","rust","sorting","sorting-algorithms","sorting-visualization","transpilation","transpiler"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amari-calipso.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-18T15:54:30.000Z","updated_at":"2025-06-29T15:43:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"1d98e8d4-25d8-4e07-ab71-b7bb99d1eff6","html_url":"https://github.com/amari-calipso/UniV","commit_stats":null,"previous_names":["amari-calipso/univ"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/amari-calipso/UniV","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2FUniV","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2FUniV/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2FUniV/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2FUniV/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amari-calipso","download_url":"https://codeload.github.com/amari-calipso/UniV/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2FUniV/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262927667,"owners_count":23386005,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["array-manipulation","array-manipulations","array-visualizer","compiler","language-design","language-engineering","programming-language","python","python3","raylib","raylib-rs","rust","sorting","sorting-algorithms","sorting-visualization","transpilation","transpiler"],"created_at":"2025-06-05T17:08:51.482Z","updated_at":"2025-07-01T08:31:47.593Z","avatar_url":"https://github.com/amari-calipso.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](resources/logo.png)\n\n# UniV - The unifying sorting visualization software\nUniV aims to be the most feature-rich, easy to use, and compatible sorting visualization software, all while being one of the fastest and most capable.\n\n# What does \"UniV\" mean?\n\"UniV\" stands for \"unifying visualizer\" or \"universal visualizer\". It's a wordplay on ArrayV, the popular sorting visualization program (don't worry, i was involved in its development, so i'm allowed to take inspiration ;3). UniV is \"unifying\" and \"universal\", because it's the only currently available visualization software that is able to implement compatibility layers with different programming languages and other visualization software. This means that it's virtually able to run algorithms written in every language, as long as a compatibility layer is written for it. UniV is also the unification of previous experiences in developing similar software, like the old \"SortTheater\" project, ArrayV, and my [opal Sorting Visualizer, \"oSV\" for short](https://github.com/amari-calipso/sorting-visualizer), the last one being the greatest ground for experimenting with techniques and approaches. The architecture of UniV's graphics and sound is heavily inspired and influenced by it, so check it out!\n\n# Why UniV?\n- UniV is **feature-rich**. It's the most advanced sorting visualization software currently available. It allows for detailed animations with plenty of encodable information, it provides great user interaction, and all of the features from modern visualization programs;\n- UniV is **easy to use**, both for users, and programmers. It's specifically designed to have an intuitive interface, and the easiest to use API available. Actually, if you're writing algorithms for UniV, you don't even have to interact with an API at all! Thanks to the dedicated virtual machine, UniV is able to automatically recognize the operations that algorithms perform and visualize them with no further efforts. UniV also tries to be extremely developer-friendly: its code is written to be as simple as possible, and to be built or ran from source without too much of a headache, check it out yourself [here](#run-or-build)!\n- UniV is **convenient**. The user interface is designed to be as intuitive as possible, without shoving too many things in front of the user. It has a bunch of quality of life features to make experimentation easier and visualization more enjoyable, and it even provides [an extremely simple custom scripting language for automating visualizations](#the-univ-automation-language), perfect for creating videos without needing to interact with the program, or for creating complex shuffles by combining existing ones!\n- UniV is **universal**. As mentioned before, you can run a lot of things on UniV, as long as it has a translation layer for your language and API;\n- UniV is **modular**. The architecture is built in such a way that it's easy to add new components to UniV. Want a new visual style? or a new sound system perhaps? a new algorithm? check how easy it is to [add it yourself](#how-to-add-an-algorithm)!\n- UniV is **great for creating videos**. Thanks to its integration with [ffmpeg](https://ffmpeg.org/), UniV is able to produce high quality videos without needing any recording software, and without any frame drops, as the video is generated from scratch instead of it being a screen recording;\n- UniV loves **open source**. Contributions and forks are more than welcome, and UniV attempts to be as open and accessible as possible for developers.\n\n# Run or build\nNote that using render mode requires having [ffmpeg](https://ffmpeg.org/) installed on your machine.\n\nJump to [releases](https://github.com/amari-calipso/UniV/releases) if you just want to use the program! If you're not planning to play around with the algorithms' code, or your machine is not particularly fast, you can download the \"lite\" version, for a version that's stripped out of the compiler capabilities, hence reducing the hardware requirements significantly.\n\nIf you're running or building from source, make sure that your machine has installed:\n- [raylib's dependencies](https://github.com/raysan5/raylib/wiki);\n- [CMake](https://cmake.org/) (note that release candidate versions, marked as \"rc\", might not work);\n- libclang (if you're on Windows, you can download [LLVM](https://releases.llvm.org/download.html), which contains libclang);\n\nTo run or build from source, clone the repository first, then you have two options:\n- To run directly, just use `cargo run`.\n- To package a release, (a `dist` folder containing the release will be created, note that **any previously existing `dist` folders will be deleted**) run:\n    - If building a full release:\n        - Unix-like: `rustc dev_util.rs -o dev_util \u0026\u0026 ./dev_util --release`\n        - Windows: `rustc dev_util.rs -o dev_util.exe \u0026\u0026 dev_util --release`\n    - If building a \"lite\" release:\n        - Unix-like: `rustc dev_util.rs -o dev_util \u0026\u0026 ./dev_util --release-lite`\n        - Windows: `rustc dev_util.rs -o dev_util.exe \u0026\u0026 dev_util --release-lite`\n\n# Architecture\n![](readme/architecture.png)\n\n# Documentation\n## Table of contents\n- [The UniV Automation Language](#the-univ-automation-language)\n    - [Syntax](#syntax)\n    - [Running an automation](#running-an-automation)\n    - [Creating a shuffle by combining existing ones](#creating-a-shuffle-by-combining-existing-ones)\n- [UniL: the \"core\" language](#unil-the-core-language)\n    - [Syntax](#syntax-1)\n    - [The standard library](#the-standard-library)\n    - [Visualizer interaction](#visualizer-interaction)\n    - [How to add an algorithm](#how-to-add-an-algorithm)\n- [Third party language support](#third-party-language-support)\n    - [Python](#python)\n        - [What is supported and what is not supported](#what-is-supported-and-what-is-not-supported)\n        - [API support](#api-support)\n    - [Java](#java)\n- [Adding visual styles](#adding-visual-styles)\n- [Adding sound engines](#adding-sound-engines)\n- [Adding API compatibility layers](#adding-api-compatibility-layers)\n- [Adding language compatibility layers](#adding-language-compatibility-layers)\n\n## The UniV Automation Language\nUniV has a powerful automation system, which allows to create scripts to automatically perform actions, such as selecting a visual style, running an algorithm, changing the visualization speed, and more... \n### Syntax\nScripts are defined using the UniV Automation Language (or UAL).\n\nTo run an algorithm, use the `run` statement\n```\nrun distribution \"Linear\" with length 64\nrun shuffle \"Random\"\nrun sort \"Bubble Sort\" in \"Exchange Sorts\"\n\n// you can specify the number of unique items\nrun distribution \"Quadratic\" with length 64 and 4 unique\nrun shuffle \"Reversed\"\nrun sort \"Sandpaper Sort\" in \"Exchange Sorts\"\n\n// the order of clauses doesn't matter\nrun distribution \"Quintic\" with 8 unique and length 64\nrun shuffle \"Sawtooth\"\nrun sort \"Insertion Sort\" in \"Insertion Sorts\"\n```\n\nSome algorithms require user input, so you can `push` values to a queue to avoid having to input them every time the algorithm runs\n\n```\nrun distribution \"Linear\" with length 512\nrun shuffle \"Random\"\n\npush 0 // the program would normally ask for buffer size, but this automatically enters \"0\" in the prompt, without showing it to the user\npush \"Gries-Mills\" // here, the program would ask for a rotation algorithm, which is instead provided here\nrun sort \"Grail Sort\" in \"Block Merge Sorts\"\n```\n\nThe queue can also be `pop`ped, in case further edits are required\n```\npush \"Hello, World!\"\npop // removes the first value from the queue\n```\n\nIf you decide you want to get rid of all values in the queue, you can `reset` it\n```\npush 1\npush 2\npush 3\nreset queue\n// no value is in the queue\n```\n\nIt is possible to set a certain visual style within your script\n```\nset visual \"Color Circle\"\n\nrun distribution \"Linear\" with length 64\nrun sort \"Bubble Sort\" in \"Exchange Sorts\"\n```\n\nAnd you can also manipulate visualization speed\n```\nset visual \"Bar Graph\"\n\nrun distribution \"Linear\" with length 256\nrun shuffle \"Random\"\nset speed 80\nrun sort \"Bubble Sort\" in \"Exchange Sorts\"\n```\n\nYou can reset the speed to its default value, if you want\n```\nset speed 80\nreset speed // i changed my mind\n```\n\nFor convenience, you can also define constants that you can reuse later on\n```\ndefine BUBBLE_SORT_SPEED 80\n\nset visual \"Bar Graph\"\n\nrun distribution \"Linear\" with length 256\nrun shuffle \"Random\"\nset speed BUBBLE_SORT_SPEED\nrun sort \"Bubble Sort\" in \"Exchange Sorts\"\n\nrun distribution \"Linear\" with length 256\nrun shuffle \"Reversed\"\nset speed BUBBLE_SORT_SPEED\nrun sort \"Bubble Sort\" in \"Exchange Sorts\"\n```\n\nYou can also `describe` your automation, to show a summary of what the automation does in UniV's GUI\n```\ndescribe \"Runs Bubble Sort on 256 random items on the Bar Graph visual style\"\n\ndefine BUBBLE_SORT_SPEED 80\n\nset visual \"Bar Graph\"\n\nrun distribution \"Linear\" with length 256\nrun shuffle \"Random\"\nset speed BUBBLE_SORT_SPEED\nrun sort \"Bubble Sort\" in \"Exchange Sorts\"\n```\n\nIt is possible to use the UniV Automation Language to define integrated procedures, such as Run All Sorts and Run All Shuffles. Check their relative files in the `automations` folder for an example of how they work.\n\n### Running an automation\nTo run an automation, you can add it to the `automations` folder in UniV. The next time you open the program (or click \"Reload algos\" in the settings) and open the \"Run automation\" menu, your automation will be there.\n\n### Creating a shuffle by combining existing ones\nAutomations can also be useful to combine shuffles together, to create more complex ones\n\n```\nrun shuffle \"Scrambled Tail\"\nrun shuffle \"Reversed\"\n```\n\nThis script will first run the \"Scrambled Tail\" shuffle, and then reverse it, creating a new shuffle which isn't present in the program. To run your shuffle automation, you can just select \"Run automation\" as a shuffle in any of the menus.\n\n## UniL: the \"core\" language\nUniL is the language native to UniV. You can write algorithms in any supported language, but using UniL will give you the best support.\n### Syntax\nIn UniL, everything is an expression and returns a value.\n#### Comments\n```\n// This is a comment\n\n/*\n    This is a multiline comment\n    It can't be nested\n*/\n```\n#### Variables\n```\na := 0; // := declares a variable. In this context, UniL will infer the variable's type\nb: Int := 0; // You can manually specify types\n\nc: any := 0; // If the specified type is \"any\", the variable will be dynamically typed\n\n// Variables can be reassigned\na = 1; \nc = \"Hello\";\n```\n#### Types\nAvailable types are:\n- `any`\n- `Int`\n- `Float`\n- `String`\n- `Value` (items in an array created from UniV)\n- `List`\n- `Object`\n- `Null`\n- `Bool` (alias of `Int`)\n#### Lists\nYou can create a list using the following syntax\n```\nmyList := [1, 2, 3, \"Hello\"];\n```\n\nTo create an array for sorting, use `Array`\n```\nmyArray := Array(10); // Creates an array of 10 elements\n```\n#### Conditionals\n##### If statements\n```\nif 2 + 2 == 4 {\n\ta := true;\n\tif (a) log(\"True!\");\n}\n```\n##### While loops\n```\na := 2;\nwhile a-- {\n    log(\"Looping\");\n}\n\na = 3;\ndo {\n    log(\"Looping yet again\");\n} while a--;\n```\n##### For loops\n```\nfor i := 0; i \u003c 10; i++ {\n    log(\"This will be printed 10 times\");\n}\n```\n##### Foreach loops\n```\n// 1 2 3\nforeach item: [1, 2, 3] {\n    log(item); \n}\n\nforeach i: Range(0, 10) {\n    log(\"This will be printed 10 times\");\n}\n```\nForeach loops can iterate any object containing a `next` field, which is a function that takes the object as parameter and returns `any`, or `Null`, when the iteration is finished.\n\n##### Switch statements\n```\na := 2;\nswitch a {\n    3 | 4 | 5 {\n        log(\"Nope!\");\n    }\n    2 {\n        log(\"Here!\");\n    }\n    default {\n        log(\"Something else\");\n    }\n}\n```\n#### Functions\nTo create a function, you can use the `fn` keyword, like so:\n```\nfn add(a: Int, b: Int) Int {\n    return a + b;\n}\n\nfn addAny(a, b) {\n    return a + b;\n}\n\nfn addNumbers(a: Int | Float, b: Int | Float) Int | Float {\n    return a + b;\n}\n\nfn sayHello() {\n    log(\"Hello!\");\n}\n```\n#### Objects\nObjects are created by defining their fields:\n```\nmyObject := #{\n    field1: 0,\n    field2: \"Field 2\",\n    sayHi: fn _() {\n        log(\"Hi!\");\n    }\n};\n```\n\n#### Exceptions\n```\nfn add(a: Int | String, b: Int | String) Int | String {\n    if stringifyType(a) == \"String\" {\n        if stringifyType(b) == \"String\" {\n            return a + b;\n        } \n    } else if stringifyType(a) == \"Int\" {\n        if stringifyType(b) == \"Int\" {\n            return a + b;\n        }\n    }\n\n    throw \"Cannot add given values\";\n}\n\ntry {\n    a := add(1, \"Hello\");\n} catch {\n    log(\"An error occurred\");\n}\n\n\ntry {\n    a := add(1, 1);\n} catch (e) {\n    log(e);\n}\n\n// using only a try branch will ignore exceptions\ntry a := add(0, 0);\n```\n#### Scoped and unscoped blocks\nBy default, blocks are unscoped, that means that if you define a variable within a block, it will be defined in the function's scope. You can change this behavior by using scoped blocks\n```\na := 1;\nif a == 1 {\n    b := 2;\n} else {\n    b := 3;\n}\n\n// b will be available here\n\nif a == 1 ${\n    c := 2;\n} else ${\n    c := 3;\n}\n\nlog(c); // Undefined variable\n```\n\n#### Main operators\n| name | syntax | additional notes |\n| ---- | ------ | ----------- |\n| Prefix increment | `++x` | Increments `x` before it's used |\n| Suffix increment | `x++` | Increments `x` after it's used |\n| Prefix decrement | `--x` | Decrements `x` before it's used |\n| Suffix decrement | `x--` | Decrements `x` after it's used |\n| Negation | `-x` | ... |\n| Boolean not | `!x` | ... |\n| Bitwise not | `~x` | ... |\n| Access | `x.y` | Accesses the `y` property of `x`, where `x` is an Object |\n| Addition | `x + y` `x += y` | ... |\n| Subtraction | `x - y` `x -= y` | ... |\n| Multiplication | `x * y` `x *= y` | ... |\n| Division | `x / y` `x /= y` | ... |\n| Modulo | `x % y` `x %= y` | ... |\n| Shift left | `x \u003c\u003c y` `x \u003c\u003c= y` | Shifts `x` left `y` times |\n| Shift right | `x \u003e\u003e y` `x \u003e\u003e= y` | Shifts `x` right `y` times |\n| Boolean or | \u003ccode\u003ex \u0026#124;\u0026#124; y\u003c/code\u003e | ... |\n| Boolean and | `x \u0026\u0026 y` | ... |\n| Bitwise xor | `x ^ y` `x ^= y` | ... |\n| Bitwise and | `x \u0026 y` `x \u0026= y` | ... |\n| Bitwise or | \u003ccode\u003ex \u0026#124; y\u003c/code\u003e \u003ccode\u003ex \u0026#124;= y\u003c/code\u003e | Can define a type group if the operands are types |\n| Greater | `x \u003e y` | ... |\n| Greater or equal | `x \u003e= y` | ... |\n| Less | `x \u003c y` | ... |\n| Less or equal | `x \u003c= y` | ... |\n| Equality | `x == y` | ... |\n| Inequality | `x != y` | ... |\n| Ternary | `x ? y : z` | Returns `y` if `x` is truthy, otherwise returns `z` |\n\n### The standard library\nThe most important functions in the standard library are:\n- `swap(List, Int, Int) Null`: swaps two indices in an array;\n- `List_push(List, any) Null`: pushes a value to the end of a List;\n- `List_clear(List) Null`: removes all elements in a List;\n- `List_min(List) any`: returns the minimum item in a List;\n- `List_max(List) any`: returns the maximum item in a List;\n- `min(any, any) any`: returns the minimum of two values;\n- `max(any, any) any`: returns the maximum of two values;\n- `log(any) Null`: prints the given object on the console;\n- `stringify(any) String`: turns the given object into a string;\n- `stringifyType(any) String`: returns a string containing the name of the value type;\n- `parseInt(String) Int`: parses an Int from a String. Throws an exception if there is no parsable Int in the String;\n- `parseFloat(String) Float`: same as `parseInt`, but with Floats\n- `asAny(any) any`: does nothing, can be useful to turn a value into the `any` type at analysis time;\n- `int(Int | Float | Value) Int`: casts the given number type into an Int. Throws an exception if the cast is impossible;\n- `float(Int | Float | Value) Float`: same as `int`, but with Floats;\n- `round(Int | Float | Value) Int`: returns the closest Int to the given value;\n- `len(String | List) Int`: returns the length of a String or List;\n- `randomInt(a: Int | Value, b: Int | Value) Int`: returns a random Int in range [a, b];\n- `randomUniform() Float`: returns a random Float in range [0, 1];\n- `math_pow(base: Int | Value | Float, exp: Int | Value | Float) Int | Float`;\n- `math_ceil(Int | Value | Float) Int`;\n- `math_floor(Int | Value | Float) Int`;\n- `Range(a: Int | Value, b: Int | Value) Object`: returns a range object for iterating in the range [a, b);\n- `RangeWithStep(a: Int | Value, b: Int | Value, step: Int | Value) Object`: like `Range`, but also accept a step. Instead of advancing iteration by 1, it will advance by `step`;\n- `Thread(Callable, List) Int`: creates a Thread given a function and the arguments to pass to it. Returns the Thread ID;\n- `Thread_start(Int) Null`: starts a Thread given its ID;\n- `Thread_join(Int) any`: waits for a Thread to finish running and returns its output given its ID.\n\n### Visualizer interaction\nUniL also provides access to functions to interact with the visualizer\n#### Auxiliary arrays\n- `Array(Int) List`: returns an auxiliary array of a given size that can be used for sorting;\n- `StandaloneArray(Int) List`: like `Array`, but the array will not be added to the visualization;\n- `UniV_setNonOrigAux(List) Null`: sets an auxiliary array as \"not having original values\", that is, it doesn't contain values from the original array. This improves the quality of visuals;\n- `UniV_removeAux(List) Null`: removes the given auxiliary array from the visualizer\n- `UniV_addAux(List) Null`: adds the given auxiliary array to the visualizer;\n\n#### Manual highlights\n- `UniV_immediateHighlight(Int) Null`: highlights the given index immediately, producing a frame;\n- `UniV_immediateHighlightAux(Int, List) Null`: like `UniV_immediateHighlight`, but it highlights the given auxiliary array;\n- `UniV_immediateMultiHighlight(List) Null`: like `UniV_immediateHighlight`, but with a list of indices;\n- `UniV_immediateHighlightAdvanced(Object) Null`: like `UniV_immediateHighlight`, but it highlights an `HighlightInfo` object;\n- `UniV_immediateMultiHighlightAdvanced(List) Null`: like `UniV_immediateHighlight`, but it highlights a list of `HighlightInfo` objects;\n- `UniV_highlight(Int) Null`: adds the given index to the list of highlights that will be visualized with the next update;\n- `UniV_highlightAux(Int, List) Null`: like `UniV_highlight`, but it highlights the given auxiliary array;\n- `UniV_multiHighlight(List) Null`: like `UniV_highlight`, but accepts a list of indices;\n- `UniV_highlightAdvanced(Object) Null`: like `UniV_highlight`, but uses a `HighlightInfo` object;\n- `UniV_multiHighlightAdvanced(List) Null`: like `UniV_highlightAdvanced`, but accepts a list of `HighlightInfo` objects;\n- `UniV_markArray(id: Int, index: Int) Null`: marks the array persistently until the end of the current algorithm;\n- `UniV_markArrayAux(id: Int, index: Int, aux: List) Null`: like `UniV_markArray`, but it highlights the given auxiliary array;\n- `UniV_markArrayAdvanced(id: Int, index: HighlightInfo) Null`: like `UniV_markArray`, but uses a `HighlightInfo` object;\n- `UniV_clearMark(id: Int)`: clears a mark precedently set through `UniV_markArray`, given its `id`. Throws an exception if the `id` of the given mark does not exist;\n- `UniV_clearAllMarks()`: clears all marks set through `markArray` and related functions.\n\n#### Speed control\n- `UniV_setSpeed(Int | Float) Null`: sets the visualization speed to the given value;\n- `UniV_resetSpeed() Null`: resets visualization speed to its default;\n- `UniV_getSpeed() Float`: returns the current visualization speed. Useful for speed editing;\n- `UniV_delay(Int | Float) Null`: sets the delay for the next highlighted operation;\n\n#### Shared algorithms\n- `UniV_getPivotSelection(String) Callable`: gets a shared pivot selection algorithm given its name. Throws an exception if the algorithm doesn't exist;\n- `UniV_getRotation(String) Object`: gets a shared rotation algorithm given its name. Throws an exception if the algorithm doesn't exist;\n\n#### User input\n- `UniV_getUserPivotSelection(String) Callable`: like `UniV_getPivotSelection`, but it asks the user to select a pivot selection algorithm. The parameter is a message to display to the user;\n- `UniV_getUserRotation(String) Object`: like `UniV_getRotation`, but it asks the user to select a rotation algorithm. The parameter is a message to display to the user;\n- `UniV_getUserSelection(List, String) Int`: asks the user to select between a list of items. Returns the selection index. The string parameter is a message to display to the user;\n- `UniV_getUserInput(message: String, default: String, convert: Callable) any`: asks the user to insert some text. The text is then passed to the `convert` callable, to convert it to the desired type. If `convert` fails, the user will be prompted to retry. Returns the converted output. If no conversion is needed, you can pass `asAny`, while if you need to get an Int, use `parseInt`;\n- `UniV_popup(String) Null`: shows a popup with a given message to the user; \n- `UniV_pushAutoValue(any) Null`: adds a value to the queue of user input values;\n- `UniV_popAutoValue() any`: pops a value from the queue of user input values;\n- `UniV_resetAutoValues() Null`: clears the queue of user input values;\n\n#### Invisible operations\n- `UniV_invisibleWrite(array: List, index: Int, value: any) Null`: equivalent to `array[index] = value`, but the operation is not visualized;\n- `UniV_invisibleSwap(array: List, a: Int, b: Int) Null`: equivalent to `swap(array, a, b)`, but the operation is not visualized;\n- `UniV_invisibleRead(array: List, index: Int) any`: equivalent to `array[index]`, but the operation is not visualized;\n- `List_invisiblePush(list: List, value: any) Null`: equivalent to `List_push(list, value)`, but the operation is not visualized;\n\n#### Manual statistics editing\n- `UniV_addWrites(Int) Null`: adds a given amount of writes to the writes counter;\n- `UniV_addReads(Int) Null`: adds a given amount of reads to the reads counter;\n- `UniV_addSwaps(Int) Null`: adds a given amount of swaps (and double the amount of writes) to the swaps and writes counters;\n- `UniV_addComparisons(Int) Null`: adds a given amount of comparisons (and double the amount of reads) to the comparisons and reads counters;\n\n#### Miscellaneous\n- `UniV_immediateSort(List, a: Int, b: Int) Null`: sorts a list from index a to index b (excluding the last element) \"immediately\", that is, the processing happens in the background, and only a linear pass is visualized. Useful for shuffles or placeholders;\n- `UniV_setCurrentlyRunning(String) Null`: sets a custom title for the currently running algorithm;\n\n`HighlightInfo` objects are composed as follows:\n```\nmyHighlightInfo := #{\n    idx: 0, // index to highlight\n    aux: null, // optional. if set, can be null or an auxiliary array to highlight\n    color: Color(255, 0, 0), // optional. if set, contains either null, to indicate the default highlighting color, or a Color object\n    silent: false, // optional. if set, can be truthy to indicate that the highlight should not produce sound, or falsey to indicate that it should\n    isWrite: true // optional. if set, can be truthy to indicate that this highlight is related to a write operation, or falsey to indicate that it's not\n};\n```\n\n### How to add an algorithm\n#### Shuffles\n```\n@shuffle { \n    name: \"My Shuffle\"\n}\nfn myShuffle(array: List) Null {\n    ...\n}\n```\n#### Distributions\nDistribution algorithms should produce Ints.\n```\n@distribution {\n    name: \"My Distribution\"\n}\nfn myDistribution(array: List) Null {\n    ...\n}\n```\n#### Pivot selections\n```\n@pivotSelection {\n    name: \"My Pivot Selection\"\n}\nfn myPivotSelection(array: List, start: Int, end: Int) Int {\n    // the pivot selection should pick an index in [start, end) \n    // and return it\n}\n```\n#### Rotations\n```\n@rotation { // alias of @indexedRotation\n    name: \"My Index-based Rotation\"\n}\nfn myIndexedRotation(array: List, start: Int, middle: Int, end: Int) Null {\n    ...\n}\n\n@lengthsRotation {\n    name: \"My Length-based Rotation\"\n}\nfn myLengthsRotation(array: LIst, start: Int, lengthA: Int, lengthB: Int) Null {\n    ...\n}\n```\n\n#### Sorts\n```\n@sort {\n    name:     \"My Sort\",\n    listName: \"My Sort\",\n    category: \"Exchange Sorts\"\n}\nfn mySort(array: List) Null {\n    ...\n}\n```\n\n## Third party language support\n### Python\n#### What is supported and what is not supported\nThe following Python constructs are not currently supported:\n- Keyword parameters\n- Variable length parameters\n- Default parameters\n- Closures\n- Most decorators\n- Multiple decorators applied to the same definition\n- Non-variable for loop targets\n- Multiple exception handlers\n- Multiple `with` items\n- Some `match` patterns\n- Non-variable assignment targets in class bodies\n- Static methods\n- Decorators on classes\n- Inheritance\n- `global`\n- Unpacking\n- Slicing\n- Matmul operator (`@`)\n- `del` of non-variable expressions\n- Type aliases\n- Imaginary values\n- Generators\n- List, set, dict comprehensions\n- Sets\n- `yield`\n- `await`\n- Formatted strings\n- `in`\n- Non-string dictionary keys\n#### API support\nVisualizer interaction in the Python layer usually happens using the [oSV API](https://github.com/amari-calipso/sorting-visualizer), but interacting with the [UniV API](#visualizer-interaction) directly also works.\n### Java\nJava support is in the works, stay tuned!\n## Adding visual styles\nVisual styles have to be added from UniV's source code, due to performance constraints. You can add one by creating a file in the `src/visuals` folder, then, create a type that has the same name of the file, but PascalCase (for example: `my_visual.rs` contains `struct MyVisual`). Now you can choose to either manually implement the `Visual` trait on your struct, or use the `visual!` macro to simplify the process. The `Visual` trait provides documentation on what each of the method does.\n\n## Adding sound engines\nSound engines also have to be added from UniV's source code, due to performance constraints. You can add one by creating a file in the `src/sounds` folder, then, create a type that has the same name of the file, but PascalCase (for example: `my_sound.rs` contains `struct MySound`). Now you can choose to either manually implement the `Sound` trait on your struct, or use the `sound!` macro to simplify the process. The `Sound` trait provides documentation on what each of the method does.\n\n## Adding API compatibility layers\nSee examples of how to add API compatibility layers in `src/api_layers`.\n\n## Adding language compatibility layers\nYou can add a language compatibiliy layer by creating a file in the `src/language_layers` folder. Inside that file, you can call the `language_layer!` macro to define your compatibility layer. See `src/language_layers/unil.rs` for a basic example. Language compatibility layers work by parsing the language you want to support, and generating a UniL AST, which will then be compiled to bytecode by the rest of the pipeline.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famari-calipso%2Funiv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famari-calipso%2Funiv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famari-calipso%2Funiv/lists"}