{"id":27936397,"url":"https://github.com/joseaverde/malef","last_synced_at":"2025-06-25T17:09:51.889Z","repository":{"id":197785475,"uuid":"323906291","full_name":"joseaverde/Malef","owner":"joseaverde","description":"Malef is a terminal/console-handling library written in Ada for TUI applications.","archived":false,"fork":false,"pushed_at":"2024-03-10T19:56:02.000Z","size":1003,"stargazers_count":7,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-29T05:06:45.456Z","etag":null,"topics":["ada","malef","ncurses","sdk","tui"],"latest_commit_sha":null,"homepage":"","language":"Ada","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joseaverde.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-12-23T13:14:18.000Z","updated_at":"2024-10-09T22:13:38.000Z","dependencies_parsed_at":"2024-01-12T22:52:49.047Z","dependency_job_id":"74f332a0-635b-4326-8a5e-3c99adcbece6","html_url":"https://github.com/joseaverde/Malef","commit_stats":null,"previous_names":["joseaverde/malef"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/joseaverde/Malef","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseaverde%2FMalef","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseaverde%2FMalef/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseaverde%2FMalef/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseaverde%2FMalef/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joseaverde","download_url":"https://codeload.github.com/joseaverde/Malef/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseaverde%2FMalef/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261917440,"owners_count":23229919,"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":["ada","malef","ncurses","sdk","tui"],"created_at":"2025-05-07T06:57:38.541Z","updated_at":"2025-06-25T17:09:51.868Z","avatar_url":"https://github.com/joseaverde.png","language":"Ada","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Malef\n**Malef** is a simple cross-compatible toolkit for writing terminal-based\napplications in Ada 2022. The library is completely written in Ada and has no\ndependencies.\n\nThis project's objective is to provide a simple and intuitive way of writting\nblazing fast Terminal User Interfaces (TUI). There is a lot of effort put into\nmaking API convenient and intuitive so the the developer doesn't neet to think\nabout low-level stuff.\n\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n[![License: FDL 1.3](https://img.shields.io/badge/License-FDL%20v1.3-blue.svg)](http://www.gnu.org/licenses/fdl-1.3)\n\n**The library is in active development. The API is not definitive yet but it is\nusable**\n\n## Description\n**Malef** is an open source and free library written in Ada to create Terminal\nbased User Interfaces. It divided in two parts: the _Drawing Toolkit_ and the\n_Widget Toolkit_. The _Drawing Toolkit_ provides the low-level stuff: mainly\ndrawing and composition primitives. And the _Widget Toolkit_ abstracts the way\nof building Applications using an interface similar to other G.U.I. toolkits\nsuch as Gtk or Qt using _widgets_.\n\n### The _Drawing Toolkit_\nThe _Drawing Toolkit_ provides a low-level API for drawing Surfaces,\ncomposing them in _Groups_ and showing them on the _Window_. If you want to\ncreate your own Widgets you will have to use this toolkit. See the packages\nunder [src/drawing](src/drawing).\n\n#### Surfaces\nA `Surface` is just a 2-dimensional Matrix of Glyphs (`Wide_Wide_Character`s),\nColours and Styles. Drawing on them is very simple, you can take a look at\nthe `malef-surfaces.ads` package to see all the available functions to draw.\nThe functions added to that package are for convenience.\n\nAlso, some types have their own String Literals (new in Ada 2022). So you can\nspecify a colour with an array or with an HTML colour tags.\n\n```ada\nwith Malef.Surfaces;\n\nprocedure Surface_Example is\n   My_Surface : Malef.Surfaces.Surface (3, 12);   -- Specify the number of\n                                                  -- Rows and Columns.\n\nbegin\n\n   My_Surface (1, 1) := 'H';\n   My_Surface.Put (1, 2, \"ello, World\");\n   My_Surface.Fill_Background (\"#507878\");\n   My_Surface.Fill_Foreground ((1, 1), (1, 12), \"#CCC\");\n   My_Surface.Fill ((1, 1), (1, 5), (Bold =\u003e True, others =\u003e False));\n\nend Surface_Example;\n```\n\nSurfaces may have transparency, colours are represented as RGBA values (Red,\nGreen, Blue and Alpha), where _Alpha_ is the opacity of the colour (255 is\ncompletely opaque and 0 is completely transparent).\n\n\n#### Groups\nA `Group` is a data-structure that may contain different `Surface`s or even\nother `Group`s. It is similar to the _Groups_ of Layers you can create when\nyou work with GIMP.\n\n```\n\n                  _________________\nBottom Layer .   /,,,,,,,,,,,,,,,,/| \u003c----------- Top Layer\n             |  /________________/ |\n             V _|_|___________   | |\n              /.|.|......... /|  | |\n         ____/..|.|........ /_|__|_|______\n        /   /...|......... /  |  | |     /\n       /   /....|........ /___|  | |    /\n      /   /______________/ .. /  | |   /\n     /    |   /.|........|.../___|_|  /\n    /     |  /..|;;;;;;;;|;;,,,,,|,/ /    \u003c----- Group Base Layer\n   /      | /............|.______|/ /\n  /       |/_____________|/        /\n /                                /\n/________________________________/\n```\n\nEach Layer has a opacity associated with it and a `Layer_Mode` (the function\nto be used in order to mix a layer with the layer below).\n\nGroups are aggregates you can define your groups just like:\n\n```ada\nwith Malef.Surfaces; use Malef.Surfaces;\nwith Malef.Groups;   use Malef.Groups;\n\nprocedure Group_Example is\n   Red      : Surface (10, 10);\n   My_Group : Group (6) := [Layer (Red, Opacity =\u003e 0.5),  -- Opacity\n                            Layer (Red, Hidden =\u003e True),  -- Hidden?\n                            Layer (Red, (2, 2)),          -- Position\n                            No_Layer,                     -- Leave free space\n                            Layer (20, 10),               -- Create a surface\n                                                          -- of a given size.\n                            Layer ([Layer (Red),          -- Add a group\n                                    Layer (Red),\n                                    Layer (Red)]\n                                    (10, 20),\n                                    Opacity =\u003e 0.9)];\n   -- When adding a Surface to a Group a copy is always made, so changing the\n   -- value of the `Red` surface won't change the contents of the group.\n   -- Instead, use the `renames` directive to take a reference of the surface.\n   -- Tampering rules will be running while you have a reference, so the group\n   -- cannot be modified while it is being referenced.\n   My_Surface renames Group (1).Set_Surface.Element;     -- Can be modified\n   Surface_View renames Group (1).Get_Surface.Element;   -- Just a view\n\nbegin\n\n   My_Surface.Fill_Background (\"#F00\");\n   Red.Fill_Background (\"#F00\");\n   My_Group.Insert (2, Red);  -- Error: Tampering because we have a reference.\n                              -- If we didn't have a reference, it would be\n                              -- correct.\n\nend Group_Example;\n```\n\nAdding a new Layer to a group implies a copy. If you are adding a group to\nanother group a deep copy is made. And it may kill performance. Instead use the\nMove function, it is similar to move semantics in C++. It takes ownership of\nthe group and clears the other group so it can be _moved_ inside another group.\n\n```ada\nwith Malef.Surfaces; use Malef.Surfaces;\nwith Malef.Groups;   use Malef.Groups;\n\nprocedure Move_A_Group_Example is\n   Red, Green, Blue : Surface (10, 10);\n   Group_A : Group (3) := [Layer (Red), Layer (Green), Layer (Blue)];\n   Group_B : Group (4) := [Layer (Red), Layer (Group_A), Layer (Green),\n                           Layer (Blue)];    -- Group_A is copied\n   Group_C : Group (4) := [Layer (Red), Move (Group_A), Layer (Green),\n                           Layer (Blue)];    -- Group_A is moved and can no\n                                             -- longer be used.\n   Group_D : Group (2) := [Layer (Blue),\n                           Layer ([Red, Green])]; -- The second group is copied\n   Group_E : Group (2) := [Layer (Blue),\n                           Move (Layer([Red, Green]))];  -- No copies\n\nbegin\n   null;\nend Move_A_Group_Example;\n\n```\n\n#### Window\nThe `Window` is a `protected` object that contains a single `Group`. You can\nassign _callbacks_ to the `Window` using a _subscription/notifier_ model, i.e.,\nwhen an event occurs, all subscribers are notified of that event. This will be\ndone in different tasks to avoid blocking the `Window` itself.\n\nLet's see the first working example.\n```ada\nwith Malef.Groups;\nwith Malef.System;\nwith Malef.Window;\n\nprocedure RGB_Window is\n   use Malef.Groups;\n   My_Group : Group := [Layer (10, 10, (1, 1), Opacity =\u003e 0.3),\n                        Layer (10, 10, (1, 5), Opacity =\u003e 0.3),\n                        Layer (10, 10, (5, 3), Opacity =\u003e 0.3)];\n   Red   renames My_Group.Set_Surface (1).Element;\n   Green renames My_Group.Set_Surface (2).Element;\n   Blue  renames My_Group.Set_Surface (3).Element;\nbegin\n\n   Malef.System.Initialize;      -- Initialize the subsystem\n\n   Red.Fill_Background (\"#FF0000\");\n   Green.Fill_Background (\"#00FF00\");\n   Blue.Fill_Background (\"#0000FF\");\n\n   Malef.Window.Window.Set_Group (My_Group);\n   -- If you want to process the group as it is in a protected object you have\n   -- to pass a function to the `Process_Group` procedure.\n   Malef.Window.Window.Display;\n\n   Malef.System.Finalize;        -- Finalize the subsystem\n\nend RGB_Window;\n```\n\n#### Callbacks\n\n#### System\nThe `Malef.System` package contains initialisation, finalisation and other\nfunctions about the underlying system. If the developer forgets to finalize the\nlibrary or even if and exception is thrown, this packages makes sure to clean\nup the terminal.\n\n### The Widget Toolkit\n**TODO**\n\nYou can see examples in the [examples directory](examples/).\n\n## Compilation\n\n| System  |                             Status                             |\n|:-------:|:--------------------------------------------------------------:|\n|  Linux  |  ![Linux](https://img.shields.io/badge/build-passing-success)  |\n| Windows | ![Windows](https://img.shields.io/badge/build-passing-success) |\n\n| Subsystem |                                  Status                                   |\n|:---------:|:-------------------------------------------------------------------------:|\n|   ANSI    |        ![ANSI](https://img.shields.io/badge/build-passing-success)        |\n|    CMD    |        ![CMD](https://img.shields.io/badge/build-passing-success)         |\n| Terminfo  | ![Terminfo](https://img.shields.io/badge/build-not_implemented-important) |\n\n_There are some problems with colours in the CMD subsystem, everything else\nworks though. But the ANSI subsystem is still more robust._\n\n## Tests\n**TODO**\n\n| System  |                                  Status                                  |\n|:-------:|:------------------------------------------------------------------------:|\n|  Linux  |  ![Linux](https://img.shields.io/badge/tests-not_implemented-important)  |\n| Windows | ![Windows](https://img.shields.io/badge/tests-not_implemented-important) |\n\n## How to build it?\n\n**IMPORTANT**: It only compiles with GCC \u003e=13.2.0\n\nMalef uses [Alire](https://alire.ada.dev/), you only have to do\n\n\u003e alr with malef\n\nOn a project and you are ready to go. (If have to publish it first)\n\nYou can clone this repository and compile the examples:\n\n\u003e cd examples\n\n\u003e alr build\n\nAll examples will appear in the `bin` directory.\n\n## Licenses\nThis library is made available under the [GPLv3](LICENSE) license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoseaverde%2Fmalef","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoseaverde%2Fmalef","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoseaverde%2Fmalef/lists"}