{"id":20676156,"url":"https://github.com/bajger/pharo-snippets","last_synced_at":"2025-08-02T16:13:09.958Z","repository":{"id":168982443,"uuid":"166846592","full_name":"Bajger/Pharo-snippets","owner":"Bajger","description":"Pharo Project code snippets and useful hints","archived":false,"fork":false,"pushed_at":"2025-03-19T06:45:18.000Z","size":590,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-06-03T03:29:30.756Z","etag":null,"topics":["pharo"],"latest_commit_sha":null,"homepage":"","language":"StringTemplate","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/Bajger.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":"2019-01-21T16:37:12.000Z","updated_at":"2025-03-19T06:45:22.000Z","dependencies_parsed_at":"2025-04-20T15:15:49.092Z","dependency_job_id":null,"html_url":"https://github.com/Bajger/Pharo-snippets","commit_stats":null,"previous_names":["bajger/pharo-snippets"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Bajger/Pharo-snippets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bajger%2FPharo-snippets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bajger%2FPharo-snippets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bajger%2FPharo-snippets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bajger%2FPharo-snippets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Bajger","download_url":"https://codeload.github.com/Bajger/Pharo-snippets/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bajger%2FPharo-snippets/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268416655,"owners_count":24246952,"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","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["pharo"],"created_at":"2024-11-16T21:11:59.704Z","updated_at":"2025-08-02T16:13:09.924Z","avatar_url":"https://github.com/Bajger.png","language":"StringTemplate","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pharo-snippets\nPharo Project code snippets and useful hints. Some topics here:  \n  * [Concurrent programming hints](./concurrent-programming.md)\n  * [Ubuntu Linux and VirtualBox hints](./linux-snippets.md)\n\n\n# Setting up Github environment\n## Step 1: SSH keys on Github\n* Generate new public/private key pair if needed: https://help.github.com/articles/generating-an-ssh-key/\n* Open Configuration on Github: User -\u003e Settings -\u003e SSH and GPG keys\n![SSH keys - Github](./images/ssh_keys_github.png)\n\n\n\n## Step 2: SSH keys, auth. token and other settings for Iceberg in Pharo\nOpen configuration of Iceberg tool (World menu \u003e Tools \u003e Iceberg \u003e click Settings icon) and set:\n- local path to ssh keys:  \n![Pharo settings - Iceberg](./images/pharo_settings_ssh_keys.png)\n- set Default Code Subdirectory to: 'src'\n- set File format type to: 'Tonel'  \n- set github token on credential list (that was previously ![generated on Github](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token)\n![image](https://user-images.githubusercontent.com/45875448/133891834-4a540fd4-6049-4e47-ae0f-a0b0e08a92d8.png)\n- see full description ![here](https://github.com/pharo-vcs/iceberg/wiki/Authentication-Credentials)\n\n## Step 2a: Optionally, setup Github CLI\nGithub CLI is useful when doing manual changes with repo (from command line).  \nThere is auth option to use GH CLI, installation here: https://github.com/cli/cli#installation  \n- install e.g. using `brew install gh`  \n- set authentication method for git command line: `gh auth login` and select: HTTPS and then 'Authenticate using browser'  \nGit remote commands then run using GH CLI authentication  \n- alternativelly, you can login via token e.g.: `gh auth login --with-token \u003c some-token.txt`\n\n## Step 3: Set local path to image directory\nOpen system configuration from World menu \u003e Pharo \u003e Settings \u003e System tab \u003e Local Directory \u003e click directory icon and navigate to path, where directory with image is located\n\n![Pharo-settings](./images/2021-04-04%2019_42_25-Window.png)\n\n## Step 4: Create new (or use existing) Github repository\n![Github-new-repo](./images/2021-04-04%2019_51_58-Clipboard.png)\n\n## Step 5: Clone repository in Iceberg from Github\n- Open Iceberg and click '+' add icon\n- Choose \"Clone from Github.com\"\n- Set your name from Github and type repository name you want to clone\n- Choose \"HTTPS\" and click Ok  \n![Github-clone-Github-repo](./images/2021-04-04%2020_00_44-CloneRepo.png)\n\n## Step 6: Repair metadata of empty repository\nAfter cloning, you'll see project in Iceberg in state, where project metadata (how packages, classes are organized in repo) are missing. State \"No project found\" will be on line with cloned repo.  \n![Github-clone-Github-repo](./images/2021-04-04%2020_42_23-Repair-repo.png)\n- Choose \"Repair repository\" in context menu (right-click on repo)\n- Select \"Create project meta-data\" and click ok\n- Choose Format \"Tonel\" instead of Filetree and then ok\n\n## Step 7: Add packages, package extensions to your repository\n- Select your repo and right-click again, Choose \"Packages\"  \n![Github-clone-Github-repo](./images/2021-04-04%2020_52_42-add-packages.png)\n\n- Click '+' icon to add your packages (including extenstions) to your repo\n- Select desired packages and then ok\n\n## Step 8: Commit and push changes to main branch directly\n- Right click on your repo and choose \"Commit\"  \n- Type message to your commit, review changes  \n- Select \"Push changes to origin/main\"  \n![Commit-changes](./images/2021-04-04%2021_00_37-commit.png)  \n- Type missing git properties (Github name, email)  \n![Git-properties](./images/2021-04-04%2021_02_02-git-credentials.png)  \n**That's it! Check your changes on Gihtub.**  \n\n## Step 8a: Optionally, commit changes using feature branch and PR  \n- Right click on repo in Pharo and select \"Github -\u003e Create new branch for an issue\"  \n![image](https://user-images.githubusercontent.com/45875448/133251077-41fd6dd0-4c6e-49dc-afa7-20ee34eee93f.png)\n- Select a remote branch (depending if you want to pull title from issue on your own repo on GH or original repo from which you did fork)  \n- Put referencing issue nr. (title will be pulled from issue on GH)  \n- Then right click and select \"commit\" and then \"Push\"  \n- Put \"Fixes #\u003cissueNr\u003e\" on first line and add description on additional lines and click \"commit\"  \n- Right click on repo and choose \"Gitbub -\u003e Create Pull request\"  \n![image](https://user-images.githubusercontent.com/45875448/133252434-df54c9df-4efd-44d3-809a-11a36845ddbc.png)\n- Check head branch and remote (base) branch and press \"Create pull request\"  \n\n\n\n## Step 9: Define Baseline to load project dependencies (packages) in correct order (recommended)\n- Define in repo BaselineOfMyProject class like this (where MyProject is name of your project):\n```\nBaselineOf subclass: #BaselineOfMyProject\n\tslots: {  }\n\tclassVariables: {  }\n\tpackage: 'BaselineOfMyProject'\n```\nThen in `BaselineOfMyProject` class define method that would define project dependencies (example below is simple and doesn't define any package dependencies):\n```\nbaseline: spec\n\t\u003cbaseline\u003e\n\tspec\n\t\tfor: #common\n\t\tdo: [\n\t\t\t\"Define packages from your project to be loaded\"\n\t\t\tspec\n\t\t\t\tpackage: 'MyProject';\n\t\t\t\tpackage: 'MyProject-Tests';\n\t\t\t\tpackage: 'MyProject-Gui';\n\t\t\t\tpackage: 'MyProject-Gui-Tests';\n\t\t\t\tpackage: 'MyProject-Examples' ]\n```\nAdd package `BaselineOfMyProject` to your repository (as in step 7). You should see a new changes (new class and method). Commit these changes to git repository and push to your remote GitHub repo. \n## Step 10: Load own Github project into Pharo image\nNext, your previous definition of Baseline can be used to load project using Metacello command. You can try it on fresh empty image to see, if everything works as expected.\nProject and its packages should be loaded to your image after evaluating:\n```\nMetacello new\n\trepository: {yourGHAccount/{YourRepository};\n\tbaseline: {MyProject};\n\tload\n```\n\u003e__Note: For more details, how baselines, dependencies and loading work, see this comprehensive guide: [How to load GitHub project using Baseline](https://github.com/pharo-open-documentation/pharo-wiki/blob/master/General/Baselines.md#how-to-load-a-git-project-using-its-baseline)__\n\n# Useful git snippets, hints\n## Resetting commits from repo\n- On local repo just checkout branch where you want to remove/wipe-out commits\n- Check stutus of last commits e.g. by: `git log --pretty=format:\"%h - %an, %ar : %s\"`  \n- Execute e.g.: `git reset --hard HEAD~3` (this will remove last 3 commits from local branch)\n- then execute:`git push origin -f` which will remove commits also on remote repo\n## Rebasing branch  \nRebasing is useful when feature or issue branch is based on deprecated state of repo (forked long time ago). Therefore it is useful to sync with main branch and rebase commits from feature branch, so related PR can be merged and conflicts can be resolved.\n- To switch to feature branch: `git checkout feature-branch`\n- Rebase commits with main branch: `git rebase main`  \n[See more](https://www.freecodecamp.org/news/the-ultimate-guide-to-git-merge-and-git-rebase)  \n\n## Squash commits into one\nSquashing is useful to put together multiple commits into just one commit  \nStep 1: run rebase command:   \n`git rebase -i HEAD~[X]` to squash last X commits  \nStep 2: edit file with commands:  \nTo define what to do wih each commit, you need to edit file and pick first and squash all others:  \n```\npick SHA1 commit 1\ns SHA2 commit 2\ns SHA3 commit 3\n...\n```\nDetails [here](https://www.baeldung.com/ops/git-squash-commits)  \n\n## Cherry picking commits\nThis is used when you want to apply commit from different branch and individually copy them do current branch  \nStep 1: Check out to branch where you want to apply your commits  \nStep 2: To cherry-pick all the commits from commit A to commit B (where A is older than B), run:  \n```\ngit cherry-pick A^..B\n```\nIf you want to ignore A itself, run: `git cherry-pick A..B`  \n\nStep 3: Some merge conflicts might occur:  \nResolve them (by editing applying incoming or using current changes) and run `git cherry-pick --continue`  \n\nDetails [here](https://stackoverflow.com/questions/1670970/how-to-cherry-pick-multiple-commits)\n\n\t\n# Pharo IDE\nUsing dark dawn UI theme: \n```\nMetacello new \n\tbaseline: 'PharoDawnTheme';\n\trepository: 'github://sebastianconcept/PharoDawnTheme:latest';\n\tload.\n```\n# Debugging / profiling\nFinding all references: `self pointersTo: anObject` \nor use reference finder by: `ReferenceFinder findPathTo: #nil` \n\n## Define custom inspector\nInspector can be adopted to show some details that are presented in nicer way than raw. Method with annotation has to be defined, e.g.:  \n```\n\u003cinspectorPresentationOrder: 1 title: 'Demo'\u003e\n    | items |\n    items := #( 1 2 3 4 5 6 7 8 ).\n\n    ^ SpListPresenter new\n        items: (items collect: [ :e |\n            StInspectorTransmissionNode hostObject: e transmissionBlock: [ :theObject | theObject + 100 ] ]);\n        display: [ :e | e hostObject ];\n        yourself\n```\nNote: See all implementors of `inspectorPresentationOrder:title:` method to see examples.  \n\n## Get package dependencies\nTo see how packages are dependent on each other, evaluate following:\n```\n|report|\nreport := DADependencyChecker new computeImageDependencies.\nreport knownDependantsOf: 'YourPackage'\n```\n\t\n# File system, handling of files\n## Line endings dependent on OS platform\n```\n\"use proper line ending on target platform\"\nlineEnding := OSPlatform current lineEnding.\n```\n## Memory file reference\n```\t\n\"using memory file reference - useful in tests\"\nmemoryFileReference := FileSystem memory root / 'exercises'.\n```\n## Using mock memory file system in tests\n```\n\"prerequisite\"\nDiskStore class\u003e\u003e currentFileSystem: fileSystem during: aBlock\n\t| backupFileSystem |\n\tbackupFileSystem := self currentFileSystem.\n\t[ CurrentFS := fileSystem.\n\taBlock value ]\n\t\tensure: [  CurrentFS:= backupFileSystem ]\n\n\n\"and then use of different FS\"\nmemoryFileSystem := FileSystem memory.\n\tDiskStore\n\t\tcurrentFileSystem: memoryFileSystem\n\t\tduring: [ location := (memoryFileSystem root / 'non-existing.image') ensureCreateFile.\n\t\t\tself should: [ command findImage: '/wrong/path' ] raise: NotFound ]\n```\n# OS interaction from Pharo\nFor runnning OS processes from Pharo program [OS Subprocess library](https://github.com/pharo-contributions/OSSubprocess) can be used.  \nMain advantage is that Pharo process is not blocked by running OS process, unlike using e.g.:` LibC runCommand: 'scp myfile.zip`.\n\n## Loading OS Subprocess dependency to own project\nAdd following method in Project baseline class (`BaselineOfMyProject`): \n```\n\"MacOS, Linux platform support\"\nBaselineOfMyProject\u003e\u003eaddOSSubprocessDependency: spec\nspec \n\tbaseline: 'OSSubprocess'\n\twith: [spec repository: 'github://pharo-contributions/OSSubprocess:master/repository'].\n\n\"Windows support\"\t\nspec \n\tbaseline: 'OSWinSubprocess'\n\twith: [spec repository: 'github://pharo-contributions/OSWinSubprocess:master/repository'].\n```\n\n## Using OS Subprocess in program\nDefine accessor instance (or class) variable to obtain Platform specific class: \n```\nMyClass\u003e\u003eosSubProcess\n^ osSubProcess \n\tifNotNil: [ osSubProcess ] \n\tifNil: [ \n\t  osSubProcess := self class subProcessClass.\n\t  osSubProcess ]\n\nMyClass class\u003e\u003esubProcessClass\n    OSPlatform current isWindows ifTrue: [ \n        ^ self class environment at: #OSWSWinProcess\n    ].\n    ^ self class environment at: #OSSUnixSubprocess \n```\nAnd then you can invoke external program fron Pharo using:\n```\n| result |\t\t\nresult := self osSubProcess new\n\tcommand: 'myOsCommand';\n\tworkingDirectory: self configletRootReference fullName;\n\targuments: {'arg1'. 'arg2'.} asArray;\n\t\tredirectStdout;\n\t\trunAndWait.\n\t\nresult isSuccess ifFalse: [ \n\tresult lastError printString.\n]\n```\n# Handling classes, methods\n## Removing classes and extension methods from system\n```Smalltalk\n\"remove classes within package\"\naPackage := Package named: 'myPackage'.\naPackage definedClasses do: [:aClass |\n\taPackage removeClassNamed: aClass name. \n\taClass removeFromSystem\n].\n\n\"remove extension methods\"\nmethodsToRemove := exercisePackage extensionMethods.\nexercisePackage removeMethods: methodsToRemove.\nmethodsToRemove do: #removeFromSystem\n```\n\n# UI frameworks, icons\nGet list of existing icons: `Smalltalk ui icons` or `ThemeIcons current`.\n\n# Pharo Projects \n## Pharo launcher \nTo load: \n```\nMetacello new\n\trepository: 'github://pharo-project/pharo-launcher:dev/src';\n\tbaseline: 'PharoLauncher';\n\tload\n```\n\n\n## Installing Seaside and Bootstrap4\nThis should work with P8 stable 64 bit  \nLoad Bootstrap that will load Seaside as dependency: \n```\nMetacello new\n      baseline:'Bootstrap4';\n      repository: 'github://astares/Seaside-Bootstrap4:master/src';\n      load\n```\n### Installing standalone Seaside\nTODO\n\n### Installing standalone Bootstrap\nTODO\n\n## Installing Magritte\n```\n\tMetacello new\n    baseline:'Magritte';\n    repository: 'github://magritte-metamodel/magritte:master';\n\tonConflictUseLoaded;\n    load.\n```\n## Pharo Web Deployment\nDeploying tips in AWS: http://forum.world.st/Getting-Pharo-running-on-AWS-td5117353.html  \nhttps://pharoweekly.wordpress.com/2020/05/20/deployment-tips-from-the-pros/  \nhttp://forum.world.st/running-Pharo8-in-Digitalocean-tt5115160.html  \n\nOptions to easily setup a custom server: running a virtual machine in Azure, AWS, Google Cloud or elsewhere usually only takes a few minutes.  So it's not different from other web deployments: run on a specific port and put a webserver like Apache, Nginx or other in front.  \n\nSome more Seaside specific resources:\n - https://www.linode.com/docs/guides/deploy-smalltalk-applications-with-seaside/  \n - http://book.seaside.st/book/advanced/deployment/deployment-preparing  \n - https://ci.inria.fr/pharo-contribution/job/EnterprisePharoBook/lastSuccessfulBuild/artifact/book-result/DeploymentWeb/DeployForProduction.html  \n\nYou can also use docker to deploy (see http://wiki.astares.com/pharo/612)\n  \n  \n### REST via Seaside\nhttps://github.com/SeasideSt/Seaside/wiki/Seaside-REST  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbajger%2Fpharo-snippets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbajger%2Fpharo-snippets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbajger%2Fpharo-snippets/lists"}