]> gitweb.factorcode.org Git - factor.git/commitdiff
Squashed commit of the following:
authorJohn Benediktsson <mrjbq7@gmail.com>
Thu, 15 Feb 2018 21:21:27 +0000 (13:21 -0800)
committerJohn Benediktsson <mrjbq7@gmail.com>
Thu, 15 Feb 2018 21:21:27 +0000 (13:21 -0800)
commit 429917d51c569b28d43b64f3b116e6b750e77c72
Author: Cat Stevens <catb0t@protonmail.ch>
Date:   Thu Feb 15 15:54:50 2018 -0500

    fix <PRIVATE> inside ARTICLE: ?!?!

commit b93243511c40ca7fd06120d089ead172df46c8b7
Author: Cat Stevens <catb0t@protonmail.ch>
Date:   Wed Feb 14 18:11:26 2018 -0500

    pluralize definition fix

commit e461c08166f98b974ae0e9075331dd388c1bcb48
Author: Cat Stevens <catb0t@protonmail.ch>
Date:   Wed Feb 14 16:28:05 2018 -0500

    update some words

commit 573ba01d6310d64788d13685dfc46099ffddb01b
Author: Cat Stevens <catb0t@protonmail.ch>
Date:   Wed Feb 14 16:06:42 2018 -0500

    remove a useless comment

commit 7733ade275a904449a3c691f4142329aaf73081e
Author: Cat Stevens <catb0t@protonmail.ch>
Date:   Wed Feb 14 14:30:06 2018 -0500

    extra/help.lint.coverage: update doctests because of new 100% coverage in basis/english

commit 9f89d2f5a261188dbd030b868323e3a0e95fb6c8
Author: Cat Stevens <catb0t@protonmail.ch>
Date:   Tue Feb 13 18:51:33 2018 -0500

    basis/english: new words; full help and test coverage

basis/english/authors.txt
basis/english/english-docs.factor [new file with mode: 0644]
basis/english/english-tests.factor
basis/english/english.factor
extra/help/lint/coverage/coverage-docs.factor
extra/math/text/english/english-docs.factor
extra/math/text/english/english-tests.factor
extra/math/text/english/english.factor

index e091bb8164f1cf80e42a2e690478bca041737945..4a2a0fd9d79810853407c22407eb72555a48ed9d 100644 (file)
@@ -1 +1,2 @@
 John Benediktsson
