Verified Commit 665caa2f authored by Jochum van der Ploeg's avatar Jochum van der Ploeg 🤔
Browse files

Initial commit

parents
Pipeline #203051981 passed with stage
in 2 minutes and 5 seconds
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
build/
coverage/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
image: cirrusci/flutter:stable
stages:
- lint
- test
- publish
dartdoc:
stage: lint
script:
- flutter pub get
- dartdoc --no-auto-include-dependencies --quiet
only:
refs:
- merge_requests
changes:
- lib/**/*
- README.md
- .gitlab-ci.yml
flutter_analyze:
stage: lint
script:
- flutter pub get
- flutter analyze --pub
- flutter format -l 240 -n . --set-exit-if-changed
only:
refs:
- merge_requests
changes:
- lib/**/*.dart
- test/**/*.dart
- .gitlab-ci.yml
unit_test:
stage: test
script:
- flutter test --coverage --pub test
- lcov --list ./coverage/lcov.info
only:
refs:
- merge_requests
- master
changes:
- lib/**/*
- test/**/*
- .gitlab-ci.yml
tag:
image: curlimages/curl
stage: publish
script:
- |
if [ -z "${GITLAB_API_TOKEN}" ]; then
echo "Missing GITLAB_API_TOKEN environment variable"
exit 1
fi
export TAG_NAME="$(awk '/^version: /{print $NF}' pubspec.yaml)"
curl --fail --request POST --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
--data-urlencode "tag_name=v${TAG_NAME}" \
--data-urlencode "ref=master" \
--data-urlencode "release_description=Check the [CHANGELOG.md](${CI_PROJECT_URL}/-/blob/master/CHANGELOG.md)" \
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/repository/tags"
environment:
name: pub-dev-plugin
url: https://pub.dev/packages/dartlin
when: manual
only:
refs:
- master
dry_run_publish:
stage: publish
script:
- flutter pub get
- flutter pub publish --dry-run
only:
refs:
- merge_requests
pub_dev_publish:
# https://robertohuertas.com/2019/01/20/publish-flutter-package-with-travis/
stage: publish
script:
- |
echo "First release needs to be done manually"
exit 0;
if [ -z "${PUB_DEV_PUBLISH_ACCESS_TOKEN}" ]; then
echo "Missing PUB_DEV_PUBLISH_ACCESS_TOKEN environment variable"
exit 1
fi
if [ -z "${PUB_DEV_PUBLISH_REFRESH_TOKEN}" ]; then
echo "Missing PUB_DEV_PUBLISH_REFRESH_TOKEN environment variable"
exit 1
fi
if [ -z "${PUB_DEV_PUBLISH_TOKEN_ENDPOINT}" ]; then
echo "Missing PUB_DEV_PUBLISH_TOKEN_ENDPOINT environment variable"
exit 1
fi
if [ -z "${PUB_DEV_PUBLISH_EXPIRATION}" ]; then
echo "Missing PUB_DEV_PUBLISH_EXPIRATION environment variable"
exit 1
fi
cat <<EOF > ~/.pub-cache/credentials.json
{
"accessToken":"$(echo "${PUB_DEV_PUBLISH_ACCESS_TOKEN}" | base64 -d)",
"refreshToken":"$(echo "${PUB_DEV_PUBLISH_REFRESH_TOKEN}" | base64 -d)",
"tokenEndpoint":"${PUB_DEV_PUBLISH_TOKEN_ENDPOINT}",
"scopes":["https://www.googleapis.com/auth/userinfo.email","openid"],
"expiration":${PUB_DEV_PUBLISH_EXPIRATION}
}
EOF
- flutter pub get
- flutter pub publish -f
only:
refs:
- /^v.*$/
except:
refs:
- branches
\ No newline at end of file
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: fba99f6cf9a14512e461e3122c8ddfaa25394e89
channel: stable
project_type: package
## 0.1.0
- Added `when` for control flows
- Added `range` for ranges
\ No newline at end of file
MIT License
Copyright (c) 2020 Jochum van der Ploeg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# dartlin
[![coverage report](https://gitlab.com/wolfenrain/dartlin/badges/master/coverage.svg)](https://gitlab.com/wolfenrain/dartlin/-/commits/master)
[![pipeline status](https://gitlab.com/wolfenrain/dartlin/badges/master/pipeline.svg)](https://gitlab.com/wolfenrain/dartlin/-/commits/master)
## Introduction
### What it does
Dartlin is a helper library that provides readable methods with which you can write cleaner looking code.
- It allows you to have more control over your code flow. By using the `when` method for example, to write switch-like expressions.
- It provides methods to create data sets of certain types, for example the `range` method.
## What does it not do
The main focus of the library is adding readable methods and readability tends to not equal performance optimization. So is the case for some of the provided methods in this library. The performance hits of these methods is very minimal, but most of them do rely on [closures](https://dart.dev/guides/language/language-tour#anonymous-functions) to work.
## Common Usage
### Control flow
The `when` method replaces the switch statement. And can be used to write expressions:
```dart
final result = when(place, {
1: () => CompetitionPlace.first,
2: () => CompetitionPlace.second,
3: () => CompetitionPlace.third,
[4,5]: () => CompetitionPlace.honourableMentions,
orElse: () => CompetitionPlace.others
});
```
See the [when](https://pub.dev/documentation/dartlin/latest/control_flow/when.html) docs for more information.
# Be aware the health of this package is based on these
# analyse options, we will get the most health points if
# we do not change anything, see:
# https://pub.dev/help#health
# Defines a default set of lint rules enforced for
# projects at Google. For details and rationale,
# see https://github.com/dart-lang/pedantic#enabled-lints.
include: package:pedantic/analysis_options.yaml
# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
# Uncomment to specify additional rules.
linter:
rules:
- unnecessary_brace_in_string_interps
- non_constant_identifier_names
- cancel_subscriptions
# analyzer:
# exclude:
# - path/to/excluded/files/**
dartdoc:
include: ['dartlin', 'control_flow', 'ranges']
errors:
- ambiguous-doc-reference
- ambiguous-reexport
- broken-link
- category-order-gives-missing-package-name
- deprecated
- ignored-canonical-for
- missing-from-search-index
- no-canonical-found
- no-library-level-docs
- not-implemented
- orphaned-file
- reexported
- private-api-across-packages
- unknown-file
- unknown-macro
- unresolved-doc-reference
\ No newline at end of file
/// Adding control flow methods for writing more readable code.
library control_flow;
part 'src/control_flow/when.dart';
part 'src/control_flow/when_checks.dart';
\ No newline at end of file
/// Dartlin is a helper library that provides readable methods
/// with which you can write cleaner looking code.
library dartlin;
export 'control_flow.dart';
export 'ranges.dart';
/// Adding methods for data set generation.
library ranges;
part 'src/ranges/range.dart';
\ No newline at end of file
part of control_flow;
/// Allows for adding a `orElse` branch to a [when] call.
const dynamic orElse = '__when__or__else__';
/// The [when] method replaces the switch statement.
///
/// The simplest form of a [when] method:
/// ```dart
/// when(x, {
/// 1: () => print('x == 1'),
/// 2: () => print('x == 2'),
/// orElse: () {
/// print('x is neither 1 nor 2');
/// },
/// });
/// ```
///
/// [when] matches its argument against all branches sequantially until a branch condition is satisified.
///
/// [when] can be used either as an expression, or as a statement. If it is used as an expression, the value of the satisfied branch
/// becomes the value of the expression. And if it is used as a statement, the values of the branches are ignored.
///
/// The `orElse` branch is checked if none of the other branches are satisified. The `orElse` is mandatory, when not supplied it will return `null`.
///
/// If many cases should be handled the same way, the branch condition can be a `List`:
/// ```dart
/// when(x, {
/// [0, 1]: () => print('x == 0 or x == 1'),
/// orElse: () => print('otherwise'),
/// });
/// ```
///
/// Unlike the switch statement in dart, we can use arbitary expressions as branch conditions:
/// ```dart
/// when(x, {
/// int.parse(s): () => print('s encodes x'),
/// orElse: () => print('s does not encode x'),
/// });
/// ```
///
/// Using the [isIn] and [isNotIn] methods we can also check if the value is in a `List`:
/// ```dart
/// when(x, {
/// isIn(range(0, to: 10)): () => print('x is in the range'),
/// isIn(validNumbers): () => print('x is valid'),
/// isNotIn(range(10, to: 20)): () => print('x is outside the range'),
/// orElse: () => print('none of the above'),
/// });
/// ```
///
/// It is also possible to check if a value [isType] or [isNotType]:
/// ```dart
/// bool hasPrefix(dynamic x) {
/// return when(x, {
/// isType<String>(): () => x.startsWith('prefix'),
/// orElse: () => false,
/// });
/// }
/// ```
/// **Note**: There is currently no smartcasting in place so you won't get autocompletion on methods and properties of the given type.
///
/// [when] can also be used as a replacement for an `if-else if` chain. If no argument is supplied,
/// the branch conditions are simply boolean expressions, and a branch is executed when the condition is true:
/// ```dart
/// when({
/// x.isOdd: () => print('x is odd'),
/// y.isEven: () => print('x is even'),
/// orElse: () => print('x+y is event'),
/// });
/// ```
/// **Note**: If you wish to use this as an statement you will have to add typings yourself. Smart casting is currently not possible:
/// ```dart
/// final int z = when({
/// x.isOdd: () => x + 1,
/// y.isEven: () => y + 1,
/// orElse: () => x + y,
/// });
/// ```
V when<T, V>(T value, [Map<T, V Function()> branches]) {
if (branches == null && value is Map) {
return when<dynamic, dynamic>(true, value as dynamic);
}
assert(branches != null && branches.isNotEmpty);
var hasElse = false;
for (var key in branches.keys) {
if ((key == value) ||
(key is List && key.contains(value)) ||
(key is _WhenCheck && key(value))) {
return branches[key]();
}
hasElse = !hasElse ? key == orElse : hasElse;
}
if (hasElse) return branches[orElse]();
return null;
}
part of control_flow;
typedef _WhenCheck = bool Function<T>(T value);
/// Allows for checking if a [when] value is in a list.
_WhenCheck isIn<T>(Iterable<T> list) => <T>(value) => list.contains(value);
/// Allows for checking if a [when] value is not in a list.
_WhenCheck isNotIn<T>(Iterable<T> list) => <T>(value) => !list.contains(value);
/// Allows for checking if a [when] value is of a certain type.
_WhenCheck isType<V>() => <T>(value) => value is V;
/// Allows for checking if a [when] value is not of a certain type.
_WhenCheck isNotType<V>() => <T>(value) => value is! V;
part of ranges;
/// Creates [progression](https://en.wikipedia.org/wiki/Arithmetic_progression) ranges of given type value.
///
/// Generally used in `for` loops:
/// ```dart
/// for (var i in range(1, to: 4)) {
/// print(i);
/// }
/// ```
///
/// To iterate in a reverse order, use the [downTo] argument:
/// ```dart
/// for (var i in range(4, downTo: 1)) {
/// print(1);
/// }
/// ```
///
/// To iterate with an arbitrary step, use the [step] argument:
/// ```dart
/// for (var i in range(1, to: 8, step: 2)) {
/// print(i);
/// }
///
/// for (var i in range(8, downTo: 1, step: 2)) {
/// print(i);
/// }
/// ```
///
/// To iterate a range which does not include the end element, use the [until] argument:
/// ```dart
/// for (var i in range(1, until: 10)) {
/// print(i);
/// }
/// ```
List<T> range<T extends num>(T value, {T to, T until, T downTo, T step}) {
assert(
(to != null && until == null && downTo == null) ||
(to == null && until != null && downTo == null) ||
(to == null && until == null && downTo != null),
'Either the `to`, `until` or `downTo` argument is required',
);
assert(
step != null && !step.isNegative || step == null,
'The `step` should be a positive number',
);
final list = <T>[];
final stepValue = downTo != null ? -(step ?? 1) : step ?? 1;
final end = downTo != null
? downTo - 1
: to != null ? to + 1 : until ?? 0;
assert(
(stepValue.isNegative && value > end) ||
(!stepValue.isNegative && value < end),
'Range out of bound',
);
while (value != end) {
list.add(value);
value += stepValue;
}
return list;
}
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.2"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.13"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
flutter:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.8"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.8"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
pedantic:
dependency: "direct dev"
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"