Added and migrated inflection2

This commit is contained in:
thomashii@dukefirehawk.com 2021-05-02 16:39:25 +08:00
parent 2deaf5d299
commit 32f3eaa5c4
36 changed files with 1326 additions and 11 deletions

View file

@ -41,7 +41,7 @@
* Updated angel_serialize to 4.0.0 (0/0 tests passed)
* Updated angel_serialize_generator to 4.0.0 (33/33 tests passed)
* Updated angel_orm to 4.0.0 (0/0 tests passed)
* Updated angel_migration to 3.0.0
* Updated angel_migration to 4.0.0 (0/0 tests passed)
* Updated angel_orm_generator to 3.0.0 (use a fork of postgres)
# 3.0.0 (Non NNBD)
@ -71,7 +71,7 @@
* Updated angel_serialize to 3.0.0 (0/0 tests passed)
* Updated angel_serialize_generator to 3.0.0 (33/33 tests passed)
* Updated angel_orm to 3.0.0 (0/0 tests passed)
* Updated angel_migration to 3.0.0
* Updated angel_migration to 3.0.0 (0/0 tests passed)
* Updated angel_orm_generator to 3.0.0 (use a fork of postgres)
* Updated angel_migration_runner to 3.0.0
* Updated angel_orm_test to 1.0.0

View file

@ -0,0 +1,3 @@
George Moschovitis <george.moschovitis@gmail.com>
Tobe O <thosakwe@gmail.com>
Thomas Hii <thomashii@dukefirehawk.com>

View file

@ -0,0 +1,40 @@
# Changelog
# 1.0.0
* Migrated to support Dart SDK 2.12.x NNBD
## 0.4.3
- Add past tense support (thanks @phodonou !)
## 0.4.2
- Dart 2 compatibility.
- Hard fork.
## 0.4.1
- Cleanup, follow latest conventions and developments in the Dartiverse.
- Added past inflections.
## 0.3.2
- Cleanup.
## 0.3.1
- Case conversion handles sentences delimited with whitespace.
## 0.3.0
- Handle irregular plural nouns.
- Added shortcut functions.
## 0.2.0
- Handle uncountable nouns.
- Added singular inflection.
- Added plural inflection.
- Refactored to use a dart:convert based API.
## 0.1.0
- Initial version, convertToSnakeCase / convertToSpinalCase.

View file