+Cat Stevens
\ No newline at end of file
diff --git a/basis/english/english-docs.factor b/basis/english/english-docs.factor
new file mode 100644 (file)
index 0000000..3f79f86
--- /dev/null
@@ -0,0 +1,209 @@
+! Copyright (C) 2018 Cat Stevens
+USING: arrays assocs help.markup help.syntax kernel math multiline
+sequences strings ;
+IN: english
+
+<PRIVATE
+: $0-plurality ( children -- )
+    drop {
+        "Due to the unique way in which the English language is structured, the number "
+        { $snippet "0" }
+        " is considered plural; "
+        { $snippet "1" }
+        " is the only singular quantity."
+    } print-element ;
+
+: $keep-case ( children -- )
+    drop
+    "This word attempts to preserve the letter case style of the input." print-element ;
+PRIVATE>
+
+ABOUT: "english"
+
+ARTICLE: "english" "English natural language transformations"
+
+"The " { $vocab-link "english" } " vocabulary implements a few simple ways of interacting with text in the English language, for improving generated text."
+$nl
+"Plural and singular forms:"
+{ $subsections plural? pluralize ?pluralize count-of-things singular? singularize }
+
+"Toy grammatical words:"
+{ $subsections a/an ?plural-article a10n comma-list-by simple-comma-list }
+
+"An example application:"
+{ $subsections or-markup-example $or-markup-example } ;
+
+{ pluralize ?pluralize plural? count-of-things singularize singular? } related-words
+{ a/an ?plural-article a10n comma-list-by simple-comma-list $or-markup-example or-markup-example } related-words
+
+HELP: singularize
+{ $values { "word" string } { "singular" string } }
+{ $description "Determine the singular form of the input English word. If the input is already singular, it is returned unchanged." }
+{ $notes $keep-case  }
+{ $examples
+    { $example
+        "USING: english io ;"
+        "\"CATS\" singularize print"
+        "CAT"
+    }
+    { $example
+        "USING: english io ;"
+        "\"Octopi\" singularize print"
+        "Octopus"
+    }
+} ;
+
+HELP: singular?
+{ $values { "word" string } { "?" boolean } }
+{ $description "Attempt to determine whether the word is in singular form." }
+{ $examples
+    { $example
+        "USING: english prettyprint ;"
+        "\"octopi\" plural? ."
+        "t"
+    }
+} ;
+
+HELP: pluralize
+{ $values { "word" string } { "plural" string } }
+{ $description "Determine the plural form of the input English word. If the input is already plural, it " { $emphasis "might" } " be returned unchanged." }
+{ $notes { $list { "If the input is already in plural form, an invaid construct such as " { $emphasis "friendses" } " may be generated. This is difficult to avoid due to the unpredictable structure of the English language." } $keep-case } }
+{ $examples
+    { $example
+        "USING: english io ;"
+        "\"CAT\" pluralize print"
+        "CATS"
+    }
+    { $example
+        "USING: english io ;"
+        "\"Octopus\" pluralize print"
+        "Octopi"
+    }
+} ;
+
+HELP: plural?
+{ $values { "word" string } { "?" boolean } }
+{ $description "Attempt to determine whether the word is in plural form." }
+{ $examples
+    { $example
+        "USING: english prettyprint ;"
+        "\"octopus\" singular? ."
+        "t"
+    }
+} ;
+
+HELP: count-of-things
+{ $values { "count" number } { "word" string } { "str" string } }
+{ $description "Transform a quantity and a word into a construct consisting of the quantity, and the correct plural or singular form of the word. " { $snippet "word" } " is expected to be in singular form." }
+{ $notes { $list $keep-case $0-plurality } }
+{ $examples
+    { $example
+        "USING: english io ;"
+        "10 \"baby\" count-of-things print"
+        "10 babies"
+    }
+    { $example
+        "USING: english io ;"
+        "2.5 \"FISH\" count-of-things print"
+        "2.5 FISH"
+    }
+} ;
+
+HELP: ?pluralize
+{ $values { "count" number } { "singular" string } { "singluar/plural" string } }
+{ $description "A simpler variant of " { $link count-of-things } " which omits its input value from the output. As with " { $link count-of-things } ", " { $snippet "word" } " is expected to be in singular form." }
+{ $notes { $list $keep-case $0-plurality } }
+{ $examples
+    { $example
+        "USING: english io ;"
+        "14 \"criterion\" ?pluralize print"
+        "criteria"
+    }
+} ;
+
+HELP: a10n
+{ $values { "word" string } { "numeronym" string } }
+{ $description "Abbreviates a word of more than three characters, by replacing the inner part of the word with the number of omitted letters. The result is an abbreviation (called a " { $emphasis "numeronym" } ") which is pronounced like the original word." }
+{ $notes { $list
+    $keep-case
+    "When the input is too short, it is returned unchanged."
+    { "The name of this word is " { $snippet "abbreviation" } ", abbreviated by its own strategy." }
+    { "This style of abbreviation originated with " { $snippet "i18n" } " (the word " { $emphasis "internationalization" } ") in the 1980s." }
+} }
+{ $examples
+    { $example
+        "USING: english io ;"
+        "\"dup\" a10n print"
+        "dup"
+    }
+    { $example
+        "USING: english io ;"
+        "\"abbreviationalism\" a10n print"
+        "a15m"
+    }
+} ;
+
+HELP: a/an
+{ $values { "word" string } { "article" { $or-markup-example "\"a\"" "\"an\"" } } }
+{ $description "Gives the proper indefinite singular article (" { $emphasis "a" } " or " { $emphasis "an" } ") for the word. For words which begin with a vowel sound, " { $emphasis "an" } " is used, whereas " { $emphasis "a" } " is used for words which begin with a consonant sound." }
+{ $notes "The output does not contain the input. The output of this word is always a singular article, regardless of the plurality of the input." }
+{ $examples
+    { $example
+        "USING: english kernel combinators sequences io ;"
+        "\"object\" [ a/an ] keep \" \" glue print"
+        "an object"
+    }
+} ;
+
+HELP: ?plural-article
+{ $values { "word" string } { "article" { $or-markup-example "\"a\"" "\"an\"" "\"the\"" } } }
+{ $description "Output the proper article given the plurality and first letter of the input. Unlike " { $link a/an } " this word handles plural inputs by outputting the definite " { $emphasis "\"the\"" } ". If the input is singular as determined by " { $link singular? } " this word operates like " { $link a/an } "." }
+{ $notes { $list "English lacks a plural indefinite article, so the plural definite is used here instead." $keep-case $0-plurality } }
+{ $examples
+    { $example
+        "USING: english sequences kernel io ;"
+        "\"cat\" [ ?plural-article ] keep \" \" glue print"
+        "a cat"
+    }
+    { $example
+        "USING: english sequences kernel io ;"
+        "\"cats\" [ ?plural-article ] keep \" \" glue print"
+        "the cats"
+    }
+} ;
+
+HELP: comma-list-by
+{ $values
+    { "parts" sequence }
+    { "quot" { $quotation ( part index -- newpart ) } }
+    { "conjunction" string }
+    { "clause-seq" sequence }
+}
+{ $description "Generate a comma-separated list of things from the result of applying " { $snippet "quot" } " to each element in "  { $snippet "parts" } ", emplacing " { $snippet "conjunction" } " before the last " { $snippet "part" } " if there are two or more elements in " { $snippet "parts" } "." }
+{ $notes $keep-case }
+{ $examples { "See the examples in " { $link $or-markup-example } " and " { $link simple-comma-list } "." } } ;
+
+HELP: simple-comma-list
+{ $values { "parts" sequence } { "conjunction" string } { "parts'" sequence } }
+{ $description "Punctuate and conjunctionize the input words into a comma-separated list construction." }
+{ $examples
+    { $example
+        "USING: english io sequences splitting ;"
+        "{ \"a cat\" \"a peach\" \"an object\" } \"or\" simple-comma-list [ \"\" join ] map \"\" join print"
+        "a cat, a peach, or an object"
+    }
+} ;
+
+HELP: or-markup-example
+{ $values { "markup" "a sequence of markup elements" } { "classes" "a sequence of words" } }
+{ $description "Used to implement " { $link $or-markup-example } " and demonstrate " { $link comma-list-by } "." }
+{ $examples { "See the examples in " { $link $or-markup-example } "." } } ;
+
+HELP: $or-markup-example
+{ $values { "classes" "a sequence of words" } }
+{ $description "An example to demonstrate a use-case for " { $link comma-list-by } ". Works like the " { $link $or } " and " { $link ($instance) } " words from " { $vocab-link "help.markup" } "." }
+{ $examples
+    { $markup-example
+        { $or-markup-example "cat" "octopus" "animal" object pair number array string sequence assoc "bird" } print-element
+    }
+} ;
index e65b247c6e422f05f92a7319936a3b7117cedf7b..5708201515ddfe32ea77e449d4d78c31433c6f7f 100644 (file)
-USE: tools.test
+USING: accessors arrays assocs english.private help.markup kernel math
+math.parser sequences strings tools.test ;
 IN: english
 
