{"id":26600821,"url":"https://github.com/airr/nim-cocoa","last_synced_at":"2025-04-09T16:24:10.204Z","repository":{"id":68787131,"uuid":"393886776","full_name":"Airr/nim-cocoa","owner":"Airr","description":"macOS GUI Library for the Nim Programming Language","archived":false,"fork":false,"pushed_at":"2023-10-14T18:04:25.000Z","size":691,"stargazers_count":37,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-10-16T04:02:45.234Z","etag":null,"topics":["gui","macos","nim","nim-lang"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","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/Airr.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}},"created_at":"2021-08-08T07:09:06.000Z","updated_at":"2023-10-12T18:15:17.000Z","dependencies_parsed_at":"2023-10-13T09:52:24.387Z","dependency_job_id":"f64aaea3-5e62-4cfc-9baa-ac86defd8a5c","html_url":"https://github.com/Airr/nim-cocoa","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airr%2Fnim-cocoa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airr%2Fnim-cocoa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airr%2Fnim-cocoa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Airr%2Fnim-cocoa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Airr","download_url":"https://codeload.github.com/Airr/nim-cocoa/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245152096,"owners_count":20569374,"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":["gui","macos","nim","nim-lang"],"created_at":"2025-03-23T18:35:35.169Z","updated_at":"2025-03-23T18:35:35.787Z","avatar_url":"https://github.com/Airr.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NimCocoa\n\nNimCocoa is an experimental implementation of a ***Native*** GUI for the Nim programming language running on macOS.\n\nRather than rely on low level calls to objc_msgsend and it's variants, it uses actual Objective-C code modules I created that are wrapped using C-Style functions, which Nim can then use.\n\nAt the moment, the following GUI objects are available:\n\n|            |             |              |               |                        |\n| ---------- | ----------- | ------------ | ------------- | ---------------------- |\n| NSWindow   | NSMenu      | NSSavedialog | NSSlider      |                        |\n| NSButton   | NSTextfield | NSMessagebox | NSListbox     | NSContainer (Groupbox) |\n| NSLabel    | NSCheckbox  | NSOpendialog | NSTextedit    | NSTableView            |\n| NSCombobox | NSDialog    | NSLine       | NSRadioButton |                        |\n\n\n\nPreliminary documentation for GUI objects is available in the `doc` folder and in the `wiki`.\n\nHere is an example of what coding with NimCocoa looks like:\n\n```nim\nimport Cocoa\nimport json, os, plists, times\n\nvar mainWin: ID\n\nvar lblFile, txtFile, btnFile, lblAuthor, txtAuthor, lblApp, \n    txtApp, lblImage, txtImage, btnImage, line1, lblVersion, \n    txtVersion, lblIdent, txtIdent, line2, chkLaunch, btnExec,\n    btnQuit: ID\n\nconst\n  width:cint = 800\n  height:cint = 310\n  winStyle = NSWindowStyleMaskTitled or NSWindowStyleMaskClosable or NSWindowStyleMaskMiniaturizable\n\nproc getExecutable(sender: ID) {.cdecl.} =\n  let fName = newOpenDialog(mainWin, \"\")\n  if fName.len \u003e 0:\n    txtFile.text = fName\n\nproc getImage(sender: ID) {.cdecl.} =\n  let fName = newOpenDialog(mainWin, \"icns\")\n  if fName.len \u003e 0:\n    txtImage.text = fName\n  \nproc quit(sender: ID) {.cdecl.} =\n  Cocoa_Quit(mainWin)\n\nproc createAppBundle(sender: ID) {.cdecl.} =\n  let dt = now()\n\n  let appAuthor = $txtAuthor.text\n  let appName = $txtFile.text\n  let iconFile = $txtImage.text\n  let bundleName = $txtApp.text\n  let bundleIdentifier = $txtIdent.text\n  let appVersion = $txtVersion.text\n  let appInfo = appVersion \u0026 \" Created by \" \u0026 appAuthor \u0026 \" on \" \u0026 dt.format(\"MM-dd-yyyy\")\n  let appCopyRight = \"Copyright\" \u0026 dt.format(\" yyyy \") \u0026 appAuthor \u0026 \". All rights reserved.\"\n  let appBundle = bundleName \u0026 \".app\"\n\n  var pl = %*\n    { \"CFBundlePackageType\" : \"APPL\",\n      \"CFBundleInfoDictionaryVersion\" : \"6.0\",\n      \"CFBundleName\" : bundleName,\n      \"CFBundleExecutable\" : bundleName,\n      \"CFBundleIconFile\" : extractFilename(iconFile) ,\n      \"CFBundleIdentifier\" : bundleIdentifier ,\n      \"CFBundleVersion\" : appVersion ,\n      \"CFBundleGetInfoString\" : appInfo,\n      \"CFBundleShortVersionString\" : appVersion ,\n      \"NSHumanReadableCopyright\" : appCopyRight ,\n      \"NSPrincipalClass\" : \"NSApplication\" ,\n      \"NSMainNibFile\" : \"MainMenu\" \n    }\n\n  createDir(appBundle \u0026 \"/Contents/MacOS\")\n  createDir(appBundle \u0026 \"/Contents/Resources\")\n  createDir(appBundle \u0026 \"/Contents/Frameworks\")\n\n  if appName.fileExists:\n    appName.copyFileWithPermissions(appBundle \u0026 \"/Contents/MacOS/\" \u0026 bundleName)\n\n    if iconFile.fileExists:\n      iconFile.copyFileWithPermissions(appBundle \u0026 \"/Contents/Resources/\" \u0026 extractFileName(iconFile))\n\n    if \"Credits.rtf\".fileExists:\n      \"Credits.rtf\".copyFileWithPermissions(appBundle \u0026 \"/Contents/Resources/Credits.rtf\")\n\n        \n    pl.writePlist(appBundle \u0026 \"/Contents/Info.plist\")\n\n    discard execShellCmd(\"touch \" \u0026 appBundle)\n\n    if chkLaunch.state == 1:\n      discard execShellCmd(\"open \" \u0026 appBundle)\n\n\nproc main() =\n\n  Cocoa_Init()\n\n  mainWin = newWindow(\"macOS Application Bundler\", width, height, winStyle)\n\n  lblFile = newLabel(mainWin, \"Select Executable\",30, 20, 120, 25)\n  txtFile = newTextField(mainWin, \"\", 160, 20, 500, 25)\n  btnFile = newButton(mainWin, \"Load\", 680, 20, 100, 25, getExecutable)\n  txtFile.anchor=akWidth; btnFile.anchor=akRight\n\n  lblAuthor = newLabel(mainWin, \"Author Name\", 30, 60, 120, 25)\n  txtAuthor = newTextField(mainWin, \"\", 160, 60, 500, 25)\n  txtAuthor.anchor=akWidth\n\n  lblApp = newLabel(mainWin, \"Application Name\", 30, 100, 120, 25)\n  txtApp = newTextField(mainWin, \"\", 160, 100, 170, 25)\n  txtApp.anchor=akWidth\n\n  lblImage = newLabel(mainWin, \"Select Icon File\", 30, 200, 120, 25)\n  txtImage = newTextField(mainWin, \"\", 160, 200, 500, 25)\n  btnImage = newButton(mainWin, \"Load\", 680, 200, 100, 25, getImage)\n  txtImage.anchor=akWidth; btnImage.anchor=akRight\n\n  line1 = newSeparator(mainWin, 30, 140, 750)\n\n  lblVersion = newLabel(mainWin, \"Application Version\", 350, 100, 130, 25)\n  txtVersion = newTextField(mainWin, \"\", 490, 100, 170, 25)\n  txtVersion.anchor=akRight; lblVersion.anchor=akRight\n\n  lblIdent = newLabel(mainWin, \"Bundle Identifier\", 30, 160, 120, 25)\n  txtIdent = newTextField(mainWin, \"\", 160, 160, 500, 25)\n  # btnCredits = newButton(mainWin, \"Load\", 680, 160, 100, 25, nil)\n  txtIdent.anchor=akWidth\n\n  line2 = newSeparator(mainWin, 20, 250, 750)\n\n  chkLaunch = newCheckBox(mainWin, \"Launch Application?\", 330, 270, 150, 25)\n  btnExec = newButton(mainWin, \"🟢 Execute\", 680, 270, 100, 25, createAppBundle)\n  chkLaunch.anchor=akLeft + akRight + akBottom; btnExec.anchor=akRight + akBottom\n\n  btnQuit = newButton(mainWin, \"🔴 Quit\", 565, 270, 100, 25, quit)\n\n  Cocoa_Run(mainWin)\n  \n\nif isMainModule:\n  main()\n```\n\nWhich results in the following (with Darkmode enabled):\n\n![](images/bundler.png)\n\nAnother screenshot:\n\n![](images/Thesaurus-org.png)\n\nSame app resized, showing how objects flow based on their associated 'anchor' setting:\n\n![](images/Thesaurus-resized.png)\n\nI am working on documenting the available objects/functions as well as examples.\n\nStay Tuned!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairr%2Fnim-cocoa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fairr%2Fnim-cocoa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairr%2Fnim-cocoa/lists"}