... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

(.require
 [library
  [lux (.except)
   ["$" documentation]
   [data
    [collection
     ["[0]" list (.use "[1]#[0]" monoid)]]]
   [meta
    [macro
     ["[0]" template]]]]]
 ["[0]" /
  ["[1][0]" buffer]
  ["[1][0]" encoding]
  ["[1][0]" escape]
  ["[1][0]" regex]
  ["[1][0]" unicode]]
 ["[0]" \\injection]
 ["[0]" \\projection]
 [\\library
  ["[0]" / (.only \n)]])

(the \\injection
  (List $.Documentation)
  (let [specific (list ($.definition \\injection.bit)
                       ($.definition \\injection.natural)
                       ($.definition \\injection.integer)
                       ($.definition \\injection.revolution)
                       ($.definition \\injection.decimal)
                       ($.definition \\injection.text)
                       
                       ($.definition \\injection.ratio)
                       ($.definition \\injection.symbol)
                       ($.definition \\injection.location)
                       ($.definition \\injection.code)
                       ($.definition \\injection.type)
                       
                       ($.definition \\injection.instant)
                       ($.definition \\injection.duration)
                       ($.definition \\injection.date)
                       ($.definition \\injection.time)
                       ($.definition \\injection.day)
                       ($.definition \\injection.month)
                       
                       ($.definition \\injection.xml)
                       ($.definition \\injection.json))
        number (list ($.definition \\injection.natural_2)
                     ($.definition \\injection.natural_8)
                     ($.definition \\injection.natural_10)
                     ($.definition \\injection.natural_16)
                     ($.definition \\injection.integer_2)
                     ($.definition \\injection.integer_8)
                     ($.definition \\injection.integer_10)
                     ($.definition \\injection.integer_16)
                     ($.definition \\injection.revolution_2)
                     ($.definition \\injection.revolution_8)
                     ($.definition \\injection.revolution_10)
                     ($.definition \\injection.revolution_16)
                     ($.definition \\injection.decimal_02)
                     ($.definition \\injection.decimal_08)
                     ($.definition \\injection.decimal_10)
                     ($.definition \\injection.decimal_16))]
    (list.partial ($.module \\injection._
                            "")

                  ($.definition \\injection.functor)

                  ($.definition \\injection.mod)
                  ($.definition \\injection.list)
                  ($.definition \\injection.maybe)

                  ($.definition (\\injection.Injection it)
                    "A way to produce readable text from values.")

                  ($.definition \\injection.message
                    "Text interpolation."
                    ($.example (' (%.message "Static part " (text static) " does not match URI: " uri))))

                  (all list#composite
                       specific
                       number
                       )
                  )))

(`` (the \\projection
      (List $.Documentation)
      (let [exception (list ($.definition \\projection.unconsumed_input)
                            ($.definition \\projection.expected_to_fail)
                            ($.definition \\projection.cannot_parse)
                            ($.definition \\projection.cannot_slice)
                            ($.definition \\projection.cannot_match)
                            ($.definition \\projection.character_should_be)
                            ($.definition \\projection.character_should_not_be)
                            ($.definition \\projection.character_does_not_satisfy_predicate))
            specific (list ($.definition \\projection.range
                             "Only yields characters within a range."
                             ($.example (' (range bottom top))))

                           (,, (template.with [<name> <desc>]
                                 [($.definition <name>
                                    (%.message "Only yields " <desc> " characters."))]

                                 [\\projection.upper "uppercase"]
                                 [\\projection.lower "lowercase"]
                                 [\\projection.decimal "decimal"]
                                 [\\projection.octal "octal"]
                                 ))

                           ($.definition \\projection.alpha
                             "Yields alphabetic characters.")

                           ($.definition \\projection.alpha_num
                             "Yields alphanumeric characters.")

                           ($.definition \\projection.hexadecimal
                             "Yields hexadecimal digits.")

                           ($.definition \\projection.space
                             "Yields white-space."))]
        (list.partial ($.module \\projection._
                                "")

                      ($.definition \\projection.Offset
                        "An offset into a block of text.")

                      ($.definition (\\projection.Projection it)
                        "A projection for text.")

                      ($.definition \\projection.Slice
                        "A slice of a block of text.")

                      ($.definition \\projection.value
                        (%.message "Executes a projection against a block of text."
                                   \n "Verifies that the entire input has been processed.")
                        ($.example (' (value projection input))))

                      ($.definition \\projection.offset
                        "Yields the current offset into the input.")

                      ($.definition \\projection.any
                        "Yields the next character without applying any logic.")

                      ($.definition \\projection.any!
                        "Yields the next character (as a slice) without applying any logic.")

                      (,, (template.with [<name> <caveat>]
                            [(`` ($.definition <name>
                                   (%.message "Produce a character" (,, (template.text [<caveat>])) " if the projection fails.")))]

                            [\\projection.not  ""]
                            [\\projection.not! " (as a slice)"]
                            ))

                      ($.definition \\projection.this
                        "Checks that a specific text shows up in the input."
                        ($.example (' (this reference))))

                      ($.definition \\projection.end
                        "Ensure the projection's input is empty.")

                      ($.definition \\projection.next
                        "Yields the next character (without consuming it from the input).")

                      ($.definition \\projection.remaining
                        "Get all of the remaining input (without consuming it).")

                      (,, (template.with [<name> <description_modifier>]
                            [($.definition <name>
                               (%.message "Yields characters that are" <description_modifier> " part of a piece of text."))]

                            [\\projection.one_of ""]
                            [\\projection.none_of " not"]
                            ))

                      (,, (template.with [<name> <description_modifier>]
                            [($.definition <name>
                               (%.message "Yields characters (as a slice) that are" <description_modifier> " part of a piece of text."))]

                            [\\projection.one_of! ""]
                            [\\projection.none_of! " not"]
                            ))

                      ($.definition \\projection.satisfies
                        "Yields characters that satisfy a predicate."
                        ($.example (' (satisfies projection))))

                      ($.definition \\projection.and
                        "Yields the outputs of both projections composed together."
                        ($.example (' (and left right))))

                      ($.definition \\projection.and!
                        "Yields the outputs of both projections composed together (as a slice)."
                        ($.example (' (and! left right))))

                      (,, (template.with [<text> <slice>]
                            [(`` ($.definition <text>
                                   (%.message "Yields " (,, (template.text [<name>])) " characters as a single continuous text.")))
                             (`` ($.definition <slice>
                                   (%.message "Yields " (,, (template.text [<name>])) " characters as a single continuous text (as a slice).")))]

                            [\\projection.some \\projection.some!]
                            [\\projection.many \\projection.many!]
                            ))

                      (,, (template.with [<text> <slice> <doc_modifier>]
                            [(`` ($.definition <text>
                                   (%.message "Yields " <doc_modifier> " N characters.")))
                             (`` ($.definition <slice>
                                   (%.message "Yields " <doc_modifier> " N characters (as a slice).")))]

                            [\\projection.exactly  \\projection.exactly!  "exactly"]
                            [\\projection.at_most  \\projection.at_most!  "at most"]
                            [\\projection.at_least \\projection.at_least! "at least"]
                            ))

                      ($.definition \\projection.between
                        ""
                        ($.example (' (between minimum additional projection))))

                      ($.definition \\projection.between!
                        ""
                        ($.example (' (between! minimum additional projection))))

                      ($.definition \\projection.enclosed
                        ""
                        ($.example (' (enclosed [start end] projection))))

                      ($.definition \\projection.local
                        "Applies a projection against the given input."
                        ($.example (' (local local_input projection))))

                      ($.definition \\projection.slice
                        "Converts a slice to a block of text."
                        ($.example (' (slice projection))))

                      ($.definition \\projection.then
                        "Embeds a text projection into an arbitrary projection that yields text."
                        ($.example (' (then structured text))))

                      (all list#composite
                           exception
                           specific
                           )
                      ))))

(the .public documentation
  (List $.Documentation)
  (let [character (list ... ($.definition /.Character
                   ...   "A character code number.")

                   ... ($.definition /.character
                   ...   "Yields the character at the specified index."
                   ...   ($.example (' (character index input))))

                   ... ($.definition /.of_character)

                   ($.definition /.\0)
                   ($.definition /.null)
                   ($.definition /.\a)
                   ($.definition /.alarm)
                   ($.definition /.\b)
                   ($.definition /.back_space)
                   ($.definition /.\t)
                   ($.definition /.tab)
                   ($.definition /.\n)
                   ($.definition /.new_line)
                   ($.definition /.\v)
                   ($.definition /.vertical_tab)
                   ($.definition /.\f)
                   ($.definition /.form_feed)
                   ($.definition /.\r)
                   ($.definition /.carriage_return)
                   ($.definition /.\'')
                   ($.definition /.double_quote)

                   ($.definition /.space)
                   
                   ($.definition /.line_feed
                     "Same as 'new_line'."))
        query (list ($.definition /.empty?)

                    ($.definition /.starts_with?
                      ""
                      ($.example (' (starts_with? prefix x))))

                    ($.definition /.ends_with?
                      ""
                      ($.example (' (ends_with? postfix x))))

                    ($.definition /.enclosed_by?
                      ""
                      ($.example (' (enclosed_by? boundary value))))

                    ($.definition /.contains?
                      ""
                      ($.example (' (contains? sub text))))

                    ($.definition /.space?
                      "Checks whether the character is white-space."
                      ($.example (' (space? character)))))]
    (list.partial ($.module /._
                            "")

                  ($.definition /.size)
                  ($.definition /.injection)
                  ($.definition /.equivalence)
                  ($.definition /.order)
                  ($.definition /.monoid)
                  ($.definition /.hash)
                  ($.definition /.together)
                  
                  ($.definition /.lower_cased)
                  ($.definition /.upper_cased)

                  ($.definition /.index_since
                    ""
                    ($.example (' (index_since from pattern input))))

                  ($.definition /.index
                    ""
                    ($.example (' (index pattern input))))

                  ($.definition /.last_index
                    ""
                    ($.example (' (last_index part text))))

                  ($.definition /.prefix
                    ""
                    ($.example (' (prefix param subject))))

                  ($.definition /.suffix
                    ""
                    ($.example (' (suffix param subject))))

                  ($.definition /.enclosed
                    "Surrounds the given content text with left and right side additions."
                    ($.example (' (enclosed [left right] content))))

                  ($.definition /.enclosed'
                    "Surrounds the given content text with the same boundary text."
                    ($.example (' (enclosed' boundary content))))

                  ($.definition /.clip
                    "Clips a chunk of text from the input at the specified offset and of the specified size."
                    ($.example (' (clip offset size input))))

                  ($.definition /.clip_since
                    "Clips the remaining text from the input at the specified offset."
                    ($.example (' (clip_since offset input))))

                  ($.definition /.split_at
                    ""
                    ($.example (' (split_at at x))))

                  ($.definition /.split_by
                    ""
                    ($.example (' (split_by token sample))))

                  ($.definition /.all_split_by
                    ""
                    ($.example (' (all_split_by token sample))))

                  ($.definition /.replaced_once
                    ""
                    ($.example (' (replaced_once pattern replacement template))))

                  ($.definition /.replaced
                    ""
                    ($.example (' (replaced pattern replacement template))))

                  ($.definition /.interposed
                    ""
                    ($.example (' (interposed separator texts))))

                  (all list#composite
                       character
                       query
                       
                       ..\\injection
                       ..\\projection
                       
                       /buffer.documentation
                       /encoding.documentation
                       /escape.documentation
                       /regex.documentation
                       /unicode.documentation
                       )
                  )))