-{ "record" } [ "records" singularize ] unit-test
-{ "FOOT" } [ "FEET" singularize ] unit-test
+{ "record" }  [ "records" singularize ] unit-test
+{ "record" }  [ "record" singularize ] unit-test
+{ "baby" }    [ "babies" singularize ] unit-test
+{ "baby" }    [ "baby" singularize ] unit-test
+{ "FOOT" }    [ "FEET" singularize ] unit-test
+{ "FOOT" }    [ "FOOT" singularize ] unit-test
+{ "cactus" }  [ "cacti" singularize ] unit-test
+{ "cactus" }  [ "cactuses" singularize ] unit-test
+{ "octopus" } [ "octopi" singularize ] unit-test
+{ "octopus" } [ "octopuses" singularize ] unit-test
 
 { "friends" } [ "friend" pluralize ] unit-test
+{ "friendlies" } [ "friendly" pluralize ] unit-test
+{ "friendlies" } [ "friendlies" pluralize ] unit-test
 { "enemies" } [ "enemy" pluralize ] unit-test
-{ "Sheep" } [ "Sheep" pluralize ] unit-test
+{ "Sheep" }   [ "Sheep" pluralize ] unit-test
+{ "Moose" }   [ "Moose" pluralize ] unit-test
+{ "cacti" }   [ "cactus" pluralize ] unit-test
+{ "octopi" }  [ "octopus" pluralize ] unit-test
 
