master 45f56f06b43e cached
58 files
358.7 KB
92.1k tokens
1 requests
Download .txt
Showing preview only (377K chars total). Download the full file or copy to clipboard to get everything.
Repository: pharo-open-documentation/pharo-wiki
Branch: master
Commit: 45f56f06b43e
Files: 58
Total size: 358.7 KB

Directory structure:
gitextract_8rwhc7yu/

├── .github/
│   └── workflows/
│       └── continuous.yml
├── .gitignore
├── CONTRIBUTION.md
├── ExternalProjects/
│   ├── DataStructures/
│   │   └── DataFrame.md
│   └── Export/
│       ├── Arff.md
│       ├── CSV.md
│       ├── ESCP.md
│       ├── HTML.md
│       ├── JSON.md
│       └── XML.md
├── ExternalResources/
│   └── Community.md
├── General/
│   ├── Baselines.md
│   ├── CJKCharacter.md
│   ├── CJKInputMethod.md
│   ├── CodingConventions.md
│   ├── CoolSnippets.md
│   ├── DeployYourPharoApplication.md
│   ├── Exceptions.md
│   ├── ExportFormats.md
│   ├── Extensions.md
│   ├── Files.md
│   ├── GithubActions.md
│   ├── Glossary.md
│   ├── HowToRunPharoFromCommandLine.md
│   ├── IcebergOnWindows.md
│   ├── ImageFileFormat.md
│   ├── Inspector.md
│   ├── InterestingsToKnowForBeginners.md
│   ├── Layout.md
│   ├── MenuBar.md
│   ├── MustKnowForBeginners.md
│   ├── Playground.md
│   ├── Pragmas.md
│   ├── Profiling.md
│   ├── ProgressBar.md
│   ├── Refactorings.md
│   ├── SessionsManagement.md
│   ├── SettingUpANewProject.md
│   ├── Settings.md
│   ├── SortingCollections.md
│   ├── Traits.md
│   ├── Travis.md
│   ├── TweakingBigImages.md
│   └── Windows10SubsystemForLinux.md
├── LICENSE
├── MANIFEST.md
├── Migration/
│   └── MigrationToPharo7.md
├── PharoProjects/
│   ├── Announcer.md
│   ├── Cursor.md
│   ├── DynamicVariables.md
│   ├── Metalinks.md
│   ├── Numbers.md
│   ├── OS.md
│   ├── ObjectsSerialization.md
│   ├── RichText.md
│   └── WebBrowser.md
├── PharoVirtualMachine/
│   └── pharo-vm-map.md
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/continuous.yml
================================================
name: Broken links

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the development branch
on:
  push:
    branches:
      - 'master'
  pull_request:
    types: [assigned, opened, synchronize, reopened]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Defining a new Environment Variable
      run: |                          
        TEMPFILES=$(ls **/*.md)    
        echo "FILES<<EOF" >> $GITHUB_ENV
        echo $TEMPFILES >> $GITHUB_ENV
        echo "EOF" >> $GITHUB_ENV
    - uses: docker://dkhamsing/awesome_bot:latest
      with:
        args: --white-list travis-ci,127.0.0.1,smalltalkhub.com/mc,github.com/MY_USERNAME/MY_PROJET_NAME --allow 403 --allow-dupe --allow-redirect --skip-save-results ${{ env.FILES }}


================================================
FILE: .gitignore
================================================
**/.DS_STORE


================================================
FILE: CONTRIBUTION.md
================================================
# Contribution guidlines

  * [Suggest new pages](#suggest-new-pages)
  * [Entries structure](#entries-structure)
  * [Edit a page](#edit-a-page)
  * [Add a new page](#add-a-new-page)
  * [Deleting, Moving or Renaming a page](#deleting-moving-or-renaming-a-page)
    + [If the content is obsolete](#if-the-content-is-obsolete)
    + [If we want to move a page](#if-we-want-to-move-a-page)
    + [If we want to split a page](#if-we-want-to-split-a-page)
    + [If we want to rename a page](#if-we-want-to-rename-a-page)
  * [Review content](#review-content)

## Suggest new pages

To suggest pages that could fit the wiki, the recommended way is to open an issue containing a summary of the page, the section in which it should be (General, Internal projects of Pharo or External projects of Pharo) and optionaly links to already existing documentation on the projects.

On the language and environment part of the wiki we accept to document a part of the system that is already documented outside the wiki at the condition that we reference in a *See also* section those documentation. The goal is to have a centralized information and to provide alternative ways of explaining.

If you wish to add the new entry yourself, see section [Add a new page](#add-a-new-page).

## Entries structure

The entries structure is free but we still have some conventions. 

* Documentation on external projects should mostly contains small example, comparaisons between multiple projects, links to official documentations and repositories. We can accept documentation on the external projects in case there is none by the official maintainer.
* Long entries should begin with a table of content. We recommand [https://ecotrust-canada.github.io/markdown-toc/](https://ecotrust-canada.github.io/markdown-toc/).
* References to external/decentralized documentation should be in a *See also* section at the end of the entry.
* Smalltalk code snippets should use *tabulation* for source code indentation.
* Smalltalk code snippets should be highlighted using this format:


<pre>```Smalltalk
 Code
```</pre>

## Edit a page

If you see some typo, wrong informations or missing informations you can report it in the issues or you can also edit the document yourself and create a pull request.

Creating a PR is as easy as clicking on the Edit (pen) button, updating the document and propose the changes.

![Gif showing how to edit a page](Resources/EditPage.gif)

## Add a new page

In order to add a page you can just go into the folder of the section where the page should be and use the "Create new file button".

![Gif showing how to add a new page](Resources/CreatePage.gif)

If you need to integrate images in your entry, add them next to the Markdown file with an name following this pattern: `<NameOfThePage>_Image_<Description>.extension`. For example for an image illustrating `Iceberg` in a page called `VCS.md`, the image should be named `VCS_Image_IcebergIllustration.png`.

Once the page is created you need to add it to the [README.md](README.md) in the right section.

> Note: If you have contents to start a page but don't have the time or the knowledge to finish it, it is advised to propose a pull request with the content you have already. Then, one can open issues with the missing sections pointing to the concerned page.

An entry in the README can also have a one short sentense explaining the purpose of the page.

The pages focus mainly on the latest stable Pharo version. This does not mean we refuse contribution on older or development version of Pharo, but those should be complement of the current stable version.

## Deleting, Moving or Renaming a page

**/!\\ We never delete a page. /!\\**

This is a rule in this wiki. What is more annoying than a 404 when we look for documentation?

Instead we have different strategies depending on why we want to delete a page.

### If the content is obsolete

If the content is obsolete, we do not delete the page but we add a note (using `> OBSOLETE : bla`) at the beginning explaining why the guide is obsolete. The guide can be removed from the README. 

### If we want to move a page

If we want to move a page, we can copy it to the new location and let the old page at the original location with an explanation and a link to the new page.

### If we want to split a page

Sometimes a page is too big and would win to be splited. In that case the content can be extracted in multiple pages but the original page should stay and contains an index of the new pages.

### If we want to rename a page

If we want to rename a page, we can copy it with the new name and let the old page at the original location with an explanation and a link to the new page.

## Review content

It is really helpful to get reviews of the wiki's content. This can be achieved in multiple ways:
- Review a Pull Request. Comments, approvals and changes request on pull request will help the intergation of new contents.
- Open issues on existing entries.
- Create a Pull Request to propose enhancements to an existing entry.


================================================
FILE: ExternalProjects/DataStructures/DataFrame.md
================================================
# DataFrame



================================================
FILE: ExternalProjects/Export/Arff.md
================================================
# Arff support in Pharo
To be done, talk about the [Arff parser/generator](https://github.com/juliendelplanque/Arff)


================================================
FILE: ExternalProjects/Export/CSV.md
================================================
# CSV support in Pharo
Currently, Pharo provides one main framework to handle the [CSV format](https://fr.wikipedia.org/wiki/Comma-separated_values): NeoCSV.

## NeoCSV
NeoJSON is actually maintained by Sven Van Caekenberghe on [github](https://github.com/svenvc/NeoCSV).
This section shows some quick examples but there is a great [documentation made by Sven](https://github.com/svenvc/docs/blob/master/neo/neo-csv-paper.md) and a chapter in [Enterprise Pharo (chapter 7)](http://books.pharo.org/enterprise-pharo/).

> NeoCSV provides utilities to map Smalltalk objects to CSV lines, this page does not cover this topic to avoid duplication with the great documentation available in [Sven's documentation](https://github.com/svenvc/docs/blob/master/neo/neo-csv-paper.md) and [Enterprise Pharo (chapter 7)](http://books.pharo.org/enterprise-pharo/). Check it out if you need to use such feature!

### Install
To install NeoCSV, simply execute the following code snippet in a playground:
```Smalltalk
Metacello new
	repository: 'github://svenvc/NeoCSV/repository';
	baseline: 'NeoCSV';
	load
```

### Parse CSV
- From `String`:
```Smalltalk
str := 'id, name
0, Julien
1, Cyril
2, Guillaume
'.
str readStreamDo: [ :s |
	(NeoCSVReader on: s)
		skipHeader;
		addIntegerField;
		addField;
		upToEnd ]
```

- From `Stream`:
```Smalltalk
stream := 'id, name
0, Julien
1, Cyril
2, Guillaume
' readStream.

(NeoCSVReader on: stream)
	skipHeader;
	addIntegerField;
	addField;
	upToEnd
```

- Read from CSV file:
```Smalltalk
'/path/to/file.csv' asFileReference
	readStreamDo: [ :readStream |
		(NeoCSVReader on: readStream)
			skipHeader;
			addIntegerField;
			addField;
			upToEnd ]
```

### Generate CSV
Let `data` be defined as:
```Smalltalk
data := #(
(0 'Julien')
(1 'Cyril')
(2 'Guillaume')).
```

- To generate a CSV `String`:
```Smalltalk
String streamContents: [ :writeStream |
	(NeoCSVWriter on: writeStream)
		writeHeader: #(id name);
		nextPutAll: data ]
```

- To generate CSV on a `Stream`:
```Smalltalk
(NeoCSVWriter on: writeStream)
	writeHeader: #(id name);
	nextPutAll: data
```

- To write a CSV file:
```Smalltalk
'/path/to/file.csv' asFileReference
	writeStreamDo: [ :writeStream |
		(NeoCSVWriter on: writeStream)
 			writeHeader: #(id name);
			nextPutAll: data ]
```


================================================
FILE: ExternalProjects/Export/ESCP.md
================================================
# ESCP support in Pharo
To be done, talk about the [ESCP parser/generator](https://github.com/juliendelplanque/ESCP)


================================================
FILE: ExternalProjects/Export/HTML.md
================================================
# HTML support in Pharo
To be done, talk about HTML parser(s)

- XMLParser-HTML

- Soup ?


================================================
FILE: ExternalProjects/Export/JSON.md
================================================
# JSON support in Pharo
Currently, Pharo provides two main frameworks to handle the [JSON format](https://en.wikipedia.org/wiki/JSON).

This page briefly present these two frameworks and expose their differences to help users to choose the one fitting their needs.

- [STONJSON](#stonjson)
  * [Parse JSON](#parse-json)
  * [Generate JSON](#generate-json)
- [NeoJSON](#neojson)
  * [Install](#install)
  * [Parse JSON](#parse-json-1)
  * [Generate JSON](#generate-json-1)
- [STONJSON v.s. NeoJSON](#stonjson-vs-neojson)
- [JSON Schema](#json-schema)

## STONJSON
STONJSON is the built-in JSON parser available in default Pharo images. It is part of the STON package and its development takes place in Pharo's [github repository](https://github.com/pharo-project/pharo).

### Parse JSON
- From `String`:
```Smalltalk
STONJSON fromString: '{ "foo" : 42.0 }' "a Dictionary('foo'->42.0 )"
```

- From `Stream`:
```Smalltalk
readStream := '{ "foo" : 42.0 }' readStream.
STONJSON fromStream: readStream "a Dictionary('foo'->42.0 )"
```

- Read from JSON file:
```Smalltalk
'/path/to/file.json' asFileReference
	readStreamDo: [ :readStream |
		STONJSON fromStream: readStream ] "a Dictionary('foo'->42.0 )"
```

### Generate JSON
- Let `jsonObject` be defined as:
```Smalltalk
jsonObject := Dictionary new
	at: 'foo' put: 42.0;
	yourself.
```

- To generate a JSON `String`:
```Smalltalk
STONJSON toString: jsonObject "'{""foo"":42.0}'"
```

- To generate JSON on a `Stream`:
```Smalltalk
STONJSON put: jsonObject onStream: writeStream
```

- To write a JSON file:
```Smalltalk
'/path/to/file.json' asFileReference
	writeStreamDo: [ :writeStream |
		STONJSON put: jsonObject onStream: writeStream ]
```

To pretty print JSON, either use `STONJSON>>#toStringPretty:` or `STONJSON>>#put:onStreamPretty:`.

## NeoJSON
NeoJSON is actually maintained by Sven Van Caekenberghe on [github](https://github.com/svenvc/NeoJSON). 
This section shows some quick examples but there is a great [documentation made by Sven](https://github.com/svenvc/docs/blob/master/neo/neo-json-paper.md) and a chapter in [Enterprise Pharo (chapter 8)](http://books.pharo.org/enterprise-pharo/).

### Install
To install NeoJSON, simply execute the following code snippet in a playground:
```
Metacello new
	repository: 'github://svenvc/NeoJSON/repository';
	baseline: 'NeoJSON';
	load
```

### Parse JSON

- From `String`:
```Smalltalk
NeoJSONReader fromString: '{ "foo" : 42.0 }' "a Dictionary('foo'->42.0 )"
```

- From `Stream`:
```Smalltalk
readStream := '{ "foo" : 42.0 }' readStream.
(NeoJSONReader on: readStream) next
```

- Read from JSON file:
```Smalltalk
'/path/to/file.json' asFileReference
	readStreamDo: [ :readStream |
		(NeoJSONReader on: readStream) next ] "a Dictionary('foo'->42.0 )"
```

### Generate JSON
Let `jsonObject` be defined as:
```Smalltalk
jsonObject := Dictionary new
	at: 'foo' put: 42.0;
	yourself.
```

- To generate a JSON `String`:
```Smalltalk
NeoJSONWriter toString: jsonObject "'{""foo"":42.0}'"
```

Pretty:
```Smalltalk
NeoJSONWriter toStringPretty: jsonObject
```

- To generate JSON on a `Stream`:
```Smalltalk
(NeoJSONWriter on: writeStream)
	nextPut: jsonObject
```

Pretty:
```Smalltalk
(NeoJSONWriter on: writeStream)
	prettyPrint: true;
	nextPut: jsonObject.
```

- To write a JSON file:
```Smalltalk
'/path/to/file.json' asFileReference
	writeStreamDo: [ :writeStream |
		(NeoJSONWriter on: writeStream)
			nextPut: jsonObject ]
```

Pretty:
```Smalltalk
'/path/to/file.json' asFileReference
	writeStreamDo: [ :writeStream |
		(NeoJSONWriter on: writeStream)
			prettyPrint: true;
			nextPut: jsonObject ]
```

## STONJSON v.s. NeoJSON

|Property                                        |STONJSON            |NeoJSON               |
|------------------------------------------------|--------------------|----------------------|
|Parse JSON                                      | :white_check_mark: | :white_check_mark:   |
|Generate JSON                                   | :white_check_mark: | :white_check_mark:   |
|Pretty-printing                                 | :white_check_mark: | :white_check_mark:   |
|Built-in                                        | :white_check_mark: | :x:                  |
|Facilities to map JSON objects to Pharo objects | :x:                | :white_check_mark:   |
|Facilities to query JSON objects                | :x:                | :white_check_mark: * |

> *See [this post](http://forum.world.st/How-to-query-a-JSON-tp4948175p4948177.html) from Sven on the mailing list to know how to use this feature implemented in `NeoJSONObject`.

## JSON Schema
JSON Schema allows to describes the structure of JSON objects. It is similar to [XML Schema](https://en.wikipedia.org/wiki/XML_Schema_(W3C)) but for JSON.

A yet incomplete (but working in its scope) implementation of JSON Schema is provided by Zweidenker [on github](https://github.com/zweidenker/JSONSchema).


================================================
FILE: ExternalProjects/Export/XML.md
================================================
# XML support in Pharo
To be done, talk about XML parsers, XML model, XPath implementation, etc...


================================================
FILE: ExternalResources/Community.md
================================================
# Community
This page lists links to external resources created by members of Pharo (and sometimes other smalltalks) community.
Links are ranked in the lexicographic order which means that the position of a link in the list is not representative of the quality of the content.

This page exists for the sake of discoverability of Pharo community.

**We do not take any responsibility for content published in these external resources as we have no control on it.**

- [https://astares.blogspot.com](https://astares.blogspot.com) - Blog related to Pharo in general.
- [https://blog.sebastiansastre.co](https://blog.sebastiansastre.co) - Blog related to Pharo in general.
- [https://clementbera.wordpress.com](https://clementbera.wordpress.com) - Blog related to the Pharo virtual machine and its development.
- [https://endormitoire.wordpress.com/2016/10/03/freewill-in-progress-4/](https://endormitoire.wordpress.com/2016/10/03/freewill-in-progress-4/) - Blog related to Pharo in general.
- [https://fuhrmanator.github.io](https://fuhrmanator.github.io) - Blog related to Moose and Pharo in general but not only.
- [https://masteringobjects.wordpress.com](https://masteringobjects.wordpress.com) - Blog related to Pharo development.
- [https://medium.com/@i.oleks](https://medium.com/@i.oleks) - Blog related to Pharo, AI and machine learning.
- [https://medium.com/concerning-pharo](https://medium.com/concerning-pharo) - Blog related to Pharo in general, multiple authors involved.
- [https://medium.com/@juliendelplanque](https://medium.com/@juliendelplanque) - Blog related to Pharo in general.
- [http://www.mirandabanda.org/cogblog/](http://www.mirandabanda.org/cogblog/) - Blog for open-smalltalk-vm.
- [https://thiscontext.com](https://thiscontext.com) - Blog related to caffeine, a smalltalk vm in Javascript and other smalltalk topics.
- [https://80738163270632.blogspot.com/] - Blog related to Pharo in general.


================================================
FILE: General/Baselines.md
================================================
# Baselines

Pharo projects often require a configuration to declare how they should be loaded. This configuration is done via **Baselines**. A baseline defines the packages of the project, their dependencies to each other and to external projects and independent sub-groups that can be loaded.

Adding a baseline to a project has some advantages:
- It makes it easier to load the project
- It makes it easier for others to contribute to your project
- It allows the users of the project to be unaware of the project's dependencies
- It makes explicit the dependencies of the project
- It ensures that packages and dependencies of the project are loaded in the right order

This documentation explains how to write a baseline and how to load the project described by this baseline.

- [Baselines](#baselines)
	- [How to define Baselines](#how-to-define-baselines)
		- [Define packages forming your project](#define-packages-forming-your-project)
		- [Define external dependencies](#define-external-dependencies)
			- [To other remote git projects](#to-other-remote-git-projects)
				- [Depend on a subset of a git project](#depend-on-a-subset-of-a-git-project)
				- [Depends on the same project with different groups](#depends-on-the-same-project-with-different-groups)
			- [To a local git project](#to-a-local-git-project)
			- [To smalltalkhub projects](#to-smalltalkhub-projects)
		- [Groups](#groups)
			- [The default group](#the-default-group)
		- [Pre/post load actions](#prepost-load-actions)
		- [Loads different packages depending on the Pharo version](#loads-different-packages-depending-on-the-pharo-version)
		- [Define custom attributes](#define-custom-attributes)
		- [Loading types](#loading-types)
			- [Linear loading](#linear-loading)
			- [Atomic loading](#atomic-loading)
		- [Full example](#full-example)
	- [How to load a git project using its baseline](#how-to-load-a-git-project-using-its-baseline)
		- [From the playground](#from-the-playground)
			- [Project managed with Git](#project-managed-with-git)
				- [Project from github/gitlab/bitbucket](#project-from-githubgitlabbitbucket)
				- [Project from local repository](#project-from-local-repository)
			- [Project managed with Smalltalkhub](#project-managed-with-smalltalkhub)
			- [Project without repository](#project-without-repository)
			- [Loading groups](#loading-groups)
			- [Conflict, Upgrade and Downgrade resolution](#conflict-upgrade-and-downgrade-resolution)
			- [Manage warnings](#manage-warnings)
		- [From Iceberg](#from-iceberg)
	- [Other features](#other-features)
		- [Metacello lock feature](#metacello-lock-feature)
		- [Metacello get feature](#metacello-get-feature)
		- [Metacello fetch feature](#metacello-fetch-feature)
		- [Metacello record feature](#metacello-record-feature)
		- [Metacello listing feature](#metacello-listing-feature)
	- [See also](#see-also)

## How to define Baselines

The first step to create a baseline is to create a new subclass of `BaselineOf`. In the following example, `MyProject` is to be substituted by the name of your project:

```Smalltalk
BaselineOf subclass: #BaselineOfMyProject
	slots: {  }
	classVariables: {  }
	package: 'BaselineOfMyProject'
```

This class should be in a package separated from other packages' projects. The package holding the baseline **must** have the same name as the baseline. To summarize, `BaselineOfMyProject` class is in the `BaselineOfMyProject` package.

Then, create a method that defines the spec of the project for the commit it will be included in.

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"The main code of the baseline will go here"
		]
```

> The name of this method does not have to be `#baseline:`; however, that is the name that is commonly used. In fact, it is the `<baseline>` pragma which specifies that the method defines the spec of the project.

If your project is stored using a metadataless format (Tonel or FileTree metadataless), which is the default since Pharo 6, you need to add this method to your baseline:

```Smalltalk
projectClass
	^ MetacelloCypressBaselineProject
```

Or, if the project should be loadable in Pharo < 6.1, use this version:

```Smalltalk
projectClass
	^ [ self class environment at: #MetacelloCypressBaselineProject ]
	on: NotFound
	do: [ super projectClass ]
```
> The method is common to all projets using the metadataless format and the class return does not depend on the name of your baseline.

This will allow Metacello to be able to update your project and is needed because the default project class of Metacello used metadata to know if an update was needed.

### Define packages forming your project

To define the packages of the project, send the message `#package:` to the spec with the name of the package as argument.

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests';
				package: 'MyProject-Gui';
				package: 'MyProject-Gui-Tests';
				package: 'MyProject-Examples' ]
```

> Note: Packages are the most atomic entities managed by the baseline. It is not possible to declare entities at the package-tag granularity.

Defining packages is not enough to load them, because some of them might depend on other packages/projects. For example, `MyProject-Tests` needs to be loaded after `MyProject`.

To manage dependencies that are external to a project, see section *[Define external dependencies](#define-external-dependencies)*.

For dependencies between the packages of your project, you can use the message `#package:with:` to give more information to the spec.

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
			do: [
				"Packages"
				spec
					package: 'MyProject';
					package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
					package: 'MyProject-Gui' with: [ spec requires: #('MyProject') ];
					package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
					package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ]
```

The method `#requires:` will define the list of dependencies of a specific package.

Another way to declare requirements is to use the method `#includes:`. This method takes a collection of declarations as a parameter and will notify Metacello that all of them should include the package if they are loaded. This is helpful when defining platform-specific requirements, in case we want one of our packages to come with a platform-dependant package, which is depending on this package. See example in section *[Loads different packages depending on the Pharo version](#loads-different-packages-depending-on-the-pharo-version)*.

### Define external dependencies

Defining external dependencies can be done in different ways depending on where the dependency is hosted.

> To improve readability, I recommend extracting the definitions of dependencies into separate methods.

#### To other remote git projects

To depend on a git project, you can use the method `#baseline:with:`.

```Smalltalk
spec
	baseline: '{BaselineName}'
	with: [ spec repository: '{prefix}://{url}:{owner}/{projectName}:{version}/{subfolder}' ]
```

This snippet should be configured with:

- `{BaselineName}`: The name of the baseline to load (e.g, `'MaterialDesignLite'` to load `BaselineOfMaterialDesignLite`)
- `{prefix}`: This is host-specific:
  - `github` for github
  - `bitbucket` for bitbucket
  - `gitlab` for gitlab
  - `git` for others (and {url} is thus mandatory)
- `{url}`: Base url to the git host. Mandatory when prefix `git` is used, optional for other prefixes (can be useful for self hosted gitlab for example)
- `{owner}`: Name of the user or organization hosting the project
- `{projectName}`: Name of the project
- `{version}`: This parameter is optional (defaults to master). It can be the name of a branch, a tag like `'v1.2.0'` or `'v1.x.x'`, or a the SHA of a commit
- `{subfolder}`: This parameter is optional in case the code is not at the root of the project. It should point to the sub-folder containing the code

Example:

```Smalltalk
spec
	baseline: 'MaterialDesignLite'
	with: [ spec repository: 'github://DuneSt/MaterialDesignLite:v1.x.x/src']
```

##### Depend on a subset of a git project

Some projects can defines `groups` in their baselines. They are subsets of the project that can be loaded independently.
The previous snippet can also be customized to load only a specific group of the dependency like this:


```Smalltalk
spec
	baseline: 'MaterialDesignLite'
	with: [
		spec
		loads: #('Extensions');
		repository: 'github://DuneSt/MaterialDesignLite:v1.x.x/src'
	]
```

Once the dependency is defined, add `BaselineName` to the list of the required dependencies of the package depending on it.

Example:

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Dependencies"
			self materialDesignLite: spec.

			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject' 'MaterialDesignLite') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ].
```

```Smalltalk
materialDesignLite: spec
	spec
		baseline: 'MaterialDesignLite'
		with: [
			spec  
				loads: #('Extensions');
				repository: 'github://DuneSt/MaterialDesignLite:v1.x.x/src'
		]
```

##### Depends on the same project with different groups

In some cases your project might depend on an external project, but two packages of your project depend on different groups of this external project.

You can use the message `#project:copyFrom:with:` to create a new dependency spec.

```Smalltalk
materialDesignLite: spec
	spec
		baseline: 'MaterialDesignLite' with: [ spec repository: 'github://DuneSt/MaterialDesignLite:v1.x.x/src' ];
		project: 'MaterialDesignLiteExtensions' copyFrom: 'MaterialDesignLite' with: [ spec loads: #('Extensions') ]
```

Then you can use the new project name in the specification of dependencies.

Example:

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Dependencies"
			self materialDesignLite: spec.

			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject' 'MaterialDesignLiteExtensions') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests' 'MaterialDesignLite' "We load the version containing MDL tests for our tests only") ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ].
```

```Smalltalk
materialDesignLite: spec
	spec
		baseline: 'MaterialDesignLite' with: [ spec repository: 'github://DuneSt/MaterialDesignLite:v1.x.x/src' ];
		project: 'MaterialDesignLiteExtensions' copyFrom: 'MaterialDesignLite' with: [ spec loads: #('Extensions') ]
```

#### To a local git project

Sometimes we do not have access to a network, so we want to define dependencies to local git repositories.

This works like in the previous section, but with this repository format:

```Smalltalk
spec
	baseline: 'MaterialDesignLite'
	with: [ spec repository: 'gitlocal://full/path/to/repository' ]
```

#### To smalltalkhub projects

Depending on a [Smalltalkhub](http://smalltalkhub.com) project is done via `#project:with`.

```Smalltalk
spec
	project: '{DependencyName}'
	with: [ spec
		className: #ConfigurationOf{ConfigurationName};
		versionString: #'{Version}';
		repository: 'http://smalltalkhub.com/mc/{owner}/{repositoryName}/main/' ]
```

The snippet should be configured with:

- `{DependencyName}`: It can be anything from your packages, groups and other dependencies names. It will be used to define dependency to this project in your packages/groups
- `{ConfigurationName}`: It is the name of the configuration you wish to reference
- `{Version}`: Name of the version you wish to reference. It can be something like `'development'`, `'stable'`, `'release1'`, `'1.2.6'`, `'1.0-baseline'`, etc.
- `{owner}`: Name of the team or user hosting the project
- `{repositoryName}`: Name of the repository on SmalltalkHub

Example:

```Smalltalk
spec
	project: 'Magritte3'
	with: [ spec
		className: #ConfigurationOfMagritte3;
		versionString: #'release3';
		repository: 'http://smalltalkhub.com/mc/Magritte/Magritte3/main/' ]
```

As for git-hosted repositories, you can ask for a specific group:

```Smalltalk
spec
	project: 'Magritte3'
	with: [ spec
		className: #ConfigurationOfMagritte3;
		versionString: #'release3';
		loads: #('Seaside');
		repository: 'http://smalltalkhub.com/mc/Magritte/Magritte3/main/' ]
```

You can now use the dependency names to add the project as a dependency of your packages.

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Dependencies"
			self magritte3: spec.

			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject' 'Magritte3') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ].
```

```Smalltalk
magritte3: spec
	spec
		project: 'Magritte3'
		with: [ spec
			className: #ConfigurationOfMagritte3;
			versionString: #'release3';
			loads: #('Seaside');
			repository: 'http://smalltalkhub.com/mc/Magritte/Magritte3/main/' ]
```

### Groups

Sometimes we don't want to load the full project, but just a sub part, e.g.:

- Only the model of a project is needed without the UI (for example to build an alternative UI)
- Only the core of the project is needed without the tests and examples
- The project has some optional modules
- etc.

To manage such cases, baselines have the concept of a `Group`. A group is a loadable spec containing only a sub part of the project.

They can be declared with the `#group:with:` message. The second parameter defines the content of the group. The content can either be a package name, a dependency name, or even another group name.

Example:

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ].

			"Groups"
			spec
				group: 'Model' with: #('MyProject');
				group: 'Tests' with: #('MyProject-Tests' 'MyProject-Gui-Tests');
				group: 'Gui' with: #('MyProject-Gui');
				group: 'Example' with: #('MyProject-Examples');
				group: 'All' with: #('Model' 'Tests' 'Gui' 'Example')
```

> To load a project with a given group, you can check the section [loading groups](#loading-groups).

#### The default group

Each baseline has a default group named `'default'`. This group includes all the packages and the dependencies declared in the baseline.

When using the message `#load` with Metacello, or when not specifying the group of a dependency, it will load the "default" group.

This group can be redefined to change what will be loaded by default in a project.

Example:

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ].

			"Groups"
			spec
				group: 'default' with: #('Model' 'Gui');
				group: 'Model' with: #('MyProject');
				group: 'Tests' with: #('MyProject-Tests' 'MyProject-Gui-Tests');
				group: 'Gui' with: #('MyProject-Gui');
				group: 'Example' with: #('MyProject-Examples');
				group: 'All' with: #('Model' 'Tests' 'Gui' 'Example')
```

### Pre/post load actions

Baselines provide some hooks to execute some code when loading a project.

Those hooks are:

- `#preLoadDoIt:` which is executed after the code and dependencies are resolved and fetched, but before the code is loaded.
- `#postLoadDoIt:` which is executed when the project finishes loading.

Those methods take a symbol as parameter, which should be the name of a method of the baseline that should be executed by the hook.

Those methods can take two optional parameters:

- A Metacello loader containing information on the current project to load
- A Metacello spec containing information on the project spec

Example:

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			spec preLoadDoIt: #'preload:package:'.
			spec postLoadDoIt: #'postload:package:'.

			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ]
```

```Smalltalk
preload: loader package: packageSpec

	Transcript crLog: 'The fetch was finished. Now let''s load the project'
```

```Smalltalk
postload: loader package: packageSpec

	Transcript crLog: 'Project loaded!'
```

### Loads different packages depending on the Pharo version

It might be useful to load some packages in specific Pharo versions only. For example, if we have a compatibility package for Pharo 6, we do not want to load it in Pharo 7.

This is possible with the different spec attributes.

Up until now we defined everything in a spec for `#common`, which applies to all versions of Pharo. But it's possible to define a spec for specific Pharo versions or even other Smalltalk environments.

We can add in the baseline a special `#for:do:` command taking as parameter a specific attribute.

Every Pharo version contains some default attributes. For a Pharo version X.Y we have:

- `#pharo`
- `#pharoX.x`
- `#pharoX.Y.x`

For example for Pharo 6.1:

- `#pharo`
- `#pharo6.x`
- `#pharo6.1.x`

Those attributes can be used to define a spec that will be executed only in the images containing the corresponding tags.

Example:

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ].

			spec
				for: #'pharo6.x'
				do: [ spec
					package: 'MyProject' with: [ spec requires: #('MyProject-Pharo6') ];
					package: 'MyProject-Pharo6' ].
			spec
				for: #(#'pharo3.x' #'pharo4.x' #'pharo5.x' #'pharo6.x')
				do: [ spec
					package: 'MyProject' with: [ spec requires: #('MyProject-Pharo3To6') ];
					package: 'MyProject-Pharo3To6' ] ]
```

The `#includes:` method explained in section *[Define packages forming your project](#define-packages-forming-your-project)* is often useful when dealing with platform-specific requirements. Imagine your package `MyProject` will work in Pharo 6 only if `MyProject-Pharo6` is present, but `MyProject-Pharo6` depends on `MyProject`. This can be resolved like this:

Example:

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ].

			spec
				for: #'pharo6.x'
				do: [ spec
					package: 'MyProject' with: [ spec includes: #('MyProject-Pharo6') ];
					package: 'MyProject-Pharo6' with: [ spec requires: #('MyProject') ] ].
			spec
				for: #(#'pharo3.x' #'pharo4.x' #'pharo5.x' #'pharo6.x')
				do: [ spec
					package: 'MyProject' with: [ spec requires: #('MyProject-Pharo3To6') ];
					package: 'MyProject-Pharo3To6' ] ]
```

### Define custom attributes

On top of attributes from Pharo, it's also possible to define our own attributes.

We override the method `#customProjectAttributes` to return the custom attributes depending on the environment.

For example:

```Smalltalk
customProjectAttributes
	Smalltalk os isMacOS ifTrue: [ ^ #(#MacOS) ].
	Smalltalk os isUnix ifTrue: [ ^ #(#Unix) ].
	Smalltalk os isWindows ifTrue: [ ^ #(#Windows) ]
```

Then they can be used in the baseline.

```Smalltalk
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests') ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ] ].

			spec
				for: #(#'MacOS' #'Unix') do: [
					self osSubprocess: spec.
					spec package: 'MyProject' with: [ spec requires: #('OSSubprocess') ] ];
				for: #'Windows' do: [
					self processWrapper: spec.
					spec package: 'MyProject' with: [ spec requires: #('ProcessWrapper') ] ]
```

```Smalltalk
osSubprocess: spec
	spec
		baseline: 'OSSubprocess'
		with: [ spec repository: 'github://pharo-contributions/OSSubprocess:v1.0.1/repository' ]
```

```Smalltalk
processWrapper: spec
	spec 
		configuration: 'ProcessWrapper'
		with: [
			spec
				versionString: '1.2';
				repository: 'http://smalltalkhub.com/mc/hernan/ProcessWrapper/main' ]
```

### Loading types

Baselines support different loading types. The loading types define how Metacello loads the project.

#### Linear loading

By default, a baseline uses linear loading, which means packages are loaded one by one with their requirements loaded before them.

#### Atomic loading

This load type forces Metacello to load the full project in an atomic load. This is useful when a project has cyclic dependencies that cannot be resolved. For example it's useful to do an atomic load of Pharo's Kernel and Collections, since they depend on each other.

To define atomic loading, override the method `#project`:

```Smalltalk
project
	^ super project
		loadType: #atomic;
		yourself
```

### Full example

Here is an example with all previous features illustrated:

```Smalltalk
"baseline"
baseline: spec
	<baseline>
	spec
		for: #common
		do: [
			spec preLoadDoIt: #'preload:package:'.
			spec postLoadDoIt: #'postload:package:'.

			"Dependencies"
			self materialDesignLite: spec.

			"Packages"
			spec
				package: 'MyProject';
				package: 'MyProject-Tests' with: [ spec requires: #('MyProject') ];
				package: 'MyProject-Gui' with: [ spec requires: #('MyProject' 'MaterialDesignLiteExtensions' 'Magritte3') ];
				package: 'MyProject-Gui-Tests' with: [ spec requires: #('MyProject-Tests' 'MaterialDesignLite' "We load the version containing MDL tests for our tests only") ];
				package: 'MyProject-Examples' with: [ spec requires: #('MyProject-Gui') ].

			"Groups"
			spec
				group: 'Model' with: #('MyProject');
				group: 'Tests' with: #('MyProject-Tests' 'MyProject-Gui-Tests');
				group: 'Gui' with: #('MyProject-Gui');
				group: 'Example' with: #('MyProject-Examples');
				group: 'All' with: #('Model' 'Tests' 'Gui' 'Example') ].

			spec
				for: #'pharo6.x'
				do: [ spec
					package: 'MyProject' with: [ spec includes: #('MyProject-Pharo6') ];
					package: 'MyProject-Pharo6' with: [ spec requires: #('MyProject') ] ].

			spec
				for: #(#'pharo3.x' #'pharo4.x' #'pharo5.x' #'pharo6.x')
				do: [ spec
					package: 'MyProject' with: [ spec requires: #('MyProject-Pharo3To6') ];
					package: 'MyProject-Pharo3To6' ] ].

			spec
				for: #(#'MacOS' #'Unix') do: [
					self osSubprocess: spec.
					spec package: 'MyProject' with: [ spec requires: #('OSSubprocess') ] ].

			spec
				for: #'Windows' do: [
					self processWrapper: spec.
					spec package: 'MyProject' with: [ spec requires: #('ProcessWrapper') ] ]
```

```Smalltalk
projectClass
	^ MetacelloCypressBaselineProject
```

```Smalltalk
"dependencies"
materialDesignLite: spec
	spec
		baseline: 'MaterialDesignLite' with: [ spec repository: 'github://DuneSt/MaterialDesignLite:v1.x.x/src' ];
		project: 'MaterialDesignLiteExtensions' copyFrom: 'MaterialDesignLite' with: [ spec loads: #('Extensions') ]
```

```Smalltalk
"dependencies"
magritte3: spec
	spec
		project: 'Magritte3'
		with: [ spec
			className: #ConfigurationOfMagritte3;
			versionString: #'release3';
			loads: #('Seaside');
			repository: 'http://smalltalkhub.com/mc/Magritte/Magritte3/main/' ]
```

```Smalltalk
"dependencies"
osSubprocess: spec
	spec
		baseline: 'OSSubprocess'
		with: [ spec repository: 'github://pharo-contributions/OSSubprocess:v1.0.1/repository' ]
```

```Smalltalk
"dependencies"
processWrapper: spec
	spec
		configuration: 'ProcessWrapper'
		with: [
			spec
				versionString: '1.2';
				repository: 'http://smalltalkhub.com/mc/hernan/ProcessWrapper/main' ]
```

```Smalltalk
"accessing"
customProjectAttributes
	Smalltalk os isMacOS ifTrue: [ ^ #(#MacOS) ].
	Smalltalk os isUnix ifTrue: [ ^ #(#Unix) ].
	Smalltalk os isWindows ifTrue: [ ^ #(#Windows) ]
```

```Smalltalk
"actions"
preload: loader package: packageSpec

	Transcript crLog: 'The fetch was finished. Now let''s load the project'
```

```Smalltalk
"actions"
postload: loader package: packageSpec

	Transcript crLog: 'Project loaded!'
```

```Smalltalk
"accessing"
project
	^ super project
		loadType: #atomic;
		yourself
```

## How to load a git project using its baseline

When you have a project with a *Baseline*, it is possible to load it in a Pharo image if the project is compatible with the Pharo version.

Here we explain how to load a git project via its baseline.

### From the playground

The first way to load a project is to create a *Metacello* request programmatically and to execute it. This request looks like this:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.x.x' path: 'src';
	baseline: 'MaterialDesignLite';
	load
```

Note the three steps:

1. Create a new Metacello request
2. Configure it (declare the repository of the project, specify the version, the baseline, optional options...)
3. Launch the loading

To configure the request, some options are necessary and some are optional. We cover in the next two sub sections how to configure the loading of a project hosted via Monticello and git, and then we detail optional parameters.

#### Project managed with Git

To load a project from git you need to execute an expression like this:

```Smalltalk
Metacello new
	repository: {repository};
	baseline: {baselineName};
	load
```

This command has two parameters:

- `repository` defining the location of the git project, the version of the project to load and the subdirectory in which the project is stored.
- `baselineName` is the name of the baseline to load. For example to load the `MaterialDesignLite` project, the baseline name is `MaterialDesignLite` to load the project with `BaselineOfMaterialDesignLite`.

The repository parameter is a string that can take different forms depending on if the project is local or hosted remotely.

##### Project from github/gitlab/bitbucket

The repository parameter to load a project from github/gitlab/bitbucket takes this form:

`{prefix}://{optionalHostname}:{owner}/{projectName}:{version}/{subFolder}`

This snippet should be configured with:

- `{prefix}`: This is host-specific:
  - `github` for github
  - `bitbucket` for bitbucket
  - `gitlab` for gitlab
- `{optionalHostname}`: Optional server host, for private git servers
- `{owner}`: Name of the user or organization hosting the project
- `{projectName}`: Name of the project
- `{version}`: This parameter is optional, and it defaults to master. It can be the name of a branch, a tag like `'v1.2.0'` or `'v1.x.x'`, or a the SHA of a commit
- `{subfolder}`: This parameter is optional in case the code is at the root of the project. It should point to the sub-folder containing the code.

Example: loading from Github.

```Smalltalk
Metacello new
	repository: 'github://DuneSt/MaterialDesignLite:v1.x.x/src';
	baseline: 'MaterialDesignLite';
	load
```

Example: loading from a private Gitlab host.

```Smalltalk
Metacello new 
	baseline: 'Ghost';
	repository: 'gitlab://gitlab.inria.fr:RMOD/Ghost';
	load
```

Metacello also comes with some syntactic sugar to define the repository to github or bitbucket:

- *Github*: `Metacello>>githubUser:project:commitish:path:`
- *Bitbucket*: `Metacello>>bitbucketUser:project:commitish:path:`

Example:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'master' path: 'src';
	baseline: 'MaterialDesignLite';
	load
```

##### Project from local repository

To load a project from a local repository you can use this form to declare the repository:

`'{prefix}://{full/path/to/repository}/{subFolder}'`

This snippet should be configured with:

- `{prefix}`: This is specific to the file format:
  - `filetree` for a Filetree project
  - `tonel` for a Tonel project
- `{full/path/to/repository}`: is the path to the project on the file system
- `{subfolder}`: This parameter is optional in case the code is at the root of the project. It should point to the subfolder containing the code.

Example:

```Smalltalk
Metacello new
	repository: 'tonel://C:\Users\Cyril\GitRepositories\Native-Browser\src';
	baseline: 'NativeBrowser';
	load
```

#### Project managed with Smalltalkhub

To load a project from Smalltalkhub you need to execute an expression like this:

```Smalltalk
Metacello new
	repository: 'http://smalltalkhub.com/mc/{owner}/{repositoryName}/main';
	configuration: {configurationName};
	version: {version};
	load
```

This command has two parameters:

- `owner`: Name of the team or user hosting the project
- `repositoryName`: Name of the repository on SmalltalkHub
- `configurationName` is the name of the configuration to load. For example to load the `MaterialDesignLite` project, the baseline name is `MaterialDesignLite` to load the project with `BaselineOfMaterialDesignLite`.
- `{version}`: Name of the version you wish to reference. It can be something like `'development'`, `'stable'`, `'release1'`, `'1.2.6'`, `'1.0-baseline'`, etc.

Example:

```Smalltalk
Metacello new
	repository: 'http://smalltalkhub.com/mc/Seaside/Seaside31/main';
	configuration: 'Seaside3';
	version: #stable;
	load
```

You can also use `Metacello>>smalltalkhubUser:project:`:

```Smalltalk
Metacello new
	smalltalkhubUser: 'Seaside' project: 'Seaside31';
	configuration: 'Seaside3';
	version: #stable;
	load
```

#### Project without repository

It is possible to use Metacello without specifying any repository. This can be useful for defining all project dependencies in a baseline and then loading them with Metacello.

```Smalltalk
Metacello new
	baseline: #TinyBlog;
	load
```

#### Loading groups

Sometimes we want to load only specific groups of a project. This can be done be replacing the `load` selector by `load:`.

The `load:` selector takes a string or a collection of strings as parameter. Each string represents a group name from the baseline.

Examples:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'master' path: 'src';
	baseline: 'MaterialDesignLite';
	load: 'Extensions'
```

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'master' path: 'src';
	baseline: 'MaterialDesignLite';
	load: #('Extensions' 'Widgets')
```

#### Conflict, Upgrade and Downgrade resolution

Sometimes there can be conflicts, updates or downgrades while loading a project.

For example, imagine in an image the project `ProjA` at version v1.0.0. We want to load our project `ProjB` that depends on `ProjA` version v2.0.0., `ProjC` version v1.0.0, and `ProjD` that loads also `ProjC` version v2.0.0.

If we load `ProjB` in those conditions, we will have two problems:

- The update of `ProjA` from v1.0.0 to v2.0.0
- A conflict between `ProjC` v1.0.0 and v2.0.0

To manage conflicts we can use the options `onConflict:`, `onUpgrade:` and `onDowngrade:`.

Example:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'master' path: 'src';
	baseline: 'MaterialDesignLite';
	onConflict: [ :ex | ex useIncoming ];
	onUpgrade: [ :ex | ex useIncoming ];
	onDowngrade: [ :ex | ex useLoaded ];
	load
```

A last conflicting situation happens if Pharo includes a project in the default distribution and you want to load a new version. To manage this case you have the `ignoreImage` option.

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'master' path: 'src';
	baseline: 'MaterialDesignLite';
	onConflict: [ :ex | ex useIncoming ];
	onUpgrade: [ :ex | ex useIncoming ];
	onDowngrade: [ :ex | ex useLoaded ];
	ignoreImage;
	load
```

Here is a last example of conflict management. The Pharo community was previously on a version control system called Monticello. Most of the community has now migrated to GitHub. Some of the projects exist on Smalltalkhub (managed with Monticello) and on GitHub. It's not unusual to have conflict between the two.

Here is a little script that loads the version managed with git when the project name is the same:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'master' path: 'src';
	baseline: 'MaterialDesignLite';
	onConflict: [ :ex :a :b | a projectName = b projectName ifTrue: [ a projectSpec isBaselineOfProjectSpec ifTrue: [ ex useLoaded ] ifFalse: [ ex useIncoming ] ] ifFalse: [ ex resume ] ];
	load
```

#### Manage warnings

In some cases a project has problems during the loading, for example, if a package loaded is missing a dependency. When this happen, Metacello will raise a warning. Most of the time the projects can still work, at least partially. If you do not want Metacello to open a warning, you can log them instead. To enable this option you can use the `onWarningLog` or `onWarning:` options.

Examples:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'master' path: 'src';
	baseline: 'MaterialDesignLite';
	onWarning: [ :ex | Transcript crShow: ex ];
	load
```

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'master' path: 'src';
	baseline: 'MaterialDesignLite';
	onWarningLog;
	load
```

### From Iceberg

In Pharo 7 a new tool to manage git repositories was introduced: *Iceberg*. This tool allows the developer to load a project via a user interface.

The first step is to add your git project to Iceberg. Then right-click on the project name to access a `Metacello` sub-menu to load the project.

![Interface of Iceberg to load a project](Baselines_Image_LoadBaselineViaIceberg.png?raw=true "Interface of Iceberg to load a project")

## Other features

This section covers other features of baselines and Metacello.

### Metacello lock feature

In the normal course of loading and upgrading, you want the correct version of dependent projects loaded. However, there are some special cases where automatic upgrading isn't desirable:

- You may be actively developing a particular version of a project and you don't want the project upgraded (or downgraded) out from under you.
- You may be working with a git checkout of a project and you want to continue using the git checkout.
- You may not want to have particular projects upgraded automatically.

The `lock` command forces a particular version.

Example:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.1.0' path: 'src';
	baseline: 'MaterialDesignLite';
	lock
```

This example will lock the project MaterialDesignLite to version v1.1.0.

You can check the list of locked projects via those snippets:

```Smalltalk
Metacello registry locked. "Return the list of locked projects from the Metacello registry"

Metacello image locked. "Return the list of locked projects loaded in the image."
```

If you wish to unlock a project, you can use the `unlock` message.

Example:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.1.0' path: 'src';
	baseline: 'MaterialDesignLite';
	unlock
```

During the loading of a project you can also do some specific actions when you encounter a lock. For this you can use the `onLock:` message.

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.1.0' path: 'src';
	baseline: 'MaterialDesignLite';
	onLock: [ :ex :loaded :incoming | loaded baseName = 'myProject' ifTrue: [ ex break ] ifFalse: [ ex honor ] ];
	load
```

### Metacello get feature

Metacello includes a command to load the baseline of a project into the image. This is useful in two cases:

- You want to load only the baseline of the project
- You already have an obsolete baseline in your image and you want to update it before loading the project

To do that you can use the `get` command.

Example:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.x.x' path: 'src';
	baseline: 'MaterialDesignLite';
	get
```

### Metacello fetch feature

The fetch command downloads all of the packages without loading them. This includes the packages of the project but also their dependencies.

Example:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.x.x' path: 'src';
	baseline: 'MaterialDesignLite';
	fetch
```

You can also specify a group:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.x.x' path: 'src';
	baseline: 'MaterialDesignLite';
	fetch: #('Extensions' 'Widgets')
```

The fetch command duplicates what the load command would do, which means if a package is already loaded in the image, it will not be fetched. To fetch packages regardless of what is loaded in the image, use the `ignoreImage` option:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.x.x' path: 'src';
	baseline: 'MaterialDesignLite';
	ignoreImage;
	fetch
```

### Metacello record feature

The `record` command performs the same function as the `fetch` command, without actually downloading any files. As a consequence, it can give you a quick report of what packages will be loaded into your image. The recording will be produced in the `Transcript` (cmd + o + t).

Example:

```Smalltalk
Metacello new
	githubUser: 'DuneSt' project: 'MaterialDesignLite' commitish: 'v1.x.x' path: 'src';
	baseline: 'MaterialDesignLite';
	record
```

### Metacello listing feature

The `list` command lists projects in the image or Metacello registry:

```Smalltalk
Metacello image
	baseline: [ :spec | true "spec name beginsWith: 'Seaside'" ];
	list
  
Metacello registry
	baseline: [ :spec | true "spec name beginsWith: 'Seaside'" ];
	list
```

This command needs to be inspected to see the list.

## See also

- Deep into pharo: [Chapter 9, Managing Projects with Metacello](http://files.pharo.org/books-pdfs/deep-into-pharo/2013-DeepIntoPharo-EN.pdf)
- [Metacello documentation](https://github.com/Metacello/metacello/tree/master/docs)


================================================
FILE: General/CJKCharacter.md
================================================
# Using CJK (Chinese, Japanese, and Korean) characters

Pharo's default font settings for code (Source Code Pro) and UI (Source Sans Pro) are unable to handle [CJK characters](https://en.wikipedia.org/wiki/CJK_characters), this page explains how to display them properly in Pharo.

![Preview string for chinese characters under Source Code Pro](CJKCharacter_Screenshot_1.png)

Operating systems may come with fonts that support those characters but they are usually not monospaced which is not good for displaying code. If one need to display CJK characters in Pharo, it is recommended to install a monospace font which also covers CJK characters. Some of them are [`Noto Sans Mono CJK`](https://www.google.com/get/noto/) , `Microsoft YaHei Mono`, [`WenQuanYi Zen Hei Mono`](http://wenq.org).

Note one must enable the option `Update fonts at startup` first and restart Pharo to make the font selection dialog below show all available fonts:
1. Select menu `Pharo` -> `Settings` to show the `Settings Browser`.
2. Enable `Appearance` -> `Use Free type...` -> `Update fonts at startup`, this can be disabled later after one changes the fonts.

![Preview string for chinese characters under Microsoft YaHei Mono](CJKCharacter_Screenshot_2.png)

Note that on Windows 10, one may need to manually copy font files to `C:\Windows\Fonts\`.

Here is a code sample:

```Smalltalk
StandardFonts 
	defaultFont: (LogicalFont familyName: 'Noto Sans CJK SC' pointSize: 9);
	codeFont: (LogicalFont familyName: 'Microsoft YaHei Mono' pointSize: 10);
	listFont: (LogicalFont familyName: 'Noto Sans CJK SC' pointSize: 9);
	menuFont: (LogicalFont familyName: 'Noto Sans CJK SC' pointSize: 9);
	buttonFont: (LogicalFont familyName: 'Noto Sans CJK SC' pointSize: 9);
	windowTitleFont: (LogicalFont familyName: 'Noto Sans CJK SC' pointSize: 10);
	balloonFont: (LogicalFont familyName: 'Noto Sans CJK SC' pointSize: 8);
	haloFont: (LogicalFont familyName: 'Noto Sans CJK SC' pointSize: 8).
```

## Related links:

https://www.samadhiweb.com/blog/2019.02.22.windows.multilingual.html  
http://forum.world.st/Japanese-Fonts-td4928056.html  
http://forum.world.st/im-using-pharo-7-with-linux-env-but-cannot-input-korean-td5095342.html


================================================
FILE: General/CJKInputMethod.md
================================================
# Using CJK (Chinese, Japanese, and Korean) Input Method

It's possible to use CJK input method in Pharo. Tested under Pharo8 on macOS, Linux and Windows.

## Linux

On linux, you need add `-compositioninput` in VM args and make sure you are using Fcitx5.


================================================
FILE: General/CodingConventions.md
================================================
# Coding conventions

Pharo is full of implicit coding conventions. 

This page aims to document all those conventions to help newcomers write Pharo code as per the community's idioms.

## Tests conventions

Pharo has some conventions when it comes to tests. This section covers those.

**Package name**

It is preferred to store tests in a separate package rather than in the package of the tested classes.
The name of this package should be `NameOfOriginalPackage-Tests`.

For example, if one wants to add tests to `Material-Design-Lite-Core`, the tests should be in a package called `Material-Design-Lite-Core-Tests`.

**Class name**

Tests classes (subclasses of `TestCase`) should end with the suffix `Test` (and not `Tests` because a test class is a test case).

In the case of unit tests, the name of the class should be `MyClassTest`. For example, if one wants to add unit tests of `MDLButton`, the test class will be named `MDLButtonTest`.

**Method name**

Test method names in Pharo need to be prefixed with `test`. This is the way the test framework recognizes them as test methods. 

In case of a unit test on a method of the tested class, the name should be prefixed by `test` followed by the name of the method to test.

For example:
- The unit test for `#click` will be named `#testClick`
- The unit test for `#clickElement:` will be named `#testClickElement`
- The unit test for `#clickElement:withShiftPressed:` will be named `#testClickElementWithShiftPressed`

By doing that, a new icon next to your actual method name will appear in the system browser.
This icon allows one to launch the unit test of the method via a click.


================================================
FILE: General/CoolSnippets.md
================================================
# Cool Snippets

This file contains snippets of code that can be useful sometimes.

- [Download a file with a progress bar](#download-a-file-with-a-progress-bar)
- [Bench and profile a project from the tests](#bench-and-profile-a-project-from-the-tests)
- [Automatic transformation of Pharo's methods source code](#automatic-transformation-of-pharo-s-methods-source-code)
- [Browse all available icons](#browse-all-available-icons)
- [Rename programatically methods](#rename-programatically-methods)
- [Get all senders/implementors of a selector](#get-all-sendersimplementors-of-a-selector)
- [Find dependencies on a package](#find-dependencies-on-a-package)
- [Embed an image (picture) into Pharo](#embed-an-image-picture-into-pharo)

## Download a file with a progress bar

```Smalltalk
| outputFileName url |
outputFileName := './pharoLogo.png'.
outputFileName asFileReference ensureDelete.
url := 'http://files.pharo.org/media/logo/logo-flat.png' asZnUrl.
[ :bar | 
	bar title: 'Download: ' , url asString , ' to ' , outputFileName.
	[ ZnClient new
		url: url;
		signalProgress: true;
		downloadTo: outputFileName ]
		on: HTTPProgress
		do: [ :progress | 
			progress isEmpty ifFalse: [ bar current: progress percentage ].
			progress resume ] ] asJob run
```

## Bench and profile a project from the tests

```Smalltalk
packageSelectionBlock := [ :e | e name beginsWith: 'Spec' ].
testSuite := TestSuite new.
	
((RPackageOrganizer default packages select: packageSelectionBlock) flatCollect: #classes) select: [ :e | e inheritsFrom: TestCase ] thenDo: [ :e | e addToSuiteFromSelectors: testSuite ].

"Bench the test suite"	
[ testSuite run ] bench.

"Profile the test suite"
TimeProfiler spyOn: [ testSuite run ]

```

## Automatic transformation of Pharo's methods source code
During software maintenance, being able to transform source code automatically can be handy. It can be done easily in Pharo using the built-in code rewriting engine.

For example, let's say that we want to replace the occurences of `#symbolToReplace` symbol with occurences of `#replacedSymbol` in the following method:

```Smalltalk
ExampleCodeTransformation>>#methodToTransform
	1 + 1 = 2
		ifTrue: [ ^ #symbolToReplace ].

	^ #symbolToReplace , #symbolNotToReplace
```

It can be done easily using the following code snippet:

```Smalltalk
compiledMethod := ExampleCodeTransformation >> #methodToTransform.

ast := compiledMethod parseTree.

"Here we select only nodes holding the target symbol and we replace it with a node representing `#replacedSymbol`."
ast allChildren
	select: [ :n | n class = RBLiteralValueNode and: [ n value = #symbolToReplace ] ]
	thenDo: [ :node |
		rewriter := RBParseTreeRewriter new
			replaceTree: node
			withTree: (RBLiteralValueNode value: #replacedSymbol);
			yourself.
		(rewriter executeTree: ast)
			ifTrue: [ node replaceWith: rewriter tree ] ].
		
"Serialize the new AST as Pharo source code."
rewrittenSourceCode := (BIConfigurableFormatter format: ast).

"Recompile the method with transformed source code."
ExampleCodeTransformation compile: rewrittenSourceCode
```

## Browse all available icons
The following code snippet opens an inspector in which the 'Icons' tab allows to browse all icons available in the image.

```
Smalltalk ui icons inspect
```

To get a specific icon, use `#iconNamed:` method as follow:

```
Smalltalk ui icons iconNamed: #arrowUp
```

## Rename methods programatically

In this section we will present a code snippet to rename all methods of a class by replacing one substring with another. First, we find all methods of a given class with names that contain a substring `A`, then we rename those methods to replace `A` with another substring `B`.

```Smalltalk
"Class in which we want to rename the methods"
class := EpApplyPreviewerTest.
"Substring to replace"
from := 'With'.
"Substring to use"
to := 'Without'.

class methods
	select: [ :method | method selector includesSubstring: from ]
	thenDo: [ :method | 
		| permutationMap |
		"We want to keep the arguments in the same order"
		permutationMap := method numArgs = 0 ifTrue: [ #() ] ifFalse: [ (1 to: method numArgs) asArray ].
		
		(RBRenameMethodRefactoring
			renameMethod: method selector
			in: class
			to: (method selector copyReplaceAll: from with: to)
			permutation: permutationMap) execute ]
```

> Be careful, this will also rename the senders of those methods and if you have two methods with the same name in the image, it might badly rename some of them. Use this only on methods with unique names.

## Get all senders/implementors of a selector
The selector of a method is kind of the equivalent of the signature of a method or function in other programming languages.
However, since Pharo is dynamically typed, this selector is only the name of the method, without the parameters.
For example, the selector of the method below is `#name:`

```
Example>>name: aString
	name := aString
```

For a given `CompiledMethod` in the system, its selector is accessible via `#selector` message.

```
(Object>>#yourself) selector. "#yourself"
```

### Senders
To get all the senders of a selector accross the image, simply call `#senders` on the selector:

```
#yourself senders
```

### Implementors
To get all `CompiledMethod`s implementing a method having a selector, simply call `#implementors` on the selector:

```
#yourself implementors
```

## Find dependencies on a package

In Pharo it is easy to find the dependencies of one package through the `Dependency Analyzer`, but there is no tool to browse the dependencies *on* a single package. 

It is possible to do it programatically via this snippet:

```Smalltalk
report := DADependencyChecker new computeImageDependencies. "This might take some time but it will run in background"
report knownDependantsOf: 'Epicea' "Replace Epicia by the name of your package."
```

## Embed an image (picture) into Pharo
If you want to add an image into Pharo, you will need to import it
```Smalltalk
ImageReadWriter formFromFileNamed: 'test.png'
```
and you may store it into the image for further reuse. This is achieved by encoding the image into a base 64 String. Then, the String can be stored in a method.
```Smalltalk
(Base64MimeConverter mimeEncode: 'test.png' asFileReference binaryReadStream) contents
```
Let's say we store the image base64 String in `Foo>>#image`. To materialize a Form from this image, you can do:
```Smalltalk
Form fromBinaryStream: Foo image base64Decoded asByteArray readStream
```
Here is a shortcut available since Pharo 8.0:
```Smalltalk
Form fromBase64String: Foo image
```


================================================
FILE: General/DeployYourPharoApplication.md
================================================
# How to deploy a Pharo application

*This guide has for purpose to help developpers deploying a Pharo application. If something is missing to you, do not hesitate to open an issue.*

**This guide is first written for Pharo 7. Some parts will not work in Pharo 6 and earlier.**

- [How to deploy a Pharo application](#how-to-deploy-a-pharo-application)
  * [Cruiser: A tool for app deployment?](#cruiser)
  * [Clean your image before deployment](#clean-your-image-before-deployment)
  * [Sources obfuscation](#sources-obfuscation)
  * [Change the logo and window title of the application](#change-the-logo-and-window-title-of-the-application)
  * [Deploy a Seaside application with Nginx](#deploy-a-seaside-application-with-nginx)

## Cruiser
Cruiser is a tool to package Pharo applications. The idea is to quickly convert an application in a development environment to a production one.
[https://github.com/VincentBlondeau/Cruiser](https://github.com/VincentBlondeau/Cruiser)


## Clean your image before deployment

In this section we explain various ways to clean an image for deployment. All steps are not necessary and the benefits are given in each subsection.

### Clean up the system

A first step is to launch a cleanup of the image. Pharo already contains a system to cleanup divers part of the system by calling the `#cleanUp(:)` method of every class implementing it.

It can be done with this snippet:

```Smalltalk
Smalltalk cleanUp: true except: {} confirming: false
```

The first parameter should be a boolean. If it's value is `true` it will launch a more aggresive cleanup and this will destroy resources, change sets, etc.
The second parameter allows the developper to exclude some classes of the cleanup by passing an array containing all the classes that should not execute their cleanup.

### Ensure logins are removed from the image

During the deployment of an application it might be a good idea to remove all login informations from the image.

In order to do that you can execute this script:

```Smalltalk
| store |

"Remove all repositories from Monticello VCS"
MCRepositoryGroup allSubInstancesDo: [ :group | group repositories do: [ :repo | group removeRepository: repo ] ].

"Remove projects and credentials from Git VCS (Tested in Pharo 7)"
IceRepository registry removeAll.
store := IceCredentialStore current.
store allCredentials do: [ :each | each removeFrom: store ]
```

With this step done all the credentials should be removed from the image if you do not use an external project from Pharo that store some credentials.

### Close all windows

While deploying an application you might want to ensure every Morph is closed (to remove the Pharo welcome window for example).

This can directly be done via the command:

```Smalltalk
World closeAllWindowsDiscardingChanges
```

### Disable deprecation warning

Pharo contains a deprecation warning system to help the developers to keep their code up to date but in productions those warnings should be removed so that the user will not be bothered by them in case a deprecated method is called.

You can do that via:

```Smalltalk
Deprecation
	raiseWarning: false;
	showWarning: false
```

### Enable the run without sources and changes files

It is possible to run a Pharo image without `.changes` or `.sources` files.

To do that you can execute:

```Smalltalk
NoChangesLog install.
NoPharoFilesOpener install
```

Note that FFI needs the sources to work properly. In Pharo 7 a pluggin to remove this need was introduced.
If your application uses FFI calls you will need to execute:

```Smalltalk
FFICompilerPlugin install
```

### Disable creation of STDio files on Windows

On Windows there is two way to launch a Pharo image. The first uses the `Pharo.exe` executable and the second `PharoConsole.exe`. The difference between those two methods is that the former will be launched without a terminal and will create files to write STDio outputs. The second will open a terminal with Pharo to manage STDio.

It is possible to disable the writing of the STDio files on Windows with this code:

```Smalltalk
Stdio useNullStreams
```

### Remove tests and example packages

In production examples and tests packages are useless. You can find bellow a script to unload them. 

> Be careful, this script is based on a heuristic. If the naming convensions or dependencies are not well managed this might break your application. Please test you application after using such a script.

```Smalltalk
| substrings |
substrings := #('Test' 'Example' 'Mock' 'Demo').

RPackageOrganizer default packages
	select: [ :p | substrings anySatisfy: [ :aString | p name includesSubstring: aString ] ]
	thenDo: #removeFromSystem
```

### Disable Monticello cache

Monticello uses by default a cache when it is used. It is possible to disable this cache with this script:

```Smalltalk
MCCacheRepository uniqueInstance disable
```

### Disable Epicea

Pharo contains a record system to recover changes: *Epicea*. This system log a lot of events on disk.

It is possible to disable Epicea like this:

```Smalltalk
EpMonitor reset
```

### Garbage collect

As last step of the deployment I would recommand the user to launch a full garbage collection of the system to clean all dead instances from the image:

```Smalltalk
5 timesRepeat: [ Smalltalk garbageCollect ]
```

### Delete pharo-local folder

Pharo works with a local folder containing caches. This folder is called `pharo-local` and is next to the image since Pharo 7. It is recommanded to delete this folder, or to not include this folder in the distribution.

## Sources obfuscation

When deploying a commercial application on the customer's infrastructure, we might want to protect our code. This section will give some advice on how to protect the source code of your application.

> WARNING: What will be describe here is not a perfect solution. We are aware it will still have some weakness, but at least it will make it much harder to get the source code of the application.

This section works with the previous section aswell. We recommand to:
* Run without the sources file
* Run without the changes file
* Disable Epicea
* Remove the loggins of your image

### Force omission of startup preferences

At launch Pharo try to load preferences. Since the user can execute Smalltalk code via those preferences, we recommand to disable the preference mechanism with this code:

```Smalltalk
PharoCommandLineHandler forcePreferencesOmission: true
```

### Protect command lines by a password

Since the user can intereact with Pharo via command line, we recommand to protect command lines with a password.

The password is not be saved in clear. It is hashed using pepper and iterations.

If you wish to define *application* command lines who does not need a password protection, implement the method `requireDeploymentPassword` on the class side of your command lines to return `false`.

```Smalltalk
"Enable password protection"
CommandLinePasswordManager protectCommandLinesByPasswordWith: 'PharoPassword'.

"You can also customize the pepper and number of iterations for the hashing of the password."
CommandLinePasswordManager protectCommandLinesByPasswordWith: 'PharoPassword' pepper: 'SomePepper' numberOfHashIterations: 10.

"Remove password protection"
CommandLinePasswordManager removePasswordProtection.
```

### Remove the decompiler

Without the sources and changes files the user does not have the source code shipped with the application, but he still has the byte code of the application. To make it harder to exploit if he succeed to get a part of the byte code, you can unload the decompiler from the image with the piece of code:

```Smalltalk
RPackageOrganizer default packages
	select: [ :p | p name includesSubstring: 'Flashback' ]
	thenDo: #removeFromSystem
```

### Disable global shortcuts

If the customer has access to the Pharo image it is recommanded to disable global shortcuts that can help to open tools. 

It is doable this way:

```Smalltalk
(KMRepository default globalCategories flatCollect: [ :each | each allEntries keymaps ]) do: #disable
```

### Disable WorldMenu, Menubar and Taskbar

To block the access to the tools it is possible to disable the world menu, the taskbar and the menu bar from Pharo with this piece of code:

```Smalltalk
"Disable world menu and menubar"
WorldState desktopMenuPragmaKeyword: ''.

"Disable Menubar only"
MenubarMorph showMenubar: false.

"Disable WorldMenu only"
PasteUpMorph shouldShowWorldMenu: false.

"Disable taskbar"
TaskbarMorph showTaskbar: false.
```

### Disable progress bar interrupt button

If you show progresses in your application via a progress bar, the user can clic on the red cross to stop the action and open a debugger.

It is possible to remove this possibility executing:

```Smalltalk
JobProgressBarMorph isInterruptable: false
```

### Disable process interruption button

In Pharo, it is possible to disable the current process via the `cmd + .` shortcut. This feature can be disabled:

```Smalltalk
UserInterruptHandler cmdDotEnabled: false
```

### Disable drag and drop in Pharo

It is possible to drop files in Pharo to install code in it. It is recommanded to disable this feature to block users to inject code into the application. Since there is no setting to do that, you can recompile a part of the Pharo image to block it this way:

```Smalltalk
WorldMorph allowDropFiles: false
```

### Disable Morph's Halos

To remove the option to open Halos around the Morphs of Pharo you can execute:

```Smalltalk
Morph halosEnabled: false
```

### Disable Debugger

#### Pharo 8

Since Pharo 8, Pharo comes with new debuggers you can choose from.

When deploying a private application you don't want the user to get a bug and access to the code through it. For that you can use the `NoDebugger`:

```Smalltalk
NoDebugger beCurrent
```

#### Pharo < 8 or specific debuggers

In case you are using Pharo < 8 or you want a special handling of the bug you can create your own debugger.

For that you need to create a object and implement a class side method called `#openOn:withFullView:andNotification:`.

For example for a `NoDebugger`:

```Smalltalk
NoDebugger class>>openOn: aDebugSession withFullView: aBool andNotification: aString
	"Do nothing"
```

For a debugger exporting in a file the error:

```Smalltalk
openOn: aDebugSession withFullView: aBool andNotification: aString
	'errors.log'
		ensureCreateFile;
		writeStreamDo: [ :s |
			s
				setToEnd;
				<< 'ERROR. Here is the stack:';
				<< OSPlatform current lineEnding.
			aDebugSession interruptedContext shortDebugStackOn: s ]
```

You then need to register the debugger:

```Smalltalk
Smalltalk tools register: NoDebugger as: #debugger
```

### Open a morph in full screen

When deploying the application, while there is no real headless mode in Pharo or when the application contains a user interface embedded we can open a Morph in full screen to ensure the user cannot access to content behind it. 

To do that we can create a Spec application (in case of headless application it can just contains a logo and a `quit` button) and open it in full screen with this command:

```Smalltalk
MyPresenter new openWorldWithSpec
```

## Change the logo and window title of the application

In Windows it is possible to change the title and the logo of the Pharo application. 

To do that you can execute:

```Smalltalk
DisplayScreen setWindowTitle: 'MyApplication'.

DisplayScreen hostWindowIcon: (FileLocator imageDirectory / 'testLogo.ico') asFileReference fullName.
```

## Deploy a Seaside application

This section will cover a specific kind of deployment: the deployment of a web application with Seaside.

### Prepare the image

It is recommanded to prepare the image for deployment. This section will cover some possible configurations you can apply to your image.

> Note: This is section only contains suggestions and it might be missing interesting options. If you have an idea of missing section do not hesitate to open an issue.

#### Set server mode

When deploying an application as a server, it is possible to change a setting to slow down the rendering cycle of the image and increase performances. It can be done like this:

```Smalltalk
WorldState serverMode: true
```

#### Unregister applications

When building your seaside image it is possible that some Seaside application got registered (demos for examples). 

It is possible to unregister them like this:

```Smalltalk
applicationsToUnregister := WAAdmin defaultDispatcher handlers keys \ #('myApplication' 'files' 'myHandler' 'config').
applicationsToUnregister do: [ :appName | WAAdmin defaultDispatcher unregister: (WAAdmin defaultDispatcher handlerAt: appName) ]
```

#### Set default application

Applications must have a name in Seaside and the name should be in the URL. However, it is possible to define a default application which will be selected in case no application name is in the URL. 

```Smalltalk
WAAdmin defaultDispatcher defaultName: 'myApplicationName'
```

#### Disable development toolbar

In case you load a version of Seaside containing development tools, your application will come with a development toolbar. 

It is possible to remove it by executing:

```Smalltalk
WAAdmin applicationDefaults removeParent: WADevelopmentConfiguration instance ].
```

Then you need to initialize you application. 

#### Protect configuration by a password

In case you keep the configuration application available to the user, you might want to protect it by a password. It wan be done like this:

```Smalltalk
| application |
application := WAAdmin defaultDispatcher handlerAt: 'config'.
application configuration addParent: WAAuthConfiguration instance.
application
	preferenceAt: #login put: 'admin';
	preferenceAt: #passwordHash put: (GRPlatform current secureHashFor: 'seasideiscool').
application addFilter: WAAuthenticationFilter new
```

### Deploy with a Ngnix server

This section will cover the configuration needed to deploy an image with a nginx server.

#### Launch the image

In general I (the author of this decumentation) use a Jenkins to generate my image and then I have a script to deploy the image.

My script looks like this:

```bash
#!/usr/bin/env bash
set -vx

# Where to deploy the application
export DEST=/srv/app/mdl
# Pharo version for the deployment
export PHARO=61
# Location of the zip containing the archive
export ARCHIVE_LOCATION=/var/lib/jenkins/workspace/MaterialDesignLite/PHARO/$PHARO/VERSION/master/

# To launch an image I uses a screen, else the image will close with my ssh session. Here I ensure the session used is closed.
screen -S mdl -X quit

# Remove the old version
rm -rf $DEST/{MaterialDesignLite.*,pharo*,*.sources,Pharo*}

# Copy the application
cp ${ARCHIVE_LOCATION}MaterialDesignLite.zip $DEST/
cd $DEST

# Get a VM and unzip the application
wget --quiet -O - get.pharo.org/vm${PHARO} | bash
unzip MaterialDesignLite.zip

# Launch the application and initialize it on a free and open port
./pharo MaterialDesignLite.image eval --save "
MDLDemo initializeAs: 'mdl'.

WAAdmin defaultDispatcher defaultName: 'mdl'.

ZnZincServerAdaptor startOn: 8088"

#Launch the image in a screen
screen -Sdm mdl ./pharo MaterialDesignLite.image --no-quit
```
#### HTTP deployment

Now that the image is launched we need to dispatch it via nginx.

In order to do that over HTTP I uses this configuration:

```nginx
server {
  listen 80; #Since it's a web application, listen port 80
  listen [::]:80; #Same for IPv6
  server_name {Domaine name. Example mysite.com}; #Set your domaine name
  server_tokens off;  #Do not display nginx version for security reasons

  access_log /var/log/nginx/{log name}.log; #loging
  error_log /var/log/nginx/{error log name}.log; #error loging

  root {Path to the root. For example /srv/myApp/};

  location = / {
    try_files $uri $uri/index.html @proxy;
  }

  #use a proxy for your seaside application
  location @proxy {
    rewrite ^ /{Seaside application name. For example TelescopeDemo}$1 last;
  }

  location /{Seaside application name. For example TelescopeDemo} {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://127.0.0.1:{Port on which your ZincServerAdaptor listen. For example 8080};
  }

  # This is for the file libraries
  location /files {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://127.0.0.1:{Port on which your ZincServerAdaptor listen. For example 8080};
  }

}
```
#### HTTPS deployment

The previous option works but is not secured. It is recommanded to generate a TLS certificate (with `let's encrypt` via `certbot` for example) and to deploy over HTTPS.

Then the configuration will look like this:

```nginx
server {
  listen 80; #Since it's a web application, listen port 80
  listen [::]:80; #Same for IPv6
  server_name {Domaine name. Example mysite.com}; #Set your domaine name
  server_tokens off;  #Do not display nginx version for security reasons
  return 301 https://$server_name$request_uri; #Redirect HTTP -> HTTPS
}

server {
  listen 443 ssl http2; #Listen to port 443 for HTTPS
  listen [::]:443 ssl http2; #Same for IPv6
  server_name {Domaine name. Example mysite.com}; #Set your domaine name
  server_tokens off;  #Do not display nginx version for security reasons
  ssl_certificate {path to your public certificate key}.pem;
  ssl_certificate_key {path to your private certificate key}.pem;

  access_log /var/log/nginx/{log name}.log; #loging
  error_log /var/log/nginx/{error log name}.log; #error loging

  root {Path to the root. For example /srv/myApp/};

  location = / {
    try_files $uri $uri/index.html @proxy;
  }

  #use a proxy for your seaside application
  location @proxy {
    rewrite ^ /{Seaside application name. For example TelescopeDemo}$1 last;
  }

  location /{Seaside application name. For example TelescopeDemo} {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://127.0.0.1:{Port on which your ZincServerAdaptor listen. For example 8080};
  }

  # This is for the file libraries
  location /files {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://127.0.0.1:{Port on which your ZincServerAdaptor listen. For example 8080};
  }
}
```



================================================
FILE: General/Exceptions.md
================================================
# Exceptions

All applications have to deal with exceptional situations.
Arithmetic errors may occur (such as division by zero), unexpected situations may arise (file not found), or resources may be exhausted (network down, disk full, etc.).
In languages like C, the solution is to have operations that fail return a special error code; this means that client code must check the return value of each operation, and take special action to handle errors. This leads to brittle code.

Modern programming languages, including Pharo, offer a dedicated exception-handling mechanism that greatly simplifies the way in which exceptional situations are signaled and handled.
This mechanism is the **Exception** mechanism.

- [Exceptions](#exceptions)
  * [Basic Uses](#basic-uses)
    + [Signaling an exception](#signaling-an-exception)
    + [Handling exceptions](#handling-exceptions)
    + [Creating your own exceptions](#creating-your-own-exceptions)
    + [Ensure](#ensure)
    + [IfCurtailed](#ifcurtailed)
  * [Advanced Uses](#advanced-uses)
    + [Return](#return)
    + [Retry](#retry)
    + [Resume](#resume)
    + [Pass](#pass)
    + [Outer](#outer)
    + [Resignal](#resignal)
  * [A deeper look at the exception mechanism](#a-deeper-look-at-the-exception-mechanism)
  * [Credits](#credits)

## Basic Uses

### Signalling an exception

**Syntax:**  
`anException signal`  
or:
`anException signal: 'message with additional information'`

Imagine you have a method `potentiallyProblematicMethod`, that sometimes sets a variable to a bad value. When this happens (line 3), you want to signal this problem by **signalling** an exception (in this example an `Error` exception).

```Smalltalk
potentiallyProblematicMethod
	self doThings.
	(myVariable = badValue) ifTrue: [ ^ Error new signal: 'Oh my god no!'].
	^ myVariable.
```

If you execute this code, the following window opens:
![Image](./Exceptions_Image_ExamplePreDebugger.png)

And if you click on "Debug", a debugger opens to help you understand why your application signalled an exception.
![Image](./Exceptions_Image_ExampleDebugger.png)

### Handling exceptions
**Syntax:**  
`protectedBlock on: anExceptionClass do: handlerBlock`.  
Handling multiple exception classes:  
`protectedBlock on: anExceptionClass, anotherExceptionClass, yetAnotherExceptionClass... do: handlerBlock`.  
Accessing the exception in the handler block:  
`protectedBlock on: anExceptionClass do: [:exceptionToHandle| yourCode]`.

As seen in the previous paragraph, if an exception is signalled and nothing else is done, a debugger opens. It is useful when developing, but in the end you probably want your application to catch these exceptions and handle them itself if possible (for example by displaying a nice pop-up informing the user of the problem). This is done with exception **handlers**.

In Pharo, an exception handler is of the form:  
`protectedBlock on: anExceptionClass do: handlerBlock`.  
Here's what happens (in English): *"Evaluate `protectedBlock`. If it signals an exception of the class `anExceptionClass`, catch this exception and evaluate `handlerBlock` instead"*.

To continue the previous example, let's say that `potentiallyProblematicMethod` is called by `solidMethod`. Now `solidMethod` is solid, so it does not want debuggers to open when it is executed. Instead, if an exception is signalled by `potentiallyProblematicMethod`, it will handle it, display a pop-up informing the user, and return `42` instead of the result of `potentiallyProblematicMethod`.

```Smalltalk
solidMethod
	^ [self potentiallyProblematicMethod]
		on: Error
		do: [UIManager default inform: 'There was an issue, but it`s ok'. 42.]
```

Now when `solidMethod` is executed, it either returns the result of `self potentiallyProblematicMethod` if no `Error` is signalled, or it displays a pop-up and returns 42 if an `Error` is signalled.

![Image](./Exceptions_Image_InformationPopUp.png)

When an exception is signalled, it walks the call stack (from the current method to its caller, then the caller of the caller, etc...) until it finds a handler that can handle it. If no handler is found, a debugger is opened.

### Creating your own exceptions
`Error` is not the only kind of exception that can be signalled, there are a lot more! The following picture shows a few examples.


![Image](./Exceptions_Image_ExceptionSample.png)

An issue with writing handlers for generic exception types like `Error` is that these handlers will not only handle errors your application signals (which is fine), but they will also handle errors signalled by the libraries you use, or code that your application uses but that is not a part of it. This is potentially dangerous, as your application may not be doing the right thing for these errors.

To prevent this, you can define your own types of exceptions by creating subclasses of the `Exception` class, and signal and catch these.

To continue the example, we could create an `Exception` subclass named `MyVariableHasABadValue`, and update `potentiallyProblematicMethod` and `solidMethod` as follows:

```Smalltalk
potentiallyProblematicMethod
	self doThings.
	(myVariable = badValue) ifTrue: [ ^ MyVariableHasABadValue new signal: 'Oh my god no!'].
	^ myVariable.
```

```Smalltalk
solidMethod
	^ [self potentiallyProblematicMethod]
		on: MyVariableHasABadValue
		do: [UIManager default inform: 'There was an issue, but it`s ok'. 42.]
```

### Ensure
**Syntax:**  
`aBlock ensure: ensuredBlock`.

The `ensure:` message can be sent to a block to make sure that, even if the block fails (e.g., signals an exception) the argument block will still be executed.  

This is useful to guarantee that `ensuredBlock` will be executed no matter what, for example to close files or clean up in case `aBlock` signals an exception, before the exception is transmitted.

### IfCurtailed
**Syntax:**  
`aBlock ifCurtailed: curtailBlock`

The `ifCurtailed:` message is similar to `ensure:`, but its argument block is evaluated **only** if the receiver block signals an exception.  

## Advanced Uses
After catching an exception in a handler, there are a number of advanced things you can do with the exception.

### Return
**Syntax:**  
`protectedBlock on: anExceptionClass do: [:ex | aValue ]`  
or: `protectedBlock on: anExceptionClass do: [:ex | ex return ]`  
or: `protectedBlock on: anExceptionClass do: [:ex | ex return: aValue ]`  

**Synopsis:**  
This is the standard behavior of handler blocks. If an exception is caught, this handler returns an alternative value for the protected block (the execution continues as if the protected block has returned that value).

Here is a picture of the context stack (a.k.a. call stack) explaining this operation.
![Image](Exceptions_Image_WhatCanYouDoWithAnExceptionYouCaught_fragment1_return.png)

### Retry
**Syntax:**  
`protectedBlock on: anExceptionClass do: [:ex | ex retry ]`  
or: `protectedBlock on: anExceptionClass do: [:ex | ex retryUsing: aBlock ]`  

**Synopsis:**  
Re-execute the protected block (if using `#retry`), or replace the protected block with a different block and then re-execute it (if using `#retryUsing:`).

Here is a picture of the context stack (a.k.a. call stack) explaining this operation.
![Image](Exceptions_Image_WhatCanYouDoWithAnExceptionYouCaught_fragment2_retry.png)

### Resume
**Syntax:**  
`protectedBlock on: anExceptionClass do: [:ex | ex resume ]`  
or: `protectedBlock on: anExceptionClass do: [:ex | ex resume: aValue ]` 

**Synopsis:**  
Resume the execution of the protected block just after the call to #signal. The call to #signal is worth `nil` (if using `#resume`) or `aValue` (if using `#resume: aValue`).


Here is a picture of the context stack (a.k.a. call stack) explaining this operation.
![Image](Exceptions_Image_WhatCanYouDoWithAnExceptionYouCaught_fragment3_resume.png)

### Pass
**Syntax:**  
`protectedBlock on: anExceptionClass do: [:ex | ex pass ]`  

**Synopsis:**  
Skip the current handler and keep looking for another handler to handle this exception.



### Outer
**Syntax:**  
`protectedBlock on: anExceptionClass do: [:ex | ex outer ]`  

**Synopsis:**  
Like `ex pass`, but if another handler later calls `#resume` on the exception, the execution resumes where `#outer` was called instead of where the exception was signalled.  
If multiple `#outer` are executed on the same exception, they will form a sort of stack of positions to go back to, in case `#resume` is called multiple times on the exception.

Here is a picture of the context stack (a.k.a. call stack) explaining this operation.
![Image](Exceptions_Image_WhatCanYouDoWithAnExceptionYouCaught_fragment4_outer.png)

### Resignal
**Syntax:**  
`protectedBlock on: anExceptionClass do: [:ex | ex resignalAs: anotherException ]`  

**Synopsis:**  
Signals `anotherException` as if it had been signalled at the same place the original exception (`ex`) was signalled.  
This can be used to catch generic exceptions and re-signal them as application-specific exceptions if they meet some criteria.

## A deeper look at the exception mechanism

The following image gives a graphical view of what happens when an exception is signalled, and the different situations that can arise.
![Image](Exceptions_Image_WhatHappensWhenAnExceptionIsSignalled.png)

## Credits
Parts of this page are based on the **Handling Exceptions** chapter of the [Deep Into Pharo book](http://files.pharo.org/books-pdfs/deep-into-pharo/2013-DeepIntoPharo-EN.pdf).  
Pictures by Thomas Dupriez.


================================================
FILE: General/ExportFormats.md
================================================
# Source Code Export formats

Pharo stores its source code in memory (by default) or in a snapshot of the memory when we save a Pharo image. This makes it complicated to manage source code in the long term or to collaborate with others.

In order to be able to save some source code in readable files, Pharo includes some textual export formats. This page will explain the main export formats used to save code in VCS such as git.

This page will present formats from the most recommended for new projects to the less recommended.

- [Comparisons](#comparisons)
  * [Overview](#overview)
  * [Supported Pharo versions](#supported-pharo-versions)
- [Tonel](#tonel)
  * [Tonel Pros and Cons](#tonel-pros-and-cons)
  * [Tonel supported Pharo versions](#tonel-supported-pharo-versions)
  * [Tonel versions](#tonel-versions)
- [FileTree metadata less](#filetree-metadata-less)
  * [FileTree metadata less Pros and Cons](#filetree-metadata-less-pros-and-cons)
  * [FileTree metadata less supported Pharo versions](#filetree-metadata-less-supported-pharo-versions)
- [FileTree metadata full](#filetree-metadata-full)
  * [FileTree metadata full Pros and Cons](#filetree-metadata-full-pros-and-cons)
  * [FileTree metadata full supported Pharo versions](#filetree-metadata-full-supported-pharo-versions)


## Comparisons

### Overview 

|| Tonel | FileTree metadata less | FileTree metadata full |
| ------------- | ------------- |------------- |------------- |
| Work out of the box since Pharo | 6.1 | 4 | 3 |
| Older version supported after update | 4 | 4 | 3 |
| Export granularity | Class | Method | Method |
| Works well on windows | :white_check_mark: | :x: | :x: |
| Easy to merge two branches | :white_check_mark: | :white_check_mark: | :x: |
| Takes a reasonable space on file system | :white_check_mark: | :x: | :x: |
| Works with Iceberg | :white_check_mark: | :white_check_mark: | :x: |
| Works with Monticello | :white_check_mark: | :white_check_mark: | :white_check_mark: |

### Supported Pharo versions

| Pharo Version | FileTree metadata full | FileTree metadata less | Tonel |
| ------------- | ------------- |------------- |------------- |
3 |  :white_check_mark: | :x: | :x: |
4 |  :white_check_mark: |  :white_check_mark: | Update Metacello + Install Tonel |
5 |  :white_check_mark: |  :white_check_mark: | Update Metacello + Install Tonel |
6.0 |  :white_check_mark: |  :white_check_mark: | Update Metacello + Install Tonel |
6.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
7 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
8 | :white_check_mark: | :white_check_mark: | :white_check_mark: |

## Tonel 

Tonel ([https://github.com/pharo-vcs/tonel](https://github.com/pharo-vcs/tonel)) is an export format introduced in Pharo 6.1. 

It creates one file by class or extended class and works well on Windows (compared to file tree).

### Tonel Pros and Cons

Pros
- Works well on Windows 
- Not much space lost because of small files
- Export readable files
- No problem during merge because of metadata

Cons
- Works out of the box since Pharo 6.1.
- Since the format is more recent than the others, some edges cases might cause trouble. (It rarely happens)

### Tonel supported Pharo versions

Tonel works out of the box in Pharo 6.1 and higher. But it is possible to make it work in Pharo 4 to 6.0 by updating Metacello and installing Tonel.

```Smalltalk
Metacello new
	baseline: 'Metacello';
	repository: 'github://Metacello/metacello:pharo-6.1_dev/repository';
	get.
Metacello new
	baseline: 'Metacello';
	repository: 'github://Metacello/metacello:pharo-6.1_dev/repository';
	onConflict: [:ex | ex allow];
	load.
Metacello new 
	repository: 'github://pharo-vcs/tonel';
	baseline: 'Tonel';
	load.
```

### Tonel versions

Tonel got multiple versions over the years, each tweaking the export format:
- version 1.0: original tonel export format
- version 2.0: this version ensure that in the metadatas the keys are symbols and the values are strings. This change happened in order to be compatible with Gemstone. Note that this format was never used as a default export format of Pharo
- version 3.0: this version has the changes of the 2.0 but it also adds the properties `package` and `tag` to replace the `category` property for class definitions. This is to remove same ambiguity in the class definitions. The `category` property is kept by default for backward compatibility, but the TonelWriter can be configured to not export this property. This format can also be improved to export more metadata. For example, it is planned to export a property `deprecatedAliases` to manage some class deprecations in the future.

If you want to change your export format and convert all the files of a repository at once to avoid to have multiple PR with format changes you can use the following script.
Take a Pharo 12 or Pharo 13 images and run the following script. It will convert all the loaded packages in your image so you may load extra packages to prepare such operation. 

```st
| projectName repository |
projectName := 'ProjectNameInIceberg'.
repository := IceRepository repositories detect: [ :repo | repo name = projectName ].
repository workingCopy packages do: [ :pkg |
IceLibgitTonelWriter forInternalStoreFileOut: pkg latestVersion mcVersion on: repository ]
```

**NOTE: you must ensure all your project packages are loaded in the image (check in the Repository | Packages window, and right click load any that aren't).**

Once you have run this script, use the "Repository, Project | Extra | Open in native file browser" menu option to open an OS terminal and then run:
```
git commit -a -m "Update tonel formal to V3"
git push
```

Since Pharo 12, it is also possible to indicate in a Tonel project which version of Tonel to use to export some code. The file to update is the `.properties` file that is in the source folder and it should look like this:

```
{
    #format : #tonel,
    #version: #'1.0' //could be 2.0 or 3.0
}
```

This is useful for example if a project has contributors on P11 using v1 format and contributors in P12 using v3 format since P11 is unable to export Tonel v3 format. 

## FileTree metadata less 

FileTree ([https://github.com/dalehenrich/filetree](https://github.com/dalehenrich/filetree)) is the first export format that was integrated in the goal to use Pharo with Git. The first version had a lot of metadata (see section Filetree metadata full), the second was a new version with metadata less format. 

This format exports one file per method. This can cause trouble with Windows because Windows has a maximum path and file name length of 255 characters. This limit can easily be reached with FileTree. 

Another problem of the FileTree format is that most Pharo's methods are short and creating one file by method waste a lot of space because the physical representation of files on a drive has a minimal size (4 KiB on NTFS file systems) that is reached by most of Pharo's method. 

Its advantage compared to FileTree metadata full is that there is no problem during the merge of the source code thanks to the absence of metadata.

### FileTree metadata less Pros and Cons 

Pros
- Easy to browse the history of a method
- Present since Pharo 4 out of the box
- No problem during merge because of metadata

Cons
- Cause trouble on Windows
- Waste space on the file system

### FileTree metadata less supported Pharo versions

FileTree metadata less is supported out of the box since Pharo 4.0 and cannot easily be used in older Pharo versions. 

## FileTree metadata full

FileTree metadata full ([https://github.com/dalehenrich/filetree](https://github.com/dalehenrich/filetree) )is the ancestor of FileTree metadata less and works in the same way but also export a lot of metadata relating to the commits such has a commit message (different from the one of the VCS), the timestamp of the method compilation, etc.

This simplifies the tooling because the tools can get some information from the metadata instead of the VCS but it also creates a lot of trouble while merging two branches using this format.

Merges can be eased via this project: [https://github.com/ThierryGoubier/GitFileTree-MergeDriver](https://github.com/ThierryGoubier/GitFileTree-MergeDriver)

This format can be used via Monticello but not via Iceberg. Iceberg will ignore the format and export in FileTree metadata less.

### FileTree metadata full Pros and Cons

Pros
- Easy to browse the history of a method
- Present in most Pharo versions out of the box

Cons
- Cause trouble on Windows
- Waste space on the file system
- Hard to merge two branches because of metadata
- Does not work with Iceberg, the default git tool since Pharo 7

### FileTree metadata full supported Pharo versions

This format works out of the box in most Pharo versions.


================================================
FILE: General/Extensions.md
================================================
# Extensions

- [Extensions](#extensions)
  - [Use of Extension methods](#use-of-extension-methods)
  - [Add a new extension method](#add-a-new-extension-method)
    - [Define an extension method in versions prior to Pharo 7](#define-an-extension-method-in-versions-prior-to-pharo-7)
    - [Define an extension method since Pharo 7](#define-an-extension-method-since-pharo-7)
    - [Define an extension method programmatically](#define-an-extension-method-programmatically)
  - [Find methods currently extending a class](#find-methods-currently-extending-a-class)
    - [In versions prior to Pharo 7](#in-versions-prior-to-pharo-7)
    - [Since Pharo 7](#since-pharo-7)
    - [Find extensions programmatically](#find-extensions-programmatically)
  - [Package loading order is important](#package-loading-order-is-important)

Pharo includes a system of extension methods. This feature allows the developer to add behavior (but not state) to existing objects in Pharo. 

> Note that it is only possible to add methods (behavior) as extension and not variables (state)

There is no syntactic difference between calling an extension method and calling a method declared in the class. The main difference between methods and extension methods is that extension methods are stored in a different package than the class they are implemented on.

## Use of Extension methods

Extension methods are useful when we want to use some behavior on an object, but it does not make sense to package it directly with the object. For example we might want to ask to a model object for information related to its display in a GUI, but to keep layers as cohesive as possible, we do not want display information stored in the code package of our application. In this case, we can add those methods to the model object but package those methods in a GUI package.

Another case might be when you want to enhance the behavior of a package that is simply not your own. You could add the methods to the class in the different package, but committing those changes to source control is not practical (i.e., you don't want to make a branch of the package, and doing a pull request would take a long time, etc.). With extension methods, the changes you make to the foreign package are stored in your own package, so they belong to you. 

## Add a new extension method

Internally, an extension method is a method whose protocol has a pattern `*MyPackageExtendingMyClass`. 

Here is more detailed information about adding an extension method via Pharo's tooling.

### Define an extension method in versions prior to Pharo 7

In the Pharo versions based on Nautilus system browser, extension methods are created when we categorize methods on a protocol beginning by a `*`.

![Add an extension method via Nautilus 1](Extensions_Image_NautilusAddExtension1.png?raw=true "Add an extension method via Nautilus 1")

![Add an extension method via Nautilus 2](Extensions_Image_NautilusAddExtension2.png?raw=true "Add an extension method via Nautilus 2")

### Define an extension method since Pharo 7

Since Pharo 7 the default system browser is Calypso. To add an extension method in Calypso you need to use the "Move to package" menu entry.

![Add an extension method via Calypso](Extensions_Image_CalypsoAddExtension.png?raw=true "Add an extension method via Calypso")

If you already have extensions in this package, you can also select the package in the list of extending packages in the protocol pane before adding a method.

### Define an extension method programmatically

```Smalltalk
ExistingClass compile: 'myMethod
	^ true' classified: '*MyPackage'
```

## Find methods currently extending a class

There are two ways to find which methods are extensions where they are located:

- Browse a class and check the protocols pane. (See examples below)

- Look at a package and check the bottom of the class pane. The last classes will appear in grey and will be the classes extended in that package.

### In versions prior to Pharo 7

![See an extension method via Nautilus](Extensions_Image_NautilusSeeExtensions.png?raw=true "See an extension method via Nautilus")

### Since Pharo 7

![See an extension method via Calypso](Extensions_Image_CalypsoSeeExtensions.png?raw=true "See an extension method via Calypso")

### Find extensions programmatically

To find extension methods programmatically you can do something like:

```Smalltalk
(Number methods select: #isExtension) groupedBy: #package
```

> **TODO: Add example of refactoring to an extension?**


## Package loading order is important

One thing developers should take into account when using extensions is to have clean dependencies between its packages. A package extending classes from another package should be loaded *after* this package.

For example, if my package `MyProject-GUI` extends `MyProject-Model`, `MyProject-Model` should always be loaded *before* `MyProject-GUI` is. For more details, see the dependencies sections in the [baseline guide](Baselines.md).


================================================
FILE: General/Files.md
================================================
# Files
TODO: explain how to manipulate files, paths, file systems, etc...


================================================
FILE: General/GithubActions.md
================================================
# Setting up your continuous integration via GitHub Actions

Previously, the Pharo community was heavily relying on Travis CI for the continuous integration of projects hosted on GitHub.
But Travis becoming pay-to-use service, the community created some tooling to manage the CI via GitHub Actions. 

This guide will get you through the process to set up your own integration.

> Note: In order to do anything for the CI of your project, you will need a `Baseline` to manage its dependencies. If it is not the case yet, you can check the [guide on baselines](Baselines.md).

- [Setting up your continuous integration via Github Actions](#setting-up-your-continuous-integration-via-github-actions)
  * [Simple case: Run tests on master branch](#simple-case-run-tests-on-the-master-branch)
  * [SmalltalkCI options](#smalltalkci-options)
    + [Load spec options](#load-spec-options)
    + [Testing options](#testing-options)
    + [Code Coverage](#code-coverage)
    + [Using custom scripts](#using-custom-scripts)
  * [Testing multiple versions of Pharo at once](#testing-multiple-versions-of-pharo-at-once)
  * [Testing on multiple OS](#testing-on-multiple-os)
  * [Manage the workflow target (branchs, PR, ...)](#manage-the-workflow-target-branchs-pr-)
    + [Target branches](#target-branches)
    + [Target pull requests](#target-pull-requests)
    + [Target releases](#target-releases)
    + [Target scheduled workflow](#target-scheduled-workflow)
    + [Other targets](#other-targets)
  * [Managing multiple workflows and SmalltalkCI configurations](#managing-multiple-workflows-and-smalltalkci-configurations)
  * [Continuous releases](#continuous-releases)
  * [Save releases artifacts](#save-releases-artifacts)
  * [Depending on resources of your repository with GitBridge](#depending-on-the-resources-of-your-repository-with-gitbridge)
  * [Add your build artifacts to PharoLauncher](#add-your-build-artifacts-to-pharolauncher)
  * [External ressources](#external-ressources)

## Simple case: Run tests on the master branch

Let's start simple! This section will explain how to set up a workflow to launch the tests of the project on every commit done on the master branch.

To load our Pharo project in the CI and execute the tests, we'll use [SmalltalkCI](https://github.com/hpi-swa/smalltalkCI).
This project needs a configuration file to fetch information on your project. This file should be at the root of your project under the name of `.smalltalk.ston`. 

Here is the most simple configuration:

```ston
SmalltalkCISpec {
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'MyProject',
      #directory : 'src'
    }
  ]
}
```

This configuration tells smalltalkCI two things:
- The baseline to use to load the project is BaselineOf`MyProject`
- The sources of the project are in /src

Now that smalltalkCI configuration file is created, we just need to define your GitHub workflow file.
This file should be located in `.github/workflows/` folder. Let's call ours `testing.yml`.

```yml
name: CI

on:
  push:
    branches:
      - 'master'

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v3
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-image: Pharo64-10
      - run: smalltalkci -s ${{ matrix.smalltalk }}
        shell: bash
        timeout-minutes: 15
```

Let's see a little about what is happening here. 

The #name parameter allows one to give a name to the workflow. This is useful because you might have more than one workflow for your project. 
For example:

![Example of different workflows](GitHubActions_workflows.png)

In this image, we can see a CI that has 3 different workflows:
- CI
- continuous
- Release

Then we have:  

```yml
on:
  push:
    branches:
      - 'master'
```

This is used to define when the workflow should enter into action. In our case, we want it when we `push` on `master` branch.

Then we have:

```yml
    runs-on: ubuntu-latest
```

With this, the workflow will run in the latest version of Ubuntu.


```yml
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

This step adds en environment variable needed by smalltalkCI.

Last but not least, we have the actions to execute:

```yml
    steps:
      - uses: actions/checkout@v3
```

Using the "checkout" action to checkout the project on the CI worker.  

```yml
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-image: Pharo64-10
```

Using the "setup-SmalltalkCI" action to prepare the setup.

```yml
      - run: smalltalkci -s ${{ matrix.smalltalk }}
        shell: bash
        timeout-minutes: 15
```

Loads the project and executes the tests of the project with a 15min timeout.  

This timeout can be increased in case your project tests are longer.  

Once you commit these two files, your project will have a working CI !  
Each time you commit to master, a new build should happen.  
You will be able to see the resulting build in the `Actions` tab in your project.

## SmalltalkCI options

We have seen in the previous section that [SmalltalkCI](https://github.com/hpi-swa/smalltalkCI) relies on a configuration file. 
We did a simple one to start, but there are more options available. We will cover them in this section.  
The full and up-to-date list is available in the [SmalltalkCI's README file](https://github.com/hpi-swa/smalltalkCI/blob/master/README.md).

### Load spec options

In the previous example, we declared a loading spec with a baseline and a code directory. But it is also possible to add more options:

```ston
SCIMetacelloLoadSpec {
  #baseline : 'MyProject',                            // Define MC Baseline
  #directory : 'src',                                 // Path to packages, if packages are on root do not use #directory : '', just don't add this option
  #failOn : [ #OCUndeclaredVariableWarning ],         // Fail build on provided list of Warnings
  #ignoreImage : true,                                // If true, Metacello will force a load of a package, overriding a previously existing one
  #load : [ 'default' ],                              // Define some specific groups to load
  #onConflict : #useIncoming,                         // When there is a conflict between loaded sources and incoming sources (can be #useIncoming|#useLoaded)
  #onUpgrade : #useIncoming,                          // When loaded sources are an older version than incoming sources (can be #useIncoming|#useLoaded)
  #onWarningLog : true,                               // Log Warning messages to Transcript
  #platforms : [ #squeak, #pharo, #gemstone ],        // Define compatible platforms
  #usernameEnvVar : 'GITHUB_USER',                    // Environment variable containing the username used for authentication
  #passwordEnvVar : 'GITHUB_TOKEN',                   // Environment variable containing the password used for authentication
  #registerInIceberg : true                           // Pharo Only | Register the tested repository in Iceberg (false by default)
}
```
### Testing options
It is also possible to customize the testing of the project:

```ston
SmalltalkCISpec {
  ...
  #testing : {
    // Include specific TestCases
    #include : {
      #classes : [ #AnotherProjectTestCase ],
      #categories : [ 'AnotherProject-Tests' ],
      #packages : [ 'AnotherProject.*' ],
      #projects : [ 'BaselineOfMyProject' ]
    },

    // Exclude specific TestCases from testing
    #exclude : {
      #classes : [ #AnotherProjectTestCase ],
      #categories : [ 'AnotherProject-Tests' ],
      #packages : [ 'AnotherProject.*' ],
      #projects : [ 'ConfigurationOfMyOtherProject' ]
    },

    #allTestCases : true, // Run all TestCases in image

    // Define TestCases explicitly
    #classes : [ #MyProjectTestCase ],
    #categories : [ 'MyProject-*' ],
    #packages : [ 'MyProject.*' ],
    #projects : [ 'BaselineOfMyProject' ],

    // Other options
    #defaultTimeout : 30, // In seconds (Squeak, and Pharo 6 or later)
    #failOnSCIDeprecationWarnings : false, // Fail if a deprecated smalltalkCI API is used
    #failOnZeroTests : false, // Pass builds that did not run any tests
    #hidePassingTests : true, // Hide passing tests when printing to stdout
    #serializeError: false // (default: true) Disable serialization of failing test case (e.g. with Fuel in Pharo)
  }
}
```

### Code Coverage

It is possible to see the coverage of our project via SmalltalkCI with [Coveralls](https://coveralls.io/).

To enable this, you need to add a "coverage" section in your configuration:

```ston
SmalltalkCISpec {
  ...
  #testing : {
    ...
    #coverage : {
      #packages : [ 'SomePackage', 'SomePack*' ],
      #classes : [ #ClassToCover ],
      #categories : [ 'SomeClassCategory', 'SomeClassCat*' ],
      #format : #coveralls
    }
  }
}
```

For example our project could look like:

```ston
SmalltalkCISpec {
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'Myproject',
      #directory : 'src'
    }
  ],
  #testing : {
    #coverage : {
      #packages : [ 'MyProject-*' ]
    }
  }
}
```

This configuration will execute all the tests loaded by the `BaselineOfMyProject` and build the coverage of all packages starting by `MyProject-` for [Coveralls](https://coveralls.io/).
If you enabled your repository in coveralls ([https://coveralls.io/repos/new](https://coveralls.io/repos/new)), the results would be uploaded automatically.

![Coveralls screenshot](GithubActions_coveralls.png)

For more information, check: [SmalltalkCI guide on coverage](https://github.com/hpi-swa/smalltalkCI/blob/master/docs/COVERAGE.md).

### Using custom scripts

SmalltalkCI offers some hooks to be able to run some Pharo scripts at different moments of the project loading and testing.
Four hooks are available:
- `preLoading` : Executed before loading the project
- `postLoading` : Executed after loading the project
- `preTesting` : Executed before testing the project
- `postTesting` : Executed after testing the project

Those parameters can take 3 different parameters. 

The first one is a single script:

```ston
SmalltalkCISpec {
  #preLoading : 'scripts/preLoading.st',
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'Myproject',
      #directory : 'src'
    }
  ]
}
```

The second one is a collection of scripts:

```ston
SmalltalkCISpec {
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'Myproject',
      #directory : 'src'
    }
  ],
  #postLoading : [
    'scripts/postLoading1.st',
    'scripts/postLoading2.st'
  ]
}
```

And the third one is an instance of SCICustomScript that allows running script only on certain platforms:

```ston
SmalltalkCISpec {
  #preLoading : 'scripts/preLoading.st',
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'Myproject',
      #directory : 'src'
    }
  ],
  #postLoading : [
    SCICustomScript {
      #path : 'scripts/postLoadingSqueak.st',
      #platforms : [ #squeak ]
    },
    SCICustomScript {
      #path : 'scripts/postLoadingPharo.st',
      #platforms : [ #pharo ]
    }
  ]
}
```

Here is a full example:

```ston
SmalltalkCISpec {
  #preLoading : 'scripts/preLoading.st',
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'Myproject',
      #directory : 'src'
    }
  ],
  #postLoading : [
    'scripts/postLoading1.st',
    'scripts/postLoading2.st'
  ],
  #preTesting : SCICustomScript {
    #path : 'scripts/preTesting.st',
    #platforms : [ #squeak, #pharo, #gemstone ]
  },
  #testing : ...,
  #postTesting : [
    SCICustomScript {
      #path : 'scripts/postTestingSqueak.st',
      #platforms : [ #squeak ]
    },
    SCICustomScript {
      #path : 'scripts/postTestingPharo.st',
      #platforms : [ #pharo ]
    }
  ]
}
```

For more informations on SmalltalkCI in general check: [SmalltalkCI documentation](https://github.com/hpi-swa/smalltalkCI).

## Testing multiple versions of Pharo at once

It is rare to have a project working only on one version of Pharo. Thus, it is often useful to have our workflows run on multiple versions. 

This can be achieved this way:

```yml
name: CI

on:
  push:
    branches:
      - 'master'

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    strategy:
      matrix:
        smalltalk: [ Pharo64-9.0, Pharo64-10, Pharo64-11 ]
    name: ${{ matrix.smalltalk }}
    steps:
      - uses: actions/checkout@v3
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-image: ${{ matrix.smalltalk }}
      - run: smalltalkci -s ${{ matrix.smalltalk }}
        shell: bash
        timeout-minutes: 15
```

Here we declared a matrix with multiple versions of Pharo as axes:

```yml
    strategy:
      matrix:
        smalltalk: [ Pharo64-9.0, Pharo64-10, Pharo64-11 ]
```

Each axe will use the name of the Pharo version as name:

```yml
    name: ${{ matrix.smalltalk }}
```

But this could also be another name, such as:

```yml
    name: MyProject-${{ matrix.smalltalk }}
```

Then the builds would be: `MyProject-Pharo64-9.0`, `MyProject-Pharo64-10` and `MyProject-Pharo64-11`.

The names will then be used to display the different builds on Github:

![Screenshot of matrix](GithubActions_matrix.png)

The list of possible Pharo versions are:

| 64bits           | 32bits           |
| ---------------- | ---------------- |
| `Pharo64-alpha`  | `Pharo32-alpha`  |
| `Pharo64-stable` | `Pharo32-stable` |
| `Pharo64-11`     | `Pharo32-11`     |
| `Pharo64-10`     | `Pharo32-10`     |
| `Pharo64-9.0`    | `Pharo32-9.0`    |
| `Pharo64-8.0`    | `Pharo32-8.0`    |
| `Pharo64-7.0`    | `Pharo32-7.0`    |
| `Pharo64-6.1`    | `Pharo32-6.1`    |
| `Pharo64-6.0`    | `Pharo32-6.0`    |
|                  | `Pharo32-5.0`    |
|                  | `Pharo32-4.0`    |
|                  | `Pharo32-3.0`    |

> Note: This list is from February 2023. More versions will be added in the future

## Testing on multiple OS

Usually, our Pharo projects are not influenced by the OS on which it runs. But in some cases, it can be important to test on multiple OS.

This can be achieved this way: 

```yml
name: CI

on:
  push:
    branches:
      - 'master'

jobs:
  build:
    strategy:
      matrix:
        os: [ macos-latest, windows-latest, ubuntu-latest]
        smalltalk: [ Pharo64-9.0, Pharo64-10]
    runs-on: ${{ matrix.os }}
    name: ${{ matrix.smalltalk }} on ${{ matrix.os }}
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v3
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-image: ${{ matrix.smalltalk }}
      - run: smalltalkci -s ${{ matrix.smalltalk }}
        shell: bash
        timeout-minutes: 15
```

As we can see here:

```yml
        os: [ macos-latest, windows-latest, ubuntu-latest]
    runs-on: ${{ matrix.os }}
```

We declare that our project will be run on the latest macos, windows and ubuntu to covers the 3 major OS. 

To distinguish the builds, we use the Pharo version and the OS name to name our builds:

```yml
    name: ${{ matrix.smalltalk }} on ${{ matrix.os }}
```

![Screenshot of ci matrix](GithubActions_os.png)

You can find more information on the available OS here: [https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners)

## Manage the workflow target (branchs, PR, ...)

In our simple example at the beginning, we were launching the CI on the master branch, but you will often need to execute the CI on multiple branches.

### Target branches

It is possible to target multiple branches at once. For example:

```yml
on:
  push:
    branches:
      - 'master'
      - 'development'
      - 'feature/**
```

This will launch your workflow for every commit on `master`, `development` or any branch starting with `feature/`. 

You can also target all branches in two ways. The first is by not specifying any:  

```yml
on: [ push ]
```

The second is to use `'**'`:

```yml
on:
  push:
    branches:
      - '**'
```

This second way of declaring "all branches" is useful when you want to execute your workflow on all branches except some of them.
In that case, you can use:

```yml
on:
  push:
    branches:
      - '**'
      - '!doc/**'
```

This template will launch the CI for every commit on any branch except the ones starting with `doc/`.

### Target pull requests

It is also possible to target others kinds of events.
Particularly pull requests made to your project:

```yml
on: [ push, pull_request ]
```

And be even more precise on the kinds of PR that should execute a workflow:  
```yml
on:
  pull_request:
    types: [assigned, opened, synchronize, reopened]
```


Note that this can be done by addition of other targets:

```yml
on:
  push:
    branches:
      - '**'
      - '!master'
  pull_request:
    types: [assigned, opened, synchronize, reopened]
```

Here the workflow runs on every pull request and every commit of any branch except `master`.

### Target releases

It is also sometimes useful to have a workflow targeting releases. We'll exploit that later in this documentation.
In that case you can use:

```yml
on:
  release:
    types: [created, edited]
```

### Target scheduled workflow

In some cases, it might be useful to target the workflow at specific times. 
For example, it happens that some projects are "meta project". Their goal is to load a bunch of other projects. In that case, it's rare that a commit is made direcly in them.
But we want to run the CI on a regular basis to be sure our project still works. In that case, we can use a cron to schedule the workflow:

```yml
on:
  push:
    branches:
      - 'master'
  schedule:
    - cron:  '0 0 * * *'
```

Some utils will help you to configure the parameter of this target such as [Crontab.guru](https://crontab.guru/).

### Other targets

GitHub actions have way more options than the options presented here. The most useful ones were presented here, but you can find more information in [Github documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on)

## Managing multiple workflows and SmalltalkCI configurations

Until now, we managed only one workflow file, but it is possible to manage multiple of them.

To demonstrate this, let's imagine that our project has two groups in its configuration.
The first group loads the core of the project and is the default group of our baseline. 
A second group loads the full projects with additional features. 

We would now like to have two workflows:
- A first workflow launched on all branches and PR to test the core in Pharo 9, 10 and 11
- A second workflow launched on master branch and PR to test the full project in Pharo 11

The first step is to get two smalltalkCI configurations.

A first one will be the default `.smalltalk.ston`.

```ston
SmalltalkCISpec {
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'MyProject',
      #directory : 'src'
    }
  ]
}
```

And a second one loads the group `all` and is named `.smalltalkFull.ston`.

```ston
SmalltalkCISpec {
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'MyProject',
      #directory : 'src',
      #load : [ 'all' ]
    }
  ]
}
```

Now that we have our two configurations, we can create our two workflow files. 

The first one is close to what we have seen until here in this documentation:

```yml
name: CI Core

on: [ push, pull_request ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        smalltalk: [ Pharo64-9.0, Pharo64-10, Pharo64-11 ]
    name: ${{ matrix.smalltalk }}
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v3
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-image: ${{ matrix.smalltalk }}
      - run: smalltalkci -s ${{ matrix.smalltalk }}
        shell: bash
        timeout-minutes: 15
```

In the second, we change the targets, and we give one more parameter to the smalltalkCI launch command to specify the path to our specific Smalltalk configuration.

```yml
name: CI Full

on:
  push:
    branches:
      - 'master'
  pull_request:
    types: [assigned, opened, synchronize, reopened]

jobs:
  build:
    runs-on: ubuntu-latest
    name: ${{ matrix.smalltalk }}
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v3
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-image: Pharo64-11
      - run: smalltalkci -s ${{ matrix.smalltalk }} .smalltalkFull.ston
        shell: bash
        timeout-minutes: 15
```

Each file uses a different configuration file.
The first workflow file is named `CI` uses the default file `smalltalk.ston` implicitly.
The second workflow file is named `CI full` uses `smalltalkFull.ston` explicitly.


```yml
      - run: smalltalkci -s ${{ matrix.smalltalk }} .smalltalkFull.ston
        shell: bash
        timeout-minutes: 15
```

> Note: If we wanted to run on the same targets with two smalltalkCI configurations, we could also have used another matrix axis and avoid needing of different workflows.

Example:

```yml
name: CI

on: [ push, pull_request ]

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    strategy:
      matrix:
        smalltalk: [ Pharo64-9.0, Pharo64-10, Pharo64-11 ]
        config: [ .smalltalk.ston, .smalltalkFull.ston ]
    name: ${{ matrix.smalltalk }} - ${{ matrix.config }}
    steps:
      - uses: actions/checkout@v3
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-image: ${{ matrix.smalltalk }}
      - run: smalltalkci -s ${{ matrix.smalltalk }} ${{ matrix.config }}
        shell: bash
        timeout-minutes: 15
```

Having multiple workflows can have other usages that we explore in the next sections.

## Continuous releases

Until now, we have used Github actions to test our project.  
But Github Actions has more features.  
For instance, we are able to realease our projects.  

In this section, we see how to save the result of the builds of our master branch in a github release.

To do that, we can first remove the master branch from the targets of our test workflow because we will handle the master branch in another workflow.

```yml
on:
  push:
    branches:
      - '**'
      - '!master'
  pull_request:
    types: [assigned, opened, synchronize, reopened]
```

Then we will create another workflow called `.github/workflows/continuous.yml`.

```yml
name: continuous

on:
  push:
    branches:
      - 'master'

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      PROJECT_NAME: MyProject-${{ matrix.smalltalk }}
    strategy:
      matrix:
        smalltalk: [ Pharo64-10, Pharo64-11 ]
    name: ${{ matrix.smalltalk }}
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v3
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-version: ${{ matrix.smalltalk }}
      - run: smalltalkci -s ${{ matrix.smalltalk }}
        shell: bash
        timeout-minutes: 15
        
      # Here we zip the result of the build to be able to keep the artefacts
      - name: package
        run: |
          mv /home/runner/.smalltalkCI/_builds/* .
          mv TravisCI.image $PROJECT_NAME.image
          mv TravisCI.changes $PROJECT_NAME.changes
          echo ${${{ matrix.smalltalk }}} | sed -e 's/.*\-//g ; s/\..*//g ; s/$/0/' > pharo.version
          zip -r $PROJECT_NAME.zip $PROJECT_NAME.image $PROJECT_NAME.changes *.sources pharo.version
          ls
        
      #Save the artefact of the build under "continuous" tag
      - name: Update release
        uses: johnwbyrd/update-release@v1.0.0
        with:
          release: 'continuous'
          token: ${{ secrets.GITHUB_TOKEN }}
          files: ${{ env.PROJECT_NAME }}.zip
```

This workflow starts to like what we have seen until now. It checkout our project, install smalltalkCI and runs it. 
But it also adds three steps to the process. 

The first step is to give a name to our project. We will use that name to name our build artifact:

```yml
    env:
      PROJECT_NAME: MyProject-${{ matrix.smalltalk }}
```

In the second step, we rename the image produced by SmalltalkCI. We generate a version file that is useful in tools such as the `PharoLauncher`. And we zip the files in the archive to save.

```yml
      # Here we zip the result of the build to be able to keep the artefacts
      - name: package
        run: |
          mv /home/runner/.smalltalkCI/_builds/* .
          mv TravisCI.image $PROJECT_NAME.image
          mv TravisCI.changes $PROJECT_NAME.changes
          echo ${${{ matrix.smalltalk }}} | sed -e 's/.*\-//g ; s/\..*//g ; s/$/0/' > pharo.version
          zip -r $PROJECT_NAME.zip $PROJECT_NAME.image $PROJECT_NAME.changes *.sources pharo.version
          ls
```

The last step is to publish the artifact in the continuous tag. For that we are using the action `johnwbyrd/update-release@v1.0.0`.

```yml
      #Save the artefact of the build under "continuous" tag
      - name: Update release
        uses: johnwbyrd/update-release@v1.0.0
        with:
          release: 'continuous'
          token: ${{ secrets.GITHUB_TOKEN }}
          files: ${{ env.PROJECT_NAME }}.zip
```

> Note: The name of the continuous release can be changed

Once this is done, each commit on master will result in updating the assets of the `continuous` release on GitHub to save the latest one.

![Screenshot of continuous release](GithubActions_continuous.png)

## Save releases artifacts

We have seen how to save the last artifact of a branch in a `continuous` release, but another case needs to be taken into account: the real releases.

It is useful when we release a project to save a Pharo image of this project with the version of the release.

This can be done with a new workflow file that will target releases:

```yml
name: Release

on:
  release:
    types: [created, edited]

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      PROJECT_NAME: MyProject-${{ matrix.smalltalk }}
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    strategy:
      matrix:
        smalltalk: [ Pharo64-10, Pharo64-11 ]
    name: ${{ matrix.smalltalk }}
    steps:
      - uses: actions/checkout@v3
      - uses: hpi-swa/setup-smalltalkCI@v1
        with:
          smalltalk-version: ${{ matrix.smalltalk }}
      - run: smalltalkci -s ${{ matrix.smalltalk }}
        shell: bash
        timeout-minutes: 15
        
      # Here we zip the result of the build to be able to keep the artefacts
      - name: package
        run: |
          mv /home/runner/.smalltalkCI/_builds/* .
          mv TravisCI.image $PROJECT_NAME.image
          mv TravisCI.changes $PROJECT_NAME.changes
          echo ${${{ matrix.smalltalk }}} | sed -e 's/.*\-//g ; s/\..*//g ; s/$/0/' > pharo.version
          zip -r $PROJECT_NAME.zip $PROJECT_NAME.image $PROJECT_NAME.changes *.sources pharo.version
          ls
        
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          files: ${{ env.PROJECT_NAME }}.zip
```

This file looks a lot like the one we wrote in the previous section.

A few changes are to be noted. The is the name of the workflow to identify it easily in the Actions tab of Github.
The second is the target to build only on releases.

```yml
on:
  release:
    types: [created, edited]
```

And the last change is the action used after creating our Pharo archive.

```yml
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          files: ${{ env.PROJECT_NAME }}.zip
```

This action will add the files matching the $files: property to the assets of the release.

![Screenshot of releases](GithubActions_releases.png)

## Depending on the resources of your repository with GitBridge

It happens in some projects that we need resources to do some tests. In the past, it was common to save those resources as a string or a byte array directly in a method of the project.
This makes can have multiple drawbacks like making the management of the project harder, dropping Pharo's performances in code management, no real versioning of those resources…

Now that we can store our projects on git, an alternative is possible: Save your resources in your git repository and use file references in Pharo to access them.

To help with that, the project [GitBridge](https://github.com/jecisc/GitBridge) was created. 
This project helps one to access resources from the git repository and information from git directly from the Pharo image.

This project can be added as a dependency of your project with this spec:

```Smalltalk
    spec
    	baseline: 'GitBridge'
    	with: [ spec repository: 'github://jecisc/GitBridge:v1.x.x/src' ]
```

In order to create a GitBridge to your project, you first need to subclass `GitBridge` and to store your bridge in a package of your project.

```Smalltalk
GitBridge subclass: #MyProjectBridge
	slots: {  }
	classVariables: {  }
	package: 'MyProject'
```

This new bridge needs a class initialization like this one:

```Smalltalk
MyProjectBridge class>>initialize
	SessionManager default registerSystemClassNamed: self name
```

This will allow the bridge to reset some cache at the image startup.

Now that your bridge is created, if it finds an Iceberg repository associated with its local clone containing the package in which the bridge is defined, you will be able to use the bridge to access some resources.

For example, you can get a file reference to the git folder like this:

```Smalltalk
MyProjectBridge root
```

And this allows you to access your test resources.

Once your project is using `GitBridge`, you just need to be sure of two things in order for the CI to work. 
The first is to have the option `#registerInIceberg` to true in your smalltalkCI configuration.

```ston
SmalltalkCISpec {
  #loading : [
    SCIMetacelloLoadSpec {
      #baseline : 'MyProject',
      #directory : 'src',
      #registerInIceberg : true
    }
  ]
}
```

And the second is to add a parameter to the checkout action of your workflow file in order to fetch the full history of git:

```yml
  steps:
    - uses: actions/checkout@v3
      with:
        fetch-depth: '0'
```

Once those steps are set up, your tests should be able to run and fetch resources from your git repository without trouble.
For more information, you can look at the [documentation of GitBridge](https://github.com/jecisc/GitBridge).

## Add your build artifacts to PharoLauncher

[Pharo launcher](https://pharo-project.github.io/pharo-launcher//) is a great tool to manage Pharo images, and here we are going to explain how to be able to get images of your project from it. 

> Note: In order to do this, you will need to have a continuous release and/or a release workflow setup as we explained earlier in this documentation.

Pharo launcher comes with a default set of sources to fetch Pharo images. It also allows one to add its own sources, and we will show here how to add your project as one of your own source.

It is doable thanks to the `mysources.list` of pharo-launcher file located in the `PhLUserTemplateSources sourcesFile` folder. If present, this file defines additional template sources beyond the official list of templates. At this time, there is no UI to add them.

To find the right folder:

* Open the Pharo Launcher
* Open a Playground (Ctrl + O, Ctrl + W)
* Execute `PhLUserTemplateSources sourcesFile`

You can now edit `mysources.list` in this folder to add the images of your project you wish to have in your Pharo launcher.

Here is how to add images from your continuous release:

```st
[
	PhLTemplateSource {
		#type : #URLGroup,
		#name : 'MyProject',
		#templates : [
			PhLTemplateSource {
				#type : #URL,
				#name : 'MyProject Pharo 10 - master',
				#url : 'https://github.com/MY_USERNAME/MY_PROJET_NAME/releases/download/continuous/MyProject-Pharo64-10.zip'
			},
			PhLTemplateSource {
				#type : #URL,
				#name : 'MyProject 11 - master',
				#url : 'https://github.com/MY_USERNAME/MY_PROJET_NAME/releases/download/continuous/MyProject-Pharo64-11.zip'
			}
		]
	}
]
```

And here is how to add images from a specific release, lets say `v1.4.3`:

```st
[
	PhLTemplateSource {
		#type : #URLGroup,
		#name : 'MyProject',
		#templates : [
			PhLTemplateSource {
				#type : #URL,
				#name : 'MyProject Pharo 10 - v1.4.3',
				#url : 'https://github.com/MY_USERNAME/MY_PROJET_NAME/releases/download/v1.4.3/MyProject-Pharo64-10.zip'
			},
			PhLTemplateSource {
				#type : #URL,
				#name : 'MyProject Pharo 11 - v1.4.3',
				#url : 'https://github.com/MY_USERNAME/MY_PROJET_NAME/releases/download/v1.4.3/MyProject-Pharo64-11.zip'
			}
		]
	}
]
```

You can then adapt those sources to what you need. Once it is done, you can click on the `New` button of the launcher and see a new source named `MyProject`.

## External ressources

Here are some resources on GitHub actions and Pharo:
- [https://badetitou.fr/blog/2020-11-30-Testing_pharo_with_github_actions](https://badetitou.fr/blog/2020-11-30-Testing_pharo_with_github_actions/)
- [https://badetitou.fr/blog/2022-10-28-test-your-moose-code-using-ci](https://badetitou.fr/blog/2022-10-28-test-your-moose-code-using-ci)
- [https://modularmoose.org/posts/2021-07-19-automatic-metamodel-documentation-generation](https://modularmoose.org/posts/2021-07-19-automatic-metamodel-documentation-generation)

Do not hesitate to do a PR to add more resources ;)


================================================
FILE: General/Glossary.md
================================================
# Pharo vocabulary
The Pharo community uses specific vocabulary to designate object oriented concepts, Pharo concepts and Pharo tools.

This page aims to provide disambiguation for the words belonging to this vocabulary.

## $a 
The character a. In Pharo strings are composed of characters, a character starts with a $. For unprintable characters such as tab, just send the message to the class e.g., `Character tab`.

## Binary message
A binary message is a [message](#message) composed of special character(s) where two objects are involved (the [receiver](#receiver) and one argument), which is the reason it is call binary. This is mostly used for arithmetic, comparison, and logical operations. For example, `+` is a binary message involving the receiver and the argument in parameter.

## Bootstrap
According to [wikipedia](https://en.wikipedia.org/wiki/Bootstrapping),

> "Bootstrapping usually refers to a self-starting process that is supposed to proceed without external input."

In the case of Pharo, [images](#image) are bootstrapped from the sources. Anyone can download the sources and [create their own custom Pharo image](https://github.com/carolahp/pharo/tree/candle). The Pharo [continuous integration server](https://ci.inria.fr/pharo-ci-jenkins2/job/Test%20pending%20pull%20request%20and%20branch%20Pipeline/) launch the bootstrap process each time a pull-request is merged into [pharo repository](https://github.com/pharo-project/pharo).
This seems to be a natural process but one has to know that up to Pharo 7.0, images were not bootstrapped. This means that, each version of Pharo was in fact a copy of the previous image with some additional changes.

## Browser
The browser is the tool for browsing and editing packages, classes and methods. In Pharo 6.1 and greater, the browser is called Calypso.

## Candidates
In the context of a method-call the candidates are the potential classes in the system that can receive the call. This list is computed from a static analysis of the source code.

## Changes (file)
The changesfile logs all source code modifications (especially all the changes you did while programming) since the [sources file](#sources) was generated. This facilitates a per-method history for diffs or reverting. It means that even if you did not manage to save the image file on a crash or you just forgot to, you can recover your changes from this file. A changes file is always coupled with an image file. They work as a pair.

> Note: Since Pharo 5, a project called Epicea implementing a new logging system has been introduced in the system. The long term goal of Epicea is to replace the changes file, but this objective has not been reached yet.

## Class-side
The class-side of a class refers to its meta-class. This meta-class contains methods that can be sent to the class directly.
For example, `#x:y:` method (which creates an instance of `Point` with arbitrary x and y coordinates) is held by the meta-class of `Point`.

In Pharo, both `Class` and `Metaclass` understand `#classSide` method.
For example:

```Smalltalk
Point classSide. "Point class"
Point class classSide. "Point class"
Point includesSelector: #x:y:. "false"
Point class includesSelector: #x:y:. "true"
```

The best way to understand what the class-side is, is to have a look at `#classSide` methods implementations:

```Smalltalk
Class>>#classSide
	^ self class
```

```Smalltalk
Metaclass>>#classSide
  ^ self
```

## Cog
Cog is the name of the [virtual machine](#virtual-machine) used by Pharo.
It is also used by other programming languages such as [Squeak](#squeak), Newspeak and Cuis.

## Context
A *Context* represent a program execution. It will store, for example, the `CompiledMethod` being currently executed, the receiver and arguments of the message that invoked this `CompiledMethod`, the temporary variables, the stack of calls until the moment of the execution, ...
In Pharo, you can use the keyword `thisContext` to interact with the current context of your code. It will return the `Context` object at the moment of the execution. This object is different on each method call.

## Debugger
The *Debugger* is a tool opened by the system when an exception is raised and never got caught. This tool allows the developer to interact with the execution [context](#context) that raised the error and its previous contexts. It lets the users inspect the objects present in this context and updates the code to fix the bug using the execution information as help.

## Dispatch
Dispatch is a technique used in object-oriented programming to delegate behavior using [polymorphism](#polymorphism). The goal is to define a concept that will change depending on the context. For example we can have an application with commands. When we need to execute the commands, instead of creating a switch/case, each object will implement its own behaviour on a method of the same name and we just need to call this method. 

## DNU
See [DoesNotUnderstand](#doesnotunderstand).

## DoesNotUnderstand
This name is used to describe the error that arises when a [message](#message) is sent to an object but the object does not understand it. It also happens that people use the "DNU" shortcut.

## Iceberg
*Iceberg* is git client integrated in the system since Pharo 7 (Pharo 6.1 contained a technical preview of the tool). It is a set of tools that allows one to handle git repositories directly from a Pharo image. Iceberg is the default repository manager for Pharo, allowing for smoother and faster integration of contributions, as well as better branch and version management.

## Image
A Pharo image is a snapshot of Pharo memory at any given moment.
This is the file where all objects are stored and as such, it’s a cross platform format.
An image file contains the live state of all objects of the system (including classes and compiled methods, since they are objects too) at a given point.
It can bee seen as a virtual object container.

## Implementors
For a given selector in the system, implementors are classes that have a method with this selector (they implement the selector). For example the implementors of the method `#banana` are all the classes containing a method named `#banana`.

## Inspector
The *Inspector* is a Pharo tool which allows one to inspect objects, see their current state, interact with them and display specific information depending on the object. It offers multiple views and it uses a Finder as a navigation. One particular feature is that you can use the evaluator tab to enter code, and evaluating it results in the opening of another pane to the right.

## Instance
An instance is a concrete realisation of a class.
One can send [messages](#message) to an instance.
These messages correspond to methods defined by the class related to the instance.
All instances of a class share the behaviour (methods) and structure ([slots](#slot)) defined by the class but two instances can hold different data in their [slots](#slot).

## Instance-side
The instance-side of a meta-class refers to its class. This class contains methods that can be sent to its instances.
For example, `#x` method (which returns the x coordinate of a point) is held by the class `Point`.

In Pharo, both `Class` and `Metaclass` understand `#instanceSide` method.
For example:

```Smalltalk
Point instanceSide. "Point"
Point class instanceSide. "Point"
Point includesSelector: #x. "true"
Point class includesSelector: #x. "false"
```

The best way to understand what the instance-side is, is to have a look at `#instanceSide` methods implementations:

```Smalltalk
Class>>#instanceSide
	^ self
```

```Smalltalk
Metaclass>>#instanceSide
  ^ self soleInstance
```

## Instance variable
See [slot](#slot).

## Keyword message
A keyword message is a [message](#message) where two or more objects are involved (the [receiver](#receiver) and the arguments). A message is composed of alphanumeric characters. The arguments are injected inside the message selector and must be preceded by a colon (`:`). For example, `between:and:` is a keyword message with a receiver and two arguments. It can be used like this: `13 between: 12 and: 14`.

## Late binding
*Late binding* (or *dynamic binding*) is a general mechanism in which methods or functions called are [looked up](#lookup) at run-time. This mechanism is the opposite of *early binding* that does the lookup at compilation-time and fixes all types of variables during that time.
More concretely, it means that in Pharo, when you send a [message](#message) to an object, the lookup of the method to execute is performed and then the method found by the lookup is executed. This simplifies the use of reflectivity since the user can invoke new methods without recompiling the whole application.

## Lookup
Method lookup is the name of the technique Pharo uses to find the method to execute when an object receives a [message](#message). It proceeds as follows: When a message is sent, methods in the [receiver](#receiver)'s class are searched for a matching method. If no match is found, the superclass is searched, and so on up the class chain. In the end, if no method is found, the object calls the method [`#doesNotUnderstand:`](#doesnotunderstand) with the message as a parameter.

## Message
A message represents an interaction between two objects.
A [sender](#sender) sends a message to a [receiver](#receiver) which will start a [lookup](#lookup).
A message is composed of two elements: the selector, which is the name of the method to lookup, and argument values which are the values of each argument of the method to execute once found by the lookup.
Three kinds of messages exists: [unary messages](#unary-message), [binary messages](#binary-message) and [keyword messages](#keyword-message).

## Message-send

## Monticello
*Monticello* is a distributed versioning system for [Squeak](#squeak) and Pharo code. It was the main versioning system until Pharo 6. It is now recommended to use [Iceberg](#iceberg).

## Object
The word object is used to refer to a particular [instance](#instance) of a [class](#class). "Object" and "instance" words are synonyms.

## Playground
The playground / workspace designate a code editor allowing one to run Smalltalk code that is not contained in a method.
This tool is useful to run small scripts that can be thrown after the execution.
If one needs to write a script that needs to be kept for a long time, it is better to right it as a class-method with the `<script>` pragma.

## Polymorphism

## Pragma
Pragmas are annotations on methods. They are used to attach additional properties to the methods to make those methods easily collectable through reflectivity and to ease the creation of special handlings.
A page dedicated to pragmas is available [here](Pragmas.md).

## Primitive
A primitive is a method for which the source code is not written in Smalltalk but directly in C code. From the inside of the image, those methods contain a `<primitive:>` pragma.

Some methods holding this primitive pragma also contain source code written in Smalltalk. For these methods, first the C version of the method is tried but if the implementation in C is not provided by the VM for some reason, Pharo falls back to the Smalltalk implementation.

## Protocol
In Pharo, each method belongs to a protocol. A protocol has a name and allows one to group methods that are related. For example, the protocol `accessing` is widely used in the system to hold accessor and mutator methods.

## Receiver
The receiver of a [message](#message) send is the instance of a class implementing the method corresponding to the message sent receiving this message.

## Selector
A selector corresponds to the signature of a method in the system. Since Pharo is not statically typed, the selector of a method is simply a Symbol. On a CompiledMethod, it is possible to send the `#selector` message to retrieve this Symbol.

## Self
Self is the [receiver](#receiver) of a [message](#message) an object sends to itself. This means that the [lookup](#lookup) of a method send will start by the sender of this message then, if not found, it will proceed with its superclass.

## Sender
The sender of a [message](#message) is the object that will send a message to another object. In case the [receiver](#receiver) of a message is [self](#self), then the sender is equal to the receiver.

## Senders
For a given selector in the system, senders are the methods sending a message with this selector. For example, the senders of the method `#banana` are all the methods sending the message `#banana` in their code.

## Sista 
Sista is the name of a [virtual machine](#virtual-machine) with adaptive optimisations such as speculative inlining (meaning that the Virtual machine tries to guess the type of receiver and the arguments. Based on this, it heavily optimises the code at runtime, in case of a wrong guess it de-optimises the code). It showed better performance but is still currently under development. It is not yet production-ready.

## Slang
The term "Slang" refers to a subset of the Smalltalk language that can be translated to C (or other language, such as Javascript). It is mainly used to develop the [Cog](#cog) virtual machine. It allows one to develop the virtual machine using Pharo tools and generates C.

## Slot
Instance variables are reified in Pharo, which means they are real objects that can be manipulated just like any other object.
Because of that, the name *slot* has been given to the general concept of an instance variable in Pharo.
In practice, most of the slots in classes of the system are `InstanceVariableSlot`.
One can create a new kind of slot by subclassing `Slot` class (see [this blogpost](https://medium.com/@juliendelplanque/typed-slots-for-pharo-98ba5d5aafbe) as an example).

## Smalltalk
Smalltalk is an object-oriented, dynamically typed reflective programming language with multiple implementations. Some implemenations include [Squeak](#squeak), VisualWorks, Gemstone, VA Smalltalk and many others. Pharo started as an implementation of Smalltalk and is still very close to it.

## Sources (file)
The sources file contains source code of Pharo. Sources file is important because the image file format stores only objects including compiled methods and their bytecode and not their source code. Originally, a new sources file was generated once per major release of Pharo. Now, Pharo changed its production mechanism to be [bootstraped](#bootstrap) and generates a new sources file for each Pharo image produced.

## Spur
Spur is the name of the current object representation in memory of Pharo used by the [virtual machine](#virtual-machine). This representation is used since Pharo 5 and was introduced to improve performances (by 30% compared to the previous implementation) and prepare Pharo to run in 64bits.

## Squeak
Squeak is a dialect of [Smalltalk](#smalltalk). Pharo started as a fork of Squeak and both still share the same [virtual machine](#virtual-machine).

## Super
Super is the [receiver](#receiver) of a [message](#message) an object send to itself, but on the contrary of [self](#self), the method lookup will start in the superclass of a receiver. Super is a unique way for the class to add behavior to the inherited methods and not just replace them.

## Traits
Traits are pure units of behavior that can be composed to form classes or other traits. The trait composition mechanism is an alternative to multiple or mixin inheritance in which the composer has full control over the trait composition. It enables more reuse than single inheritance without introducing the drawbacks of multiple or mixin inheritance.
A page dedicated to traits is available [here](Traits.md).

## Unary message
An unary message is a [message](#message) where only the [receiver](#receiver) of the message will be required, which is the reason it is called unary. This means that the message will have no argument. For example, `#factorial` is an unary message that will only require the number receiving the message.

## VM
See [virtual machine](#virtual-machine).

## Virtual Machine
The virtual machine of Pharo is the execution engine. It takes Pharo bytecode that is generated each time the user compiles a piece of code, converts it to machine code and executes it. The VM is different for each platform running Pharo (windows, OSX, linux, arm, 32/64bits) and allows the other part of Pharo to be platform independent.

## Workspace
Workspace is the previous name of the [Playground](#playground).


================================================
FILE: General/HowToRunPharoFromCommandLine.md
================================================
# Getting Pharo running from the command line

Here are some simple steps to get Pharo ready from the command line. The script 
assumes that you have a bin folder in your home directory. 

The following script downloads the stable vm version of Pharo 80. Check the web page [https://get.pharo.org/64/](https://get.pharo.org/64/)
to get the possible choices. 

```bash
mkdir bin
cd bin
curl https://get.pharo.org/64/vm80 | bash
```

This script creates two scripts, pharo-ui and pharo-vm both using the contents of the Pharo folder that is also created. 

Once installed you can execute pharo as follows: 

```bash
./pharo-ui Pharo8.image 
```

If you do not want Pharo displaying a user interface as a pop-up, you can invoke it as follows: 

```bash
./pharo Pharo8.image 
```


================================================
FILE: General/IcebergOnWindows.md
================================================
# Iceberg on Windows Workaround

- [Make path to the Pharo Image shorter](#make-path-to-the-pharo-image-shorter)
- [Convert the repository to the Tonel format](#convert-the-repository-to-the-tonel-format)

Long file names in Windows raise the error message  “Failed to stat file ‘filename’: The filename or extension is too long”.

The Windows problem with long filenames is a constraint of [libgit](https://libgit2.org/libgit2/#HEAD) library that is used in Pharo (Iceberg accesses git through this exact library). It occurs because FileTree format tends to have long paths and was one of the main drivers in creating the Tonel format. This error can occur, for example, when you are trying to clone your Pharo fork on Github into Pharo local. There are two possible ways to fix it:

1. Make path to Pharo Image short.
2. Convert repo to Tonel format — in Iceberg there is a menu item under one of the Extras menus.

Here’s more about them:

## Make path to the Pharo Image shorter

If you are simply using a standalone Pharo [download](http://pharo.org/download/#standalone), you can just move your image and VM a few folders up. However, if you are using [Pharo Launcher](http://pharo.org/download/), you have to access the settings, to change where it stores images it will create in the future, as well as move all the existing images and VMs up. Here’s how to do it.

In Pharo Launcher, in the bottom right corner you can see a button ‘open settings’ — click on it.

![alt text](https://github.com/myroslavarm/pharo-wiki/blob/patch-1/General/win_2.png)

In the settings, if you expand the ‘Pharo Launcher’ tab you can see the following options:

![alt text](https://github.com/myroslavarm/pharo-wiki/blob/patch-1/General/win_3.png)

In the first, third and fourth options, change directories without disrupting the dependencies (images in ‘images’, template sources one folder up, etc). When you change the paths, the upper right corner of each of the text boxes will be yellow, which means unsaved changes (that is also the logic inside Pharo). You have to position your cursor in each of the text boxes and press (ctrl+s) to save the changes.

Don’t forget that this section only means images and VMs it will create in the future, so you should also manually move your already existing images and VMs to the same folder you listed. 

Now, everything should work!

## Convert the repository to the Tonel format

Note re FileTree/Tonel: A FileTree represents a hierarchy of files. [Tonel](https://github.com/pharo-vcs/tonel) is a file-per-class format — class and all methods are stored in a single file, which is better than having a file for each method because the code is easier to read outside of Pharo and it creates less files on the hard drive. Tonel also prevents some trouble with git on Windows due to number of files and subdirectory depth that create path exceeding windows limit.

If you are using an older version of Pharo, you need to download Tonel by running the code below in a playground (in Pharo 7 and 8 it comes by default):

```Smalltalk
Metacello new
  baseline: 'Tonel';
  repository: 'github://pharo-vcs/tonel:v1.0.12';
  load.
```

> Note: In Pharo 7 and 8 you don’t need any kind of script to convert to Tonel — there’s a UI option available. But in Pharo 6.1 you need to upgrade Iceberg first, and Tonel will come with it. Link with the script [here](https://github.com/pharo-vcs/iceberg/#for-pharo-61).

With Tonel loaded, if you go to Iceberg repositories and right-click on the specific repository, you can go to ‘extra’ category and click on ‘convert repository sources to tonel’ button. It will migrate the code for you.

![alt text](https://github.com/myroslavarm/pharo-wiki/blob/patch-1/General/win_4.png)

> Note: this option is only possible if the repository isn’t already in the Tonel format. So if your problem is cloning the Pharo fork (Pharo repo is partially Tonel, partially Filetree), then the only option that will actually solve it, is  shortening the path.




================================================
FILE: General/ImageFileFormat.md
================================================
# Image file format
Pharo image is a binary file containing a snapshot of the runtime.
However, there is only a little documentation about its structure (how information is encoded as bytes).
This page is an early work to document the binary format of Pharo images.

- [Determinate the format of an image](#determinate-the-format-of-an-image)
- [Image format accross Pharo versions](#image-format-accross-pharo-versions)

## Determinate the format of an image
Each image has a format. The format can be retrieved by reading the 4 first bytes of an image file.
These bytes encode an integer from least significant to most significant byte (little-endian).

On MacOS, you can use `od` shell command to show these 4 bytes:

```bash
od -t x1 -N 4 Pharo.image
```

You will get an output as follow:

```
0000000    b5  09  01  00                                                
0000004
```

Which correspond to `68021` in decimal.

## Image format accross Pharo versions

| Pharo version                | Image format code | Image first 4 bytes (hex) |
|:-----------------------------|:------------------|:--------------------------|
| version <= 1.3               | 6504              | 68  19  00  00            |
| 1.3 < version <= 5.0-preSpur | 6505              | 69  19  00  00            |
| version (32bits) >= 5.0      | 6521              | 79  19  00  00            |
| version (64bits) >= 5.0      | 68021             | b5  09  01  00            |


================================================
FILE: General/Inspector.md
================================================
# Inspector

*Written based on Pharo 12.0.0 - Build information: Pharo-12.0.0+build.710.sha9e02d19b14a8ecb9cbd45d6ba0166d3b92202c3c (64 Bit)*

The Inspector is a tool that is used to look at an object. In Pharo, inspecting an object means opening this tool. It allows to navigate the object structure and look at the state of the variables, but can show other information.

You can inspect the result of an execution by selecting the code and using the shortcut`Cmd/ctrl + i` or `right-clic + "Do & inspect it"`. This will execute the code and open an inspector on the result. 


The  [🐥 Learn Keyboard Shortcuts \[W1-Live D\]](https://www.youtube.com/watch?v=7YTsys2qxMU&list=PL2okA_2qDJ-kCHVcNXdO5wsUZJCY31zwf&index=10&t=133s) video from the [Pharo MOOC](https://mooc.pharo.org/) demonstrate how to open it.

By inspecting `1/3` we get the following inspector :

![Raw tab](Inspector_raw_tab.png)


## A first look at the inspector

![Raw tab areas](Inspector_raw_tab_areas.png)

The tree framed areas in the next pictures are :
1. This text starts with the **class** of the inspected object. Here we have an instance of Fraction.
2. This is the raw view object. It shows the internal state of the object. Here the fraction as a `numerator` instance variable holding the value 1, and a `denominator` instance variable holding the value 3. 

This is a tree list. When you see the small grey triangle on the left side, by clicking it you can unfold the state of the object inside the instance variable. 
By clicking on an instance variable you can also open a new inspector pane.

This is recursive : if you click on more variables, more pane will open. By default only the last two panes are visible at any time. You can use the small rectangles at the bottom of the window to navigate in the opened pane. You can also choose how many panes and showing at the same times and which one. 

Here is a small demonstration :
![Navigating in the inspector](Inspector_pane_navigation.gif)

3. This last area is the evaluator. In this area you can write expression and evaluate them like you would do it in the playground. In a given evaluator, `self` is referring to the inspected object. This can be seen in the raw view above the evaluator showing the value of the `self` variable.

## The pane tool bar

Each inspector pane has the following toolbar :


![Raw tab areas](Inspector_pane_toolbar.png)

- The **last button** allows one to open a browser on the class of the inspected object. It can be used to check for available methods to use in the evaluator
- The **green glasses** button opens another inspector window on the current object
- The **circling arrows** button allow to refresh the crurent view of the object. Fields of an object are not updated live, so if the object is modified from elsewhere, the new values will only show if the refresh button is used.
- The **triangle button** is related to object-centric debugging. It allows one to put breakpoints on state access (read and/or write) of a specific object.The following animation shows how to put a breakpoint on writing an instance variable, the `Breakpoints` tab listing breakpoints on the current object and how to deactivate one :

![Breakpoints](Inspector_breakpoints.gif)

## The Meta tab : searching for methods and class hierarchy
The `Meta` tab is the last one that is available on most objects.
On the left it shows the class hierarchy of the current object's class and on the right the methods available. Clicking on parent classes in the hierarchy will show methods implemented in this class on the right. Selecting a method will display its source code at the bottom of the tab.


![Meta tab](Inspector_meta_tab.png)

## Creating custom tabs

If you used the inspector a bit, you might have noticed that some objects have additional tabs showing up in the inspector.
For example both Floats and Integer have their first tabs showing different representations of the numbers :

![Inspecting numbers](Inspector_numbers_tabs.png)

Another example is the `FileReference` class. When a file reference is inspected, according to the type of the file, different tab show up with relevant information.

Creating a new tab requires being able to build UI elements called presenters with spec 2. For more explanation on how to build a spec 2 presenters, please see the [Spec 2 documentation](https://github.com/SquareBracketAssociates/BuildingApplicationWithSpec2/tree/master).

For people building visualisation, [Roassal 3](https://github.com/ObjectProfile/Roassal3) visualisations can be embedded in a spec 2 presenter by sending the `asPresenter` message to an instance of RSCanvas.

The following sections will explain how to add a few additional tabs to instances of `OrderedCollection`. This class already as a custom tab showing the list of its items which is defined by its superclass `Collection`.

### Adding a tab with text

Let's add a first tab containing a text describing the first element of the collection. Define the following method :

```Smalltalk
OrderedCollection << inspectionFirstElement

	<inspectorPresentationOrder: 1 title: 'First Element'>

	^ SpTextPresenter new text: 'The first element is ', self first asString; beNotEditable; yourself
```
`<inspectorPresentationOrder: 1 title: 'First Element'>` is a pragma that is detected when creating an inspector on an object. When creating an inspector on an instance of `OrderedCollection`, this method will now be used to generate a tab. The title of the tab will be `First Element`, it will be in position 1 in the order of tabs.

The content of the tab is returned by the method. Here we are creating a text presenter with the content we want and we specify it should not be editable.

This gives us the following result :

![First element tab](Inspector_expension_first_element.png)
We notice that our new tab is in second position. This is because in `Collection<<inspectionItems:` (the method defining the Items tab) the order parameter is 0.

### Adding a tab with a table and conditions on when to display it

Let's create a new tab that will display a table only when the collection contains only numbers. It will show each number and the results of 2 times that number.

First let's create the tab with the table:
```Smalltalk
OrderedCollection << inspectionMultipliedByTwo

	<inspectorPresentationOrder: 10 title: 'Multiply by 2'>
	| presenter |
	presenter := SpTablePresenter new
		             addColumn:
			             ((SpStringTableColumn
				               title: 'Item'
				               evaluated: #yourself)
				              width: 30;
				              yourself);
		             addColumn: (SpStringTableColumn
				              title: 'Multiply by 2'
				              evaluated: [ :each | each * 2 ]);
		             items: self;
		             beResizable;
		             yourself.
	^ presenter
```
If we inspect a collection of numbers we get the following tab :
![Mutliplied by 2 tab](Inspector_expension_multiplied_by_two.png)

However if the collection contains elements that are not numbers, the tab crashes and looks like a red rectangle. By defining a method with the name `<name of the method defining the tab>Context:` we can specify when we want to activate a given tab.
For example :
```Smalltalk
OrderedCollection << containsOnlyNumbers 
	^ self allSatisfy: [ :each | each isNumber  ]


OrderedCollection << inspectionMultipliedByTwoContext: aContext
	^ aContext active: self containsOnlyNumbers.
```
Will ensure that the tab will be displayed only when there is only number in the collection.



## Adding a raw view of a specific element of the collection and removing the evaluator

We can also add a tab showing the raw view of the max value :
```Smalltalk
OrderedCollection << inspectionIMaxValue
	<inspectorPresentationOrder: 5 title: 'Max Value'>
	^ StRawInspectionPresenter on: self max.

OrderedCollection << inspectionIMaxValueContext: aContext
	^ aContext active: self containsOnlyIntegers.
```
![Inspect max value tab](Inspector_expension_max.png)

However as we can see above, the self in the evaluator does not match the self in the max value which is confusing so we will hide the evaluator.

```Smalltalk
OrderedCollection << inspectionIMaxValueContext: aContext
	aContext withoutEvaluator.
	^ aContext active: self containsOnlyIntegers.
```
By reinspecting the same collection we get :
![Removing the evaluator](Inspector_expension_max_without_evaluator.png)

### How to add Roassal charts ?
As said above, Roassal, allow one to build visualisations.
The library includes some common graphs like the histogram for example.
Let's add a histogram of the values if there are only numbers in the collection :

```Smalltalk

OrderedCollection << inspectionIntegerHistogram

	<inspectorPresentationOrder: -1 title: 'Histogram'>
	| plot |
	plot := RSHistogramPlot new x: self.
	^ plot asPresenter


OrderedCollection << inspectionIntegerHistogramContext: aContext 

	aContext active: self containsOnlyIntegers.
	aContext withoutEvaluator.
```
By inspecting `{ 1 . 1 . 3 . 2 . 5 . 2. 2 . 1. 9. 3 . 2. 2. 5 . 7 . 7 . 8  } asOrderedCollection` we get :
![Histogram tab](Inspector_expension_histogram.png)




================================================
FILE: General/InterestingsToKnowForBeginners.md
================================================
# Interesting things to know for beginners

This page will expose different things that might be interesting to know for beginners. Tools, API, shortcuts...

The goal is to ease the use of Pharo for beginners.

- [API](#api)
- [Evaluatable objects (Blocks and Symbols)](#evaluatable-objects--blocks-and-symbols-)
- [Tools](#tools)
  * [Calypso System Browser](#calypso)
- [Flags](#flags)
- [Useful pragmas](#useful-pragmas)
  * [Modify IDE](#modify-ide)
  * [Influence execution of methods](#influence-execution-of-methods)
  * [Influence Debugger](#influence-debugger)

## API

The Pharo API is extensive. In this section we will explain various methods existing in Pharo that have proven to be useful in our experience.

**String class>>#streamContents:**

String concatenation can be costly because it will create a new string instance and copy the content of the two strings at each concatenation. To make it more efficient, Pharo includes a method to create a String via a stream:

```Smalltalk
'This is a ', 'string concatenation ' , 'that is not really' , ' ' , ' efficient'.

String streamContents: [ :aStream | aStream << 'This is a '<< 'string concatenation ' << 'that is ' << ' ' << ' efficient' ]
```

## Evaluatable objects (Blocks and Symbols)
Pharo's Blocks and Symbols have an interesting property: they are polymorphic through `#value:` and `#cull:` methods.

For example, the two code snippets below are equivalent:

```Smalltalk
#class value: Object new
```

```
[ :o | o class ] value: Object new
```

They both return the class of an object.

This means that for methods taking a one-argument block as a parameter, this block can be replaced by a symbol. The effect is that the unary method named by the symbol will be executed with the object as the receiver.

The difference between `#value:` and `#cull:` is that `#value:` requires a parameter when `#cull:` can work with or without a parameter.

The common usage of this feature is via iterators. For example, if you want to collect the result of the `name` method of all objects in a collection you can either do:

```
objectCollection collect: [ :o | o name ].
```

or

```
objectCollecton collect: #name
```

The second way is shorter and often more readable.

## Tools

### Calypso (System browser)

- Display the differences between two methods
	* Click on a method
	* Hold down the `SHIFT` key
	* Click on the second method
	* Click on the tab Diff to see the differences
	
- Editing multiple methods side by side
	* Click on a method
	* Hold down the `CTRL` key
	* Click on all the methods you want to edit. 
	* Tabs are displayed with the source code of the methods selected.

## Flags

It is possible to "flag" methods in Pharo in order to be able to retrieve them later. This can be done by sending the `#flag:` message to self with a symbol as parameter which is the flag to be used.

Commonly used flags are:
- `#todo` to mark code that needs work to be done.
- `#hack` to mark hackish code.
- `#broken` to mark broken code.
- `#clean` to mark code that needs cleaning.
- `#toCheck` to mark code that should be checked later.
- `#pharoX` to mark code present for compatibility with `X` being the version of Pharo.

Flags will not modify the execution of a method. Flags are just used to tag methods.

For example, the method below will return `42` if executed as if there was no call to `#flag:` method.

```
myUnfinishedMethod
	self flag: #TODO. "Some process to be done here."
	^ 42
```

To retrieve methods for which you set flag(s), just search for senders of your flag. For example, to retrieve methods flagged with `#todo`, either inspect the result of the following script: `#todo senders` or just select the symbol and press Meta+N (shortcut for "Browse senders").

## Useful pragmas

Pragmas allow one to tag methods. They are similar to Java's annotations. Some pragmas allow the developer to modify the IDE or to influence execution of methods. This section presents some of these useful pragmas.

### Modify IDE

- `<script>` for class-side methods, adds a button next to the method name in the IDE. This button, when clicked, executes the method.
- `<script: 'Smalltalk code to run'>` is similar to `<script>` but the button executes the Smalltalk code held by the string provided as parameter to the pragma.
- `<sampleInstance>` for class-side methods, adds a button next to the method name in the IDE. When clicked, the method is executed and an inspector is opened on its result.
- `<worldMenu>` for class-side methods, add a menu entry in the Pharo menu. The method with this pragma should take a builder as a parameter. You can browse the senders of the `worldMenu` pragma to find the API.
- `<systemsettings>` for class-side methods, add an entry in the Pharo settings. The method with this pragma should take a builder as a parameter. You can browse the senders of the `systemsettings` pragma to find the API.
- `<haltOrBreakpointForTesting>` should be used in methods using breakpoints that should not be listed in the Breakpoint browser. For example, it can be used in examples using breakpoints to highlight a feature of the example.

### Influence execution of methods

- `<expectedFailure>` for instance-side methods of subclasses of `TestCase`, will make the test green when it is failing. But, although we expect that the test will fail, a success of the test (i.e. not assertion missed) will show as a failure.

### Influence Debugger
- `<debuggerCompleteToSender>` allows one to tell the debugger to open itself on the method that sends the message corresponding to the method holding the `<debuggerCompleteToSender>` pragma.

For example, let us consider these two methods:
```st
foo
	<debuggerCompleteToSender>
	Error signal: 'foo'
```

```st
fooCaller
	self foo
```

Because of the `<debuggerCompleteToSender>`, when `#fooCaller` is executed, the debugger will show `#fooCaller` method source code.
If the pragma was not there, the debugger would show `#foo` method source code.


================================================
FILE: General/Layout.md
================================================
# Mohpic's Layouts

The Morphic Library of Pharo is a low level UI framework. This page aims at describing how to layout morphes together.

- [Mohpic's Layouts](#mohpic-s-layouts)
  * [Row layout](#row-layout)
  * [Table Layout](#table-layout)
  * [Stack Layout](#stack-layout)
  * [Proportionnal layout](#proportionnal-layout)
  * [Annexe](#annexe)


## Row layout

This layout displays a morph's submorphs horizontally aligned.
By default, the submorphs display start at the topLeft corner of the morph.
With this layout, the submorphs are display in a array. This array associate a submorph with a cell of the array.
The size of a cell in Y depends of the max size of the morph in Y. However, the length in X of a cell depends of the size of the submorph who are displayed in this cell.
We modify the display of the submorph with several attribut :
- `cellPositioning` takes several values : center, bottomLeft, bottomRight, topLeft, topRight. This value allow to modify the display of the submorphs.
- `cellInset` : set a space between each cell of the morph, it takes an integer.
- `extent` : set the size of the morph, it takes a point.
- `hResizing` : allows to modify a morph horizontally. It takes several value : shrinkWrap, spaceFill, rigid.
  - `rigid` allows to not modify the morph
  - `shrinkWrap` resizes the morph to fit the frame of his submorph
  - `spaceFill` fills the empty space with this morph
- `vResizing`: allows to modify a morph vertically. It takes the same value as hResizing.

Example 1 : Row layout with two morphs

![alt text](layout_screenshot/RowLayoutExampleWithTwoMorph.png)
```st
| m1 m2 m3|
m1 := Morph new layoutPolicy: RowLayout new; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.`
```
Example 2 : Row layout with three morphs

![alt text](layout_screenshot/RowLayoutExampleWithThreeMorph.png)
```st
| m1 m2 m3 m4|
m1 := Morph new layoutPolicy: RowLayout new; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow.
m4 := Morph new color: Color purple.
m1 addMorph: m2.
m1 addMorph: m3.
m1 addMorph: m4.
m1 openInWorld.
```
Example 3 : Row layout with two morphs with cellPositioning : bottomLeft

![alt text](layout_screenshot/RowLayoutExampleWithTwoMorphCellPositionBottomLeft.png)
```st
| m1 m2 m3|
m1 := Morph new color: Color blue; layoutPolicy: RowLayout new;extent: (200@200);cellPositioning: #bottomLeft; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow; extent: (100@100); yourself.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld .
```
Example 4 : Row layout with two morphs with cellPositioning : center

![alt text](layout_screenshot/RowLayoutExampleWithTwoMorphCellPositionCenter.png)
```st
|m1 m2 m3|
m1 := Morph new color: Color blue; layoutPolicy: RowLayout new; extent: (200@200); cellPositioning: #center; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow; extent: (100@100); yourself.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld .
```

Exemple 5 : Row layout example with two morphs with cellPositioning : topLeft

![alt text](layout_screenshot/RowLayoutExampleWithTwoMorphCellPositionTopLeft.png)
```st
|m1 m2 m3|
m1 := Morph new color: Color blue; layoutPolicy: RowLayout new; extent: (200@200); cellPositioning: #topLeft; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow; extent: (100@100); yourself.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld .
```

Exemple 6 : Row layout with hResizing and vResizing : spaceFill

![alt text](layout_screenshot/RowLayoutwithvResizingAndhResizingAtSpacefillForOneMorph.png)
```st
| m1 m2 m3|
m1 := Morph new layoutPolicy: RowLayout new; yourself.
m1 extent: 250@250.
m2 := Morph new color: Color green.
m3 := Morph new color: Color purple.
m2 vResizing: #spaceFill.
m2 hResizing: #spaceFill.
m3 extent: 100@100.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
```

Exemple 7 : Row layout with hResizing and vResizing : shrinkWrap

![alt text](layout_screenshot/RowLayoutwithvResizingAndhResizingAtshrinkWrap.png)
```st
| m1 m2 m3|
m1 := Morph new layoutPolicy: RowLayout new; yourself.
m1 vResizing: #shrinkWrap.
m1 hResizing: #shrinkWrap.
m1 extent: 250@250.
m2 := Morph new color: Color green.
m3 := Morph new color: Color purple.

m3 extent: 100@100.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
```

## Table Layout

The layout is processed like this:
For computing the new layout for the children of any morph, we start with an initial rectangle which is provided as a reference.

Step 1: The first step of this layout computation is to compute the minimum extent each of our children can have. The minimum extent is mapped through both the local layout frame of the morph (for relative positioning) and the global layout frame (for insets, such as cursor indication) to obtain the minimal size required for each cell.

Step 2: Based on the cell sizes, the number of cells we can put into each row and column is computed. For equal spacing, the maximum size of the cells is taken into account here.

Step 3: Based on the row/column sizes, we compute the extra space which should be added to each row/column. For:
- `#leftFlush/#topFlush` - we add all extra space add the end
- `#rightFlush/#bottomFlush` - we add all extra space at the start
- `#centering` - we add 1/2 of the extra space at start and end
- `#justified` - we distribute the space evenly between the morphs
> NOTE: If any #spaceFill morphs are encountered during this step, #justified is implied and the space is exclusively and equally distributed between those #spaceFill morphs. This is for backward compatibility and should *never* be necessary in the new regime.

Step 4: The morphs are placed in the computed cells and the extra space is distributed as necessary. Placing the submorphs is done by mapping through the global and the local layout frame as requested.

Start point:
=> bounds: new rectangle for the morph.

Compute basic arrangement of morphs:
=> For each submorph compute minExtent
- if global layout frame inset in global layout frame
- if local layout frame inset in local layout frame
=> Compute number of morphs per, width and height of row/column
- if equal spacing based on max size
=> Compute extra space per row/column
- if centering = #justified; distribute space equally
- if centering #leftFlush/#topFlush (-1) add start extra
- if centering #rightFlush/#bottomFlush (1) add end extra
- if centering #centered add 1/2 extra to start/end
<extra space must be float and rounded accordingly!>
=> Place morphs in appropriate cells
- if global layout frame inset in global layout frame
- if local layout frame inset in local layout frame
<will likely cause #layoutChanged by submorphs>

Distribute morphs in row/column:

=> Compute the max length of each row/column

Example 1 : Table layout with two morphs

![alt text](layout_screenshot/TableLayoutExampleWithTwoMorph.png)
```st
|m1 m2 m3|
m1 := Morph new layoutPolicy: TableLayout new; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
```

Example 2 : Table layout with three morphs

![alt text](layout_screenshot/TableLayoutExampleWithThreeMorph.png)
```st
|m1 m2 m3 m4|
m1 := Morph new layoutPolicy: TableLayout new; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow.
m4 := Morph new color: Color purple.
m1 addMorph: m2.
m1 addMorph: m3.
m1 addMorph: m4.
m1 openInWorld.
```

Exemple 3 : Table layout with two morphs with cellPositioning : center

![alt text](layout_screenshot/TableLayoutExampleWithTwoMorphWithCenteringMorph.png)
```st
|m1 m2 m3|
m1 := Morph new color: Color blue; layoutPolicy: TableLayout new; extent: (200@200); cellPositioning: #center; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow; extent:  (100@100); yourself.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
```

Exemple 4 : Table layout with two morphs with cellPositioning : topLeft

![alt text](layout_screenshot/TableLayoutExampleWithTwoMorphWithTopLeftMorph.png)
```st
|m1 m2 m3|
m1 := Morph new color: Color blue; layoutPolicy: TableLayout new; extent: (200@200); cellPositioning: #topRight; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow; extent: (100@100); yourself.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
```

Exemple 5 : Table layout with two morphs with cellPositioning : topRight

![alt text](layout_screenshot/TableLayoutExampleWithTwoMorphWithTopRightMorph.png)
```st
|m1 m2 m3|
m1 := Morph new color: Color blue; layoutPolicy: TableLayout new; extent: (200@200); cellPositioning: #topLeft; yourself.
m2 :=  Morph new color: Color green.
m3 := Morph new color: Color yellow; extent: (100@100); yourself.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
```

Exemple 6 : Table layout with vResizing and hResizing : shrinkWrap.

![alt text](layout_screenshot/TableLayoutWithverticalandHorizontalShrinkwrapResizing.png)
```st
| m1 m2 m3 m4|
m1 := Morph new layoutPolicy: TableLayout new; yourself.
m1 vResizing: #shrinkWrap.
m1 hResizing: #shrinkWrap.
m1 extent: 1500@1500.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow.
m4 := Morph new color: Color purple.
m4 extent: 100@100.
m1 addMorph: m2.
m1 addMorph: m3.
m1 addMorph: m4.
m1 openInWorld.
```

Exemple 7 : Table layout with vResizing and hResizing : spaceFill

![alt text](layout_screenshot/TableLayoutWithVResizingAndhResizingAsSpacefill.png)
```st
| m1 m2 m3|
m1 := Morph new layoutPolicy: TableLayout new; yourself.
m1 extent: 250@250.
m2 := Morph new color: Color green.
m3 := Morph new color: Color purple.
m2 vResizing: #spaceFill.
m2 hResizing: #spaceFill.
m3 extent: 100@100.
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
```

Exemple 8 : Table layout with wrapCentering : center

![alt text](layout_screenshot/TableLayoutWithWrapCenteringCenter.png)
```st
| m1 m2 m3 |
m1 := Morph new layoutPolicy: TableLayout new; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow; layoutPolicy: TableLayout new; yourself.
m1 extent: 200@200.
m1 wrapCentering: #center.
m1 addMorph: m2.
m3 extent: (100@100).
m1 addMorph: m3.
m1 openInWorld.
```

Exemple 9 : Table layout with wrapCentering : bottomRight

![alt text](layout_screenshot/TableLayoutWithWrapCenteringbottomRight.png)
```st
| m1 m2 m3 |
m1 := Morph new layoutPolicy: TableLayout new; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow; layoutPolicy: TableLayout new; yourself.
m1 extent: 200@200.
m1 wrapCentering: #bottomRight.
m1 addMorph: m2.
m3 extent: (100@100).
m1 addMorph: m3.
m1 openInWorld.
```

Exemple 10 : Table layout with wrapCentering : topLeft

![alt text](layout_screenshot/TableLayoutWithWrapCenteringtopLeft.png)
```st
| m1 m2 m3 |
m1 := Morph new layoutPolicy: TableLayout new; yourself.
m2 := Morph new color: Color green.
m3 := Morph new color: Color yellow; layoutPolicy: TableLayout new; yourself.
m1 extent: 200@200.
m1 wrapCentering: #topLeft.
m1 addMorph: m2.
m3 extent: (100@100).
m1 addMorph: m3.
m1 openInWorld.
```

## Stack Layout

Unstack the submorphs at the center of the morph in default.
It could be a problem if the last submorph unstack was bigger than the other submorph, because the last one was display on the other.
It takes several attribut but the most relevant attribut was :
- cellPositioning
- extent
cellPositioning set the point of reference to display morph. For example, if the value was center, the morphs were gonna display with the center, if the value was : topRight, they gonna stack on the top right corner of parent morph

Example 1 : Stack layout with two morphs with lower morph extent

![alt text](layout_screenshot/StackLayoutExampleWithTwoMorphWithLowerMorphExtent.png)
 ```st
|m1 m2 m3|
m1 := Morph new layoutPolicy: StackLayout new; yourself.
m2 :=  Morph new color: Color green; extent: (100@100); yourself.
m3 := Morph new color: Color yellow .
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
```

Example 2 : Stack layout with two morphs with upper morph extent

![alt text](layout_screenshot/StackLayoutExampleWithTwoMorphWithUpperMorphExtent.png)
 ```st
|m1 m2 m3|
m1 := Morph new layoutPolicy: StackLayout new ; yourself.
m2 :=  Morph new color: Color green.
m3 := Morph new color: Color yellow; extent: (100@100); yourself .
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
 ```
Exemple 3 : Stack layout with two morphs with cellPositioning : topRight

![alt text](layout_screenshot/StackLayoutExampleWithTwoMorphCellPositioningTopRight.png)
```st
|m1 m2 m3|
m1 := Morph new layoutPolicy: StackLayout new; cellPositioning: #topRight; yourself.
m2 :=  Morph new color: Color green; extent: (100@100); yourself.
m3 := Morph new color: Color yellow .
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.  
```

Exemple 4 :  Stack layout with two morphs with cellPositioning : bottomRight

![alt text](layout_screenshot/StackLayoutExampleWithTwoMorphCellPositioningBottomRight.png)
```st
|m1 m2 m3|
m1 := Morph new layoutPolicy: StackLayout new; cellPositioning: #bottomRight; yourself.
m2 :=  Morph new color: Color green; extent: (100@100); yourself.
m3 := Morph new color: Color yellow .
m1 addMorph: m2.
m1 addMorph: m3.
m1 openInWorld.
 ```

## Proportionnal layout

This layout allows to modify the relative size of a submorph when the size of the container change.
The goal is to change proportionnaly to the size of the morph.
For doing this, the submorph need a frame where it will be display.
This frame is a percentage of the morph.
For example: if we give a frame of (0 @ 0 corner: 0.5 @ 0.5) to a submorph, it occupies 25% of the morph.
And if we resize the container, the size of the submorph will be resize proportionaly to stay with a occupied frame of 25%.

Exemple 1 : Proportionnal layout with 25% of the morph area.

![alt text](layout_screenshot/ProportionnalLayoutWithLeftTop50perX50perY.png)
```st
|frame sub|
m1 :=SystemWindow new.
m1 layoutPolicy: ProportionalLayout new.
frame := (0 @ 0 corner: 0.5 @ 0.5) asLayoutFrame .
sub := Morph new color: Color red.
m1 addMorph: sub fullFrame: frame.
m1 extent:300@300.
m1 openInWorld.
```
Exemple 2 : Proportionnal layout with 50% of the morph area.

![alt text](layout_screenshot/ProportionnalLayoutWithLeftTop50perY.png)
```st
|frame sub|
m1 :=SystemWindow new.
m1 layoutPolicy: ProportionalLayout new.
frame := (0 @ 0 corner: 1.0 @ 0.5) asLayoutFrame .
sub := Morph new color: Color red.
m1 addMorph: sub fullFrame: frame.
m1 extent:300@300.
m1 openInWorld.
```
Example 3 : Proportionnal layout with 100% of the morph area.

![alt text](layout_screenshot/ProportionnalLayoutExampleWithSystemWIndowWithFulllWindow.png)
```st
|frame sub|
m1 :=SystemWindow new.
m1 layoutPolicy: ProportionalLayout new.
frame := (0 @ 0 corner: 1.0 @ 1.0) asLayoutFrame .
sub := Morph new color: Color red.
m1 addMorph: sub fullFrame: frame.
m1 extent:300@300.
m1 openInWorld.
```
Example 4 : Proportionnal layout with 2 Morph, each Morph was display on 50% of the morph area.

![alt text](layout_screenshot/ProportionnalLayoutExampleWithSystemWIndowWithTwoMorph.png)
```st
|frame sub|
m1 := SystemWindow new.
m1 layoutPolicy: ProportionalLayout new.
frame := (0 @ 0 corner: 1.0 @ 1.0) asLayoutFrame .
sub := Morph new layoutPolicy: TableLayout new.
m3 := Morph new color: Color green; yourself.
m2 := Morph new color: Color red; yourself.
sub addMorph: m2 fullFrame: frame.
sub addMorph: m3 fullFrame: frame.
m1 addMorph: sub fullFrame: frame.
m1 extent: 300@300.
m1 openInWorld.
```

Example 5: Proportional layout with scrollbar
![alt text](layout_screenshot/ProportionnalLayoutWithScrollBar.png)
```st
| window scrollPane pasteUpMorph |
	window := Morph new layoutPolicy: ProportionalLayout new.
	window extent: (500@500).
	scrollPane := ScrollPane new.
	pasteUpMorph := Morph new color: Color yellow .
	pasteUpMorph extent: 1000@1000.
	scrollPane scroller addMorph: pasteUpMorph.
	window addMorph: scrollPane fullFrame: (0@0 corner: 1@1).

	window openInWorld.
```

## Annexe

No minimal size in particular


================================================
FILE: General/MenuBar.md
================================================
# Menubar and World menu

In Pharo, to open tools or execute actions a Menubar (At the top of the screen) and a WorldMenu (Appears on a left click in the world) are present.

This page will document some aspects of those features. 

- [Disable the Menubar/WorldMenu](#disable-the-menubarworldmenu)
- [Add your own entries](#add-your-own-entries)
  * [Add a simple entry](#add-a-simple-e
Download .txt
gitextract_8rwhc7yu/

├── .github/
│   └── workflows/
│       └── continuous.yml
├── .gitignore
├── CONTRIBUTION.md
├── ExternalProjects/
│   ├── DataStructures/
│   │   └── DataFrame.md
│   └── Export/
│       ├── Arff.md
│       ├── CSV.md
│       ├── ESCP.md
│       ├── HTML.md
│       ├── JSON.md
│       └── XML.md
├── ExternalResources/
│   └── Community.md
├── General/
│   ├── Baselines.md
│   ├── CJKCharacter.md
│   ├── CJKInputMethod.md
│   ├── CodingConventions.md
│   ├── CoolSnippets.md
│   ├── DeployYourPharoApplication.md
│   ├── Exceptions.md
│   ├── ExportFormats.md
│   ├── Extensions.md
│   ├── Files.md
│   ├── GithubActions.md
│   ├── Glossary.md
│   ├── HowToRunPharoFromCommandLine.md
│   ├── IcebergOnWindows.md
│   ├── ImageFileFormat.md
│   ├── Inspector.md
│   ├── InterestingsToKnowForBeginners.md
│   ├── Layout.md
│   ├── MenuBar.md
│   ├── MustKnowForBeginners.md
│   ├── Playground.md
│   ├── Pragmas.md
│   ├── Profiling.md
│   ├── ProgressBar.md
│   ├── Refactorings.md
│   ├── SessionsManagement.md
│   ├── SettingUpANewProject.md
│   ├── Settings.md
│   ├── SortingCollections.md
│   ├── Traits.md
│   ├── Travis.md
│   ├── TweakingBigImages.md
│   └── Windows10SubsystemForLinux.md
├── LICENSE
├── MANIFEST.md
├── Migration/
│   └── MigrationToPharo7.md
├── PharoProjects/
│   ├── Announcer.md
│   ├── Cursor.md
│   ├── DynamicVariables.md
│   ├── Metalinks.md
│   ├── Numbers.md
│   ├── OS.md
│   ├── ObjectsSerialization.md
│   ├── RichText.md
│   └── WebBrowser.md
├── PharoVirtualMachine/
│   └── pharo-vm-map.md
└── README.md
Condensed preview — 58 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (382K chars).
[
  {
    "path": ".github/workflows/continuous.yml",
    "chars": 879,
    "preview": "name: Broken links\n\nenv:\n  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n# Controls when the action will run. Triggers the "
  },
  {
    "path": ".gitignore",
    "chars": 13,
    "preview": "**/.DS_STORE\n"
  },
  {
    "path": "CONTRIBUTION.md",
    "chars": 5060,
    "preview": "# Contribution guidlines\n\n  * [Suggest new pages](#suggest-new-pages)\n  * [Entries structure](#entries-structure)\n  * [E"
  },
  {
    "path": "ExternalProjects/DataStructures/DataFrame.md",
    "chars": 13,
    "preview": "# DataFrame\n\n"
  },
  {
    "path": "ExternalProjects/Export/Arff.md",
    "chars": 117,
    "preview": "# Arff support in Pharo\nTo be done, talk about the [Arff parser/generator](https://github.com/juliendelplanque/Arff)\n"
  },
  {
    "path": "ExternalProjects/Export/CSV.md",
    "chars": 2282,
    "preview": "# CSV support in Pharo\nCurrently, Pharo provides one main framework to handle the [CSV format](https://fr.wikipedia.org/"
  },
  {
    "path": "ExternalProjects/Export/ESCP.md",
    "chars": 117,
    "preview": "# ESCP support in Pharo\nTo be done, talk about the [ESCP parser/generator](https://github.com/juliendelplanque/ESCP)\n"
  },
  {
    "path": "ExternalProjects/Export/HTML.md",
    "chars": 90,
    "preview": "# HTML support in Pharo\nTo be done, talk about HTML parser(s)\n\n- XMLParser-HTML\n\n- Soup ?\n"
  },
  {
    "path": "ExternalProjects/Export/JSON.md",
    "chars": 4918,
    "preview": "# JSON support in Pharo\nCurrently, Pharo provides two main frameworks to handle the [JSON format](https://en.wikipedia.o"
  },
  {
    "path": "ExternalProjects/Export/XML.md",
    "chars": 99,
    "preview": "# XML support in Pharo\nTo be done, talk about XML parsers, XML model, XPath implementation, etc...\n"
  },
  {
    "path": "ExternalResources/Community.md",
    "chars": 1923,
    "preview": "# Community\nThis page lists links to external resources created by members of Pharo (and sometimes other smalltalks) com"
  },
  {
    "path": "General/Baselines.md",
    "chars": 39745,
    "preview": "# Baselines\n\nPharo projects often require a configuration to declare how they should be loaded. This configuration is do"
  },
  {
    "path": "General/CJKCharacter.md",
    "chars": 2209,
    "preview": "# Using CJK (Chinese, Japanese, and Korean) characters\n\nPharo's default font settings for code (Source Code Pro) and UI "
  },
  {
    "path": "General/CJKInputMethod.md",
    "chars": 256,
    "preview": "# Using CJK (Chinese, Japanese, and Korean) Input Method\n\nIt's possible to use CJK input method in Pharo. Tested under P"
  },
  {
    "path": "General/CodingConventions.md",
    "chars": 1646,
    "preview": "# Coding conventions\n\nPharo is full of implicit coding conventions. \n\nThis page aims to document all those conventions t"
  },
  {
    "path": "General/CoolSnippets.md",
    "chars": 6583,
    "preview": "# Cool Snippets\n\nThis file contains snippets of code that can be useful sometimes.\n\n- [Download a file with a progress b"
  },
  {
    "path": "General/DeployYourPharoApplication.md",
    "chars": 18370,
    "preview": "# How to deploy a Pharo application\n\n*This guide has for purpose to help developpers deploying a Pharo application. If s"
  },
  {
    "path": "General/Exceptions.md",
    "chars": 9518,
    "preview": "# Exceptions\n\nAll applications have to deal with exceptional situations.\nArithmetic errors may occur (such as division b"
  },
  {
    "path": "General/ExportFormats.md",
    "chars": 8832,
    "preview": "# Source Code Export formats\n\nPharo stores its source code in memory (by default) or in a snapshot of the memory when we"
  },
  {
    "path": "General/Extensions.md",
    "chars": 5006,
    "preview": "# Extensions\n\n- [Extensions](#extensions)\n  - [Use of Extension methods](#use-of-extension-methods)\n  - [Add a new exten"
  },
  {
    "path": "General/Files.md",
    "chars": 75,
    "preview": "# Files\nTODO: explain how to manipulate files, paths, file systems, etc...\n"
  },
  {
    "path": "General/GithubActions.md",
    "chars": 33668,
    "preview": "# Setting up your continuous integration via GitHub Actions\n\nPreviously, the Pharo community was heavily relying on Trav"
  },
  {
    "path": "General/Glossary.md",
    "chars": 16551,
    "preview": "# Pharo vocabulary\nThe Pharo community uses specific vocabulary to designate object oriented concepts, Pharo concepts an"
  },
  {
    "path": "General/HowToRunPharoFromCommandLine.md",
    "chars": 776,
    "preview": "# Getting Pharo running from the command line\n\nHere are some simple steps to get Pharo ready from the command line. The "
  },
  {
    "path": "General/IcebergOnWindows.md",
    "chars": 4015,
    "preview": "# Iceberg on Windows Workaround\n\n- [Make path to the Pharo Image shorter](#make-path-to-the-pharo-image-shorter)\n- [Conv"
  },
  {
    "path": "General/ImageFileFormat.md",
    "chars": 1453,
    "preview": "# Image file format\nPharo image is a binary file containing a snapshot of the runtime.\nHowever, there is only a little d"
  },
  {
    "path": "General/Inspector.md",
    "chars": 9202,
    "preview": "# Inspector\n\n*Written based on Pharo 12.0.0 - Build information: Pharo-12.0.0+build.710.sha9e02d19b14a8ecb9cbd45d6ba0166"
  },
  {
    "path": "General/InterestingsToKnowForBeginners.md",
    "chars": 5998,
    "preview": "# Interesting things to know for beginners\n\nThis page will expose different things that might be interesting to know for"
  },
  {
    "path": "General/Layout.md",
    "chars": 16208,
    "preview": "# Mohpic's Layouts\n\nThe Morphic Library of Pharo is a low level UI framework. This page aims at describing how to layout"
  },
  {
    "path": "General/MenuBar.md",
    "chars": 5030,
    "preview": "# Menubar and World menu\n\nIn Pharo, to open tools or execute actions a Menubar (At the top of the screen) and a WorldMen"
  },
  {
    "path": "General/MustKnowForBeginners.md",
    "chars": 5315,
    "preview": "# Must know for beginners\n\nThis page includes knowledge about thing the Pharo community think important to know as a Pha"
  },
  {
    "path": "General/Playground.md",
    "chars": 9533,
    "preview": "# Playground\n\n- [Basic usage](#basic-usage)\n  * [Do it](#do-it)\n  * [Print it](#print-it)\n  * [Do it and go](#do-it-and-"
  },
  {
    "path": "General/Pragmas.md",
    "chars": 7802,
    "preview": "# Pragmas\n\n- [Description](#description)\n- [How to declare a new pragma](#how-to-declare-a-new-pragma)\n- [Collect pragma"
  },
  {
    "path": "General/Profiling.md",
    "chars": 3100,
    "preview": "# Profiling\nProfiling a program is the act of measuring, for example, the time or space it takes to execute.\n\n- [Time Pr"
  },
  {
    "path": "General/ProgressBar.md",
    "chars": 2022,
    "preview": "# Progress bar\n\nThis document covers different ways to display a progress bar during code execution.\n\n## Progress bar on"
  },
  {
    "path": "General/Refactorings.md",
    "chars": 16456,
    "preview": "# Refactoring in Pharo 8.0\n\n## Introduction\n\nPharo offers many automatic refactoring tools. This tutorial presents what "
  },
  {
    "path": "General/SessionsManagement.md",
    "chars": 5797,
    "preview": "# Sessions Management\n\n * [Description](#description)\n * [Quick start](#quick-start)\n * [Register a class to the session"
  },
  {
    "path": "General/SettingUpANewProject.md",
    "chars": 11316,
    "preview": "# Setting up a new project\n\nIn this article, we describe the good workflow for setting up a new project in Pharo. We wil"
  },
  {
    "path": "General/Settings.md",
    "chars": 14095,
    "preview": "# Settings\n\nA Pharo developer can define **settings** to give users a way to easily customise... well, anything really.\n"
  },
  {
    "path": "General/SortingCollections.md",
    "chars": 5754,
    "preview": "# Sorting collections\n\nA common requirement in software engineering is to sort collections. This page provides informati"
  },
  {
    "path": "General/Traits.md",
    "chars": 8949,
    "preview": "# Traits\n\n- [Description](#description)\n- [Create and use a new Trait](#create-and-use-a-new-trait)\n- [Abstract methods]"
  },
  {
    "path": "General/Travis.md",
    "chars": 1475,
    "preview": "# Setting up Travis Continuous Integration\n\n> IMPORTANT NOTE: Since Travis is becoming a pay to use service, it is possi"
  },
  {
    "path": "General/TweakingBigImages.md",
    "chars": 7374,
    "preview": "# Tweaking big images\n\nPharo is special in the sense that the language and IDE are mixed. It means that your application"
  },
  {
    "path": "General/Windows10SubsystemForLinux.md",
    "chars": 1049,
    "preview": "# How to get Pharo running on WSL\n\nPharo can be run under Windows 10 Subsystem for Linux (WSL).\n\n- Install WSL (see [mic"
  },
  {
    "path": "LICENSE",
    "chars": 18677,
    "preview": "Copyright (c) 2018 pharo-wiki\n\nAttribution 4.0 International\n\n=========================================================="
  },
  {
    "path": "MANIFEST.md",
    "chars": 2497,
    "preview": "# Pharo wiki manifest\n\nThis file will explain the goals of this project and define its boundaries. \n\nPharo-wiki is a use"
  },
  {
    "path": "Migration/MigrationToPharo7.md",
    "chars": 5748,
    "preview": "# Migration from Pharo 6.1 to Pharo 7.0 guideline\n\n## Pharo 7 file streams guideline\n\nSince version 5, Pharo provides a "
  },
  {
    "path": "PharoProjects/Announcer.md",
    "chars": 4739,
    "preview": "# Announcer\n`Announcer` and `Announcement` classes provide an implementation of the [observer design pattern](https://en"
  },
  {
    "path": "PharoProjects/Cursor.md",
    "chars": 955,
    "preview": "# Cursor\n\nThe `Cursor` class in Pharo manages the display of the cursor on the screen.\n\nIt is possible to change the way"
  },
  {
    "path": "PharoProjects/DynamicVariables.md",
    "chars": 2298,
    "preview": "# Dynamic variables\n\nPharo contains a system of dynamic variables which are global variables whose value can be changed "
  },
  {
    "path": "PharoProjects/Metalinks.md",
    "chars": 24,
    "preview": "# Metalinks\n\n> **TODO**\n"
  },
  {
    "path": "PharoProjects/Numbers.md",
    "chars": 1947,
    "preview": "# Numbers\nThis page provides some hints for using Pharo's numbers. For more detailled information, check [Pharo by Examp"
  },
  {
    "path": "PharoProjects/OS.md",
    "chars": 1715,
    "preview": "# Basic interactions with the OS\nThis page describes basic interactions with the OS. The code snippet below should be wo"
  },
  {
    "path": "PharoProjects/ObjectsSerialization.md",
    "chars": 949,
    "preview": "# Objects serialization support\nTo be done.\n\n## STON\n-> [doc](https://github.com/svenvc/ston/blob/master/ston-paper.md)\n"
  },
  {
    "path": "PharoProjects/RichText.md",
    "chars": 3337,
    "preview": "# Rich text in Pharo\n\n`Text` object models rich text. That is to say text that can be stylised with **bold**, *italics*,"
  },
  {
    "path": "PharoProjects/WebBrowser.md",
    "chars": 374,
    "preview": "# Web browser\n\n*WebBrowser* is a project included since Pharo 7. The goal of the project is to offer to the user the pos"
  },
  {
    "path": "PharoVirtualMachine/pharo-vm-map.md",
    "chars": 15558,
    "preview": "\n# Introduction\n\n## design principles behind smalltalk\nhttps://www.cs.virginia.edu/~evans/cs655/readings/smalltalk.html\n"
  },
  {
    "path": "README.md",
    "chars": 7786,
    "preview": "# Pharo wiki\n\nWiki for the [Pharo](https://pharo.org/features) programming language and development environment.\n\nThe go"
  }
]

About this extraction

This page contains the full source code of the pharo-open-documentation/pharo-wiki GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 58 files (358.7 KB), approximately 92.1k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!