{"id":18082828,"url":"https://github.com/ranfdev/nickel-gtk-ui","last_synced_at":"2025-04-12T17:13:43.656Z","repository":{"id":104101896,"uuid":"499101005","full_name":"ranfdev/nickel-gtk-ui","owner":"ranfdev","description":"gtk .ui DSL written in nickel","archived":false,"fork":false,"pushed_at":"2022-06-02T16:03:49.000Z","size":33,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-12T17:13:39.419Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/ranfdev.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}},"created_at":"2022-06-02T11:05:20.000Z","updated_at":"2023-09-29T08:00:12.000Z","dependencies_parsed_at":"2023-05-16T03:58:26.710Z","dependency_job_id":null,"html_url":"https://github.com/ranfdev/nickel-gtk-ui","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranfdev%2Fnickel-gtk-ui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranfdev%2Fnickel-gtk-ui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranfdev%2Fnickel-gtk-ui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranfdev%2Fnickel-gtk-ui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ranfdev","download_url":"https://codeload.github.com/ranfdev/nickel-gtk-ui/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248602312,"owners_count":21131616,"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":[],"created_at":"2024-10-31T14:06:10.757Z","updated_at":"2025-04-12T17:13:43.634Z","avatar_url":"https://github.com/ranfdev.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nickel-gtk-ui\ngtk .ui DSL written in [nickel]. - Alpha, test project -\n\nThe following ui was decleared in only 59 lines, animations included.\n\nhttps://user-images.githubusercontent.com/23294184/171616820-ec34d959-20da-4f63-a9bf-3039e5aa82f2.mp4\n\n\n## Why?\nFrustrated by the standard .ui file writing experience (that xml is very verbose) and inspired by the [blueprint compiler](https://gitlab.gnome.org/jwestman/blueprint-compiler), I've decided to write a custom Domain Specific Language to generate .ui files. Compared to blueprint compiler, this let's you use a complete programming language, with variables and functions, to generate your ui. \n\nIf you squint hard enough, gtk builder .ui files are configuration files. [nickel] is a programming language created specifically to generate configuration files. Because of that, I've decided to write the DSL in nickel.\n\nNickel supports type checks and contract, so this DSL could have type checks in the future.\n\n## Example\nSee the [examples directory](./examples) or the example below.\n\nThis will generate the ui you can see in the video above.\nNotice: this file is ~60 lines long, while the generated .ui file is 305 lines long. This DSL will drastically reduce the code you need to write :).\n\n```nickel\nlet {to_builder_xml, template, child_type, build, style, attributes, signal, margins, ..} = import \"../ui_builder.ncl\" in\nlet Gtk = build \"Gtk\" in\nlet Adw = build \"Adw\" in\nlet numbers = array.map (fun i =\u003e (i + 2) / 2) (array.generate function.id 10) in\nlet animation_signal = fun nname i =\u003e \n  signal { name = nname, object = \"animation%{string.from_num i}\", handler = \"play\", swapped = \"no\", }\nin\nlet label_id = fun i =\u003e \"label%{string.from_num i}\" in\nto_builder_xml ([\n    template `NickeltestWindow (Gtk `ApplicationWindow ([\n        { \n            default-height = 600,\n            default-width = 1280\n        },\n        Gtk `HeaderBar `header_bar [\n          Gtk `Button `button [\n              { icon-name = \"open-menu-symbolic\" }\n          ] |\u003e child_type `end\n        ] |\u003e child_type `titlebar,\n        Gtk `Box ([\n          { \n              orientation = `vertical,\n          } \u0026 margins 16,\n          Gtk `Button ([\n              {label = \"Animate!\", margin-bottom = 16},\n              style [\"pill\", \"suggested-action\"]\n          ] @ array.map (animation_signal \"clicked\") numbers),\n        ] @ array.map (fun size =\u003e \n            Gtk `Label (label_id size) [\n                {\n                    label = \"Hello, World!\",\n                    xalign = 0\n                },\n                attributes {\n                    scale = size,     \n                    weight = \"bold\",\n                },\n                animation_signal \"map\" size\n            ]\n          ) numbers)\n        ])\n    ),\n] @ array.map (fun n =\u003e Adw `TimedAnimation \"animation%{string.from_num n}\" [\n    {\n        widget = label_id n,\n        duration = 1000 + n*300,\n        value-from = 0,\n        value-to = 240,\n        alternate = true,\n        easing = `ease-out-elastic,\n        repeat-count = 2,\n        target = Adw `PropertyAnimationTarget [\n            { \n              object = widget,\n              property-name = `margin-start\n            }               \n        ]\n    }  \n]) numbers)\n```\n\nThis python file builds the widget from the .ui file.\n\n```py\n@Gtk.Template(filename='./src/window.ui')\nclass NickeltestWindow(Gtk.ApplicationWindow):\n    __gtype_name__ = 'NickeltestWindow'\n    @Gtk.Template.Callback()\n    def play(_, target):\n        Adw.TimedAnimation.play(target)\n\n    def __init__(self, **kwargs):\n        super().__init__(**kwargs)\n```\n\n## Get started\n\n- Download [nickel]\n- Run\n```bash\ngit clone https://github.com/ranfdev/nickel-gtk-ui.git\ncd nickel-gtk-ui\nnickel export -f examples/titles_bounce_animation.ncl --format raw \u003e generated.ui`\n```\n\n\n\n[nickel]: https://github.com/tweag/nickel\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Franfdev%2Fnickel-gtk-ui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Franfdev%2Fnickel-gtk-ui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Franfdev%2Fnickel-gtk-ui/lists"}