-{ "a10n" } [ "abbreviation" a10n ] unit-test
-{ "i18n" } [ "internationalization" a10n ] unit-test
+{ t } [ "singular" singular? ] unit-test
+{ f } [ "singulars" singular? ] unit-test
+{ t } [ "singularity" singular? ] unit-test
+{ f } [ "singularities" singular? ] unit-test
+{ t } [ "thesis" singular? ] unit-test
+{ f } [ "theses" singular? ] unit-test
+{ t } [ "goose" singular? ] unit-test
+{ t } [ "baby" singular? ] unit-test
+{ t } [ "bird" singular? ] unit-test
+{ f } [ "birds" singular? ] unit-test
+{ t } [ "octopus" singular? ] unit-test
+{ f } [ "octopi" singular? ] unit-test
+
+{ t } [ "geese" plural? ] unit-test
+{ f } [ "goose" plural? ] unit-test
+{ t } [ "birds" plural? ] unit-test
+{ f } [ "bird" plural? ] unit-test
+{ t } [ "cats" plural? ] unit-test
+{ f } [ "cat" plural? ] unit-test
+{ t } [ "babies" plural? ] unit-test
+{ f } [ "baby" plural? ] unit-test
+{ t } [ "octopi" plural? ] unit-test
+{ f } [ "octopus" plural? ] unit-test
+
+! they are both singular and plural
+{ t } [ "moose" plural? ] unit-test
+{ t } [ "moose" singular? ] unit-test
+{ t } [ "sheep" plural? ] unit-test
+{ t } [ "sheep" singular? ] unit-test
 
 { "3 babies" } [ 3 "baby" count-of-things ] unit-test