@ -0,0 +1,27 @@
Copyright (c) 2015, George Moschovitis <george.moschovitis@gmail.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,49 @@
# Forked
**IMPORTANT NOTE**: This is a *hard fork* of the original `inflection` package,
as the former is now archived, and abandoned.
# Inflection
[![Build Status](https://travis-ci.org/thosakwe/dart-inflection.svg)](https://travis-ci.org/thosakwe/dart-inflection)
In grammar, inflection or inflexion is the modification of a word to express
different grammatical categories such as tense, mood, voice, aspect, person,
number, gender and case.
A port of the Rails/ActiveSupport inflector library to Dart.
## Usage
A simple usage example:
```dart
import 'package:inflection2/inflection2.dart';
main() {
// Using 'shortcut' functions.
print(pluralize("house")); // => "houses"
print(convertToPlural("house")); // => "houses", alias for pluralize
print(pluralizeVerb("goes")); // => "go"
print(singularize("axes")); // => "axis"
print(convertToSingular("axes")); // => "axis", alias for pluralize
print(singularizeVerb("write")); // => "writes"
print(convertToSnakeCase("CamelCaseName")); // => "camel_case_name"
print(convertToSpinalCase("CamelCaseName")); // => "camel-case-name"
print(past("forgo")); // => "forwent"
// Using default encoders.
print(PLURAL.convert("virus")); // => "viri"
print(SINGULAR.convert("Matrices")); // => "Matrix"
print(SINGULAR.convert("species")); // => "species"
print(SNAKE_CASE.convert("CamelCaseName")); // => "camel_case_name"
print(SPINAL_CASE.convert("CamelCaseName")); // => "camel-case-name"
print(PAST.convert("miss")); // => "missed"
}
```
## Features and bugs
Please file feature requests and bugs at the
[issue tracker](https://github.com/thosakwe/dart-inflection/issues).

View file

@ -0,0 +1,3 @@
analyzer:
strong-mode:
implicit-casts: false

View file

@ -0,0 +1,24 @@
import '../lib/inflection2.dart';
main() {
// Using 'shortcut' functions.
print(pluralize("house")); // => "houses"
print(convertToPlural("house")); // => "houses", alias for pluralize
print(pluralizeVerb("goes")); // => "go"
print(singularize("axes")); // => "axis"
print(convertToSingular("axes")); // => "axis", alias for pluralize
print(singularizeVerb("write")); // => "writes"
print(convertToSnakeCase("CamelCaseName")); // => "camel_case_name"
print(convertToSpinalCase("CamelCaseName")); // => "camel-case-name"
print(past("forgo")); // => "forwent"
// Using default encoders.
print(PLURAL.convert("virus")); // => "viri"
print(SINGULAR.convert("Matrices")); // => "Matrix"
print(SINGULAR.convert("species")); // => "species"
print(SNAKE_CASE.convert("CamelCaseName")); // => "camel_case_name"
print(SPINAL_CASE.convert("CamelCaseName")); // => "camel-case-name"
print(PAST.convert("miss")); // => "missed"
}

View file

@ -0,0 +1,43 @@
/// In grammar, inflection or inflexion is the modification of a word to express
/// different grammatical categories such as tense, mood, voice, aspect, person,
/// number, gender and case.
///
/// [ActiveSupport Inflector](https://github.com/rails/rails/tree/master/activesupport/lib/active_support/inflector)
/// [Letter case](http://en.wikipedia.org/wiki/Letter_case#Special_case_styles)
library inflection2;
import 'src/past.dart';
import 'src/plural.dart';
import 'src/plural_verb.dart';
import 'src/singular.dart';
import 'src/singular_verb.dart';
import 'src/snake_case.dart';
import 'src/spinal_case.dart';
export 'src/past.dart';
export 'src/plural.dart';
export 'src/plural_verb.dart';
export 'src/singular.dart';
export 'src/singular_verb.dart';
export 'src/snake_case.dart';
export 'src/spinal_case.dart';
export 'src/is_tense.dart';
String convertToPlural(String word) => PLURAL.convert(word);
String pluralize(String word) => PLURAL.convert(word);
String convertToPluralVerb(String word) => PLURALVERB.convert(word);
String pluralizeVerb(String word) => PLURALVERB.convert(word);
String convertToSingular(String word) => SINGULAR.convert(word);
String singularize(String word) => SINGULAR.convert(word);
String convertToSingularVerb(String word) => SINGULARVERB.convert(word);
String singularizeVerb(String word) => SINGULARVERB.convert(word);
String convertToSnakeCase(String word) => SNAKE_CASE.convert(word);
String convertToSpinalCase(String word) => SPINAL_CASE.convert(word);
String convertToPast(String word) => PAST.convert(word);
String past(String word) => PAST.convert(word);

View file

@ -0,0 +1,323 @@
//library inflection2.irregular_past_verbs;
/// A collection of verbs with irregular past.
final Map<String, String> irregularPastVerbs = const {
"backslidden": "backslid",
"forbidden": "forbade",
"stridden": "strode",
"stricken": "struck",
"brought": "brought",
"striven": "strove",
"swollen": "swelled",
"thought": "thought",
"trodden": "trod",
"forbade": "forbade",
"arisen": "arose",
"awoken": "awoke",
"beaten": "beat",
"became": "became",
"become": "became",
"bidden": "bid",
"bitten": "bit",
"broken": "broke",
"bought": "bought",
"caught": "caught",
"choose": "chose",
"chosen": "chose",
"forbid": "forbade",
"dreamt": "dreamt",
"driven": "drove",
"fallen": "fell",
"fought": "fought",
"freeze": "froze",
"frozen": "froze",
"gotten": "got",
"ground": "ground",
"hidden": "hid",
"learnt": "learnt",
"proven": "proved",
"sought": "sought",
"shaken": "shook",
"shaven": "shaved",
"shrank": "shrank",
"shrink": "shrank",
"shrunk": "shrank",
"spoken": "spoke",
"spoilt": "spoilt",
"spread": "spread",
"sprang": "sprang",
"spring": "sprang",
"sprung": "sprang",
"stolen": "stole",
"strewn": "strewed",
"strode": "strode",
"stride": "strode",
"strike": "struck",
"strove": "strove",
"struck": "struck",
"string": "strung",
"strung": "strung",
"taught": "taught",
"thrown": "threw",
"thrust": "thrust",
"arise": "arose",
"arose": "arose",
"awake": "awoke",
"awoke": "awoke",
"borne": "bore",
"began": "began",
"begin": "began",
"begun": "began",
"bound": "bound",
"bleed": "bled",
"blown": "blew",
"break": "broke",
"breed": "bred",
"bring": "brought",
"broke": "broke",
"build": "built",
"built": "built",
"burnt": "burnt",
"catch": "caught",
"chose": "chose",
"cling": "clung",
"clung": "clung",
"creep": "crept",
"crept": "crept",
"dealt": "dealt",
"wound": "wound",
"wring": "wrung",
"wrung": "wrung",
"write": "wrote",
"wrote": "wrote",
"drawn": "drew",
"drank": "drank",
"drink": "drank",
"drunk": "drank",
"drive": "drove",
"drove": "drove",
"dwelt": "dwelt",
"eaten": "ate",
"fight": "fought",
"found": "found",
"fling": "flung",
"flung": "flung",
"flown": "flew",
"froze": "froze",
"given": "gave",
"grind": "ground",
"grown": "grew",
"heard": "heard",
"knelt": "knelt",
"known": "knew",
"leant": "leant",
"leapt": "leapt",
"leave": "left",
"meant": "meant",
"risen": "rose",
"shake": "shook",
"shorn": "sheared",
"shone": "shone",
"shook": "shook",
"shoot": "shot",
"shown": "showed",
"slain": "slew",
"sleep": "slept",
"slept": "slept",
"slide": "slid",
"sling": "slung",
"slung": "slung",
"slunk": "slunk",
"smelt": "smelt",
"snuck": "snuck",
"speak": "spoke",
"spelt": "spelt",
"spend": "spent",
"spent": "spent",
"spilt": "spilt",
"split": "split",
"spoke": "spoke",
"stand": "stood",
"stood": "stood",
"steal": "stole",
"stick": "stuck",
"stole": "stole",
"stuck": "stuck",
"sting": "stung",
"stung": "stung",
"stank": "stank",
"stink": "stank",
"stunk": "stank",
"swear": "swore",
"swore": "swore",
"sworn": "swore",
"sweep": "swept",
"swept": "swept",
"swing": "swung",
"swung": "swung",
"taken": "took",
"teach": "taught",
"think": "thought",
"threw": "threw",
"throw": "threw",
"tread": "trod",
"wake": "woke",
"woken": "woke",
"woven": "wove",
"bear": "bore",
"bore": "bore",
"born": "bore",
"beat": "beat",
"bend": "bent",
"bent": "bent",
"bind": "bound",
"bite": "bit",
"bled": "bled",
"blew": "blew",
"blow": "blew",
"bred": "bred",
"cast": "cast",
"clad": "clad",
"come": "came",
"cost": "cost",
"deal": "dealt",
"does": "did",
"done": "did",
"draw": "drew",
"drew": "drew",
"fall": "fell",
"feed": "fed",
"feel": "felt",
"fell": "fell",
"felt": "felt",
"find": "found",
"flee": "fled",
"fled": "fled",
"flew": "flew",
"gave": "gave",
"give": "gave",
"gone": "went",
"grew": "grew",
"grow": "grew",
"hang": "hung",
"hung": "hung",
"have": "had",
"hear": "heard",
"hewn": "hewed",
"hide": "hid",
"hold": "held",
"held": "held",
"hurt": "hurt",
"keep": "kept",
"kept": "kept",
"knew": "knew",
"know": "knew",
"laid": "laid",
"lead": "led",
"left": "left",
"lend": "lent",
"lent": "lent",
"lain": "lay",
"lose": "lost",
"lost": "lost",
"make": "made",
"made": "made",
"mean": "meant",
"meet": "met",
"mown": "mowed",
"paid": "paid",
"pled": "pled",
"read": "read",
"ride": "rode",
"rode": "rode",
"ring": "rang",
"rung": "rang",
"rise": "rose",
"rose": "rose",
"sang": "sang",
"sawn": "sawed",
"said": "said",
"seen": "saw",
"seek": "sought",
"sell": "sold",
"slew": "slew",
"sold": "sold",
"send": "sent",
"sent": "sent",
"sewn": "sewed",
"shed": "shed",
"shot": "shot",
"shut": "shut",
"sing": "sang",
"sung": "sang",
"slid": "slid",
"slit": "slit",
"sown": "sowed",
"sped": "sped",
"spin": "spun",
"spun": "spun",
"spit": "spit",
"spat": "spat",
"swam": "swam",
"swim": "swam",
"swum": "swam",
"take": "took",
"tear": "tore",
"tore": "tore",
"torn": "tore",
"tell": "told",
"told": "told",
"took": "took",
"trod": "trod",
"wear": "wore",
"wore": "wore",
"worn": "wore",
"weep": "wept",
"went": "went",
"wept": "wept",
"were": "were",
"wind": "wound",
"woke": "woke",
"wove": "wove",
"are": "were",
"ate": "ate",
"bet": "bet",
"bid": "bid",
"bit": "bit",
"buy": "bought",
"cut": "cut",
"did": "did",
"dig": "dug",
"dug": "dug",
"eat": "ate",
"fed": "fed",
"fly": "flew",
"get": "got",
"got": "got",
"had": "had",
"has": "had",
"hid": "hid",
"hit": "hit",
"lay": "laid",
"led": "led",
"let": "let",
"lit": "lit",
"met": "met",
"pay": "paid",
"put": "put",
"ran": "ran",
"rid": "rid",
"run": "ran",
"saw": "saw",
"say": "said",
"see": "saw",
"sit": "sat",
"sat": "sat",
"set": "set",
"was": "was",
"win": "won",
"won": "won",
"do": "did",
"go": "went",
"is": "was",
};

View file

@ -0,0 +1,11 @@
//library inflection2.irregular_plural_nouns;
/// A collection of nouns with irregular plurals.
///
/// [A List of 100 Irregular Plural Nouns in English](http://grammar.about.com/od/words/a/A-List-Of-Irregular-Plural-Nouns-In-English.htm)
final Map<String, String> irregularPluralNouns = const {
"person": "people",
"man": "men",
"child": "children",
"sex": "sexes"
};

View file

@ -0,0 +1,9 @@
//library inflection2.irregular_plural_verbs;
/// A collection of verbs with irregular plurals.
final Map<String, String> irregularPluralVerbs = const {
"is": "are",
"am": "are",
"was": "were",
"has": "have"
};

View file

@ -0,0 +1,6 @@
import '../inflection2.dart';
/// returns true if this word is in the past tense
bool isPastTense(String word) {
return word.toLowerCase().trim() == past(word).toLowerCase().trim();
}

View file

@ -0,0 +1,68 @@
//library inflection2.past;
import 'dart:convert';
import 'irregular_past_verbs.dart';
import 'verbs_ending_with_ed.dart';
import 'util.dart';
class PastEncoder extends Converter<String, String> {
final List<List> _inflectionRules = [];
PastEncoder() {
irregularPastVerbs.forEach((String presentOrParticiple, String past) {
addIrregularInflectionRule(presentOrParticiple, past);
});
[
[r'.+', (Match m) => '${m[0]}ed'],
[r'([^aeiou])y$', (Match m) => '${m[1]}ied'],
[r'([aeiou]e)$', (Match m) => '${m[1]}d'],
[r'[aeiou][^aeiou]e$', (Match m) => '${m[0]}d']
]
.reversed
.forEach((rule) => addInflectionRule(rule.first as String, rule.last));
}
void addInflectionRule(String presentOrParticiple, dynamic past) {
_inflectionRules
.add([new RegExp(presentOrParticiple, caseSensitive: false), past]);
}
void addIrregularInflectionRule(String presentOrParticiple, String past) {
_inflectionRules.add([
new RegExp(
r'^(back|dis|for|fore|in|inter|mis|off|over|out|par|pre|re|type|un|under|up)?' +
presentOrParticiple +
r'$',
caseSensitive: false),
(Match m) => (m[1] == null) ? past : m[1]! + past
]);
}
@override
String convert(String word) {
if (!word.isEmpty) {
if (word.contains("ed", word.length - 2)) {
RegExp reg = new RegExp(
r'^(back|dis|for|fore|in|inter|mis|off|over|out|par|pre|re|type|un|under|up)(.+)$');
if (reg.hasMatch(word)) {
if (!verbsEndingWithEd.contains(reg.firstMatch(word)!.group(2)))
return word;
} else if (!verbsEndingWithEd.contains(word)) {
return word;
}
}
for (var r in _inflectionRules) {
var pattern = r.first as RegExp;
if (pattern.hasMatch(word)) {
return word.replaceAllMapped(pattern, r.last as MatchToString);
}
}
}
return word;
}
}
final Converter<String, String> PAST = new PastEncoder();

View file

@ -0,0 +1,87 @@
//library inflection2.plural;
import 'dart:convert';
import 'uncountable_nouns.dart';
import 'irregular_plural_nouns.dart';
import 'util.dart';
class PluralEncoder extends Converter<String, String> {
final List<List> _inflectionRules = [];
PluralEncoder() {
irregularPluralNouns.forEach((singular, plural) {
addIrregularInflectionRule(singular, plural);
});
[
[r'$', (Match m) => 's'],
[r's$', (Match m) => 's'],
[r'^(ax|test)is$', (Match m) => '${m[1]}es'],
[r'(octop|vir)us$', (Match m) => '${m[1]}i'],
[r'(octop|vir)i$', (Match m) => m[0]],
[r'(alias|status)$', (Match m) => '${m[1]}es'],
[r'(bu)s$', (Match m) => '${m[1]}ses'],
[r'(buffal|tomat)o$', (Match m) => '${m[1]}oes'],
[r'([ti])um$', (Match m) => '${m[1]}a'],
[r'([ti])a$', (Match m) => m[0]],
[r'sis$', (Match m) => 'ses'],
[r'(?:([^f])fe|([lr])f)$', (Match m) => '${m[1]}${m[2]}ves'],
[r'([^aeiouy]|qu)y$', (Match m) => '${m[1]}ies'],
[r'(x|ch|ss|sh)$', (Match m) => '${m[1]}es'],
[r'(matr|vert|ind)(?:ix|ex)$', (Match m) => '${m[1]}ices'],
[r'^(m|l)ouse$', (Match m) => '${m[1]}ice'],
[r'^(m|l)ice$', (Match m) => m[0]],
[r'^(ox)$', (Match m) => '${m[1]}en'],
[r'^(oxen)$', (Match m) => m[1]],
[r'(quiz)$', (Match m) => '${m[1]}zes']
]
.reversed
.forEach((rule) => addInflectionRule(rule.first as String, rule.last));
}
void addInflectionRule(String singular, dynamic plural) {
_inflectionRules.add([new RegExp(singular, caseSensitive: false), plural]);
}
void addIrregularInflectionRule(String singular, String plural) {
final s0 = singular.substring(0, 1);
final srest = singular.substring(1);
final p0 = plural.substring(0, 1);
final prest = plural.substring(1);
if (s0.toUpperCase() == p0.toUpperCase()) {
addInflectionRule('(${s0})${srest}\$', (Match m) => '${m[1]}${prest}');
addInflectionRule('(${p0})${prest}\$', (Match m) => '${m[1]}${prest}');
} else {
addInflectionRule('${s0.toUpperCase()}(?i)${srest}\$',
(Match m) => '${p0.toUpperCase()}${prest}');
addInflectionRule('${s0.toLowerCase()}(?i)${srest}\$',
(Match m) => '${p0.toUpperCase()}${prest}');
addInflectionRule('${p0.toUpperCase()}(?i)${prest}\$',
(Match m) => '${p0.toUpperCase()}${prest}');
addInflectionRule('${p0.toLowerCase()}(?i)${prest}\$',
(Match m) => '${p0.toLowerCase()}${prest}');
}
}
@override
String convert(String word) {
if (!word.isEmpty) {
if (uncountableNouns.contains(word.toLowerCase())) {
return word;
} else {
for (var r in _inflectionRules) {
var pattern = r.first as RegExp;
if (pattern.hasMatch(word)) {
return word.replaceAllMapped(pattern, r.last as MatchToString);
}
}
}
}
return word;
}
}
final Converter<String, String> PLURAL = new PluralEncoder();

View file

@ -0,0 +1,49 @@
//library inflection2.plural_verb;
import 'dart:convert';
import 'irregular_plural_verbs.dart';
import 'util.dart';
class PluralVerbEncoder extends Converter<String, String> {
final List<List> _inflectionRules = [];
PluralVerbEncoder() {
irregularPluralVerbs.forEach((singular, plural) {
addInflectionRule(singular, (Match m) => plural);
});
[
[r'e?s$', (Match m) => ''],
[r'ies$', (Match m) => 'y'],
[r'([^h|z|o|i])es$', (Match m) => '${m[1]}e'],
[r'ses$', (Match m) => 's'],
[r'zzes$', (Match m) => 'zz'],
[r'([cs])hes$', (Match m) => '${m[1]}h'],
[r'xes$', (Match m) => 'x'],
[r'sses$', (Match m) => 'ss']
]
.reversed
.forEach((rule) => addInflectionRule(rule.first as String, rule.last));
}
void addInflectionRule(String singular, dynamic plural) {
_inflectionRules.add([new RegExp(singular, caseSensitive: false), plural]);
}
@override
String convert(String word) {
if (!word.isEmpty) {
for (var r in _inflectionRules) {
var pattern = r.first as RegExp;
if (pattern.hasMatch(word)) {
return word.replaceAllMapped(pattern, r.last as MatchToString);
}
}
}
return word;
}
}
final Converter<String, String> PLURALVERB = new PluralVerbEncoder();

View file

@ -0,0 +1,95 @@
//library inflection2.singular;
import 'dart:convert';
import 'uncountable_nouns.dart';
import 'irregular_plural_nouns.dart';
import 'util.dart';
class SingularEncoder extends Converter<String, String> {
final List<List> _inflectionRules = [];
SingularEncoder() {
irregularPluralNouns.forEach((singular, plural) {
addIrregularInflectionRule(singular, plural);
});
[
[r's$', (Match m) => ''],
[r'(ss)$', (Match m) => m[1]],
[r'(n)ews$', (Match m) => '${m[1]}ews'], // TODO: uncountable?
[r'([ti])a$', (Match m) => '${m[1]}um'],
[
r'((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$',
(Match m) => '${m[1]}sis'
],
[r'(^analy)(sis|ses)$', (Match m) => '${m[1]}sis'], // TODO: not needed?
[r'([^f])ves$', (Match m) => '${m[1]}fe'],
[r'(hive|tive)s$', (Match m) => m[1]],
[r'([lr])ves$', (Match m) => '${m[1]}f'],
[r'([^aeiouy]|qu)ies$', (Match m) => '${m[1]}y'],
[r'(s)eries$', (Match m) => '${m[1]}eries'], // TODO: uncountable
[r'(m)ovies$', (Match m) => '${m[1]}ovie'],
[r'(x|ch|ss|sh)es$', (Match m) => m[1]],
[r'^(m|l)ice$', (Match m) => '${m[1]}ouse'],
[r'(bus)(es)?$', (Match m) => m[1]],
[r'(shoe)s$', (Match m) => m[1]],
[r'(cris|test)(is|es)$', (Match m) => '${m[1]}is'],
[r'^(a)x[ie]s$', (Match m) => '${m[1]}xis'],
[r'(octop|vir)(us|i)$', (Match m) => '${m[1]}us'],
[r'(alias|status)(es)?$', (Match m) => m[1]],
[r'^(ox)en', (Match m) => m[1]],
[r'(vert|ind)ices$', (Match m) => '${m[1]}ex'],
[r'(matr)ices$', (Match m) => '${m[1]}ix'],
[r'(quiz)zes$', (Match m) => m[1]],
[r'(database)s$', (Match m) => m[1]]
]
.reversed
.forEach((rule) => addInflectionRule(rule.first as String, rule.last));
}
void addInflectionRule(String plural, dynamic singular) {
_inflectionRules.add([new RegExp(plural, caseSensitive: false), singular]);
}
void addIrregularInflectionRule(String singular, String plural) {
final s0 = singular.substring(0, 1);
final srest = singular.substring(1);
final p0 = plural.substring(0, 1);
final prest = plural.substring(1);
if (s0.toUpperCase() == p0.toUpperCase()) {
addInflectionRule('(${s0})${srest}\$', (Match m) => '${m[1]}${srest}');
addInflectionRule('(${p0})${prest}\$', (Match m) => '${m[1]}${srest}');
} else {
addInflectionRule('${s0.toUpperCase()}(?i)${srest}\$',
(Match m) => '${s0.toUpperCase()}${srest}');
addInflectionRule('${s0.toLowerCase()}(?i)${srest}\$',
(Match m) => '${s0.toUpperCase()}${srest}');
addInflectionRule('${p0.toUpperCase()}(?i)${prest}\$',
(Match m) => '${s0.toUpperCase()}${srest}');
addInflectionRule('${p0.toLowerCase()}(?i)${prest}\$',
(Match m) => '${s0.toLowerCase()}${srest}');
}
}
@override
String convert(String word) {
if (!word.isEmpty) {
if (uncountableNouns.contains(word.toLowerCase())) {
return word;
} else {
for (var r in _inflectionRules) {
var pattern = r.first as RegExp;
if (pattern.hasMatch(word)) {
return word.replaceAllMapped(pattern, r.last as MatchToString);
}
}
}
}
return word;
}
}
final Converter<String, String> SINGULAR = new SingularEncoder();

View file

@ -0,0 +1,46 @@
//library inflection2.singular_verb;
import 'dart:convert';
import 'irregular_plural_verbs.dart';
import 'util.dart';
class SingularVerbEncoder extends Converter<String, String> {
final List<List> _inflectionRules = [];
SingularVerbEncoder() {
irregularPluralVerbs.forEach((singular, plural) {
addInflectionRule(plural, (Match m) => singular);
});
[
[r'$', (Match m) => 's'],
[r'([^aeiou])y$', (Match m) => '${m[1]}ies'],
[r'(z)$', (Match m) => '${m[1]}es'],
[r'(ss|zz|x|h|o|us)$', (Match m) => '${m[1]}es'],
[r'(ed)$', (Match m) => '${m[1]}']
]
.reversed
.forEach((rule) => addInflectionRule(rule.first as String, rule.last));
}
void addInflectionRule(String singular, dynamic plural) {
_inflectionRules.add([new RegExp(singular, caseSensitive: false), plural]);
}
@override
String convert(String word) {
if (!word.isEmpty) {
for (var r in _inflectionRules) {
var pattern = r.first as RegExp;
if (pattern.hasMatch(word)) {
return word.replaceAllMapped(pattern, r.last as MatchToString);
}
}
}
return word;
}
}
final Converter<String, String> SINGULARVERB = new SingularVerbEncoder();

View file

@ -0,0 +1,24 @@
//library inflection2.snake_case;
import 'dart:convert';
final _underscoreRE0 = new RegExp(r'''([A-Z\d]+)([A-Z][a-z])''');
final _underscoreRE1 = new RegExp(r'''([a-z\d])([A-Z])''');
final _underscoreRE2 = new RegExp(r'[-\s]');
class SnakeCaseEncoder extends Converter<String, String> {
const SnakeCaseEncoder();
/// Converts the input [phrase] to 'spinal case', i.e. a hyphen-delimited,
/// lowercase form. Also known as 'kebab case' or 'lisp case'.
@override
String convert(String phrase) {
return phrase
.replaceAllMapped(_underscoreRE0, (match) => "${match[1]}_${match[2]}")
.replaceAllMapped(_underscoreRE1, (match) => "${match[1]}_${match[2]}")
.replaceAll(_underscoreRE2, "_")
.toLowerCase();
}
}
const Converter<String, String> SNAKE_CASE = const SnakeCaseEncoder();

View file

@ -0,0 +1,24 @@
//library inflection2.spinal_case;
import 'dart:convert';
final _underscoreRE0 = new RegExp(r'''([A-Z\d]+)([A-Z][a-z])''');
final _underscoreRE1 = new RegExp(r'''([a-z\d])([A-Z])''');
final _underscoreRE2 = new RegExp(r'[_\s]');
class SpinalCaseEncoder extends Converter<String, String> {
const SpinalCaseEncoder();
/// Converts the input [phrase] to 'spinal case', i.e. a hyphen-delimited,
/// lowercase form. Also known as 'kebab case' or 'lisp case'.
@override
String convert(String phrase) {
return phrase
.replaceAllMapped(_underscoreRE0, (match) => "${match[1]}-${match[2]}")
.replaceAllMapped(_underscoreRE1, (match) => "${match[1]}-${match[2]}")
.replaceAll(_underscoreRE2, "-")
.toLowerCase();
}
}
const Converter<String, String> SPINAL_CASE = const SpinalCaseEncoder();

View file

@ -0,0 +1,16 @@
//library inflection2.uncountable;
/// Uncountable nouns are substances, concepts etc that we cannot divide into
/// separate elements. We cannot "count" them.
final Set<String> uncountableNouns = new Set.from(const [
"equipment",
"information",
"rice",
"money",
"species",
"series",
"fish",
"sheep",
"jeans",
"police"
]);

View file

@ -0,0 +1 @@
typedef MatchToString = String Function(Match m);

View file

@ -0,0 +1,21 @@
//library inflection2.verbs_ending_with_ed;
/// A collection of verbs ending with -ed.
final List<String> verbsEndingWithEd = const [
"bed",
"bleed",
"breed",
"embed",
"exceed",
"feed",
"heed",
"need",
"proceed",
"seed",
"shred"
"speed",
"succeed",
"ted",
"wed",
"weed"
];

View file

@ -0,0 +1,9 @@
name: inflection2
version: 1.0.0
description: Grammatical Inflection encoders.
homepage: https://github.com/thosakwe/dart-inflection
publish_to: none
environment:
sdk: '>=2.12.0 <3.0.0'
dev_dependencies:
test: ^1.17.3

View file

@ -0,0 +1,21 @@
import 'inflection_test.dart' as inflection_test;
import 'past_test.dart' as past_test;
import 'plural_test.dart' as plural_test;
import 'plural_verb_test.dart' as plural_verb_test;
import 'singular_test.dart' as singular_test;
import 'singular_verb_test.dart' as singular_verb_test;
import 'snake_case_test.dart' as snake_case_test;
import 'spinal_case_test.dart' as spinal_case_test;
import 'is_tense_test.dart' as is_tense_test;
void main() {
inflection_test.main();
past_test.main();
plural_test.main();
plural_verb_test.main();
singular_test.main();
singular_verb_test.main();
snake_case_test.main();
spinal_case_test.main();
is_tense_test.main();
}

View file

@ -0,0 +1,18 @@
library inflection.test;
import 'package:test/test.dart';
import '../lib/inflection2.dart';
void main() {
group("The inflection library", () {
test("provides a few convenient helper functions", () {
expect(pluralize("axis"), equals("axes"));
expect(convertToPlural("axis"), equals("axes"));
expect(singularize("Houses"), equals("House"));
expect(convertToSingular("Houses"), equals("House"));
expect(convertToSnakeCase("CamelCase"), equals("camel_case"));
expect(convertToSpinalCase("CamelCase"), equals("camel-case"));
});
});
}

View file

@ -0,0 +1,16 @@
library inflection.is_tense.test;
import 'package:test/test.dart';
import '../lib/inflection2.dart';
void main() {
group("isTense", () {
test('correctly identifies if a word is in past tense', () {
expect(isPastTense('run'), false);
expect(isPastTense('ran'), true);
expect(isPastTense('PusHed'), true);
expect(isPastTense('PusH'), false);
});
});
}

View file

@ -0,0 +1,46 @@
library inflection.past.test;
import 'package:test/test.dart';
import '../lib/src/irregular_past_verbs.dart';
import '../lib/src/past.dart';
void main() {
group("The PastEncoder", () {
test("converts verbs from present or participle to past", () {
expect(PAST.convert(""), equals(""));
expect(PAST.convert("ask"), equals("asked"));
expect(PAST.convert("close"), equals("closed"));
expect(PAST.convert("die"), equals("died"));
expect(PAST.convert("phone"), equals("phoned"));
expect(PAST.convert("play"), equals("played"));
expect(PAST.convert("destroy"), equals("destroyed"));
expect(PAST.convert("show"), equals("showed"));
expect(PAST.convert("marry"), equals("married"));
expect(PAST.convert("study"), equals("studied"));
expect(PAST.convert("visit"), equals("visited"));
expect(PAST.convert("miss"), equals("missed"));
expect(PAST.convert("watch"), equals("watched"));
expect(PAST.convert("finish"), equals("finished"));
expect(PAST.convert("fix"), equals("fixed"));
expect(PAST.convert("buzz"), equals("buzzed"));
expect(PAST.convert("asked"), equals("asked"));
expect(PAST.convert("closed"), equals("closed"));
expect(PAST.convert("reopened"), equals("reopened"));
expect(PAST.convert("unseed"), equals("unseeded"));
});
test("handles irregular past verbs", () {
irregularPastVerbs.forEach((String presentOrParticiple, String past) {
expect(PAST.convert(presentOrParticiple), equals(past));
});
expect(PAST.convert("forgo"), equals("forwent"));
expect(PAST.convert("undo"), equals("undid"));
expect(PAST.convert("outsell"), equals("outsold"));
expect(PAST.convert("rebreed"), equals("rebred"));
expect(PAST.convert("arose"), equals("arose"));
expect(PAST.convert("backslid"), equals("backslid"));
expect(PAST.convert("forbade"), equals("forbade"));
});
});
}

View file

@ -0,0 +1,66 @@
library inflection.plural.test;
import 'package:test/test.dart';
import '../lib/inflection2.dart';
import '../lib/src/uncountable_nouns.dart';
void main() {
group("The PluralEncoder", () {
test("converts nouns from singular to plural", () {
expect(PLURAL.convert(""), equals(""));
expect(PLURAL.convert("House"), equals("Houses"));
expect(PLURAL.convert("house"), equals("houses"));
expect(PLURAL.convert("dog"), equals("dogs"));
expect(PLURAL.convert("axis"), equals("axes"));
expect(PLURAL.convert("testis"), equals("testes"));
expect(PLURAL.convert("octopus"), equals("octopi"));
expect(PLURAL.convert("virus"), equals("viri"));
expect(PLURAL.convert("octopi"), equals("octopi"));
expect(PLURAL.convert("viri"), equals("viri"));
expect(PLURAL.convert("alias"), equals("aliases"));
expect(PLURAL.convert("status"), equals("statuses"));
expect(PLURAL.convert("bus"), equals("buses"));
expect(PLURAL.convert("buffalo"), equals("buffaloes"));
expect(PLURAL.convert("tomato"), equals("tomatoes"));
expect(PLURAL.convert("ultimatum"), equals("ultimata"));
expect(PLURAL.convert("pentium"), equals("pentia"));
expect(PLURAL.convert("ultimata"), equals("ultimata"));
expect(PLURAL.convert("pentia"), equals("pentia"));
expect(PLURAL.convert("nemesis"), equals("nemeses"));
expect(PLURAL.convert("hive"), equals("hives"));
expect(PLURAL.convert("fly"), equals("flies"));
expect(PLURAL.convert("dish"), equals("dishes"));
expect(PLURAL.convert("bench"), equals("benches"));
expect(PLURAL.convert("matrix"), equals("matrices"));
expect(PLURAL.convert("vertex"), equals("vertices"));
expect(PLURAL.convert("index"), equals("indices"));
expect(PLURAL.convert("mouse"), equals("mice"));
expect(PLURAL.convert("louse"), equals("lice"));
expect(PLURAL.convert("mice"), equals("mice"));
expect(PLURAL.convert("lice"), equals("lice"));
expect(PLURAL.convert("ox"), equals("oxen"));
expect(PLURAL.convert("ox"), equals("oxen"));
expect(PLURAL.convert("oxen"), equals("oxen"));
expect(PLURAL.convert("quiz"), equals("quizzes"));
});
test("handles uncountable nouns", () {
uncountableNouns.forEach((noun) {
expect(PLURAL.convert(noun), equals(noun));
});
uncountableNouns.forEach((noun) {
final upperNoun = noun.toUpperCase();
expect(PLURAL.convert(upperNoun), equals(upperNoun));
});
});
test("handles irregular plural nouns", () {
expect(PLURAL.convert("person"), equals("people"));
expect(PLURAL.convert("Child"), equals("Children"));
expect(PLURAL.convert("children"), equals("children"));
expect(PLURAL.convert("man"), equals("men"));
});
});
}

View file

@ -0,0 +1,35 @@
library inflection.plural_verb.test;
import 'package:test/test.dart';
import '../lib/src/plural_verb.dart';
void main() {
group("The PluralVerbEncoder", () {
test("converts verbs from singular to plural", () {
expect(PLURALVERB.convert(""), equals(""));
expect(PLURALVERB.convert("eats"), equals("eat"));
expect(PLURALVERB.convert("goes"), equals("go"));
expect(PLURALVERB.convert("boxes"), equals("box"));
expect(PLURALVERB.convert("pays"), equals("pay"));
expect(PLURALVERB.convert("rides"), equals("ride"));
expect(PLURALVERB.convert("writes"), equals("write"));
expect(PLURALVERB.convert("wears"), equals("wear"));
expect(PLURALVERB.convert("steals"), equals("steal"));
expect(PLURALVERB.convert("springs"), equals("spring"));
expect(PLURALVERB.convert("speaks"), equals("speak"));
expect(PLURALVERB.convert("sings"), equals("sing"));
expect(PLURALVERB.convert("buses"), equals("bus"));
expect(PLURALVERB.convert("knows"), equals("know"));
expect(PLURALVERB.convert("hides"), equals("hide"));
expect(PLURALVERB.convert("catches"), equals("catch"));
});
test("handles irregular plural verbs", () {
expect(PLURALVERB.convert("am"), equals("are"));
expect(PLURALVERB.convert("is"), equals("are"));
expect(PLURALVERB.convert("was"), equals("were"));
expect(PLURALVERB.convert("has"), equals("have"));
});
});
}

View file

@ -0,0 +1,65 @@
library inflection.singular.test;
import 'package:test/test.dart';
import '../lib/src/singular.dart';
import '../lib/src/uncountable_nouns.dart';
void main() {
group("The SingularEncoder", () {
test("converts nouns from plural to singular", () {
expect(SINGULAR.convert(""), equals(""));
expect(SINGULAR.convert("Houses"), equals("House"));
expect(SINGULAR.convert("houses"), equals("house"));
expect(SINGULAR.convert("ultimata"), equals("ultimatum"));
expect(SINGULAR.convert("pentia"), equals("pentium"));
expect(SINGULAR.convert("analyses"), equals("analysis"));
expect(SINGULAR.convert("diagnoses"), equals("diagnosis"));
expect(SINGULAR.convert("Parentheses"), equals("Parenthesis"));
expect(SINGULAR.convert("lives"), equals("life"));
expect(SINGULAR.convert("hives"), equals("hive"));
expect(SINGULAR.convert("tives"), equals("tive"));
expect(SINGULAR.convert("shelves"), equals("shelf"));
expect(SINGULAR.convert("qualities"), equals("quality"));
expect(SINGULAR.convert("series"), equals("series"));
expect(SINGULAR.convert("movies"), equals("movie"));
expect(SINGULAR.convert("benches"), equals("bench"));
expect(SINGULAR.convert("fishes"), equals("fish"));
expect(SINGULAR.convert("mice"), equals("mouse"));
expect(SINGULAR.convert("lice"), equals("louse"));
expect(SINGULAR.convert("buses"), equals("bus"));
expect(SINGULAR.convert("shoes"), equals("shoe"));
expect(SINGULAR.convert("testis"), equals("testis"));
expect(SINGULAR.convert("crisis"), equals("crisis"));
expect(SINGULAR.convert("axes"), equals("axis"));
expect(SINGULAR.convert("axis"), equals("axis"));
expect(SINGULAR.convert("viri"), equals("virus"));
expect(SINGULAR.convert("octopi"), equals("octopus"));
expect(SINGULAR.convert("aliases"), equals("alias"));
expect(SINGULAR.convert("statuses"), equals("status"));
expect(SINGULAR.convert("vertices"), equals("vertex"));
expect(SINGULAR.convert("indices"), equals("index"));
expect(SINGULAR.convert("Matrices"), equals("Matrix"));
expect(SINGULAR.convert("quizzes"), equals("quiz"));
expect(SINGULAR.convert("databases"), equals("database"));
});
test("handles uncountable nouns", () {
uncountableNouns.forEach((noun) {
expect(SINGULAR.convert(noun), equals(noun));
});
uncountableNouns.forEach((noun) {
final upperNoun = noun.toUpperCase();
expect(SINGULAR.convert(upperNoun), equals(upperNoun));
});
});
test("handles irregular plural nouns", () {
expect(SINGULAR.convert("people"), equals("person"));
expect(SINGULAR.convert("Children"), equals("Child"));
expect(SINGULAR.convert("child"), equals("child"));
expect(SINGULAR.convert("men"), equals("man"));
});
});
}

View file

@ -0,0 +1,34 @@
library inflection.singular_verb.test;
import 'package:test/test.dart';
import '../lib/src/singular_verb.dart';
void main() {
group("The SingularVerbEncoder", () {
test("converts verbs from singular to plural", () {
expect(SINGULARVERB.convert(""), equals(""));
expect(SINGULARVERB.convert("eat"), equals("eats"));
expect(SINGULARVERB.convert("go"), equals("goes"));
expect(SINGULARVERB.convert("box"), equals("boxes"));
expect(SINGULARVERB.convert("pay"), equals("pays"));
expect(SINGULARVERB.convert("ride"), equals("rides"));
expect(SINGULARVERB.convert("write"), equals("writes"));
expect(SINGULARVERB.convert("wear"), equals("wears"));
expect(SINGULARVERB.convert("steal"), equals("steals"));
expect(SINGULARVERB.convert("spring"), equals("springs"));
expect(SINGULARVERB.convert("speak"), equals("speaks"));
expect(SINGULARVERB.convert("sing"), equals("sings"));
expect(SINGULARVERB.convert("bus"), equals("buses"));
expect(SINGULARVERB.convert("know"), equals("knows"));
expect(SINGULARVERB.convert("hide"), equals("hides"));
expect(SINGULARVERB.convert("catch"), equals("catches"));
});
test("handles irregular plural verbs", () {
expect(SINGULARVERB.convert("are"), equals("is"));
expect(SINGULARVERB.convert("were"), equals("was"));
expect(SINGULARVERB.convert("have"), equals("has"));
});
});
}

View file

@ -0,0 +1,19 @@
library inflection.snake_case.test;
import 'package:test/test.dart';
import '../lib/src/snake_case.dart';
void main() {
group("The SnakeCaseEncoder", () {
test("converts phrases to 'snake_case'", () {
expect(SNAKE_CASE.convert(''), equals(''));
expect(SNAKE_CASE.convert("CamelCaseName"), equals("camel_case_name"));
expect(SNAKE_CASE.convert("propertyName"), equals("property_name"));
expect(SNAKE_CASE.convert("property"), equals("property"));
expect(SNAKE_CASE.convert("lisp-case"), equals("lisp_case"));
expect(SNAKE_CASE.convert("This is a nice article"),
equals("this_is_a_nice_article"));
});
});
}

View file

@ -0,0 +1,19 @@
library inflection.spinal_case.test;
import 'package:test/test.dart';
import '../lib/src/spinal_case.dart';
void main() {
group("The SpinalCaseEncoder", () {
test("converts phrases to 'spinal-case'", () {
expect(SPINAL_CASE.convert(''), equals(''));
expect(SPINAL_CASE.convert("CamelCaseName"), equals("camel-case-name"));
expect(SPINAL_CASE.convert("propertyName"), equals("property-name"));
expect(SPINAL_CASE.convert("property"), equals("property"));
expect(SPINAL_CASE.convert("snake_case"), equals("snake-case"));
expect(SPINAL_CASE.convert("This is a nice article"),
equals("this-is-a-nice-article"));
});
});
}

View file

@ -1,7 +1,7 @@
name: angel_migration
version: 4.0.0
description: Database migration runtime for Angel's ORM. Use this package to define schemas.
homepage: https://github.com/angel-dart/migration
homepage: https://github.com/dukefirehawk/angel
publish_to: none
environment:
sdk: '>=2.12.0 <3.0.0'

View file

@ -1,8 +1,7 @@
name: angel_orm
version: 4.0.0
description: Runtime support for Angel's ORM. Includes base classes for queries.
homepage: https://github.com/angel-dart/orm
environment:
homepage: https://github.com/dukefirehawk/angel
sdk: '>=2.12.0 <3.0.0'
dependencies:
charcode: ^1.2.0

View file

@ -1,8 +1,7 @@
name: angel_orm_generator
version: 3.0.0
version: 4.0.0
description: Code generators for Angel's ORM. Generates query builder classes.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/orm
homepage: https://github.com/dukefirehawk/angel
publish_to: none
environment:
sdk: '>=2.10.0 <3.0.0'
@ -52,7 +51,7 @@ dev_dependencies:
build_runner: ^1.11.5
collection: ^1.0.0
pedantic: ^1.11.0
postgres:
git:
url: https://github.com/dukefirehawk/postgresql-dart
postgres: ^2.2.0
# git:
# url: https://github.com/dukefirehawk/postgresql-dart
test: ^1.16.5