trackler 2.2.1.10 → 2.2.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/CONTRIBUTING.md +1 -1
- data/problem-specifications/TOPICS.txt +1 -0
- data/problem-specifications/exercises/accumulate/description.md +0 -3
- data/problem-specifications/exercises/hamming/canonical-data.json +3 -3
- data/problem-specifications/exercises/house/canonical-data.json +322 -0
- data/problem-specifications/exercises/palindrome-products/description.md +2 -2
- data/problem-specifications/exercises/simple-cipher/description.md +1 -1
- data/tracks/bash/config.json +0 -11
- data/tracks/cpp/docs/ABOUT.md +12 -37
- data/tracks/csharp/config.json +37 -0
- data/tracks/csharp/config/maintainers.json +10 -0
- data/tracks/csharp/docs/ABOUT.md +1 -1
- data/tracks/csharp/docs/RESOURCES.md +2 -2
- data/tracks/csharp/exercises/Exercises.All.sln +50 -8
- data/tracks/csharp/exercises/Exercises.Default.sln +50 -8
- data/tracks/csharp/exercises/collatz-conjecture/CollatzConjecture.cs +9 -0
- data/tracks/csharp/exercises/collatz-conjecture/CollatzConjecture.csproj +18 -0
- data/tracks/csharp/exercises/collatz-conjecture/CollatzConjectureTest.cs +43 -0
- data/tracks/csharp/exercises/collatz-conjecture/Example.cs +30 -0
- data/tracks/csharp/exercises/collatz-conjecture/README.md +38 -0
- data/tracks/csharp/exercises/diamond/Diamond.cs +1 -1
- data/tracks/csharp/exercises/diamond/Diamond.csproj +3 -1
- data/tracks/csharp/exercises/diamond/DiamondTest.cs +39 -21
- data/tracks/csharp/exercises/diamond/Example.cs +2 -2
- data/tracks/csharp/exercises/diamond/HINTS.md +3 -1
- data/tracks/csharp/exercises/spiral-matrix/Example.cs +40 -0
- data/tracks/csharp/exercises/spiral-matrix/README.md +36 -0
- data/tracks/csharp/exercises/spiral-matrix/SpiralMatrix.cs +9 -0
- data/tracks/csharp/exercises/spiral-matrix/SpiralMatrix.csproj +18 -0
- data/tracks/csharp/exercises/spiral-matrix/SpiralMatrixTest.cs +78 -0
- data/tracks/csharp/exercises/two-fer/Example.cs +16 -0
- data/tracks/csharp/exercises/two-fer/README.md +25 -0
- data/tracks/csharp/exercises/two-fer/TwoFer.cs +9 -0
- data/tracks/csharp/exercises/two-fer/TwoFer.csproj +18 -0
- data/tracks/csharp/exercises/two-fer/TwoFerTest.cs +24 -0
- data/tracks/dart/README.md +1 -1
- data/tracks/dart/docs/EXERCISE_README_INSERT.md +9 -0
- data/tracks/dart/docs/INSTALLATION.md +13 -0
- data/tracks/dart/docs/LEARNING.md +6 -0
- data/tracks/dart/docs/RESOURCES.md +7 -0
- data/tracks/dart/docs/TESTS.md +133 -0
- data/tracks/delphi/docs/ABOUT.md +18 -5
- data/tracks/delphi/docs/Getting_Started_Guide.md +930 -0
- data/tracks/delphi/exercises/hamming/uHammingExample.pas +1 -1
- data/tracks/delphi/exercises/hamming/uHammingTests.pas +15 -15
- data/tracks/ecmascript/.travis.yml +2 -1
- data/tracks/ecmascript/Makefile +19 -8
- data/tracks/ecmascript/config.json +16 -0
- data/tracks/ecmascript/exercises/accumulate/package.json +5 -5
- data/tracks/ecmascript/exercises/acronym/package.json +5 -5
- data/tracks/ecmascript/exercises/all-your-base/package.json +5 -5
- data/tracks/ecmascript/exercises/allergies/package.json +5 -5
- data/tracks/ecmascript/exercises/alphametics/package.json +5 -5
- data/tracks/ecmascript/exercises/anagram/package.json +5 -5
- data/tracks/ecmascript/exercises/atbash-cipher/package.json +5 -5
- data/tracks/ecmascript/exercises/beer-song/package.json +5 -5
- data/tracks/ecmascript/exercises/binary-search-tree/package.json +5 -5
- data/tracks/ecmascript/exercises/binary-search/package.json +5 -5
- data/tracks/ecmascript/exercises/binary/package.json +5 -5
- data/tracks/ecmascript/exercises/bob/package.json +5 -5
- data/tracks/ecmascript/exercises/bracket-push/package.json +5 -5
- data/tracks/ecmascript/exercises/circular-buffer/package.json +5 -5
- data/tracks/ecmascript/exercises/clock/package.json +5 -5
- data/tracks/ecmascript/exercises/connect/package.json +5 -5
- data/tracks/ecmascript/exercises/crypto-square/package.json +5 -5
- data/tracks/ecmascript/exercises/custom-set/package.json +5 -5
- data/tracks/ecmascript/exercises/diamond/package.json +5 -5
- data/tracks/ecmascript/exercises/difference-of-squares/package.json +5 -5
- data/tracks/ecmascript/exercises/diffie-hellman/package.json +5 -5
- data/tracks/ecmascript/exercises/etl/package.json +5 -5
- data/tracks/ecmascript/exercises/flatten-array/package.json +5 -5
- data/tracks/ecmascript/exercises/food-chain/package.json +5 -5
- data/tracks/ecmascript/exercises/gigasecond/package.json +5 -5
- data/tracks/ecmascript/exercises/grade-school/package.json +5 -5
- data/tracks/ecmascript/exercises/grains/package.json +5 -5
- data/tracks/ecmascript/exercises/hamming/package.json +5 -5
- data/tracks/ecmascript/exercises/hello-world/package.json +5 -5
- data/tracks/ecmascript/exercises/hexadecimal/package.json +5 -5
- data/tracks/ecmascript/exercises/isogram/package.json +5 -5
- data/tracks/ecmascript/exercises/kindergarten-garden/package.json +5 -5
- data/tracks/ecmascript/exercises/largest-series-product/package.json +5 -5
- data/tracks/ecmascript/exercises/leap/package.json +5 -5
- data/tracks/ecmascript/exercises/linked-list/package.json +5 -5
- data/tracks/ecmascript/exercises/list-ops/package.json +5 -5
- data/tracks/ecmascript/exercises/luhn/package.json +5 -5
- data/tracks/ecmascript/exercises/matrix/package.json +5 -5
- data/tracks/ecmascript/exercises/meetup/package.json +5 -5
- data/tracks/ecmascript/exercises/minesweeper/package.json +5 -5
- data/tracks/ecmascript/exercises/nth-prime/package.json +5 -5
- data/tracks/ecmascript/exercises/ocr-numbers/package.json +5 -5
- data/tracks/ecmascript/exercises/octal/package.json +5 -5
- data/tracks/ecmascript/exercises/palindrome-products/package.json +5 -5
- data/tracks/ecmascript/exercises/pangram/package.json +5 -5
- data/tracks/ecmascript/exercises/pascals-triangle/package.json +5 -5
- data/tracks/ecmascript/exercises/perfect-numbers/package.json +5 -5
- data/tracks/ecmascript/exercises/phone-number/package.json +5 -5
- data/tracks/ecmascript/exercises/pig-latin/package.json +5 -5
- data/tracks/ecmascript/exercises/prime-factors/package.json +5 -5
- data/tracks/ecmascript/exercises/pythagorean-triplet/package.json +5 -5
- data/tracks/ecmascript/exercises/queen-attack/package.json +5 -5
- data/tracks/ecmascript/exercises/raindrops/package.json +5 -5
- data/tracks/ecmascript/exercises/rna-transcription/package.json +5 -5
- data/tracks/ecmascript/exercises/robot-name/package.json +5 -5
- data/tracks/ecmascript/exercises/robot-simulator/package.json +5 -5
- data/tracks/ecmascript/exercises/roman-numerals/package.json +5 -5
- data/tracks/ecmascript/exercises/run-length-encoding/README.md +59 -0
- data/tracks/ecmascript/exercises/run-length-encoding/example.js +13 -0
- data/tracks/ecmascript/exercises/run-length-encoding/package.json +69 -0
- data/tracks/ecmascript/exercises/run-length-encoding/run-length-encoding.spec.js +59 -0
- data/tracks/ecmascript/exercises/saddle-points/package.json +5 -5
- data/tracks/ecmascript/exercises/say/package.json +5 -5
- data/tracks/ecmascript/exercises/scrabble-score/package.json +5 -5
- data/tracks/ecmascript/exercises/secret-handshake/package.json +5 -5
- data/tracks/ecmascript/exercises/series/package.json +5 -5
- data/tracks/ecmascript/exercises/sieve/package.json +5 -5
- data/tracks/ecmascript/exercises/simple-cipher/package.json +5 -5
- data/tracks/ecmascript/exercises/space-age/package.json +5 -5
- data/tracks/ecmascript/exercises/strain/package.json +5 -5
- data/tracks/ecmascript/exercises/sublist/package.json +5 -5
- data/tracks/ecmascript/exercises/sum-of-multiples/package.json +5 -5
- data/tracks/ecmascript/exercises/triangle/package.json +5 -5
- data/tracks/ecmascript/exercises/trinary/package.json +5 -5
- data/tracks/ecmascript/exercises/twelve-days/package.json +6 -5
- data/tracks/ecmascript/exercises/two-bucket/package.json +5 -5
- data/tracks/ecmascript/exercises/word-count/package.json +5 -5
- data/tracks/ecmascript/exercises/wordy/package.json +5 -5
- data/tracks/ecmascript/package.json +5 -5
- data/tracks/ecmascript/yarn.lock +403 -152
- data/tracks/elixir/docs/ABOUT.md +7 -20
- data/tracks/erlang/docs/ABOUT.md +4 -6
- data/tracks/fsharp/config.json +2 -1
- data/tracks/fsharp/docs/ABOUT.md +6 -2
- data/tracks/gnu-apl/.gitignore +4 -0
- data/tracks/gnu-apl/.travis.yml +5 -0
- data/tracks/gnu-apl/LICENSE +21 -0
- data/tracks/gnu-apl/README.md +67 -0
- data/tracks/gnu-apl/bin/fetch-configlet +32 -0
- data/tracks/gnu-apl/config.json +15 -0
- data/tracks/{scala/exercises/binary-search/src/main/scala/BinarySearch.scala → gnu-apl/config/exercise-readme-insert.md} +0 -0
- data/tracks/gnu-apl/config/exercise-readme.go.tmpl +16 -0
- data/tracks/gnu-apl/config/maintainers.json +6 -0
- data/tracks/gnu-apl/docs/ABOUT.md +0 -0
- data/tracks/gnu-apl/docs/INSTALLATION.md +0 -0
- data/tracks/gnu-apl/docs/LEARNING.md +0 -0
- data/tracks/gnu-apl/docs/RESOURCES.md +0 -0
- data/tracks/gnu-apl/docs/TESTS.md +0 -0
- data/tracks/gnu-apl/img/.keep +0 -0
- data/tracks/go/docs/ABOUT.md +4 -2
- data/tracks/go/exercises/pangram/example.go +1 -1
- data/tracks/go/exercises/pangram/pangram.go +1 -1
- data/tracks/go/exercises/pangram/pangram_test.go +1 -3
- data/tracks/groovy/README.md +2 -0
- data/tracks/groovy/config.json +25 -20
- data/tracks/groovy/docs/ABOUT.md +10 -3
- data/tracks/groovy/exercises/difference-of-squares/DifferenceOfSquares.groovy +19 -0
- data/tracks/groovy/exercises/difference-of-squares/{SquaresSpec.groovy → DifferenceOfSquaresSpec.groovy} +3 -3
- data/tracks/groovy/exercises/difference-of-squares/Example.groovy +1 -1
- data/tracks/groovy/exercises/hamming/Hamming.groovy +7 -0
- data/tracks/groovy/exercises/leap/Example.groovy +2 -2
- data/tracks/groovy/exercises/leap/Leap.groovy +11 -0
- data/tracks/groovy/exercises/leap/LeapSpec.groovy +4 -4
- data/tracks/groovy/exercises/nth-prime/Example.groovy +1 -1
- data/tracks/groovy/exercises/nth-prime/NthPrime.groovy +7 -0
- data/tracks/groovy/exercises/nth-prime/{PrimeSpec.groovy → NthPrimeSpec.groovy} +6 -6
- data/tracks/groovy/exercises/phone-number/PhoneNumber.groovy +17 -0
- data/tracks/groovy/exercises/raindrops/Raindrops.groovy +7 -0
- data/tracks/groovy/exercises/rna-transcription/Example.groovy +1 -1
- data/tracks/groovy/exercises/rna-transcription/RnaTranscription.groovy +7 -0
- data/tracks/groovy/exercises/rna-transcription/{ComplementSpec.groovy → RnaTranscriptionSpec.groovy} +2 -2
- data/tracks/groovy/exercises/robot-name/Example.groovy +2 -2
- data/tracks/groovy/exercises/robot-name/RobotName.groovy +9 -0
- data/tracks/groovy/exercises/robot-name/{RobotSpec.groovy → RobotNameSpec.groovy} +6 -6
- data/tracks/groovy/exercises/roman-numerals/Example.groovy +2 -2
- data/tracks/groovy/exercises/roman-numerals/RomanNumerals.groovy +7 -0
- data/tracks/groovy/exercises/roman-numerals/{RomanSpec.groovy → RomanNumeralsSpec.groovy} +2 -2
- data/tracks/groovy/exercises/word-count/Example.groovy +2 -2
- data/tracks/groovy/exercises/word-count/{Phrase.groovy → WordCount.groovy} +2 -2
- data/tracks/groovy/exercises/word-count/WordCountSpec.groovy +47 -0
- data/tracks/java/config.json +84 -74
- data/tracks/java/docs/ABOUT.md +11 -5
- data/tracks/java/exercises/house/README.md +124 -0
- data/tracks/java/exercises/house/build.gradle +18 -0
- data/tracks/java/exercises/house/src/example/java/House.java +55 -0
- data/tracks/java/exercises/house/src/main/java/.keep +0 -0
- data/tracks/java/exercises/house/src/test/java/HouseTest.java +341 -0
- data/tracks/java/exercises/minesweeper/src/example/java/MinesweeperBoard.java +3 -3
- data/tracks/java/exercises/series/src/test/java/SeriesTest.java +6 -5
- data/tracks/java/exercises/settings.gradle +1 -0
- data/tracks/java/exercises/two-fer/src/test/java/TwoferTest.java +9 -0
- data/tracks/javascript/exercises/circular-buffer/circular-buffer.spec.js +8 -0
- data/tracks/javascript/exercises/simple-cipher/README.md +1 -1
- data/tracks/kotlin/docs/ABOUT.md +7 -10
- data/tracks/lisp/.travis.yml +26 -11
- data/tracks/purescript/docs/ABOUT.md +16 -0
- data/tracks/r/config.json +1 -1
- data/tracks/r/config/maintainers.json +9 -9
- data/tracks/r/docs/ABOUT.md +9 -11
- data/tracks/r/docs/snippet.txt +10 -0
- data/tracks/ruby/docs/ABOUT.md +5 -5
- data/tracks/ruby/exercises/collatz-conjecture/.meta/generator/collatz_conjecture_case.rb +1 -2
- data/tracks/ruby/exercises/space-age/.meta/generator/space_age_case.rb +1 -2
- data/tracks/ruby/exercises/sum-of-multiples/.meta/generator/sum_of_multiples_case.rb +1 -1
- data/tracks/ruby/lib/generator/exercise_case.rb +15 -0
- data/tracks/scala/exercises/alphametics/src/test/scala/AlphameticsTest.scala +42 -28
- data/tracks/scala/exercises/binary-search/example.scala +1 -1
- data/tracks/scala/exercises/binary-search/src/main/scala/.keep +0 -0
- data/tracks/scala/exercises/binary-search/src/test/scala/BinarySearchTest.scala +13 -22
- data/tracks/scala/exercises/bowling/src/main/scala/.keep +0 -0
- data/tracks/scala/exercises/bowling/src/test/scala/BowlingSuite.scala +30 -17
- data/tracks/scala/exercises/change/src/test/scala/ChangeTest.scala +14 -4
- data/tracks/scala/exercises/custom-set/src/test/scala/CustomSetTest.scala +6 -4
- data/tracks/scala/exercises/food-chain/example.scala +4 -2
- data/tracks/scala/exercises/food-chain/src/test/scala/FoodChainTest.scala +170 -59
- data/tracks/scala/exercises/luhn/example.scala +9 -21
- data/tracks/scala/exercises/luhn/src/test/scala/LuhnTest.scala +46 -10
- data/tracks/scala/testgen/src/main/scala/AlphametricsTestGenerator.scala +42 -0
- data/tracks/scala/testgen/src/main/scala/BinarySearchTestGenerator.scala +32 -42
- data/tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala +22 -7
- data/tracks/scala/testgen/src/main/scala/ChangeTestGenerator.scala +37 -0
- data/tracks/scala/testgen/src/main/scala/CustomSetTestGenerator.scala +25 -20
- data/tracks/scala/testgen/src/main/scala/FoodChainTestGenerator.scala +13 -2
- data/tracks/scala/testgen/src/main/scala/LuhnTestGenerator.scala +15 -0
- data/tracks/scala/testgen/src/main/scala/TestBuilder.scala +10 -0
- data/tracks/sml/.travis.yml +9 -2
- data/tracks/sml/Makefile +42 -0
- data/tracks/sml/docs/EXERCISE_README_INSERT.md +21 -5
- data/tracks/sml/docs/RESOURCES.md +1 -1
- data/tracks/sml/docs/TESTS.md +2 -2
- metadata +67 -17
- data/tracks/bash/exercises/word-count/README.md +0 -24
- data/tracks/bash/exercises/word-count/example.awk +0 -12
- data/tracks/bash/exercises/word-count/example.sh +0 -21
- data/tracks/dart/.github/PULL_REQUEST_TEMPLATE.md +0 -23
- data/tracks/ecmascript/.babelrc +0 -3
- data/tracks/groovy/exercises/roman-numerals/Roman.groovy +0 -33
- data/tracks/groovy/exercises/word-count/PhraseSpec.groovy +0 -47
- data/tracks/scala/exercises/bowling/src/main/scala/Bowling.scala +0 -11
data/tracks/dart/README.md
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
## Dart
|
2
|
+
* [Install Dart](https://www.dartlang.org/install)
|
3
|
+
* Add the Dart SDK to your path.
|
4
|
+
* From a new command window, type `dart --version` to verify that Dart is now available.
|
5
|
+
|
6
|
+
## Dart Plugin for your IDE or Editor
|
7
|
+
* If you are using an IDE or an editor, [install and configure the Dart plugin](https://www.dartlang.org/tools).
|
8
|
+
|
9
|
+
## Setting up Dart on your IDE
|
10
|
+
* Setup the Dart SDK and Dartium by going in your IDE's settings and add the Dart SDK
|
11
|
+
* Note: For HomeBrew Mac users the Dart SDK and Dartium locations are:
|
12
|
+
* SDK directory: HOMEBREW_INSTALL/dart/1.24.2/libexec
|
13
|
+
* Dartium: HOMEBREW_INSTALL/dart/1.24.2/Chromium.app
|
@@ -0,0 +1,6 @@
|
|
1
|
+
## Recommended Learning Resources
|
2
|
+
* [Dart Language Overview](https://www.dartlang.org/guides/language/language-tour)
|
3
|
+
* [Getting Started](https://www.dartlang.org/tutorials/dart-vm/get-started)
|
4
|
+
* [Make a command line app](https://www.dartlang.org/tutorials/dart-vm/cmdline)
|
5
|
+
* [Free Programming Books - Dart](https://github.com/EbookFoundation/free-programming-books/blob/master/free-programming-books.md#dart)
|
6
|
+
* [Dart Testing Overview](https://www.dartlang.org/guides/testing)
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Useful Resources
|
2
|
+
* [Dart API Documentation](https://api.dartlang.org/)
|
3
|
+
* [Dart Gitter Chat](https://gitter.im/dart-lang/home)
|
4
|
+
* [Community Information](https://www.dartlang.org/community)
|
5
|
+
* [Stack Overflow](http://stackoverflow.com/questions/tagged/dart)
|
6
|
+
* [Dart Subreddit](https://www.reddit.com/r/dartlang)
|
7
|
+
* [Free Programming Books - Dart](https://github.com/EbookFoundation/free-programming-books/blob/master/free-programming-books.md#dart)
|
data/tracks/dart/docs/TESTS.md
CHANGED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Running the Tests
|
2
|
+
|
3
|
+
Choose your operating system:
|
4
|
+
|
5
|
+
* [Windows](#windows)
|
6
|
+
* [Mac OS X](#mac-os-x)
|
7
|
+
* [Linux](#linux)
|
8
|
+
|
9
|
+
----
|
10
|
+
|
11
|
+
# Windows
|
12
|
+
|
13
|
+
1. Open a Command Prompt.
|
14
|
+
|
15
|
+
2. Get the first exercise:
|
16
|
+
|
17
|
+
```batchfile
|
18
|
+
exercism fetch dart
|
19
|
+
|
20
|
+
Not Submitted: 1 problem
|
21
|
+
dart (Hello World) C:\Users\JohnDoe\exercism\dart\hello-world
|
22
|
+
|
23
|
+
New: 1 problem
|
24
|
+
dart (Hello World) C:\Users\JohnDoe\exercism\dart\hello-world
|
25
|
+
|
26
|
+
unchanged: 0, updated: 0, new: 1
|
27
|
+
```
|
28
|
+
|
29
|
+
3. Change directory into the exercism:
|
30
|
+
|
31
|
+
```batchfile
|
32
|
+
C:\Users\JohnDoe>cd C:\Users\JohnDoe\exercism\dart\hello-world
|
33
|
+
```
|
34
|
+
|
35
|
+
4. Download the dependent packages:
|
36
|
+
|
37
|
+
```batchfile
|
38
|
+
C:\Users\JohnDoe>pub get
|
39
|
+
```
|
40
|
+
|
41
|
+
5. Run the tests:
|
42
|
+
|
43
|
+
```batchfile
|
44
|
+
C:\Users\JohnDoe>pub run test
|
45
|
+
```
|
46
|
+
*(Don't worry about the tests failing, at first, this is how you begin each exercise.)*
|
47
|
+
|
48
|
+
6. Solve the exercise. Find and work through the `README.md` guide ([view on GitHub](https://github.com/exercism/dart/blob/master/exercises/hello-world/README.md)).
|
49
|
+
|
50
|
+
|
51
|
+
Good luck! Have fun!
|
52
|
+
|
53
|
+
If you get stuck, at any point, don't forget to reach out for [help](http://exercism.io/languages/dart/help).
|
54
|
+
|
55
|
+
----
|
56
|
+
|
57
|
+
# Mac OS X
|
58
|
+
|
59
|
+
1. In the terminal window, get the first exercise:
|
60
|
+
|
61
|
+
```batchfile
|
62
|
+
$ exercism fetch dart
|
63
|
+
|
64
|
+
New: 1 problem
|
65
|
+
Dart (Etl) /Users/johndoe/exercism/dart/hello-world
|
66
|
+
|
67
|
+
unchanged: 0, updated: 0, new: 1
|
68
|
+
```
|
69
|
+
|
70
|
+
2. Change directory into the exercise:
|
71
|
+
|
72
|
+
```batchfile
|
73
|
+
$ cd /Users/johndoe/exercism/dart/hello-world
|
74
|
+
```
|
75
|
+
|
76
|
+
3. Download the dependent packages:
|
77
|
+
|
78
|
+
```batchfile
|
79
|
+
$ pub get
|
80
|
+
```
|
81
|
+
|
82
|
+
4. Run the tests:
|
83
|
+
|
84
|
+
```batchfile
|
85
|
+
$ pub run test
|
86
|
+
```
|
87
|
+
*(Don't worry about the tests failing, at first, this is how you begin each exercise.)*
|
88
|
+
|
89
|
+
6. Solve the exercise. Find and work through the `README.md` guide ([view on GitHub](https://github.com/exercism/dart/blob/master/exercises/hello-world/README.md)).
|
90
|
+
|
91
|
+
Good luck! Have fun!
|
92
|
+
|
93
|
+
If you get stuck, at any point, don't forget to reach out for [help](http://exercism.io/languages/dart/help).
|
94
|
+
|
95
|
+
----
|
96
|
+
|
97
|
+
# Linux
|
98
|
+
|
99
|
+
1. In the terminal window, get the first exercise:
|
100
|
+
|
101
|
+
```batchfile
|
102
|
+
$ exercism fetch dart
|
103
|
+
|
104
|
+
New: 1 problem
|
105
|
+
Dart (Etl) /home/johndoe/exercism/dart/hello-world
|
106
|
+
|
107
|
+
unchanged: 0, updated: 0, new: 1
|
108
|
+
```
|
109
|
+
|
110
|
+
2. Change directory into the exercise:
|
111
|
+
|
112
|
+
```batchfile
|
113
|
+
$ cd /home/johndoe/exercism/dart/hello-world
|
114
|
+
```
|
115
|
+
|
116
|
+
3. Download the dependent packages:
|
117
|
+
|
118
|
+
```batchfile
|
119
|
+
$ pub get
|
120
|
+
```
|
121
|
+
|
122
|
+
4. Run the tests:
|
123
|
+
|
124
|
+
```batchfile
|
125
|
+
$ pub run test
|
126
|
+
```
|
127
|
+
*(Don't worry about the tests failing, at first, this is how you begin each exercise.)*
|
128
|
+
|
129
|
+
6. Solve the exercise. Find and work through the `README.md` guide ([view on GitHub](https://github.com/exercism/dart/blob/master/exercises/hello-world/README.md)).
|
130
|
+
|
131
|
+
Good luck! Have fun!
|
132
|
+
|
133
|
+
If you get stuck, at any point, don't forget to reach out for [help](http://exercism.io/languages/dart/help).
|
data/tracks/delphi/docs/ABOUT.md
CHANGED
@@ -1,10 +1,23 @@
|
|
1
|
-
|
2
|
-
*From Wikipedia, the free encyclopedia*
|
1
|
+
**Delphi** is an Object Pascal based programming language for desktop, mobile, web, and console software development. Delphi was the [code name](https://edn.embarcadero.com/article/20396) for a yet unnamed product during its initial development prior to its debut in 1995.
|
3
2
|
|
4
|
-
|
3
|
+
Delphi was originally developed by [Borland](https://en.wikipedia.org/wiki/Borland), lead by Anders Heilsberg as a [RAD](https://en.wikipedia.org/wiki/Rapid_application_development) tool for Windows as the successor of [Turbo Pascal](https://en.wikipedia.org/wiki/Turbo_Pascal). Delphi added full object-orientation to the existing language, and since then the language has grown and supports many other modern language features, including:
|
4
|
+
|
5
|
+
- **Generics**
|
6
|
+
- **Anonymous Methods (Closures)**
|
7
|
+
- **Dynamic Constructs (Attributes)**
|
8
|
+
- **Abstract Methods**
|
9
|
+
- **Inbuilt string types**
|
10
|
+
- **Native COM support**
|
11
|
+
- **RTTI**
|
5
12
|
|
6
|
-
|
13
|
+
Like its predecessor Turbo Pascal, at the core of Delphi is a native code compiler. Turbo Pascal provided an ideal balance between the speed of
|
14
|
+
programming and the speed of the resulting programs, clarity of syntax and power
|
15
|
+
of expression, these tenets remain true today in Delphi. More recent versions of Delphi are able to compile native code for many different platforms:
|
7
16
|
|
8
|
-
|
17
|
+
- **Windows (x86 and x64)**
|
18
|
+
- **OS X (32 bit only)**
|
19
|
+
- **iOS (32 and 64 bit)**
|
20
|
+
- **Android**
|
21
|
+
- **Linux (64 bit only)**
|
9
22
|
|
10
23
|
In 2006, Borland’s developer tools section were transferred from Borland to a wholly owned subsidiary known as [CodeGear](https://en.wikipedia.org/wiki/CodeGear), which was sold to [Embarcadero Technologies](https://en.wikipedia.org/wiki/Embarcadero_Technologies) in 2008. In 2015, Embarcadero was purchased by Idera, but the Embarcadero mark was retained for the developer tools division.
|
@@ -0,0 +1,930 @@
|
|
1
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
2
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
3
|
+
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
4
|
+
|
5
|
+
- [Object Pascal Style Guide](#object-pascal-style-guide)
|
6
|
+
- [Preface](#preface)
|
7
|
+
- [Introduction](#introduction)
|
8
|
+
- [Background](#background)
|
9
|
+
- [Acknowledgments](#acknowledgments)
|
10
|
+
- [Source Files](#source-files)
|
11
|
+
- [Source-File Naming](#source-file-naming)
|
12
|
+
- [Source-File Organization](#source-file-organization)
|
13
|
+
- [Copyright/ID block comment](#copyrightid-block-comment)
|
14
|
+
- [Unit declaration](#unit-declaration)
|
15
|
+
- [uses declarations](#uses-declarations)
|
16
|
+
- [class/interface declarations](#classinterface-declarations)
|
17
|
+
- [Naming Conventions](#naming-conventions)
|
18
|
+
- [Unit Naming](#unit-naming)
|
19
|
+
- [Class/Interface Naming](#classinterface-naming)
|
20
|
+
- [Field Naming](#field-naming)
|
21
|
+
- [Method Naming](#method-naming)
|
22
|
+
- [Local Variable Naming](#local-variable-naming)
|
23
|
+
- [Reserved Words](#reserved-words)
|
24
|
+
- [Type Declarations](#type-declarations)
|
25
|
+
- [White Space Usage](#white-space-usage)
|
26
|
+
- [Blank Lines](#blank-lines)
|
27
|
+
- [Blank Spaces](#blank-spaces)
|
28
|
+
- [Blanks should not be used:](#blanks-should-not-be-used)
|
29
|
+
- [Indentation](#indentation)
|
30
|
+
- [Continuation Lines](#continuation-lines)
|
31
|
+
- [Comments](#comments)
|
32
|
+
- [Block Comments](#block-comments)
|
33
|
+
- [Single-Line Comments](#single-line-comments)
|
34
|
+
- [Classes](#classes)
|
35
|
+
- [Class Body Organization](#class-body-organization)
|
36
|
+
- [Access levels](#access-levels)
|
37
|
+
- [Constructor declarations](#constructor-declarations)
|
38
|
+
- [Method Declarations](#method-declarations)
|
39
|
+
- [Interfaces](#interfaces)
|
40
|
+
- [Interface Body Organization](#interface-body-organization)
|
41
|
+
- [Statements](#statements)
|
42
|
+
- [Simple](#simple)
|
43
|
+
- [Compound](#compound)
|
44
|
+
- [Assignment and expression](#assignment-and-expression)
|
45
|
+
- [Local variable declarations](#local-variable-declarations)
|
46
|
+
- [Array declarations](#array-declarations)
|
47
|
+
- [if then](#if-then)
|
48
|
+
- [for do](#for-do)
|
49
|
+
- [while do](#while-do)
|
50
|
+
- [repeat until](#repeat-until)
|
51
|
+
- [case](#case)
|
52
|
+
- [try](#try)
|
53
|
+
|
54
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
55
|
+
|
56
|
+
Object Pascal Style Guide
|
57
|
+
-----------------------------------------------------------------
|
58
|
+
|
59
|
+
Abstract: This article documents a standard style for formatting Delphi code. It is based on the conventions developed by the Delphi team.
|
60
|
+
|
61
|
+
This document is an excerpt from the [original guide](http://edn.embarcadero.com/article/10280) authored by Charles Calvert. Dated portions of the original document have been left out as they are not pertitent to the intended audience.
|
62
|
+
|
63
|
+
Preface
|
64
|
+
-----------------------------------------------
|
65
|
+
|
66
|
+
This article documents a standard style for formatting Delphi code. It is based on the conventions developed by the Delphi team.
|
67
|
+
|
68
|
+
Object Pascal is a beautifully designed language. One of its great virtues is its readability. These standards are designed to enhance that readability of Object Pascal code. When developers follow the simple conventions laid out in this guide, they will be promoting standards that benefit all Delphi developers by using a uniform style that is easy to read. Efforts to enforce these standards will increase the value of a developer's source code, particularly during maintenance and debugging cycles.
|
69
|
+
|
70
|
+
It goes without saying that these are conventions based primarily on matters of taste. Though we believe in, and admire the style promoted in these pages, we support them not necessarily because we believe they are right and others are wrong, but because we believe in the efficacy of having a standard which most developers follow. The human mind adapts to standards, and finds ways to quickly recognize familiar patterns, thereby assimilating meaning quickly and effortlessly. It is the desire to create a standard that will make reading code as simple as possible for the largest number of people that is behind this effort. If at first our guidelines seem strange to you, we ask you to try them for awhile, and then we are sure you will grow used to them over time.
|
71
|
+
|
72
|
+
Introduction
|
73
|
+
----------------------------------------------------
|
74
|
+
|
75
|
+
This document is not an attempt to define a grammar for the Object Pascal language. For instance, it is illegal to place a semicolon before an else statement; the compiler simply won't let you do it. As a result, I do not lay that rule out in this style guide. This document is meant to define the proper course of action in places where the language gives you a choice. I usually remain mute on matters that can only be handled one way.
|
76
|
+
|
77
|
+
### Background
|
78
|
+
|
79
|
+
The guidelines presented here are based on thepublic portions of the Delphi source. The Delphi source should follow these guidelines precisely. If you find cases where the source varies from these guidelines, then these guidelines, and not the errant source code, should be considered your standard. Nevertheless, you should use the source as a supplement to these guidelines, at least so far as it can help you get a general feel for how your code should look.
|
80
|
+
|
81
|
+
### Acknowledgments
|
82
|
+
|
83
|
+
The format of this document and some of its language is based on work done to define a style standard for the Java language. Java has had no influence on the rules for formatting Object Pascal source, but documents found on the Sun web site formed the basis for this document. In particular the style and format of this document were heavily influenced by "A Coding Style Guide for Java WorkShop and Java Studio Programming" by Achut Reddy. That document can be found at the following URL: <http://www.sun.com/workshop/java/wp-coding>
|
84
|
+
|
85
|
+
The Delphi team also contributed heavily to the generation of this document, and indeed, it would not have been possible to create it without their help.
|
86
|
+
|
87
|
+
Source Files
|
88
|
+
----------------------------------------------------
|
89
|
+
|
90
|
+
Object Pascal source is divided up primarily into units and Delphi Project files, which both follow the same conventions. A Delphi Project file has a `DPR` extension. It is the main source file for a project. Any units used in the project will have a `PAS` extension. Additional files, such as batch files, html files, or DLLs, may play a role in a project, but this paper only treats the formatting of `DPR` and `PAS` files.
|
91
|
+
|
92
|
+
### Source-File Naming
|
93
|
+
|
94
|
+
Object Pascal supports long file names. If you are appending several words to create a single name, then it is best to use capital letters for each word in the name: MyFile.pas. This is known as InfixCaps, or Camel Caps. Extensions should be in lower case. For historical reasons, the Delphi source itself often confines itself to 8:3 naming patterns, but developers no longer need feel constrained by those limits, even if turning in source that might be used by the Delphi team.
|
95
|
+
|
96
|
+
If you are translating a C/C++ header file, then your Pascal header translation will usually have the same name as the file you are translating, except it should have a `PAS` extension. For instance, `Windows.h` would become `Windows.pas`. If the rules of Pascal grammar force you to combine multiple header files into a single unit, then use the name of the base unit into which you are folding the other files. For instance, if you fold `WinBase.h` into `Windows.h`, then call the resulting file Windows.pas.
|
97
|
+
|
98
|
+
### Source-File Organization
|
99
|
+
|
100
|
+
All Object Pascal units should contain the following elements in the following order: Copyright/ID block comment Unit Name Interface section Implementation A closing end and a period. At least one blank line should separate each of these elements.
|
101
|
+
|
102
|
+
Additional elements can be structured in the order you find most appropriate, except that the top of the file should always list the copyright first, the unit name second, then any conditional defines, compiler directives or include statements, then the uses clause:
|
103
|
+
|
104
|
+
``` example
|
105
|
+
{*******************************************************}
|
106
|
+
{ }
|
107
|
+
{ Embarcadero Delphi Visual Component Library }
|
108
|
+
{ }
|
109
|
+
{ Copyright (c) Idera Corporation }
|
110
|
+
{ }
|
111
|
+
{*******************************************************}
|
112
|
+
|
113
|
+
unit Buttons;
|
114
|
+
|
115
|
+
{$S-,W-,R-}
|
116
|
+
{$C PRELOAD}
|
117
|
+
|
118
|
+
interface
|
119
|
+
|
120
|
+
uses
|
121
|
+
Windows, Messages, Classes,
|
122
|
+
Controls, Forms, Graphics,
|
123
|
+
StdCtrls, ExtCtrls, CommCtrl;
|
124
|
+
|
125
|
+
It does not matter if you place a type section before a const section,
|
126
|
+
or if you mix type and const sections up in any order you choose.
|
127
|
+
|
128
|
+
The implementation should list the word implementation first, then the
|
129
|
+
uses clause, then any include statements or other directives:
|
130
|
+
|
131
|
+
implementation
|
132
|
+
|
133
|
+
uses
|
134
|
+
Consts, SysUtils, ActnList,
|
135
|
+
ImgList;
|
136
|
+
|
137
|
+
{$R BUTTONS.RES}
|
138
|
+
```
|
139
|
+
|
140
|
+
#### Copyright/ID block comment
|
141
|
+
|
142
|
+
Every source file should start with a block comment containing version information and a standard copyright notice. The version information should be in the following format:
|
143
|
+
|
144
|
+
``` example
|
145
|
+
{*******************************************************}
|
146
|
+
{ }
|
147
|
+
{ Widgets Galore }
|
148
|
+
{ }
|
149
|
+
{ Copyright (c) 1995,98 Your Company }
|
150
|
+
{ }
|
151
|
+
{*******************************************************}
|
152
|
+
```
|
153
|
+
|
154
|
+
The copyright notice should contain at least the following line: Copyright (c) yearlist CopyrightHolder. If you are a third party creating a file for use by Borland, you may add your name at the bottom of the copyright notice:
|
155
|
+
|
156
|
+
``` example
|
157
|
+
{*******************************************************}
|
158
|
+
{ }
|
159
|
+
{ Borland Delphi Visual Component Library }
|
160
|
+
{ Copyright (c) 1995,99 Borland International }
|
161
|
+
{ Created by Project JEDI }
|
162
|
+
{ }
|
163
|
+
{*******************************************************}
|
164
|
+
```
|
165
|
+
|
166
|
+
#### Unit declaration
|
167
|
+
|
168
|
+
Every source file should contain a unit declaration. The word `unit` is a reserved word, so it should be in lower case. The name of the unit should be in mixed upper and lowercase, and must be the same as the name used by the operating system's file system. Example:
|
169
|
+
|
170
|
+
``` example
|
171
|
+
unit MyUnit;
|
172
|
+
```
|
173
|
+
|
174
|
+
This unit would be called `MyUnit.pas` when an entry is placed in the file system.
|
175
|
+
|
176
|
+
#### uses declarations
|
177
|
+
|
178
|
+
Inside units, a uses declaration should begin with the word `uses`, in lowercase. Add the names of the units, following the capitalization conventions used in the declaration found inside the units:
|
179
|
+
|
180
|
+
``` example
|
181
|
+
uses MyUnit;
|
182
|
+
```
|
183
|
+
|
184
|
+
Each unit must be separated from its neighbor by a comma, and the last unit should have a semicolon after it:
|
185
|
+
|
186
|
+
``` example
|
187
|
+
uses
|
188
|
+
Windows, SysUtils, Classes, Graphics, Controls, Forms,
|
189
|
+
TypInfo;
|
190
|
+
```
|
191
|
+
|
192
|
+
It is correct to start the uses clause on the next line, as in the previous example, or you may start the list of units on the same line:
|
193
|
+
|
194
|
+
``` example
|
195
|
+
uses Windows, SysUtils, Classes, Graphics, Controls, Forms,
|
196
|
+
TypInfo;
|
197
|
+
```
|
198
|
+
|
199
|
+
You may format the list of units in your uses clause so that they wrap just shy of 80 characters, or so that one unit appears on each line.
|
200
|
+
|
201
|
+
#### class/interface declarations
|
202
|
+
|
203
|
+
A class declaration begins with two spaces, followed by an identifier prefaced by a capital `T`. Identifiers should begin with a capital letter, and should have capital letters for each embedded word (InfixCaps). Never use tab characters in your Object Pascal source.
|
204
|
+
|
205
|
+
Example:
|
206
|
+
|
207
|
+
``` example
|
208
|
+
TMyClass
|
209
|
+
```
|
210
|
+
|
211
|
+
Follow the identifier with a space, then an equals sign, then the word class, all in lower case:
|
212
|
+
|
213
|
+
``` example
|
214
|
+
TMyClass = class
|
215
|
+
```
|
216
|
+
|
217
|
+
If you want to specify the ancestor for a class, add a parenthesis, the name of the ancestor class, and closing parenthesis:
|
218
|
+
|
219
|
+
``` example
|
220
|
+
TMyClass = class(TObject)
|
221
|
+
```
|
222
|
+
|
223
|
+
Scoping directives should be two spaces in from the margin, and declared in the order shown in this example:
|
224
|
+
|
225
|
+
``` example
|
226
|
+
TMyClass = class(TObject)
|
227
|
+
private
|
228
|
+
protected
|
229
|
+
public
|
230
|
+
published
|
231
|
+
end;
|
232
|
+
```
|
233
|
+
|
234
|
+
Data should always be declared only in the `private` section, and its identifier should be prefaced by an `F`. All type declarations should be four spaces in from the margin:
|
235
|
+
|
236
|
+
``` example
|
237
|
+
TMyClass = class(TObject)
|
238
|
+
private
|
239
|
+
FMyData: Integer;
|
240
|
+
function GetData: Integer;
|
241
|
+
procedure SetData(Value: Integer);
|
242
|
+
public
|
243
|
+
published
|
244
|
+
property MyData: Integer read GetData write SetData;
|
245
|
+
end;
|
246
|
+
```
|
247
|
+
|
248
|
+
Interfaces follow the same rules as class declarations, except you should omit any scoping directives or private data, and should use the word interface rather than class.
|
249
|
+
|
250
|
+
Naming Conventions
|
251
|
+
----------------------------------------------------------
|
252
|
+
|
253
|
+
Except for reserved words and directives, which are in all lowercase, all Pascal identifiers should use InfixCaps, which means the first letter should be a capital, and any embedded words in an identifier should be in caps, as well as any acronym that is embedded:
|
254
|
+
|
255
|
+
`MyIdentifier` `MyFTPClass`
|
256
|
+
|
257
|
+
The major exception to this rule is in the case of header translations, which should always follow the conventions used in the header. For instance, write `WM_LBUTTONDOWN`, not `wm_LButtonDown`.
|
258
|
+
|
259
|
+
Except in header translations, do not use underscores to separate words. Class names should be nouns or noun phrases. Interface or class names depend on the salient purpose of the interface.
|
260
|
+
|
261
|
+
GOOD type names:
|
262
|
+
|
263
|
+
``` example
|
264
|
+
AddressForm, ArrayIndexOutOfBoundsException
|
265
|
+
```
|
266
|
+
|
267
|
+
BAD type names:
|
268
|
+
|
269
|
+
``` example
|
270
|
+
ManageLayout // verb phrase
|
271
|
+
delphi_is_new_to_me // underscores
|
272
|
+
```
|
273
|
+
|
274
|
+
### Unit Naming
|
275
|
+
|
276
|
+
Use InfixCaps, as described at the beginning of this section. See also the section on unit declarations.
|
277
|
+
|
278
|
+
### Class/Interface Naming
|
279
|
+
|
280
|
+
Use InfixCaps, as described at the beginning of this section. Begin each type declaration with a capital `T`:
|
281
|
+
|
282
|
+
`TMyType`
|
283
|
+
|
284
|
+
See also the section on class/interface declarations.
|
285
|
+
|
286
|
+
### Field Naming
|
287
|
+
|
288
|
+
Use InfixCaps, as described at the beginning of this section. Begin each type declaration with a capital `F`, and declare all data types in the `private` section, using properties or getters and setters to provide public access. For example, use the name `GetSomething` to name a function returning an internal field value and use `SetSomething` to name a procedure setting that value.
|
289
|
+
|
290
|
+
Do not use all caps for const declarations except where required in header translations.
|
291
|
+
|
292
|
+
Delphi is created in California, so we discourage the use of notation, except where required in header translations:
|
293
|
+
|
294
|
+
CORRECT
|
295
|
+
|
296
|
+
`FMyString: string;`
|
297
|
+
|
298
|
+
INCORRECT
|
299
|
+
|
300
|
+
`lpstrMyString: string;`
|
301
|
+
|
302
|
+
The exception to the Hungarian notation rule is in enumerated types.
|
303
|
+
|
304
|
+
``` example
|
305
|
+
TBitBtnKind = (bkCustom, bkOK, bkCancel, bkHelp,
|
306
|
+
bkYes, bkNo, bkClose, bkAbort, bkRetry,
|
307
|
+
bkIgnore, bkAll);
|
308
|
+
```
|
309
|
+
|
310
|
+
In this case the letters `bk` are inserted before each element of this enumeration. `bk` stands for `ButtonKind`.
|
311
|
+
|
312
|
+
When thinking about naming conventions, consider that one-character field names should be avoided except for temporary and looping variables.
|
313
|
+
|
314
|
+
Avoid variable `l` ("el") because it is hard to distinguish it from `1` ("one") on some printers and displays.
|
315
|
+
|
316
|
+
### Method Naming
|
317
|
+
|
318
|
+
Method names should use the InfixCaps style. Start with a capital letter, and capitalize the first letter of any subsequent word in the name, as well as any letters that are part of an acronym. All other characters in the name are lower case. Do not use underscores to separate words. Note that this is identical to the naming convention for non-constant fields; however it should always be easy to distinguish the two from context. Method names should be imperative verbs or verb phrases.
|
319
|
+
|
320
|
+
Examples:
|
321
|
+
|
322
|
+
GOOD method names:
|
323
|
+
|
324
|
+
``` example
|
325
|
+
ShowStatus, DrawCircle, AddLayoutComponent
|
326
|
+
```
|
327
|
+
|
328
|
+
BAD method names:
|
329
|
+
|
330
|
+
``` example
|
331
|
+
MouseButton // noun phrase; doesn't describe function
|
332
|
+
drawCircle // starts with lower-case letter
|
333
|
+
add_layout_component // underscores
|
334
|
+
|
335
|
+
// The function of this method is unclear. Does
|
336
|
+
// it start the server running (better: StartServer),
|
337
|
+
// or test whether or not it is running
|
338
|
+
// (better: IsServerRunning)?
|
339
|
+
ServerRunning // verb phrase, but not imperative
|
340
|
+
```
|
341
|
+
|
342
|
+
A method to get or set some property of the class should be called `GetProperty` or `SetProperty` respectively, where `Property` is the name of the property.
|
343
|
+
|
344
|
+
Examples:
|
345
|
+
|
346
|
+
`GetHeight, SetHeight`
|
347
|
+
|
348
|
+
A method to test some boolean property of the class should be called `IsVisible`, where `Visible` is the name of the property.
|
349
|
+
|
350
|
+
Examples:
|
351
|
+
|
352
|
+
`IsResizable, IsVisible`
|
353
|
+
|
354
|
+
### Local Variable Naming
|
355
|
+
|
356
|
+
Local variables follow the same naming rules as field names, except you omit the initial `F`, since this is not a Field of an object. (see section ).
|
357
|
+
|
358
|
+
### Reserved Words
|
359
|
+
|
360
|
+
Reserved words and directives should be all lowercase. This can be a bit confusing at times. For instance types such as `Integer` are just identifiers, and appear with a first cap. Strings, however, are declared with the reserved word string, which should be all lowercase.
|
361
|
+
|
362
|
+
### Type Declarations
|
363
|
+
|
364
|
+
All type declarations should begin with the letter `T`, and should follow the same capitalization specification laid out in the beginning of this section, or in the section on class declarations.
|
365
|
+
|
366
|
+
White Space Usage
|
367
|
+
---------------------------------------------------------
|
368
|
+
|
369
|
+
### Blank Lines
|
370
|
+
|
371
|
+
Blank lines can improve readability by grouping sections of the code that are logically related. A blank line should also be used in the following places:
|
372
|
+
|
373
|
+
After the copyright block comment, package declaration, and import section.
|
374
|
+
|
375
|
+
Between class declarations.
|
376
|
+
|
377
|
+
Between method declarations.
|
378
|
+
|
379
|
+
### Blank Spaces
|
380
|
+
|
381
|
+
Object Pascal is a very clean, easy to read language. In general, you don't need to add a lot of spaces in your code to break up lines. The next few sections give you some guidelines to follow when placing spaces in your code.
|
382
|
+
|
383
|
+
#### Blanks should not be used:
|
384
|
+
|
385
|
+
- Between a method name and its opening parenthesis.
|
386
|
+
- Before or after a .(dot) operator.
|
387
|
+
- Between a unary operator and its operand.
|
388
|
+
- Between a cast and the expression being cast.
|
389
|
+
- After an opening parenthesis or before a closing parenthesis.
|
390
|
+
- After an opening square bracket \[ or before a closing square bracket \].
|
391
|
+
- Before a semicolon.
|
392
|
+
|
393
|
+
Examples of correct usage:
|
394
|
+
|
395
|
+
``` example
|
396
|
+
function TMyClass.MyFunc(var Value: Integer);
|
397
|
+
MyPointer := @MyRecord;
|
398
|
+
MyClass := TMyClass(MyPointer);
|
399
|
+
MyInteger := MyIntegerArray[5];
|
400
|
+
```
|
401
|
+
|
402
|
+
Examples of incorrect usage:
|
403
|
+
|
404
|
+
``` example
|
405
|
+
function TMyClass.MyFunc( var Value: Integer ) ;
|
406
|
+
MyPointer := @ MyRecord;
|
407
|
+
MyClass := TMyClass ( MyPointer ) ;
|
408
|
+
MyInteger := MyIntegerArray [ 5 ] ;
|
409
|
+
```
|
410
|
+
|
411
|
+
### Indentation
|
412
|
+
|
413
|
+
You should always indent two spaces for all indentation levels. In other words, the first level of indentation is two spaces, the second level four spaces, the third level 6 spaces, etc. Never use tab characters.
|
414
|
+
|
415
|
+
There are few exceptions. The reserved words `unit`, `users`, `type`, `interface`, `implementation`, `initialization` and `finalization` should always be flush with the margin. The final `end` statement at the end of a unit should be flush with the margin. In the project file, the word `program`, and the main `begin` and `end` block should all be flush with the margin. The code inside the `begin..end` block, should be indented at least two spaces.
|
416
|
+
|
417
|
+
### Continuation Lines
|
418
|
+
|
419
|
+
Lines should be limited to 80 columns. Lines longer than 80 columns should be broken into one or more continuation lines, as needed. All the continuation lines should be aligned and indented from the first line of the statement, and indented two characters. Always place begin statements on their own line.
|
420
|
+
|
421
|
+
Examples:
|
422
|
+
|
423
|
+
``` example
|
424
|
+
// CORRECT
|
425
|
+
|
426
|
+
function CreateWindowEx(dwExStyle: DWORD;
|
427
|
+
lpClassName: PChar; lpWindowName: PChar;
|
428
|
+
dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
|
429
|
+
hWndParent: HWND; hMenu: HMENU; hInstance: HINST;
|
430
|
+
lpParam: Pointer): HWND; stdcall;
|
431
|
+
|
432
|
+
// CORRECT
|
433
|
+
|
434
|
+
if ((X = Y) or (Y = X) or
|
435
|
+
(Z = P) or (F = J) then
|
436
|
+
begin
|
437
|
+
S := J;
|
438
|
+
end;
|
439
|
+
```
|
440
|
+
|
441
|
+
Never wrap a line between a parameter and its type, unless it is a comma separated list, then wrap at least before the last parameter so the type name follows to the next line. The colon for all variable declarations contains no whitespace between it and the variable. There should be a single space following the colon before the type name:
|
442
|
+
|
443
|
+
``` example
|
444
|
+
// CORRECT
|
445
|
+
|
446
|
+
procedure Foo(Param1: Integer; Param2: Integer);
|
447
|
+
|
448
|
+
// INCORRECT
|
449
|
+
|
450
|
+
procedure Foo( Param :Integer; Param2:Integer );
|
451
|
+
```
|
452
|
+
|
453
|
+
A continuation line should never start with a binary operator.\[???\] Avoid breaking a line where normally no white space appears, such as between a method name and its opening parenthesis, or between an array name and its opening square bracket. If you must break under these circumstances, then one viable place to begin is after the opening parenthesis that follows a method name. Never place a begin statement on the same line with any other code.
|
454
|
+
|
455
|
+
Examples:
|
456
|
+
|
457
|
+
``` example
|
458
|
+
// INCORRECT
|
459
|
+
while (LongExpression1 or LongExpression2) do begin
|
460
|
+
// DoSomething
|
461
|
+
// DoSomethingElse;
|
462
|
+
end;
|
463
|
+
|
464
|
+
// CORRECT
|
465
|
+
while (LongExpression1 or LongExpression2) do
|
466
|
+
begin
|
467
|
+
// DoSomething
|
468
|
+
// DoSomethingElse;
|
469
|
+
end;
|
470
|
+
|
471
|
+
// CORRECT
|
472
|
+
if (LongExpression1) or
|
473
|
+
(LongExpression2) or
|
474
|
+
(LongExpression3) then
|
475
|
+
```
|
476
|
+
|
477
|
+
Comments
|
478
|
+
------------------------------------------------
|
479
|
+
|
480
|
+
The Object Pascal language supports two kinds of comments: block, and single-line comments.
|
481
|
+
|
482
|
+
It is helpful to place comments: - near the top of unit to explain its purpose. - before a class declaration. - before some method declarations.
|
483
|
+
|
484
|
+
Avoid making obvious comments:
|
485
|
+
|
486
|
+
``` example
|
487
|
+
i := i + 1; // Add one to i
|
488
|
+
```
|
489
|
+
|
490
|
+
Remember that misleading comments are worse than no comments at all. Avoid putting any information into comments that is likely to become out of date. Avoid enclosing comments in boxes drawn with asterisks or other special typography. Temporary comments that are expected to be changed or removed later should be marked with the special tag `???:` so that they can easily be found afterwards. Ideally, all temporary comments should have been removed by the time a program is ready to be shipped.
|
491
|
+
|
492
|
+
Example:
|
493
|
+
|
494
|
+
``` example
|
495
|
+
// ???: Change this to call Sort when it is fixed
|
496
|
+
List.MySort;
|
497
|
+
```
|
498
|
+
|
499
|
+
### Block Comments
|
500
|
+
|
501
|
+
Object Pascal supports two types of block comments. The most commonly used block comment is a pair of curly braces: `{ }`. The Delphi team prefers to keep comments of this type as spare and simple as possible. For instance, you should avoid using asterisks to create patterns or lines inside your comments. Instead, make use of white space to break your comments up, much as you would in a word processing document. The words in your comments should start on the same line as the first curly brace, as shown in this excerpt from DsgnIntf.pas:
|
502
|
+
|
503
|
+
``` example
|
504
|
+
{ TPropertyEditor
|
505
|
+
|
506
|
+
Edits a property of a component, or list of components,
|
507
|
+
selected into the Object Inspector. The property
|
508
|
+
editor is created based on the type of the
|
509
|
+
property being edited as determined by the types
|
510
|
+
registered by...
|
511
|
+
|
512
|
+
etc...
|
513
|
+
|
514
|
+
GetXxxValue
|
515
|
+
Gets the value of the first property in the
|
516
|
+
Properties property. Calls the appropriate
|
517
|
+
TProperty GetXxxValue method to retrieve the
|
518
|
+
value.
|
519
|
+
|
520
|
+
SetXxxValue Sets the value of all the properties
|
521
|
+
in the Properties property. Calls the appropriate
|
522
|
+
TProperty SetXxxxValue methods to set the value. }
|
523
|
+
```
|
524
|
+
|
525
|
+
A block comment is always used for the copyright/ID comment at the beginning of each source file. It is also used to "comment out" several lines of code.
|
526
|
+
|
527
|
+
Block comments used to describe a method should appear before the method declaration.
|
528
|
+
|
529
|
+
Example:
|
530
|
+
|
531
|
+
``` example
|
532
|
+
// CORRECT
|
533
|
+
|
534
|
+
{ TMyObject.MyMethod
|
535
|
+
|
536
|
+
This routine allows you to execute code. }
|
537
|
+
|
538
|
+
procedure TMyObject.MyMethod;
|
539
|
+
begin
|
540
|
+
end;
|
541
|
+
|
542
|
+
// INCORRECT
|
543
|
+
|
544
|
+
procedure TMyObject.MyMethod;
|
545
|
+
{******************************************************
|
546
|
+
TMyObject.MyMethod
|
547
|
+
|
548
|
+
This routine allows you to execute code.
|
549
|
+
*******************************************************}
|
550
|
+
begin
|
551
|
+
end;
|
552
|
+
```
|
553
|
+
|
554
|
+
A second kind of block comment contains two characters, a parenthesis and an asterisk: `(*` `*)`. This is sometimes called starparen comments. These comments are generally useful only during code development, as their primary benefit is that they allow nesting of comments, as long as the nest level is less than 2. Object Pascal doesn't support nesting comments of the same type within each other, so really there is only one level of comment nesting: curly inside of starparen, and starparen inside of curly. As long as you don't nest them, any other standard Pascal comments between comments of this type will be ignored. As a result, you can use this syntax to comment out a large chunk of code that is full of mixed code and comments:
|
555
|
+
|
556
|
+
``` example
|
557
|
+
(* procedure TForm1.Button1Click(Sender: TObject);
|
558
|
+
begin
|
559
|
+
DoThis; // Start the process
|
560
|
+
DoThat; // Continue iteration
|
561
|
+
{ We need a way to report errors here, perhaps using
|
562
|
+
a try finally block ??? }
|
563
|
+
CallMoreCode; // Finalize the process
|
564
|
+
end; *)
|
565
|
+
```
|
566
|
+
|
567
|
+
In this example, the entire Button1Click method is commented out, including any of the subcomments found between the procedure's `begin..end` pair.
|
568
|
+
|
569
|
+
### Single-Line Comments
|
570
|
+
|
571
|
+
A single-line comment consists of the characters `//` followed by text. Include a single space between the `//` and the comment itself. Place single line comments at the same indentation level as the code that follows it. You can group single-line comments to form a larger comment.
|
572
|
+
|
573
|
+
A single-line comment or comment group should always be preceded by a blank line, unless it is the first line in a block. If the comment applies to a group of several statements, then the comment or comment group should also be followed by a blank line. If it applies only to the next statement (which may be a compound statement), then do not follow it with a blank line.
|
574
|
+
|
575
|
+
Example:
|
576
|
+
|
577
|
+
``` example
|
578
|
+
// Open the database
|
579
|
+
Table1.Open;
|
580
|
+
```
|
581
|
+
|
582
|
+
Single-line comments can also follow the code they reference. These comments, sometimes referred to as trailing comments, appear on the same line as the code they describe. They should have at least one space-character separating them from the code they reference. If more than one trailing comment appears in a block of code, they should all be aligned to the same column.
|
583
|
+
|
584
|
+
Example:
|
585
|
+
|
586
|
+
``` example
|
587
|
+
if (not IsVisible) then
|
588
|
+
Exit; // nothing to do
|
589
|
+
Inc(StrLength); // reserve space for null terminator
|
590
|
+
```
|
591
|
+
|
592
|
+
Avoid commenting every line of executable code with a trailing comment. It is usually best to limit the comments inside the `begin..end` pair of a method or function to a bare minimum. Longer comments can appear in a block comment before the method or function declaration.
|
593
|
+
|
594
|
+
Classes
|
595
|
+
-----------------------------------------------
|
596
|
+
|
597
|
+
### Class Body Organization
|
598
|
+
|
599
|
+
The body of a class declaration should be organized in the following order:
|
600
|
+
|
601
|
+
Field declarations Method declarations Property declarations The fields, properties and methods in your class should be arranged alphabetically by name.
|
602
|
+
|
603
|
+
#### Access levels
|
604
|
+
|
605
|
+
Except for code inserted by the IDE, the scoping directives for a class should be declared in the following order:
|
606
|
+
|
607
|
+
Private declarations Protected declarations Public declarations Published declarations There are four access levels for class members in Object Pascal: `published`, `public`, `protected`, and `private` – in order of decreasing accessibility. By default, the access level is `published`. In general, a member should be given the lowest access level which is appropriate for the member. For example, a member which is only accessed by classes in the same unit should be set to private access. Also, declaring a lower access level will often give the compiler increased opportunities for optimization. On the other hand, use of private makes it difficult to extend the class by sub-classing. If there is reason to believe the class might be sub-classed in the future, then members that might be needed by sub-classes should be declared `protected` instead of `private`, and the properties used to access private data should be given `protected` status.
|
608
|
+
|
609
|
+
You should never allow public access to data. Data should always be declared in the `private` section, and any public access should be via getter and setter methods, or properties.
|
610
|
+
|
611
|
+
#### Constructor declarations
|
612
|
+
|
613
|
+
Methods should be arranged alphabetically. It is correct either to place your constructors and destructors at the head of this list in the public section, or to arrange them in alphabetical order within the public section.
|
614
|
+
|
615
|
+
If there is more than one constructor, and if you choose to give them all the same name, then sort them lexically by formal parameter list, with constructors having more parameters always coming after those with fewer parameters. This implies that a constructor with no arguments (if it exists) is always the first one. For greatest compatibility with C++Builder, try to make the parameter lists of your constructors unique. C++ cannot call constructors by name, so the only way to distinguish between multiple constructors is by parameter list.
|
616
|
+
|
617
|
+
### Method Declarations
|
618
|
+
|
619
|
+
If possible, a method declaration should appear on one line.
|
620
|
+
|
621
|
+
Examples:
|
622
|
+
|
623
|
+
``` example
|
624
|
+
// Broken line is aligned two spaces in from left.
|
625
|
+
procedure ImageUpdate(Image img, infoflags: Integer,
|
626
|
+
x: Integer, y: Integer, w: Integer, h: Integer)
|
627
|
+
```
|
628
|
+
|
629
|
+
Interfaces
|
630
|
+
---------------------------------------------------
|
631
|
+
|
632
|
+
Interfaces are declared in a manner that runs parallel to the declaration for classes:
|
633
|
+
|
634
|
+
``` example
|
635
|
+
InterfaceName = interface([Inherited Interface])
|
636
|
+
{InterfaceBody}
|
637
|
+
end;
|
638
|
+
```
|
639
|
+
|
640
|
+
An interface declaration should be indented two spaces. The body of the interface is indented by the standard indentation of four spaces. The closing end statement should also be indented two characters. There should be a semi-colon following the closing end statement.
|
641
|
+
|
642
|
+
There are no fields in an interface declaration. Properties, however, are allowed.
|
643
|
+
|
644
|
+
All interface methods are inherently public and abstract; do not explicitly include these keywords in the declaration of an interface method.
|
645
|
+
|
646
|
+
Except as otherwise noted, interface declarations follow the same style guidelines as classes.
|
647
|
+
|
648
|
+
### Interface Body Organization
|
649
|
+
|
650
|
+
The body of an interface declaration should be organized in the following order:
|
651
|
+
|
652
|
+
Interface method declarations Interface property declarations The declaration styles of interface properties and methods are identical to the styles for class properties and methods.
|
653
|
+
|
654
|
+
Statements
|
655
|
+
---------------------------------------------------
|
656
|
+
|
657
|
+
Statements are one or more lines of code followed by a semicolon. Simple statements have one semicolon, while compound statements have more than one semicolon and therefore consist of multiple simple statements.
|
658
|
+
|
659
|
+
Here is a simple statement:
|
660
|
+
|
661
|
+
``` example
|
662
|
+
A := B;
|
663
|
+
```
|
664
|
+
|
665
|
+
Here is a compound, or structured, statement:
|
666
|
+
|
667
|
+
``` example
|
668
|
+
begin
|
669
|
+
B := C;
|
670
|
+
A := B;
|
671
|
+
end;
|
672
|
+
```
|
673
|
+
|
674
|
+
### Simple
|
675
|
+
|
676
|
+
A simple statement contains a single semicolon. If you need to wrap the statement, indent the second line two spaces in from the previous line:
|
677
|
+
|
678
|
+
``` example
|
679
|
+
MyValue :=
|
680
|
+
MyValue + (SomeVeryLongStatement / OtherLongStatement);
|
681
|
+
```
|
682
|
+
|
683
|
+
### Compound
|
684
|
+
|
685
|
+
Compound Statements always end with a semicolon, unless they immediately precede an end statement, in which case the semicolon is optional.
|
686
|
+
|
687
|
+
``` example
|
688
|
+
begin
|
689
|
+
MyStatement;
|
690
|
+
MyNextStatement;
|
691
|
+
MyLastStatement // semicolon optional
|
692
|
+
end;
|
693
|
+
```
|
694
|
+
|
695
|
+
### Assignment and expression
|
696
|
+
|
697
|
+
Each line should contain at most one statement. For example:
|
698
|
+
|
699
|
+
``` example
|
700
|
+
a := b + c; Inc(Count); // INCORRECT
|
701
|
+
a := b + c; // CORRECT
|
702
|
+
Inc(Count); // CORRECT
|
703
|
+
```
|
704
|
+
|
705
|
+
### Local variable declarations
|
706
|
+
|
707
|
+
Local variables should have Camel Caps, that is, they should start with a capital letter, and have capital letters for the beginning of each embedded word. Do not preface variable names with an `F`, as that convention is reserved for Fields in a class declaration:
|
708
|
+
|
709
|
+
``` example
|
710
|
+
var
|
711
|
+
MyData: Integer;
|
712
|
+
MyString: string;
|
713
|
+
```
|
714
|
+
|
715
|
+
You may declare multiple identifiers of the same type on a single line:
|
716
|
+
|
717
|
+
``` example
|
718
|
+
var
|
719
|
+
ArraySize, ArrayCount: Integer;
|
720
|
+
```
|
721
|
+
|
722
|
+
This practice is discouraged in class declarations. There you should place each field on a separate line, along with its type.
|
723
|
+
|
724
|
+
### Array declarations
|
725
|
+
|
726
|
+
There should always be a space before the opening bracket "\[" and after the closing bracket.
|
727
|
+
|
728
|
+
``` example
|
729
|
+
type
|
730
|
+
TMyArray = array [0..100] of Char;
|
731
|
+
```
|
732
|
+
|
733
|
+
### if then
|
734
|
+
|
735
|
+
If statements should always appear on at least two lines.
|
736
|
+
|
737
|
+
Example:
|
738
|
+
|
739
|
+
``` example
|
740
|
+
// INCORRECT
|
741
|
+
if A < B then DoSomething;
|
742
|
+
|
743
|
+
// CORRECT
|
744
|
+
if A < B then
|
745
|
+
DoSomething;
|
746
|
+
```
|
747
|
+
|
748
|
+
In compound if statements, put each element separating statements on a new line:
|
749
|
+
|
750
|
+
Example:
|
751
|
+
|
752
|
+
``` example
|
753
|
+
// INCORRECT
|
754
|
+
if A < B then begin
|
755
|
+
DoSomething;
|
756
|
+
DoSomethingElse;
|
757
|
+
end else begin
|
758
|
+
DoThis;
|
759
|
+
DoThat;
|
760
|
+
end;
|
761
|
+
|
762
|
+
// CORRECT
|
763
|
+
if A < B then
|
764
|
+
begin
|
765
|
+
DoSomething;
|
766
|
+
DoSomethingElse;
|
767
|
+
end
|
768
|
+
else
|
769
|
+
begin
|
770
|
+
DoThis;
|
771
|
+
DoThat;
|
772
|
+
end;
|
773
|
+
```
|
774
|
+
|
775
|
+
Here are a few more variations that are considered valid:
|
776
|
+
|
777
|
+
``` example
|
778
|
+
// CORRECT
|
779
|
+
if Condition then
|
780
|
+
begin
|
781
|
+
DoThis;
|
782
|
+
end else
|
783
|
+
begin
|
784
|
+
DoThat;
|
785
|
+
end;
|
786
|
+
|
787
|
+
// CORRECT
|
788
|
+
if Condition then
|
789
|
+
begin
|
790
|
+
DoThis;
|
791
|
+
end
|
792
|
+
else
|
793
|
+
DoSomething;
|
794
|
+
|
795
|
+
// CORRECT
|
796
|
+
if Condition then
|
797
|
+
begin
|
798
|
+
DoThis;
|
799
|
+
end else
|
800
|
+
DoSomething;
|
801
|
+
```
|
802
|
+
|
803
|
+
One that has fallen out of favor but deserves honorable mention:
|
804
|
+
|
805
|
+
``` example
|
806
|
+
if Condition then
|
807
|
+
DoThis
|
808
|
+
else DoThat;
|
809
|
+
```
|
810
|
+
|
811
|
+
### for do
|
812
|
+
|
813
|
+
Example:
|
814
|
+
|
815
|
+
``` example
|
816
|
+
// INCORRECT
|
817
|
+
for i := 0 to 10 do begin
|
818
|
+
DoSomething;
|
819
|
+
DoSomethingElse;
|
820
|
+
end;
|
821
|
+
|
822
|
+
// CORRECT
|
823
|
+
for i := 0 to 10 do
|
824
|
+
begin
|
825
|
+
DoSomething;
|
826
|
+
DoSomethingElse;
|
827
|
+
end;
|
828
|
+
```
|
829
|
+
|
830
|
+
### while do
|
831
|
+
|
832
|
+
Example:
|
833
|
+
|
834
|
+
``` example
|
835
|
+
// INCORRECT
|
836
|
+
while x < j do begin
|
837
|
+
DoSomething;
|
838
|
+
DoSomethingElse;
|
839
|
+
end;
|
840
|
+
|
841
|
+
|
842
|
+
// CORRECT
|
843
|
+
while x < j do
|
844
|
+
begin
|
845
|
+
DoSomething;
|
846
|
+
DoSomethingElse;
|
847
|
+
end;
|
848
|
+
```
|
849
|
+
|
850
|
+
### repeat until
|
851
|
+
|
852
|
+
Example:
|
853
|
+
|
854
|
+
``` example
|
855
|
+
// CORRECT
|
856
|
+
repeat
|
857
|
+
x := j;
|
858
|
+
j := UpdateValue;
|
859
|
+
until j > 25;
|
860
|
+
```
|
861
|
+
|
862
|
+
### case
|
863
|
+
|
864
|
+
Example:
|
865
|
+
|
866
|
+
``` example
|
867
|
+
// CORRECT
|
868
|
+
case Control.Align of
|
869
|
+
alLeft, alNone: NewRange := Max(NewRange, Position);
|
870
|
+
alRight: Inc(AlignMargin, Control.Width);
|
871
|
+
end;
|
872
|
+
|
873
|
+
// CORRECT
|
874
|
+
case x of
|
875
|
+
csStart:
|
876
|
+
begin
|
877
|
+
j := UpdateValue;
|
878
|
+
end;
|
879
|
+
|
880
|
+
csBegin: x := j;
|
881
|
+
|
882
|
+
csTimeOut:
|
883
|
+
begin
|
884
|
+
j := x;
|
885
|
+
x := UpdateValue;
|
886
|
+
end;
|
887
|
+
end;
|
888
|
+
|
889
|
+
// CORRECT
|
890
|
+
case ScrollCode of
|
891
|
+
SB_LINEUP, SB_LINEDOWN:
|
892
|
+
begin
|
893
|
+
Incr := FIncrement div FLineDiv;
|
894
|
+
FinalIncr := FIncrement mod FLineDiv;
|
895
|
+
Count := FLineDiv;
|
896
|
+
end;
|
897
|
+
SB_PAGEUP, SB_PAGEDOWN:
|
898
|
+
begin
|
899
|
+
Incr := FPageIncrement;
|
900
|
+
FinalIncr := Incr mod FPageDiv;
|
901
|
+
Incr := Incr div FPageDiv;
|
902
|
+
Count := FPageDiv;
|
903
|
+
end;
|
904
|
+
else
|
905
|
+
Count := 0;
|
906
|
+
Incr := 0;
|
907
|
+
FinalIncr := 0;
|
908
|
+
end;
|
909
|
+
```
|
910
|
+
|
911
|
+
### try
|
912
|
+
|
913
|
+
Example:
|
914
|
+
|
915
|
+
``` example
|
916
|
+
// Correct
|
917
|
+
try
|
918
|
+
try
|
919
|
+
EnumThreadWindows(CurrentThreadID, @Disable, 0);
|
920
|
+
Result := TaskWindowList;
|
921
|
+
except
|
922
|
+
EnableTaskWindows(TaskWindowList);
|
923
|
+
raise;
|
924
|
+
end;
|
925
|
+
finally
|
926
|
+
TaskWindowList := SaveWindowList;
|
927
|
+
TaskActiveWindow := SaveActiveWindow;
|
928
|
+
end;
|
929
|
+
```
|
930
|
+
|