-{ "1 pipe" } [ 1 "pipe" count-of-things ] unit-test
-{ "0 pipes" } [ 0 "pipe" count-of-things ] unit-test
+{ "2.5 cats" } [ 2.5 "cat" count-of-things ] unit-test
+{ "2.5 CATS" } [ 2.5 "CAT" count-of-things ] unit-test
+{ "1 pipe" }   [ 1 "pipe" count-of-things ] unit-test
+{ "0 pipes" }  [ 0 "pipe" count-of-things ] unit-test
+
+{ "babies" } [ 3 "baby" ?pluralize ] unit-test
+{ "BABIES" } [ 3 "BABY" ?pluralize ] unit-test
+{ "cats" } [ 2.5 "cat"  ?pluralize ] unit-test
+{ "Cats" } [ 2.5 "Cat"  ?pluralize ] unit-test
+{ "pipe" } [ 1 "pipe"   ?pluralize ] unit-test
+{ "pipes" } [ 0 "pipe"  ?pluralize ] unit-test
+
+{ "a5s" }     [ "address" a10n ] unit-test
+{ "a10n" }    [ "abbreviation" a10n ] unit-test
+{ "l10n" }    [ "localization" a10n ] unit-test
+{ "i18n" }    [ "internationalization" a10n ] unit-test
+{ "f28n" }    [ "floccinauccinihilipilification" a10n ] unit-test
+{ "p43s" }    [ "pneumonoultramicroscopicsilicovolcanoconiosis" a10n ] unit-test
+{ "a10000c" } [ 10000 CHAR: b <string> "a" "c" surround a10n ] unit-test
+
+{ "an" } [ "object" a/an ] unit-test
+{ "an" } [ "elephant" a/an ] unit-test
+{ "a" }  [ "moose" a/an ] unit-test
+{ "a" }  [ "xylophone" a/an ] unit-test
+
+{ "the" } [ "objects" ?plural-article ] unit-test
+{ "an" }  [ "object" ?plural-article ] unit-test
+{ "the" } [ "elephants" ?plural-article ] unit-test
+{ "an" }  [ "elephant" ?plural-article ] unit-test
+{ "a" }   [ "moose" ?plural-article ] unit-test
+{ "a" }   [ "goose" ?plural-article ] unit-test
+{ "the" } [ "geese" ?plural-article ] unit-test
+{ "a" }   [ "sheep" ?plural-article ] unit-test
+
+{ { "" } }
+    [ { } "or" simple-comma-list ] unit-test
+
+{ { { "a" } } }
+    [ { "a" } "or" simple-comma-list ] unit-test
+
+{ { { "a" } { " or " "b" } } }
+    [ { "a" "b" } "or" simple-comma-list ] unit-test
+
+{ { { "a" ", " } { "b" } { ", or " "c" } } }
+    [ { "a" "b" "c" } "or" simple-comma-list ] unit-test
+
+{ { { "a" ", " } { "b" ", " } { "x" } { ", and " "c" } } }
+    [ { "a" "b" "x" "c" } "and" simple-comma-list ] unit-test
+
+{ {
+    { "an " { $link object } ", " }
+    { "a " { $link pair } ", " }
+    { "a " { $link number } ", " }
+    { "an " { $link array } ", " }
+    { "a " { $link string } ", " }
+    { "a " { $link sequence } }
+    { ", or " "an " { $link assoc } }
+} } [
+    { object pair number array string sequence assoc }
+    or-markup-example
+    ! an object, a pair, a number, an array, a string, a sequence, or an assoc
+] unit-test
+
+{ {
+    { "an " { $link object } }
+} } [ { object } or-markup-example ] unit-test
+
+{ {
+    { "an " { $link object } }
+    { " or " "a " { $link pair } }
+} } [ { object pair } or-markup-example ] unit-test
index 488e34af1a56291881ea4f53b28c556235137439..55a8840c20c726d180c6911f75d94dc4c1ff24b5 100644 (file)
@@ -1,7 +1,8 @@
-! Copyright (C) 2015 John Benediktsson
+! Copyright (C) 2015, 2018 John Benediktsson
 ! See http://factorcode.org/license.txt for BSD license
-USING: assocs assocs.extras combinators formatting kernel literals
-locals math math.parser sequences splitting unicode ;
+USING: arrays accessors assocs assocs.extras combinators fry formatting kernel
+literals locals math math.parser sequences splitting words unicode ;
+USE: help.markup
 
 IN: english
 
@@ -14,6 +15,7 @@ CONSTANT: singular-to-plural H{
     ! us -> i
     { "alumnus" "alumni" }
     { "cactus" "cacti" }
+    { "octopus" "octopi" }
     { "focus" "foci" }
     { "fungus" "fungi" }
     { "nucleus" "nuclei" }
@@ -141,11 +143,57 @@ PRIVATE>
         [ "s" append ]
     } cond match-case ;
 
+: singular? ( word -- ? )
+    [ singularize ] [ = ] bi ;
+
+: plural? ( word -- ? )
+    [ singularize pluralize ] [ = ] bi ;
+
 : count-of-things ( count word -- str )
-    over 1 = [ pluralize ] unless "%d %s" sprintf ;
+    over 1 = [ pluralize ] unless [ number>string ] dip " " glue ;
 
-: a10n ( str -- str' )
+: ?pluralize ( count singular -- singular/plural )
+    swap 1 = [ pluralize ] unless ;
+
+: a10n ( word -- numeronym )
     dup length 3 > [
         [ 1 head ] [ length 2 - number>string ] [ 1 tail* ] tri
         3append
     ] when ;
+
+: a/an ( word -- article )
+    [ first ] [ length ] bi 1 = "afhilmnorsx" "aeiou" ?
+    member? "an" "a" ? ;
+
+: ?plural-article ( word -- article )
+    dup singular? [ a/an ] [ drop "the" ] if ;
+
+: comma-list-by ( parts quot conjunction  -- clause-seq )
+    ! using map-index for maximum flexibility
+    [ '[ _ call( x n -- x ) ] map-index
+        ! not using oxford comma for 2 objects: "a, or b"; instead it's "a or b"
+        dup length 2 > ", " " " ? " "
+    ] dip glue
+
+    over length {
+        { [ dup 0 = ] [ 3drop { "" } ] }
+        { [ dup 1 = ] [ 2drop ] }
+        [ drop [ unclip-last [
+                dup length 1 - '[ _ - zero? [ ", " suffix ] unless ] map-index
+            ] dip ] dip prefix suffix
+        ]
+    } cond ;
+
+: simple-comma-list ( parts conjunction -- parts' )
+    [ drop 1array ] swap comma-list-by ;
+
+: or-markup-example ( classes -- markup )
+    [ drop dup word? [
+            [ name>> a/an " " append ] [ \ $link swap 2array ] bi 2array
+        ] [
+            [ "\"" ?head drop a/an ] keep 1array \ $snippet prefix " " swap 3array
+        ] if
+    ] "or" comma-list-by ;
+
+: $or-markup-example ( classes -- )
+    or-markup-example print-element ;
index c591786629b7b5dcabea1d3bc47a36436dcb9dbe..3509d3423ed7f7e33bb52d054e54caaae6366f28 100644 (file)
@@ -72,12 +72,21 @@ HELP: vocab-help-coverage.
     { $example
         "USING: help.lint.coverage ;"
         "\"english\" vocab-help-coverage."
-"[english] a10n: needs help sections: $description $examples
-[english] count-of-things: needs help sections: $description $examples
-[english] pluralize: needs help sections: $description $examples
-[english] singularize: needs help sections: $description $examples
+"[english] $or-markup-example: full help coverage
+[english] ?plural-article: full help coverage
+[english] ?pluralize: full help coverage
+[english] a/an: full help coverage
+[english] a10n: full help coverage
+[english] comma-list-by: full help coverage
+[english] count-of-things: full help coverage
+[english] or-markup-example: full help coverage
+[english] plural?: full help coverage
+[english] pluralize: full help coverage
+[english] simple-comma-list: full help coverage
+[english] singular?: full help coverage
+[english] singularize: full help coverage
 
-0.0% of words have complete documentation"
+100.0% of words have complete documentation"
     }
 } ;
 
@@ -88,15 +97,26 @@ HELP: prefix-help-coverage.
     { $example
         "USING: help.lint.coverage ;"
         "\"english\" t prefix-help-coverage."
-"[english] a10n: needs help sections: $description $examples
-[english] count-of-things: needs help sections: $description $examples
-[english] pluralize: needs help sections: $description $examples
-[english] singularize: needs help sections: $description $examples
+"[english] $or-markup-example: full help coverage
+[english] ?plural-article: full help coverage
+[english] ?pluralize: full help coverage
+[english] a/an: full help coverage
+[english] a10n: full help coverage
+[english] comma-list-by: full help coverage
+[english] count-of-things: full help coverage
+[english] or-markup-example: full help coverage
+[english] plural?: full help coverage
+[english] pluralize: full help coverage
+[english] simple-comma-list: full help coverage
+[english] singular?: full help coverage
+[english] singularize: full help coverage
+[english.private] $0-plurality: needs help sections: $description $examples
+[english.private] $keep-case: needs help sections: $description $examples
 [english.private] match-case: needs help sections: $description $examples
 [english.private] plural-to-singular: needs help sections: $description $examples
 [english.private] singular-to-plural: needs help sections: $description $examples
 
-0.0% of words have complete documentation"
+72.2% of words have complete documentation"
     }
 } ;
 
@@ -106,22 +126,66 @@ HELP: <prefix-help-coverage>
 { $examples
     { $example
         "USING: help.lint.coverage prettyprint ;"
-        "\"english\" t <prefix-help-coverage> ."
+        "\"english\" t <prefix-help-coverage> ..."
 "{
+    T{ word-help-coverage
+        { word-name $or-markup-example }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name ?plural-article }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name ?pluralize }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name a/an }
+        { 100%-coverage? t }
+    }
     T{ word-help-coverage
         { word-name a10n }
-        { omitted-sections { $description $examples } }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name comma-list-by }
+        { 100%-coverage? t }
     }
     T{ word-help-coverage
         { word-name count-of-things }
-        { omitted-sections { $description $examples } }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name or-markup-example }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name plural? }
+        { 100%-coverage? t }
     }
     T{ word-help-coverage
         { word-name pluralize }
-        { omitted-sections { $description $examples } }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name simple-comma-list }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name singular? }
+        { 100%-coverage? t }
     }
     T{ word-help-coverage
         { word-name singularize }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name $0-plurality }
+        { omitted-sections { $description $examples } }
+    }
+    T{ word-help-coverage
+        { word-name $keep-case }
         { omitted-sections { $description $examples } }
     }
     T{ word-help-coverage
@@ -146,7 +210,7 @@ HELP: <word-help-coverage>
 { $examples
     { $example
         "USING: help.lint.coverage prettyprint ;"
-        "\\ <word-help-coverage> <word-help-coverage> ."
+        "\\ <word-help-coverage> <word-help-coverage> ..."
 "T{ word-help-coverage
     { word-name <word-help-coverage> }
     { 100%-coverage? t }
@@ -160,23 +224,59 @@ HELP: <vocab-help-coverage>
 { $examples
     { $example
         "USING: help.lint.coverage prettyprint ;"
-        "\"english\" <vocab-help-coverage> ."
+        "\"english\" <vocab-help-coverage> ..."
 "{
+    T{ word-help-coverage
+        { word-name $or-markup-example }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name ?plural-article }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name ?pluralize }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name a/an }
+        { 100%-coverage? t }
+    }
     T{ word-help-coverage
         { word-name a10n }
-        { omitted-sections { $description $examples } }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name comma-list-by }
+        { 100%-coverage? t }
     }
     T{ word-help-coverage
         { word-name count-of-things }
-        { omitted-sections { $description $examples } }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name or-markup-example }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name plural? }
+        { 100%-coverage? t }
     }
     T{ word-help-coverage
         { word-name pluralize }
-        { omitted-sections { $description $examples } }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name simple-comma-list }
+        { 100%-coverage? t }
+    }
+    T{ word-help-coverage
+        { word-name singular? }
+        { 100%-coverage? t }
     }
     T{ word-help-coverage
         { word-name singularize }
-        { omitted-sections { $description $examples } }
+        { 100%-coverage? t }
     }
 }"
     }
index 5bd24c3e98e40fdf102f419faa2eeb30092825e5..2c72c56ee7e6407589a6ec75c10e0446be397028 100644 (file)
@@ -3,5 +3,16 @@ IN: math.text.english
 
 HELP: number>text
 { $values { "n" integer } { "str" string } }
-{ $description "Converts an integer to a text string representation in English, including appropriate punctuation and conjunctions." }
+{ $contract "Converts an integer to a text string representation in English, including appropriate punctuation and conjunctions." }
 { $examples { $example "USING: math.text.english prettyprint ;" "12345 number>text ." "\"twelve thousand, three hundred and forty-five\"" } } ;
+
+HELP: ordinal-suffix
+{ $values { "n" number } { "suffix" string } }
+{ $description "Determine the ordinal suffix for the input number. Non-integral numbers get the ordinal suffix of their integral part." }
+{ $examples
+    { $example
+        "USING: kernel math.parser math.text.english prettyprint sequences ;"
+        "783 [ number>string ] [ ordinal-suffix ] bi append ."
+        "\"783rd\""
+    }
+} ;
index 53e33cdc7975bc993c469fa185d29b6c649dfc66..4a455abd43deef5968ca0b139ce720a79aa74306 100644 (file)
@@ -1,4 +1,5 @@
-USING: math.functions math.text.english tools.test ;
+USING: kernel math.functions math.parser math.text.english
+sequences tools.test ;
 
 { "zero" } [ 0 number>text ] unit-test
 { "twenty-one" } [ 21 number>text ] unit-test
@@ -12,3 +13,30 @@ USING: math.functions math.text.english tools.test ;
 { "one duotrigintillion" } [ 10 99 ^ number>text ] unit-test
 
 { "negative one hundred and twenty-three" } [ -123 number>text ] unit-test
+
+{ "0th" } [ 0 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "1st" } [ 1 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "2nd" } [ 2 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "3rd" } [ 3 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "4th" } [ 4 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "5th" } [ 5 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "6th" } [ 6 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "7th" } [ 7 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "10th" } [ 10 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "11th" } [ 11 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "12th" } [ 12 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "13th" } [ 13 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "101st" } [ 101 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "110th" } [ 110 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "111th" } [ 111 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "112th" } [ 112 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "113th" } [ 113 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+
+{ "-101st" } [ -101 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "-110th" } [ -110 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "-111th" } [ -111 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "-112th" } [ -112 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+{ "-113th" } [ -113 [ number>string ] [ ordinal-suffix ] bi append ] unit-test
+
+{ "th" } [ 13.5 ordinal-suffix ] unit-test
+{ "th" } [ 9+1/3 ordinal-suffix ] unit-test
index 5a4d7ae0f900afe6967760002583f75ddcdf10e4..0de9903d360212136a2b8ec5e7823a3b57668355 100644 (file)
@@ -1,8 +1,8 @@
-! Copyright (c) 2007, 2008 Aaron Schaefer.
+! Copyright (c) 2007, 2008, 2018 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: combinators.short-circuit grouping kernel math
-math.functions math.parser math.text.utils namespaces sequences
-splitting ;
+USING: combinators combinators.short-circuit grouping kernel
+math math.functions math.parser math.order math.text.utils namespaces
+sequences splitting ;
 IN: math.text.english
 
 <PRIVATE
@@ -112,3 +112,13 @@ M: complex number>text
         [ 0 < " minus " " plus " ? ]
         [ abs number>text " i" append ] bi
     ] bi* 3append ;
+
+: ordinal-suffix ( n -- suffix )
+    abs dup 100 mod 11 13 between? [ drop "th" ] [
+        10 mod {
+            { 1 [ "st" ] }
+            { 2 [ "nd" ] }
+            { 3 [ "rd" ] }
+            [ drop "th" ]
+        } case
+    ] if ;