text:
| T004 | 2016-11-01 | S    |  7.55 | T   | F    |   6811 |   966 |  5845 | 0.2453 | 0.1924 |
        | T005 | 2016-11-01 | S    |   7.5 | F   | F    |   4000 |   572 |  3428 | 0.2453 | 0.1924 |
        | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 |   143 |   857 | 0.2453 | 0.1924 |
        | T007 | 2016-11-01 | S    |  7.65 | T   | F    |    200 |    28 |   172 | 0.2453 | 0.1924 |
        | T008 | 2016-11-01 | P    |  7.65 | F   | F    |   2771 |   393 |  2378 | 0.2453 | 0.1924 |
        | T009 | 2016-11-01 | P    |   7.6 | F   | F    |   9550 |  1363 |  8187 | 0.2453 | 0.1924 |
        | T010 | 2016-11-01 | P    |  7.55 | F   | T    |   3175 |   451 |  2724 | 0.2453 | 0.1924 |
        | T011 | 2016-11-02 | P    | 7.425 | T   | F    |    100 |    14 |    86 | 0.2453 | 0.1924 |
        | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |   677 |  4023 | 0.2453 | 0.1924 |
        | T013 | 2016-11-02 | P    |  7.35 | T   | T    |  53100 |  7656 | 45444 | 0.2453 | 0.1924 |
        | T014 | 2016-11-02 | P    |  7.45 | F   | T    |   5847 |   835 |  5012 | 0.2453 | 0.1924 |
        | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |    72 |   428 | 0.2453 | 0.1924 |
        | T016 | 2016-11-02 | P    |  8.25 | T   | T    |    100 |    14 |    86 | 0.2453 | 0.1924 |
        | T017 | 2016-11-01 | P    |   8.3 | F   | T    |   1801 |  1201 |   600 | 0.2453 | 0.1924 |
        | T018 | 2016-11-01 | S    | 7.152 | T   | F    |   2516 |  2400 |   116 | 0.2453 | 0.1924 |
        | T019 | 2017-01-15 | S    |  8.75 | T   | F    |    300 |   175 |   125 | 0.2453 | 0.1924 |
        | T020 | 2017-01-19 | S    |  8.25 | F   | T    |    700 |   615 |    85 | 0.2453 | 0.1924 |
        | T021 | 2017-01-23 | P    |  7.16 | T   | T    |  12100 | 11050 |  1050 | 0.2453 | 0.1924 |

        tab1.union_all(tab2).to_aoa

        | Ref  |       Date | Code | Price | G10 | QP10 | Shares |    Lp |    Qp |   Iplp |   Ipqp |
        |------|------------|------|-------|-----|------|--------|-------|-------|--------|--------|
        | T001 | 2016-11-01 | P    |   7.7 | T   | F    |    100 |    14 |    86 | 0.2453 | 0.1924 |
        | T002 | 2016-11-01 | P    |  7.75 | T   | F    |    200 |    28 |   172 | 0.2453 | 0.1924 |
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 |   112 |   688 | 0.2453 | 0.1924 |
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 |   112 |   688 | 0.2453 | 0.1924 |
        |------|------------|------|-------|-----|------|--------|-------|-------|--------|--------|
        | T004 | 2016-11-01 | S    |  7.55 | T   | F    |   6811 |   966 |  5845 | 0.2453 | 0.1924 |
        | T005 | 2016-11-01 | S    |   7.5 | F   | F    |   4000 |   572 |  3428 | 0.2453 | 0.1924 |
        | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 |   143 |   857 | 0.2453 | 0.1924 |
        | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 |   143 |   857 | 0.2453 | 0.1924 |
        | T007 | 2016-11-01 | S    |  7.65 | T   | F    |    200 |    28 |   172 | 0.2453 | 0.1924 |
        | T008 | 2016-11-01 | P    |  7.65 | F   | F    |   2771 |   393 |  2378 | 0.2453 | 0.1924 |
        | T009 | 2016-11-01 | P    |   7.6 | F   | F    |   9550 |  1363 |  8187 | 0.2453 | 0.1924 |
        |------|------------|------|-------|-----|------|--------|-------|-------|--------|--------|
        | T010 | 2016-11-01 | P    |  7.55 | F   | T    |   3175 |   451 |  2724 | 0.2453 | 0.1924 |
        | T011 | 2016-11-02 | P    | 7.425 | T   | F    |    100 |    14 |    86 | 0.2453 | 0.1924 |
        | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |   677 |  4023 | 0.2453 | 0.1924 |
        | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |   677 |  4023 | 0.2453 | 0.1924 |
        | T013 | 2016-11-02 | P    |  7.35 | T   | T    |  53100 |  7656 | 45444 | 0.2453 | 0.1924 |
        |------|------------|------|-------|-----|------|--------|-------|-------|--------|--------|
        | T014 | 2016-11-02 | P    |  7.45 | F   | T    |   5847 |   835 |  5012 | 0.2453 | 0.1924 |
        | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |    72 |   428 | 0.2453 | 0.1924 |
        | T016 | 2016-11-02 | P    |  8.25 | T   | T    |    100 |    14 |    86 | 0.2453 | 0.1924 |
        |------|------------|------|-------|-----|------|--------|-------|-------|--------|--------|
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 |   112 |   688 | 0.2453 | 0.1924 |
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 |   112 |   688 | 0.2453 | 0.1924 |
        | T017 | 2016-11-01 | P    |   8.3 | F   | T    |   1801 |  1201 |   600 | 0.2453 | 0.1924 |
        |------|------------|------|-------|-----|------|--------|-------|-------|--------|--------|
        | T018 | 2016-11-01 | S    | 7.152 | T   | F    |   2516 |  2400 |   116 | 0.2453 | 0.1924 |
        | T018 | 2016-11-01 | S    | 7.152 | T   | F    |   2516 |  2400 |   116 | 0.2453 | 0.1924 |
        | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 |   143 |   857 | 0.2453 | 0.1924 |
        | T007 | 2016-11-01 | S    |  7.65 | T   | F    |    200 |    28 |   172 | 0.2453 | 0.1924 |
        |------|------------|------|-------|-----|------|--------|-------|-------|--------|--------|
        | T014 | 2016-11-02 | P    |  7.45 | F   | T    |   5847 |   835 |  5012 | 0.2453 | 0.1924 |
        | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |    72 |   428 | 0.2453 | 0.1924 |
        | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |    72 |   428 | 0.2453 | 0.1924 |
        | T016 | 2016-11-02 | P    |  8.25 | T   | T    |    100 |    14 |    86 | 0.2453 | 0.1924 |
        |------|------------|------|-------|-----|------|--------|-------|-------|--------|--------|
        | T019 | 2017-01-15 | S    |  8.75 | T   | F    |    300 |   175 |   125 | 0.2453 | 0.1924 |
        | T020 | 2017-01-19 | S    |  8.25 | F   | T    |    700 |   615 |    85 | 0.2453 | 0.1924 |
        | T021 | 2017-01-23 | P    |  7.16 | T   | T    |  12100 | 11050 |  1050 | 0.2453 | 0.1924 |
        | T021 | 2017-01-23 | P    |  7.16 | T   | T    |  12100 | 11050 |  1050 | 0.2453 | 0.1924 |

2.  Intersections

    The `intersect` method returns a table having only rows common to both tables,
    eliminating any duplicate rows in the result.

        tab1.intersect(tab2).to_aoa

        | Ref  |       Date | Code | Price | G10 | QP10 | Shares |  Lp |   Qp |   Iplp |   Ipqp |
        |------|------------|------|-------|-----|------|--------|-----|------|--------|--------|
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 | 112 |  688 | 0.2453 | 0.1924 |
        | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 | 143 |  857 | 0.2453 | 0.1924 |
        | T007 | 2016-11-01 | S    |  7.65 | T   | F    |    200 |  28 |  172 | 0.2453 | 0.1924 |
        | T014 | 2016-11-02 | P    |  7.45 | F   | T    |   5847 | 835 | 5012 | 0.2453 | 0.1924 |
        | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |  72 |  428 | 0.2453 | 0.1924 |
        | T016 | 2016-11-02 | P    |  8.25 | T   | T    |    100 |  14 |   86 | 0.2453 | 0.1924 |

    With `intersect_all`, all the rows of the first table, including duplicates, are
    included in the result if they also occur in the second table. However,
    duplicates in the second table do not appear.

        tab1.intersect_all(tab2).to_aoa

        | Ref  |       Date | Code | Price | G10 | QP10 | Shares |  Lp |   Qp |   Iplp |   Ipqp |
        |------|------------|------|-------|-----|------|--------|-----|------|--------|--------|
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 | 112 |  688 | 0.2453 | 0.1924 |
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 | 112 |  688 | 0.2453 | 0.1924 |
        | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 | 143 |  857 | 0.2453 | 0.1924 |
        | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 | 143 |  857 | 0.2453 | 0.1924 |
        | T007 | 2016-11-01 | S    |  7.65 | T   | F    |    200 |  28 |  172 | 0.2453 | 0.1924 |
        | T014 | 2016-11-02 | P    |  7.45 | F   | T    |   5847 | 835 | 5012 | 0.2453 | 0.1924 |
        | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |  72 |  428 | 0.2453 | 0.1924 |
        | T016 | 2016-11-02 | P    |  8.25 | T   | T    |    100 |  14 |   86 | 0.2453 | 0.1924 |

    As a result, it makes a difference which table is the receiver of the
    `intersect_all` method call and which is the argument.  In other words, order of
    operation matters.

        tab2.intersect_all(tab1).to_aoa

        | Ref  |       Date | Code | Price | G10 | QP10 | Shares |  Lp |   Qp |   Iplp |   Ipqp |
        |------|------------|------|-------|-----|------|--------|-----|------|--------|--------|
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 | 112 |  688 | 0.2453 | 0.1924 |
        | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 | 112 |  688 | 0.2453 | 0.1924 |
        | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 | 143 |  857 | 0.2453 | 0.1924 |
        | T007 | 2016-11-01 | S    |  7.65 | T   | F    |    200 |  28 |  172 | 0.2453 | 0.1924 |
        | T014 | 2016-11-02 | P    |  7.45 | F   | T    |   5847 | 835 | 5012 | 0.2453 | 0.1924 |
        | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |  72 |  428 | 0.2453 | 0.1924 |
        | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |  72 |  428 | 0.2453 | 0.1924 |
        | T016 | 2016-11-02 | P    |  8.25 | T   | T    |    100 |  14 |   86 | 0.2453 | 0.1924 |

3.  Differences with Except

    You can use the `except` method to delete from a table any rows that occur in
    another table, that is, compute the set difference between the tables.

        tab1.except(tab2).to_aoa

        | Ref  |       Date | Code | Price | G10 | QP10 | Shares |   Lp |    Qp |   Iplp |   Ipqp |
        |------|------------|------|-------|-----|------|--------|------|-------|--------|--------|
        | T001 | 2016-11-01 | P    |   7.7 | T   | F    |    100 |   14 |    86 | 0.2453 | 0.1924 |
        | T002 | 2016-11-01 | P    |  7.75 | T   | F    |    200 |   28 |   172 | 0.2453 | 0.1924 |
        | T004 | 2016-11-01 | S    |  7.55 | T   | F    |   6811 |  966 |  5845 | 0.2453 | 0.1924 |
        | T005 | 2016-11-01 | S    |   7.5 | F   | F    |   4000 |  572 |  3428 | 0.2453 | 0.1924 |
        | T008 | 2016-11-01 | P    |  7.65 | F   | F    |   2771 |  393 |  2378 | 0.2453 | 0.1924 |
        | T009 | 2016-11-01 | P    |   7.6 | F   | F    |   9550 | 1363 |  8187 | 0.2453 | 0.1924 |
        | T010 | 2016-11-01 | P    |  7.55 | F   | T    |   3175 |  451 |  2724 | 0.2453 | 0.1924 |
        | T011 | 2016-11-02 | P    | 7.425 | T   | F    |    100 |   14 |    86 | 0.2453 | 0.1924 |
        | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |  677 |  4023 | 0.2453 | 0.1924 |
        | T013 | 2016-11-02 | P    |  7.35 | T   | T    |  53100 | 7656 | 45444 | 0.2453 | 0.1924 |

    Like subtraction, though, the order of operands matters with set difference
    computed by `except`.

        tab2.except(tab1).to_aoa

        | Ref  |       Date | Code | Price | G10 | QP10 | Shares |    Lp |   Qp |   Iplp |   Ipqp |
        |------|------------|------|-------|-----|------|--------|-------|------|--------|--------|
        | T017 | 2016-11-01 | P    |   8.3 | F   | T    |   1801 |  1201 |  600 | 0.2453 | 0.1924 |
        | T018 | 2016-11-01 | S    | 7.152 | T   | F    |   2516 |  2400 |  116 | 0.2453 | 0.1924 |
        | T019 | 2017-01-15 | S    |  8.75 | T   | F    |    300 |   175 |  125 | 0.2453 | 0.1924 |
        | T020 | 2017-01-19 | S    |  8.25 | F   | T    |    700 |   615 |   85 | 0.2453 | 0.1924 |
        | T021 | 2017-01-23 | P    |  7.16 | T   | T    |  12100 | 11050 | 1050 | 0.2453 | 0.1924 |

    As with `intersect_all`, `except_all` includes any duplicates in the first,
    receiver table, but not those in the second, argument table.

        tab1.except_all(tab2).to_aoa

        | Ref  |       Date | Code | Price | G10 | QP10 | Shares |   Lp |    Qp |   Iplp |   Ipqp |
        |------|------------|------|-------|-----|------|--------|------|-------|--------|--------|
        | T001 | 2016-11-01 | P    |   7.7 | T   | F    |    100 |   14 |    86 | 0.2453 | 0.1924 |
        | T002 | 2016-11-01 | P    |  7.75 | T   | F    |    200 |   28 |   172 | 0.2453 | 0.1924 |
        | T004 | 2016-11-01 | S    |  7.55 | T   | F    |   6811 |  966 |  5845 | 0.2453 | 0.1924 |
        | T005 | 2016-11-01 | S    |   7.5 | F   | F    |   4000 |  572 |  3428 | 0.2453 | 0.1924 |
        | T008 | 2016-11-01 | P    |  7.65 | F   | F    |   2771 |  393 |  2378 | 0.2453 | 0.1924 |
        | T009 | 2016-11-01 | P    |   7.6 | F   | F    |   9550 | 1363 |  8187 | 0.2453 | 0.1924 |
        | T010 | 2016-11-01 | P    |  7.55 | F   | T    |   3175 |  451 |  2724 | 0.2453 | 0.1924 |
        | T011 | 2016-11-02 | P    | 7.425 | T   | F    |    100 |   14 |    86 | 0.2453 | 0.1924 |
        | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |  677 |  4023 | 0.2453 | 0.1924 |
        | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |  677 |  4023 | 0.2453 | 0.1924 |
        | T013 | 2016-11-02 | P    |  7.35 | T   | T    |  53100 | 7656 | 45444 | 0.2453 | 0.1924 |

    And, of course, the order of operands matters here as well.

        tab2.except_all(tab1).to_aoa

        | Ref  |       Date | Code | Price | G10 | QP10 | Shares |    Lp |   Qp |   Iplp |   Ipqp |
        |------|------------|------|-------|-----|------|--------|-------|------|--------|--------|
        | T017 | 2016-11-01 | P    |   8.3 | F   | T    |   1801 |  1201 |  600 | 0.2453 | 0.1924 |
        | T018 | 2016-11-01 | S    | 7.152 | T   | F    |   2516 |  2400 |  116 | 0.2453 | 0.1924 |
        | T018 | 2016-11-01 | S    | 7.152 | T   | F    |   2516 |  2400 |  116 | 0.2453 | 0.1924 |
        | T019 | 2017-01-15 | S    |  8.75 | T   | F    |    300 |   175 |  125 | 0.2453 | 0.1924 |
        | T020 | 2017-01-19 | S    |  8.25 | F   | T    |    700 |   615 |   85 | 0.2453 | 0.1924 |
        | T021 | 2017-01-23 | P    |  7.16 | T   | T    |  12100 | 11050 | 1050 | 0.2453 | 0.1924 |
        | T021 | 2017-01-23 | P    |  7.16 | T   | T    |  12100 | 11050 | 1050 | 0.2453 | 0.1924 |

### Uniq (aka Distinct)

The `uniq` method takes no arguments and simply removes any duplicate rows from
the input table.  The `distinct` method is an alias for `uniq`.  Any groups in
the input table are lost.

    tab1.uniq.to_aoa

    | Ref  |       Date | Code | Price | G10 | QP10 | Shares |   Lp |    Qp |   Iplp |   Ipqp |
    |------|------------|------|-------|-----|------|--------|------|-------|--------|--------|
    | T001 | 2016-11-01 | P    |   7.7 | T   | F    |    100 |   14 |    86 | 0.2453 | 0.1924 |
    | T002 | 2016-11-01 | P    |  7.75 | T   | F    |    200 |   28 |   172 | 0.2453 | 0.1924 |
    | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 |  112 |   688 | 0.2453 | 0.1924 |
    | T004 | 2016-11-01 | S    |  7.55 | T   | F    |   6811 |  966 |  5845 | 0.2453 | 0.1924 |
    | T005 | 2016-11-01 | S    |   7.5 | F   | F    |   4000 |  572 |  3428 | 0.2453 | 0.1924 |
    | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 |  143 |   857 | 0.2453 | 0.1924 |
    | T007 | 2016-11-01 | S    |  7.65 | T   | F    |    200 |   28 |   172 | 0.2453 | 0.1924 |
    | T008 | 2016-11-01 | P    |  7.65 | F   | F    |   2771 |  393 |  2378 | 0.2453 | 0.1924 |
    | T009 | 2016-11-01 | P    |   7.6 | F   | F    |   9550 | 1363 |  8187 | 0.2453 | 0.1924 |
    | T010 | 2016-11-01 | P    |  7.55 | F   | T    |   3175 |  451 |  2724 | 0.2453 | 0.1924 |
    | T011 | 2016-11-02 | P    | 7.425 | T   | F    |    100 |   14 |    86 | 0.2453 | 0.1924 |
    | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |  677 |  4023 | 0.2453 | 0.1924 |
    | T013 | 2016-11-02 | P    |  7.35 | T   | T    |  53100 | 7656 | 45444 | 0.2453 | 0.1924 |
    | T014 | 2016-11-02 | P    |  7.45 | F   | T    |   5847 |  835 |  5012 | 0.2453 | 0.1924 |
    | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |   72 |   428 | 0.2453 | 0.1924 |
    | T016 | 2016-11-02 | P    |  8.25 | T   | T    |    100 |   14 |    86 | 0.2453 | 0.1924 |

### Remove groups with degroup!

Finally, it is sometimes helpful to remove any group boundaries from a table.
You can do this with `.degroup!`, which is the only operation that mutates its
receiver table by removing its groups.

    tab1.degroup!.to_aoa

    | Ref  |       Date | Code | Price | G10 | QP10 | Shares |   Lp |    Qp |   Iplp |   Ipqp |
    |------|------------|------|-------|-----|------|--------|------|-------|--------|--------|
    | T001 | 2016-11-01 | P    |   7.7 | T   | F    |    100 |   14 |    86 | 0.2453 | 0.1924 |
    | T002 | 2016-11-01 | P    |  7.75 | T   | F    |    200 |   28 |   172 | 0.2453 | 0.1924 |
    | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 |  112 |   688 | 0.2453 | 0.1924 |
    | T003 | 2016-11-01 | P    |   7.5 | F   | T    |    800 |  112 |   688 | 0.2453 | 0.1924 |
    | T004 | 2016-11-01 | S    |  7.55 | T   | F    |   6811 |  966 |  5845 | 0.2453 | 0.1924 |
    | T005 | 2016-11-01 | S    |   7.5 | F   | F    |   4000 |  572 |  3428 | 0.2453 | 0.1924 |
    | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 |  143 |   857 | 0.2453 | 0.1924 |
    | T006 | 2016-11-01 | S    |   7.6 | F   | T    |   1000 |  143 |   857 | 0.2453 | 0.1924 |
    | T007 | 2016-11-01 | S    |  7.65 | T   | F    |    200 |   28 |   172 | 0.2453 | 0.1924 |
    | T008 | 2016-11-01 | P    |  7.65 | F   | F    |   2771 |  393 |  2378 | 0.2453 | 0.1924 |
    | T009 | 2016-11-01 | P    |   7.6 | F   | F    |   9550 | 1363 |  8187 | 0.2453 | 0.1924 |
    | T010 | 2016-11-01 | P    |  7.55 | F   | T    |   3175 |  451 |  2724 | 0.2453 | 0.1924 |
    | T011 | 2016-11-02 | P    | 7.425 | T   | F    |    100 |   14 |    86 | 0.2453 | 0.1924 |
    | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |  677 |  4023 | 0.2453 | 0.1924 |
    | T012 | 2016-11-02 | P    |  7.55 | F   | F    |   4700 |  677 |  4023 | 0.2453 | 0.1924 |
    | T013 | 2016-11-02 | P    |  7.35 | T   | T    |  53100 | 7656 | 45444 | 0.2453 | 0.1924 |
    | T014 | 2016-11-02 | P    |  7.45 | F   | T    |   5847 |  835 |  5012 | 0.2453 | 0.1924 |
    | T015 | 2016-11-02 | P    |  7.75 | F   | F    |    500 |   72 |   428 | 0.2453 | 0.1924 |
    | T016 | 2016-11-02 | P    |  8.25 | T   | T    |    100 |   14 |    86 | 0.2453 | 0.1924 |

## Formatting Tables

Besides creating and operating on tables, you may want to display the resulting
table. `FatTable` seeks to provide a set of formatting directives that are the
most common across many output media. It provides directives for alignment, for
color, for adding currency symbols and grouping commas to numbers, for padding
numbers, and for formatting dates and booleans.

In addition, you can add any number of footers to a table, which appear at the
end of the table, and any number of group footers, which appear after each group
in the table. These can be formatted independently of the table body.

If the target output medium does not support a formatting directive or the
directive does not make sense, it is simply ignored. For example, you can output
an `org-mode` table as a String, and since `org-mode` does not support colors,
any color directives are ignored. Some of the output targets are not strings,
but ruby data structures, and for them, things such as alignment are irrelevant.

### Available Formatters

`FatTable` supports the following output targets for its tables:

-   **Text:** form the table with ACSII characters,
-   **Org:** form the table with ASCII characters but in the form used by Emacs
    org-mode for constructing tables,
-   **Term:** form the table with ANSI terminal codes and unicode characters,
    possibly including colored text and cell backgrounds,
-   **LaTeX:** form the table as input for LaTeX’s longtable environment,
-   **Aoh:** output the table as a ruby data structure, building the table as an
    array of hashes, and
-   **Aoa:** output the table as a ruby data structure, building the table as an
    array of array,

These are all implemented by classes that inherit from `FatTable::Formatter`
class by defining about a dozen methods that get called at various places during
the construction of the output table. The idea is that more classes can be
defined by adding additional classes.

### Table Locations

In the formatting methods, the table is divided into several “locations” for
which separate formatting directives may be given. These locations are
identified with the following symbols:

-   **:header:** the first row of the output table containing the headers,
-   **:footer:** all rows of the table’s footers,
-   **:gfooter:** all rows of the table’s group footers,
-   **:body:** all the data rows of the table, that is, those that are neither part
    of the header, footers, or gfooters,
-   **:bfirst:** the first row of the table’s body, and
-   **:gfirst:** the first row in each group in the table’s body.

### Formatting Directives

The formatting methods explained in the next section all take formatting
directives as strings in which letters and other characters signify what
formatting applies.  For example, we may apply the formatting directive `'R,$'`
to numbers in a certain part of the table.  Each of those characters, and in
some cases a whole substring, is a single directive.  They can appear in any
order, so `'$R,'` and `',$R'` are equivalent.

Here is a list of all the formatting directives that apply to each cell type:

1.  String

    For a string element, the following instructions are valid. Note that these can
    also be applied to all the other cell types as well since they are all converted
    to a string in forming the output.

    -   **u:** convert the element to all lowercase,
    -   **U:** convert the element to all uppercase,
    -   **t:** title case the element, that is, upcase the initial letter in
        each word and lower case the other letters
    -   **B ~B:** make the element bold, or turn off bold
    -   **I ~I:** make the element italic, or turn off italic
    -   **R:** align the element on the right of the column
    -   **L:** align the element on the left of the column
    -   **C:** align the element in the center of the column
    -   **c[color]:** render the element in the given color; the color can have
        the form fgcolor, fgcolor.bgcolor, or .bgcolor, to set the
        foreground or background colors respectively, and each of those can
        be an ANSI or X11 color name in addition to the special color,
        ’none’, which keeps the terminal’s default color.
    -   **\_ ~\_:** underline the element, or turn off underline
    -   **\* ~\*:** cause the element to blink, or turn off blink

    For example, the directive `'tCc[red.yellow]'` would title-case the element,
    center it, and color it red on a yellow background. The directives that are
    boolean have negating forms so that, for example, if bold is turned on for all
    columns of a given type, it can be countermanded in formatting directives for
    particular columns.

2.  Numeric

    For a numeric element, all the instructions valid for string are available, in
    addition to the following:

    -   **, ~,:** insert grouping commas, or do not insert grouping commas,
    -   **$ ~$:** format the number as currency according to the locale, or not,
    -   **m.n:** include at least m digits before the decimal point, padding on
        the left with zeroes as needed, and round the number to the n
        decimal places and include n digits after the decimal point,
        padding on the right with zeroes as needed,
    -   **H:** convert the number (assumed to be in units of seconds) to `HH:MM:SS.ss`
        form. So a column that is the result of subtracting two :datetime forms
        will result in a :numeric expressed as seconds and can be displayed in
        hours, minutes, and seconds with this formatting instruction.

    For example, the directive `'R5.0c[blue]'` would right-align the numeric
    element, pad it on the left with zeros, and color it blue.

3.  DateTime

    For a `DateTime`, all the instructions valid for string are available, in
    addition to the following:

    -   **d[fmt]:** apply the format to a `Date` or a  `DateTime` that is a whole day,
        that is that has no or zero hour, minute, and second components, where fmt
        is a valid format string for `Date#strftime`, otherwise, the datetime will
        be formatted as an ISO 8601 string, YYYY-MM-DD.
    -   **D[fmt]:** apply the format to a datetime that has at least a non-zero hour
        component where fmt is a valid format string for Date#strftime, otherwise,
        the datetime will be formatted as an ISO 8601 string, YYYY-MM-DD.

    For example, `'c[pink]d[%b %-d, %Y]C'`, would format a date element like ’Sep
    22, 1957’, center it, and color it pink.

4.  Boolean

    For a boolean cell, all the instructions valid for string are available, in
    addition to the following:

    -   **Y:** print true as ’`Y`’ and false as ’`N`’,
    -   **T:** print true as ’`T`’ and false as ’`F`’,
    -   **X:** print true as ’`X`’ and false as an empty string ’’,
    -   **b[xxx,yyy]:** print true as the string given as `xxx` and false as the string
        given as `yyy`,
    -   **c[tcolor,fcolor]:** color a true element with `tcolor` and a false element
        with `fcolor`. Each of the colors may be specified in the same manner as
        colors for strings described above.

    For example, the directive ’`b[Yeppers,Nope]c[green.pink,red.pink]`’ would
    render a true boolean as ’`Yeppers`’ colored green on pink and render a false
    boolean as ’`Nope`’ colored red on pink. See [Yeppers](https://www.youtube.com/watch?v=oLdFFD8II8U) for additional information.

5.  NilClass

    By default, `nil` elements are rendered as blank cells, but you can make them
    visible with the following, and in that case, all the formatting instructions
    valid for strings are also available:

    -   **n[niltext]:** render a `nil` item with the given niltext.

    For example, you might want to use `'n[-]Cc[purple]'` to make nils visible as a
    centered purple hyphen.

### Footers Methods

You can call the `footer` and `gfooter` methods on `Formatter` objects to add
footers and group footers. Their signatures are:

-   **`footer(label, *sum_cols, **agg_cols)`:** where `label` is a label to be
    placed in the first cell of the footer (unless that column is named as one
    of the `sum_cols` or `agg_cols`, in which case the label is ignored),
    `*sum_cols` are zero or more symbols for columns to be summed, and
    `**agg_cols` is zero or more hash-like parameters with a column symbol as a
    key and a symbol for an aggregate method as the value. This causes a
    table-wide header to be added at the bottom of the table applying the
    `:sum` aggregate to the `sum_cols` and the named aggregate method to the
    `agg_cols`. A table can have any number of footers attached, and they will
    appear at the bottom of the output table in the order they are given.

-   **`gfooter(label, *sum_cols, **agg_cols)`:** where the parameters have the same
    meaning as for the `footer` method, but result in a footer for each group
    in the table rather than the table as a whole. These will appear in the
    output table just below each group.

There are also a number of convenience methods for adding common footers:

-   **`sum_footer(*cols)`:** Add a footer summing the given columns with the label
    ’Total’.
-   **`sum_gfooter(*cols)`:** Add a group footer summing the given columns with the
    label ’Group Total’.
-   **`avg_footer(*cols)`:** Add a footer averaging the given columns with the label
    ’Average’.
-   **`avg_gfooter(*cols)`:** Add a group footer averaging the given columns with the label
    ’Group Average’.
-   **`min_footer(*cols)`:** Add a footer showing the minimum for the given columns
    with the label ’Minimum’.
-   **`min_gfooter(*cols)`:** Add a group footer showing the minumum for the given
    columns with the label ’Group Minimum’.
-   **`max_footer(*cols)`:** Add a footer showing the maximum for the given columns
    with the label ’Maximum’.
-   **`max_gfooter(*cols)`:** Add a group footer showing the maximum for the given
    columns with the label ’Group Maximum’.

### Formatting Methods

You can call methods on  `Formatter` objects to specify formatting directives
for specific columns or types.  There are two methods for doing so, `format_for`
and `format`.

1.  Instantiating a Formatter

    There are several ways to invoke the formatting methods on a table. First, you
    can instantiate a `XXXFormatter` object and feed it a table as a parameter.
    There is a Formatter subclass for each target output medium, for example,
    `AoaFormatter` will produce a ruby array of arrays. You can then call the
    `output` method on the `XXXFormatter`.

        FatTable::AoaFormatter.new(tab_a).output

        | Id | Name  | Age | Address    | Salary |  Join Date |
        |----|-------|-----|------------|--------|------------|
        |  1 | Paul  |  32 | California |  20000 | 2001-07-13 |
        |  3 | Teddy |  23 | Norway     |  20000 | 2007-12-13 |
        |  4 | Mark  |  25 | Rich-Mond  |  65000 | 2007-12-13 |
        |  5 | David |  27 | Texas      |  85000 | 2007-12-13 |
        |  2 | Allen |  25 | Texas      |        | 2005-07-13 |
        |  8 | Paul  |  24 | Houston    |  20000 | 2005-07-13 |
        |  9 | James |  44 | Norway     |   5000 | 2005-07-13 |
        | 10 | James |  45 | Texas      |   5000 |            |

    The `XXXFormatter.new` method yields the new instance to any block given, and
    you can call methods on it to affect the formatting of the output:

        FatTable::AoaFormatter.new(tab_a) do |f|
          f.format(numeric: '0.0,R', id: '3.0C')
        end.output

        |  Id | Name  | Age | Address    | Salary |  Join Date |
        |-----|-------|-----|------------|--------|------------|
        | 001 | Paul  |  32 | California | 20,000 | 2001-07-13 |
        | 003 | Teddy |  23 | Norway     | 20,000 | 2007-12-13 |
        | 004 | Mark  |  25 | Rich-Mond  | 65,000 | 2007-12-13 |
        | 005 | David |  27 | Texas      | 85,000 | 2007-12-13 |
        | 002 | Allen |  25 | Texas      |        | 2005-07-13 |
        | 008 | Paul  |  24 | Houston    | 20,000 | 2005-07-13 |
        | 009 | James |  44 | Norway     |  5,000 | 2005-07-13 |
        | 010 | James |  45 | Texas      |  5,000 |            |

2.  `FatTable` module-level method calls

    The `FatTable` module provides a set of methods of the form `to_aoa`, `to_text`,
    etc., to access a `Formatter` without having to create an instance yourself.
    Without a block, they apply the default formatting to the table and call the
    `.output` method automatically:

        FatTable.to_aoa(tab_a)

        | Id | Name  | Age | Address    | Salary |  Join Date |
        |----|-------|-----|------------|--------|------------|
        |  1 | Paul  |  32 | California |  20000 | 2001-07-13 |
        |  3 | Teddy |  23 | Norway     |  20000 | 2007-12-13 |
        |  4 | Mark  |  25 | Rich-Mond  |  65000 | 2007-12-13 |
        |  5 | David |  27 | Texas      |  85000 | 2007-12-13 |
        |  2 | Allen |  25 | Texas      |        | 2005-07-13 |
        |  8 | Paul  |  24 | Houston    |  20000 | 2005-07-13 |
        |  9 | James |  44 | Norway     |   5000 | 2005-07-13 |
        | 10 | James |  45 | Texas      |   5000 |            |

    With a block, these methods yield a `Formatter` instance on which you can call
    formatting and footer methods. The `.output` method is called on the `Formatter`
    automatically after the block:

        FatTable.to_aoa(tab_a) do |f|
          f.format(numeric: '0.0,R', id: '3.0C')
        end

        |  Id | Name  | Age | Address    | Salary |  Join Date |
        |-----|-------|-----|------------|--------|------------|
        | 001 | Paul  |  32 | California | 20,000 | 2001-07-13 |
        | 003 | Teddy |  23 | Norway     | 20,000 | 2007-12-13 |
        | 004 | Mark  |  25 | Rich-Mond  | 65,000 | 2007-12-13 |
        | 005 | David |  27 | Texas      | 85,000 | 2007-12-13 |
        | 002 | Allen |  25 | Texas      |        | 2005-07-13 |
        | 008 | Paul  |  24 | Houston    | 20,000 | 2005-07-13 |
        | 009 | James |  44 | Norway     |  5,000 | 2005-07-13 |
        | 010 | James |  45 | Texas      |  5,000 |            |

3.  Calling methods on Table objects

    Finally, you can call methods such as `to_aoa`, `to_text`, etc., directly on a
    Table:

        tab_a.to_aoa

        | Id | Name  | Age | Address    | Salary |  Join Date |
        |----|-------|-----|------------|--------|------------|
        |  1 | Paul  |  32 | California |  20000 | 2001-07-13 |
        |  3 | Teddy |  23 | Norway     |  20000 | 2007-12-13 |
        |  4 | Mark  |  25 | Rich-Mond  |  65000 | 2007-12-13 |
        |  5 | David |  27 | Texas      |  85000 | 2007-12-13 |
        |  2 | Allen |  25 | Texas      |        | 2005-07-13 |
        |  8 | Paul  |  24 | Houston    |  20000 | 2005-07-13 |
        |  9 | James |  44 | Norway     |   5000 | 2005-07-13 |
        | 10 | James |  45 | Texas      |   5000 |            |

    And you can supply a block to them as well to specify formatting or footers:

        tab_a.to_aoa do |f|
          f.format(numeric: '0.0,R', id: '3.0C')
          f.sum_footer(:salary, :age)
        end

        |    Id | Name  | Age | Address    |  Salary |  Join Date |
        |-------|-------|-----|------------|---------|------------|
        |   001 | Paul  |  32 | California |  20,000 | 2001-07-13 |
        |   003 | Teddy |  23 | Norway     |  20,000 | 2007-12-13 |
        |   004 | Mark  |  25 | Rich-Mond  |  65,000 | 2007-12-13 |
        |   005 | David |  27 | Texas      |  85,000 | 2007-12-13 |
        |   002 | Allen |  25 | Texas      |         | 2005-07-13 |
        |   008 | Paul  |  24 | Houston    |  20,000 | 2005-07-13 |
        |   009 | James |  44 | Norway     |   5,000 | 2005-07-13 |
        |   010 | James |  45 | Texas      |   5,000 |            |
        |-------|-------|-----|------------|---------|------------|
        | Total |       | 245 |            | 220,000 |            |

### The `format` and `format_for` methods

Formatters take only two kinds of methods, those that attach footers to a
table, which are discussed in the next section, and those that specify
formatting for table cells, which are the subject of this section.

To set formatting directives for all locations in a table at once, use the
`format` method; to set formatting directives for a particular location in the
table, use the `format_for` method, giving the location as the first parameter.

Other than that first parameter, the two methods take the same types of
parameters. The remaining parameters are hash-like parameters that use either a
column name or a type as the key and a string with the formatting directives to
apply as the value. The following example says to set the formatting for all
locations in the table and to format all numeric fields as strings that are
rounded to whole numbers (the ’0.0’ part), that are right-aligned (the ’R’
part), and have grouping commas inserted (the ’,’ part). But the `:id` column is
numeric, and the second parameter overrides the formatting for numerics in
general and calls for the `:id` column to be padded to three digits with zeros
on the left (the ’3.0’ part) and to be centered (the ’C’ part).

    tab_a.to_aoa do |f|
      f.format(numeric: '0.0,R', id: '3.0C')
    end

    |  Id | Name  | Age | Address    | Salary |  Join Date |
    |-----|-------|-----|------------|--------|------------|
    | 001 | Paul  |  32 | California | 20,000 | 2001-07-13 |
    | 003 | Teddy |  23 | Norway     | 20,000 | 2007-12-13 |
    | 004 | Mark  |  25 | Rich-Mond  | 65,000 | 2007-12-13 |
    | 005 | David |  27 | Texas      | 85,000 | 2007-12-13 |
    | 002 | Allen |  25 | Texas      |        | 2005-07-13 |
    | 008 | Paul  |  24 | Houston    | 20,000 | 2005-07-13 |
    | 009 | James |  44 | Norway     |  5,000 | 2005-07-13 |
    | 010 | James |  45 | Texas      |  5,000 |            |

The `numeric:` directive affected the `:age` and `:salary` columns and the `id:`
directive affected only the `:id` column. All the other cells in the table had
the default formatting applied.

1.  Location priority

    Formatting for any given cell depends on its location in the table. The
    `format_for` method takes a location to which its formatting directive are
    restricted as the first argument. It can be one of the following:

    -   **`:header`:** directive apply only to the header row, that is the first row, of
        the output table,

    -   **`:footer`:** directives apply to all the footer rows of the output table,
        regardless of how many there are,

    -   **`gfooter`:** directives apply to all group footer rows of the output tables,
        regardless of how many there are,

    -   **`:body`:** directives apply to all rows in the body of the table unless the
        row is the first row in the table or in a group and separate directives for
        those have been given, in which case those directives apply,

    -   **`:gfirst`:** directives apply to the first row in each group in the body of
        the table, unless the row is also the first row in the table as a whole, in
        which case the `:bfirst` directives apply,

    -   **`:bfirst`:** directives apply to the first row in the body of the table.

    If you give directives for `:body`, they are copied to `:bfirst` and `:gfirst`
    as well and can be overridden by directives for those locations.

    Directives given to the `format` method apply the directives to all locations in
    the table, but they can be overridden by more specific directives given in a
    `format_for` directive.

2.  Type and Column priority

    A directive based on type applies to all columns having that type unless
    overridden by a directive specific to a named column; a directive based on a
    column name applies only to cells in that column.

    However, there is a twist.  Since the end result of formatting is to convert all
    columns to strings, the formatting directives for the `:string` type applies to
    all columns.  Likewise, since all columns may contain nils, the `nil:` type
    applies to nils in all columns regardless of the column’s type.

        require 'fat_table'
          tab_a.to_text do |f|
            f.format(string: 'R', id: '3.0C', salary: 'n[N/A]')
          end

        +=====+=======+=====+============+========+============+
        |  Id |  Name | Age |    Address | Salary |  Join Date |
        +-----|-------|-----|------------|--------|------------+
        | 001 |  Paul |  32 | California |  20000 | 2001-07-13 |
        | 003 | Teddy |  23 |     Norway |  20000 | 2007-12-13 |
        | 004 |  Mark |  25 |  Rich-Mond |  65000 | 2007-12-13 |
        | 005 | David |  27 |      Texas |  85000 | 2007-12-13 |
        | 002 | Allen |  25 |      Texas |    N/A | 2005-07-13 |
        | 008 |  Paul |  24 |    Houston |  20000 | 2005-07-13 |
        | 009 | James |  44 |     Norway |   5000 | 2005-07-13 |
        | 010 | James |  45 |      Texas |   5000 |            |
        +=====+=======+=====+============+========+============+

    The `string: 'R'` directive causes all the cells to be right-aligned except
    `:id` which specifies centering for the `:id` column only. The `n[N/A]`
    directive for specifies how nil are displayed in the numeric column, `:salary`,
    but not for other nils, such as in the last row of the `:join_date` column.

# Development

After checking out the repo, run \`bin/setup\` to install dependencies. Then, run
\`rake spec\` to run the tests. You can also run \`bin/console\` for an interactive
prompt that will allow you to experiment.

To install this gem onto your local machine, run \`bundle exec rake install\`. To
release a new version, update the version number in \`version.rb\`, and then run
\`bundle exec rake release\`, which will create a git tag for the version, push
git commits and tags, and push the \`.gem\` file to
[rubygems.org](<https://rubygems.org>).

# Contributing

Bug reports and pull requests are welcome on GitHub at
<https://github.com/ddoherty03/fat_table>.

license: MIT

extension: md

gha_license_id: MIT

license_type: permissive


text:
# Add Expression-Based Contract Syntax

| Field             | Value                                                           |
|-------------------|-----------------------------------------------------------------|
| DIP:              | 1009                                                            |
| Review Count:     | 3                                                               |
| Author:           | Zach<EMAIL_ADDRESS>                               |
| Implementation:   | [Timon Gehr]                                                    |
| Status:           | Accepted                                                        |

[Timon Gehr]: https://github.com/dlang/dmd/compare/master...tgehr:contract-syntax

## Abstract

The D programming language has built-in support for [Contract Programming](https://dlang.org/spec/contracts.html).
The `in`, `out` and `invariant` constructs are used to specify preconditions, postconditions and aggregate invariants.
Conditions inside contracts are encoded as a sequence of statements that explicitly throws an ``AssertError`` exactly in those cases where the condition fails.
This is a general way to specify runtime-checkable contracts, but it usually suffices to check that an expression evaluates to `true`. The present DIP proposes adding shorthand syntax for this use case.

### Links
- [DIP1003 discussion thread](http://forum.dlang.org/post/cklhgfbnpajbeefmwjrf@forum.dlang.org).

## Rationale

Although D contracts are statements, most contracts are specified as simple Boolean expressions that should evaluate to `true`. To wit, many programming languages with built-in support for contracts support only Boolean expressions to express contracts. This predominant use case should be supported with a more concise syntax in the D programming language. We expect that the prevalence of function contracts and invariants will increase in response to the improved ergonomics proposed by this DIP.

D code before the proposed change (which will remain valid):
```d
ulong strToDecInt(string s)
in
{
    assert(s.length > 0, "s must not be empty");
}
body
{
    ulong ret = 0;
}
```

Improved D code after the proposed change:
```d
ulong strToDecInt(string s)
    in(s.length > 0, "s must not be empty");
{
    ulong ret = 0;
}
```

## Description

We propose to introduce, in addition to the current statement-based contract syntax, a short-hand expression-based syntax for `in` and `out` contracts as well as `invariant` contracts. The syntax is designed to mimic that of a call to `assert`. A few additional considerations are necessary for `out` contracts, as they require access to the function's return value. (Different options for the `out` syntax are discussed in the section ["new `out` syntax"](#new-out-syntax), where we also motivate our recommended syntax.)

Multiple `in` and `out` contracts are permitted for a single function. Expression-based contracts have no terminating semicolons, and the `do` keyword indicating the beginning of the function body is optional; the body's opening brace is sufficient.

Example:
```d
int fun(ref int a, int b)
    in(a > 0)
    in(b >= 0, "b cannot be negative")
    out(r; r > 0, "return must be positive")
    out(; a != 0)
{
    // function body
}
```

Contracts can use either the statement-based syntax or the expression-based syntax. Both may be present in the same function declaration. The `do` keyword continues to be required as a separator between a statement-based contract and the function body.

Example:
```d
int fun(ref int a, int b)
in(a > 0)
in
{
    assert(b >= 0, "b cannot be negative!");
}
do
{
    // function body
}
```

For virtual interface functions without a specified function body, a semicolon is required to terminate the function declaration after an expression-based contract specification. (No semicolon is required to terminate such a function declaration after a statement-based contract specification, which is consistent with the current behavior.)

Example:
```d
interface I
{
    int fun(int a) in(a > 0);
}
```

This DIP also proposes similar syntax for `invariant` contracts. Like the proposed function contract syntax, the new `invariant` contract syntax is designed to mimic a call to `assert`.
Expression-based `invariant` contracts must be terminated with a semicolon. A `class` or `struct` definition may contain multiple `invariant` contracts using either syntactic form.

Example:
```d
class C {
    int data;
    invariant(data != 0, "data cannot be 0");
}
```

The semantics of the new expression-based contracts is specified by lowering to contracts using the existing statement-based syntax.
Expression-based contracts are lowered to statement-based contracts containing a single `assert` statement with the arguments of the contract.

Example:
```d
int fun(ref int a, int b)
    in(a > 0)
    in(b >= 0, "b cannot be negative!")
    out(r; r > 0, "return must be positive")
    out(; a != 0)
{
    // function body
}

interface I {
    int fun(int a)
        in(a > 0);
}

class C {
    int data;
    invariant(data != 0, "data cannot be 0");
}
```
Turns into:
```d
int fun(ref int a, int b)
in
{
    assert(a > 0);
}
in
{
    assert(b >= 0, "b cannot be negative!");
}
out(r)
{
    assert(r > 0, "return must be positive");
}
out
{
    assert(a != 0);
}
do
{
    // function body
}

interface I {
    int fun(int a)
    in
    {
        assert(a > 0);
    }
}

class C {
    int data;
    invariant
    {
        assert(data != 0, "data cannot be 0");
    }
}
```

Multiple statement-based `in` and `out` contracts are lowered into single statement-based contracts that execute the statements in the order they appear in the source, but in separated scopes. This is similar to the manner multiple statement-based `invariant` contracts are already lowered.

Example:

```d
int fun(int x)
in
{
    assert(x > 0);
}
in
{
    assert(x < 10);
}
out(r)
{
    assert(r <1 0);
}
out(s)
{
    assert(s % 2 == 0);
}
out
{
    assert(true);
}
do
{
    // function body
}
```
Turns into:
```d
int fun(int x)
in
{
    {
        assert(x > 0);
    }
    {
        assert(x < 10);
    }
}
out(__result)
{
    {
        alias r = __result;
        assert(r < 10);
    }
    {
        alias s = __result;
        assert(s % 2 == 0);
    }
}
do
{
    // function body
}
```
(The implementation can use temporary `ref` variables instead of `alias` declarations for better error messages.)

## New `out` syntax

Note that our proposed `out` contract syntax contains a semicolon that is not present in the `in` contract syntax. This semicolon separates the identifier for the function's return value to be used within the contract condition from the contract condition. The identifier for the return value is optional, but the semicolon is always required. We have considered multiple alternatives before reaching this recommendation:

1. Require the semicolon only if the return value needs to be bound to an identifier. This leads to ambiguities with the old syntax: `out(i)` could be parsed as either a contract expression asserting that `i` is true, or the beginning of an `out` contract using the old contract syntax that introduces the identifier `i` for the function's return value.

Example:
```d
int fun(ref int i)
    out(i != 0) // okay
    out(i) // whoops! ambiguous with existing contract syntax
{
   // out contract, not function body
}
```

2. Use two sets of parentheses; one to introduce the identifier and one for the contract expression. This is analogous to the statement-based `out` contract syntax in case the return value needs to be bound (but not otherwise). It also resembles the syntax of template function declarations.

Example:
```d
int fun(ref int i)
    out(r)(r > 0)
    out()(i) // unambiguous with the current contract syntax
{
  // function body
}
```

3. (Our recommended solution.) Require the use of a semicolon to separate the contract parameter from the expression body. This resembles the syntax of `for` and `foreach` loops, and does not require multiple sets of parentheses. It is also more concise.

Example:
```d
int fun(ref int i)
    out(r; r > 0)
    out(; i > 0)
    out(; i)  // these are all unambiguous
{
    // function body
}
```

Note that existing `foreach` statements do not allow omitting the initial identifier, but the proposed syntax does. If more consistency with `foreach` is desired, we could require that `out` contracts always introduce an identifier by removing the relevant grammar rule.

## Grammar
The grammar for `assert` arguments is redefined in terms of `ContractArguments`, which is then used in the grammar rules for all newly-proposed expression-based contract specifications.
Existing statement-based `in`, `out` and `invariant` contracts are preserved (with the same semantics).
However, in contrast to before, multiple `in` and `out` contracts are now allowed on the same function declaration, even if they are statement-based.

Changed grammar rules:
```diff
- AssertExpression:
-    assert ( AssignExpression ,[opt] )
-    assert ( AssignExpression , AssignExpression ,[opt] )
+    assert(ContractArguments)

- FunctionContracts:
-     InStatement OutStatement[opt]
-     OutStatement InStatement[opt]
+     FunctionContract
+     FunctionContract FunctionContracts

- FunctionBody:
-     BlockStatement
-     FunctionContracts[opt] BodyStatement
-     FunctionContracts
+     SpecifiedFunctionBody
+     MissingFunctionBody

- FunctionLiteralBody:
-     BlockStatement
-     FunctionContracts[opt] BodyStatement
+     SpecifiedFunctionBody

Invariant:
-     invariant ( ) BlockStatement
-     invariant BlockStatement
+     invariant ( ) BlockStatement
+     invariant BlockStatement
+     invariant ( ContractArguments ) ;

+ ContractArguments:
+     AssignExpression ,[opt]
+     AssignExpression , AssignExpression ,[opt]

+ InContractExpression:
+     in ( ContractArguments )

+ OutContractExpression:
+     out ( ; ContractArguments )
+     out ( Identifier ; ContractArguments )

+ InOutContractExpression:
+     InContractExpression
+     OutContractExpression

+ InOutStatement:
+     InStatement
+     OutStatement

+ FunctionContract:
+     InOutContractExpression
+     InOutStatement

+ SpecifiedFunctionBody:
+     do[opt] BlockStatement
+     FunctionContracts[opt] InOutContractExpression do[opt] BlockStatement
+     FunctionContracts[opt] InOutStatement do BlockStatement

+ MissingFunctionBody:
+     ;
+     FunctionContracts[opt] InOutContractExpression ;
+     FunctionContracts[opt] InOutStatement
```

## Code Breakage

This DIP exclusively proposes additional syntax and thus no code breakage is anticipated.

## Acknowledgments

This DIP is based upon an idea initially proposed by H.S. Teoh. It incorporates ideas from Moritz Maxeiner, Solomon E, Timon Gehr, and the DIP author, and was very helpfully edited by Mike Parker and Timon Gehr.

## Copyright & License

Copyright (c) 2017 by the D Language Foundation

Licensed under [Creative Commons Zero 1.0](https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt)

## Reviews

### Preliminary Review Round 1

[Reviewed Version](https://github.com/dlang/DIPs/blob/d2dc77802c74378cf4545069eced21f85fbf893f/DIPs/DIP1009.md)

<EMAIL_ADDRESS>
The version of the DIP reviewed in this round laid out three requirements for the proposed syntax:

1. semi-colons must be allowed to terminate contracts in expression form
2. multiple in/out contracts must be allowed
3. contracts should be allowed in the function body

During the course of the review, requirements 1 and 2 received negative feedback, the former for being "noisy" and the latter for introducing too much cognitive dissonance. Both were removed from the DIP for the next review round.

This version proposed the syntax `in assert(arg)` and `out(ret) assert(ret)`. This syntax received negative feedback for being too significant a change and too dissimilar to the syntax of other D language features. This proposed syntax was replaced in the next iteration of the DIP.

### Preliminary Review Round 2

[Reviewed Version](https://github.com/dlang/DIPs/blob/5ac6323098035773fe8ca18362832e0162344b7f/DIPs/DIP1009.md)

<EMAIL_ADDRESS>
The overall feedback for the proposed syntax in this revision of the DIP was positive. It was noted that an example of the syntax in a bodyless function should be provided, so one was added in the next iteration of the DIP.

### Final Review

[Reviewed Version](https://github.com/dlang/DIPs/blob/98052839441fdb8c6cc05afccb9a81d084051c4d/DIPs/DIP1009.md)

<EMAIL_ADDRESS>
No revisions were made to the DIP as a result of this review round and the DIP was submitted without changes for Formal Assessment.

### Formal Assessment

[Reviewed Version A](https://github.com/dlang/DIPs/blob/98052839441fdb8c6cc05afccb9a81d084051c4d/DIPs/DIP1009.md)

[Reviewed Version B](https://github.com/dlang/DIPs/blob/a44646afe51318a4ceb90467b2a98213cb44555e/DIPs/DIP1009.md)

[Reviewed Version C](https://github.com/dlang/DIPs/blob/ef2aacc254d51412537e7af8c4750e634d554c41/DIPs/DIP1009.md)

The Language Maintainers approved of the proposed feature without objection, but found the language of the DIP as it existed in Version A to be below the standards expected of a quality proposal. A further round of revisions by both the DIP Author and Jared Hanson resulted in Version B. This version still failed to meet the expected standards. After further revision by Timon Gehr, the DIP was accepted with minor edits by the Language Maintainers.

repository: dlang/DIPs

branch_name: refs/heads/master

gha_language: D

repo_name: dlang/DIPs


text:
# Code-Refractor
By Jennifer Detmering

# Project Description
Improved website's code using HTML Semantics. Improved search engine optimization and improved accessibilty.

# Technologies Used
HTML, CSS

# Installation-Link to Project

Code-Refractor Homework

# Picture of Site

# Contributors
W3 Schools Website

Mozilla Developer Network Website

# License
License Document

repository: kodiakshuksan/Code-Refractor

branch_name: refs/heads/main

repo_name: kodiakshuksan/Code-Refractor


text:
# GWT Styles

!INCLUDE "../dependencies.md"

## Adding Style to Our Component

Vue GWT is compatible with GSS styles.
You can declare your `CssResource` interfaces and use them within your Vue GWT Components.

You also get type checking of your styles rules at compile type.
So if you try to use `myStyle.bob()` in your template, and this style doesn't exist, the compilation will break with an explicit error.

Let see it in action with a simple example.

We will create a simple style that set the text color to red.

***MelisandreComponentStyle.java***

First, we create a `CssResource` interface.
We also add the `@Style` annotation to it.
This annotation will automatically generate a GWT Bundle for us.

```java
@Style
public interface MelisandreComponentStyle extends CssResource {
    String red();
    String bold();
}
```

***MelisandreComponentStyle.gss***

We then create the style for this interface.
It's important to give the gss file the same name as your Interface.
This is because the binding is made automatically by Vue GWT based on the name.

```css
.red {
    color: red;
}
.bold {
	font-weight: bold;
}
```

***MelisandreComponent.java***

Let's use our style in a small Component.
For the Java part, nothing is needed, so we can just create an empty Component class.

```java
@Component
public class MelisandreComponent extends VueComponent {
}
```

***MelisandreComponent.html***

In the template, we can now import our style.
We just have to add an `vue-gwt:import` statement on top of our component.
In the `style` attribute, we put the full class name of our Style interface.
We also add a `name` attribute to give our style a name in the template.

We can then simply use Vue `v-bind` directive to bind our style.

```html
<vue-gwt:import style="com.mypackage.MelisandreComponentStyle" name="myStyle"/>
<div v-bind:class="myStyle.red()">
    For the night is dark and full of terrors.
</div>
```

## Adding More Than One CSS Class

You can add more than one CSS Class to your Components by using the [`array` builder](../js-interop/README.md#array):

```html
<div v-bind:class="array(myStyle.red(), myStyle.bold())">
    For the night is dark, full of terrors and bold.
</div>
```

## Conditional Styling

You can apply a Style conditionally.
First we add a boolean in our `MelisandreComponent`:

```java
@Component
public class MelisandreComponent extends VueComponent {
    @JsProperty boolean isRed = true;
}
```

Then we simply use a ternary expression (be careful with the quotes):

```html
<div v-bind:class='isRed ? myStyle.red() : ""'>
    For the night is dark, full of terrors and might or not be red.
</div>
```

## Conditional Styling With Several CSS Class

You can combine both the `array` and the ternary syntax:

```html
<div v-bind:class='array(isRed ? myStyle.red() : "", myStyle.bold())'>
    For the night is dark, full of terrors, might or not be red and always BOLD.
</div>
```

## Here is our finished `MelisandreComponent`

{% raw %}

{% endraw %}

You can try toggling the red color on the two bottom sentences by typing in your browser console:

```
melisandreComponent.isRed = false;
```


text:
#### Scripts
##### CommonServerPython
- Fixed an issue in the **Common** class, which would cause a failure while using *to_context* on a list of **FeedRelatedIndicators** objects.

repository: demisto/content

gha_language: Python

repo_name: demisto/content


text:
# AudioSpeedUp
![GitHub release (latest by date)](https://img.shields.io/github/v/release/bonsky97/AudioSpeedUp?style=social)
![GitHub Releases](https://img.shields.io/github/downloads/bonsky97/AudioSpeedUp/total?style=social)
### [**Download now!**](https://github.com/bonsky97/AudioSpeedUp/releases/latest/download/AudioSpeedUp.apk)

**NOTE: Supported on Andoird 7.1 or newer**

*AudioSpeedUp* is the open source app for Android for reproducing at different speed your audio files. Select a sound to play, such as WhatsApp voice notes, and select *AudioSpeedUp* from the share button. This app has been developed with non-profit intent by Lorenzo D'Auria for helping people who are to busy for listening to slow voice notes.

_**For italian users**: This project has been presented also in video on [YouTube](https://youtu.be/IKIYfGBtt2g)._

## New Features!

  - New user interface
  - Add dark theme

**You can also:**
  - Donate using the donate button
  - Set italian language
  - Control the music player from notification bar
  - Switch applications during reproduction

## Donations

Donations are always welcome, you can use this [link](https://paypal.me/AudioSpeedUp). Thank you in advise!

## Contributions

A big thank you to:

 - [@Fast0n](https://github.com/fast0n)

Want to contribute? Great! See [here](https://github.com/bonsky97/AudioSpeedUp/blob/master/AudioSpeedUp/CONTRIBUTING.md).

## Todos

 - Add in-ear audio when proximity sensor detect contact
 - Improve notification buttons efficiency
 - Add support for .opus file also in older Android versions.
 - Auto-update application

License
----
MIT

_See [here](https://github.com/bonsky97/AudioSpeedUp/blob/master/LICENSE) for details._

repository: massimopagani/AudioSpeedUp

repo_name: massimopagani/AudioSpeedUp


text:
# Groovy - README

## 安装

### Operating system/package manager installation

* Install Binary

  `Groovy 2.5` requires `Java 6+` with full support up to Java 8. There are currently some known
  issues for some aspects when using Java 9 snapshots. The `groovy-nio` module requires `Java 7+`.
  Using Groovy’s `invokeDynamic` features require `Java 7+` but we recommend `Java 8`.

  * [下载](http://groovy-lang.org/install.html#download-groovy) Groovy二进制包，并解压至你想要的目录
  * 配置`GROOVY_HOME`环境变量，指向你的安装目录
  * `PATH`环境变量追加`GROOVY_HOME/bin`
  * 配置`JAVA_HOME`环境变量

  创建一个交互式的 groovy shell：
  ```shell script
  $ groovysh
  ```

  运行 Swing interactive console：
  ```shell script
  $ groovyConsole
  ```

  执行指定的Groovy 脚本：
  ```shell script
  $ groovy SomeScript
  ```

  If you embed Groovy in your application. To use the
  [InvokeDynamic](http://docs.groovy-lang.org/latest/html/documentation/invokedynamic-support.html)
  version of the jars just append `:indy` for Gradle or `<classifier>indy</classifier>` for Maven.

* [SDKMAN!](http://sdkman.io/) is a tool for managing parallel versions of multiple Software
  Development Kits on most Unix-based systems:

  ```shell script
  $ sdk install groovy
  ```

  Windows users: see the SDKMAN [install](https://sdkman.io/install) instructions for potential options.

  > `SDKMAN`可以支持安装JDK及Java相关的工具（Maven、Ant、SpringBoot、Scala等），并支持同时安装多个版本

* [Homebrew](http://brew.sh/) is "the missing package manager for macOS":

  ```shell script
  $ brew install groovy
  ```

* [SnapCraft](https://snapcraft.io/) is "the app store for Linux". Groovy is supported in the
  [store](https://snapcraft.io/groovy) or via the commandline:

  ```shell script
  $ sudo snap install groovy --classic
  ```

* [MacPorts](http://www.macports.org/) is a system for managing tools on macOS:

  ```shell script
  $ sudo port install groovy
  ```

* [Scoop](http://scoop.sh/) is a command-line installer for Windows inspired by Homebrew:

  ```shell script
  > scoop install groovy
  ```

* [Chocolatey](https://chocolatey.org/) provides a sane way to manage software on Windows:

  ```shell script
  > choco install groovy
  ```

Linux/*nix users: you may also find Groovy is available using your preferred operating system
package manager, e.g.: apt, dpkg, pacman, etc.

> [参考文档](http://groovy-lang.org/download.html#osinstall)

## Note

### Default imports

All these packages and classes are imported by default, i.e. you do not have to use an explicit import statement to use them:

* java.io.*
* java.lang.*
* java.math.BigDecimal
* java.math.BigInteger
* java.net.*
* java.util.*
* groovy.lang.*
* groovy.util.*

### Static import aliasing

Static imports with the `as` keyword provide an elegant solution to namespace problems. Suppose you
want to get a `Calendar` instance, using its `getInstance()` method. It’s a static method, so we can
use a static import. But instead of calling `getInstance()` every time, which can be misleading when
separated from its class name, we can import it with an alias, to increase code readability:

```groovy
import static Calendar.getInstance as now

assert now().class == Calendar.getInstance().class
```

### Import aliasing

With type aliasing, we can refer to a fully qualified class name using a name of our choice. This
can be done with the as keyword, as before.

For example we can import `java.sql.Date` as `SQLDate` and use it in the same file as
`java.util.Date` without having to use the fully qualified name of either class:

```groovy
import java.util.Date
import java.sql.Date as SQLDate

Date utilDate = new Date(1000L)
SQLDate sqlDate = new SQLDate(1000L)

assert utilDate instanceof java.util.Date
assert sqlDate instanceof java.sql.Date
```

### Shebang line

Beside the single-line comment, there is a special line comment, often called the shebang line
understood by UNIX systems which allows scripts to be run directly from the command-line,
provided you have installed the Groovy distribution and the `groovy` command is available on the `PATH`.

```shell script
#!/usr/bin/env groovy
println "Hello from the shebang line"
```

> The `#` character must be the first character of the file. Any indentation would yield a compilation error.

### [Method pointer operator](http://groovy-lang.org/operators.html#method-pointer-operator)

The method pointer operator (`.&`) call be used to store a reference to a method in a variable, in
order to call it later:

```groovy
def str = 'example of method reference'
def fun = str.&toUpperCase
def upper = fun()
assert upper == str.toUpperCase()
```

There are multiple advantages in using method pointers. First of all, the type of such a method
pointer is a `groovy.lang.Closure`, so it can be used in any place a closure would be used. In
particular, it is suitable to convert an existing method for the needs of the strategy pattern:

```groovy
def transform(List elements, Closure action) {
    def result = []
    elements.each {
        result << action(it)
    }
    result
}
String describe(Person p) {
    "$p.name is $p.age"
}
def action = this.&describe
def list = [
    new Person(name: 'Bob',   age: 42),
    new Person(name: 'Julia', age: 35)]
assert transform(list, action) == ['Bob is 42', 'Julia is 35']
```

Method pointers are bound by the receiver and a method name. Arguments are resolved at runtime, meaning that if you have multiple methods with the same name, the syntax is not different, only resolution of the appropriate method to be called will be done at runtime:

```groovy
def doSomething(String str) { str.toUpperCase() }
def doSomething(Integer x) { 2*x }
def reference = this.&doSomething
assert reference('foo') == 'FOO'
assert reference(123)   == 246
```

### [Regular expression operators](http://groovy-lang.org/operators.html#_regular_expression_operators)

#### Pattern operator

The pattern operator (`~`) provides a simple way to create a `java.util.regex.Pattern` instance:

```groovy
def p = ~/foo/
assert p instanceof Pattern
```

while in general, you find the pattern operator with an expression in a slashy-string, it can be
used with any kind of `String` in Groovy:

```groovy
// using single quote strings
p = ~'foo'
// using double quotes strings
p = ~"foo"
// the dollar-slashy string lets you use slashes and the dollar sign without having to escape them
p = ~$/dollar/slashy $ string/$
// you can also use a GString!
p = ~"${pattern}"
```

#### Find operator

Alternatively to building a pattern, you can directly use the find operator `=~` to build a
`java.util.regex.Matcher` instance:

```groovy
def text = "some text to match"
// `=~` creates a matcher against the `text` variable, using the pattern on the right hand side
def m = text =~ /match/
// the return type of `=~` is a `Matcher`
assert m instanceof Matcher
// equivalent to calling `if (!m.find())`                  `
if (!m) {
    throw new RuntimeException("Oops, text not found!")
}
```

Since a `Matcher` coerces to a `boolean` by calling its `find` method, the `=~` operator is
consistent with the simple use of Perl’s `=~` operator, when it appears as a predicate (in `if`,
`while`, etc.).

#### Match operator

The match operator (`==~`) is a slight variation of the find operator, that does not return a
`Matcher` but a boolean and requires a strict match of the input string:

```groovy
// `==~` matches the subject with the regular expression, but match must be strict
m = text ==~ /match/
// the return type of `==~` is therefore a `boolean`
assert m instanceof Boolean
// equivalent to calling `if (text ==~ /match/)`
if (m) {
    throw new RuntimeException("Should not reach that point!")
}
```

### [Spread operator](http://groovy-lang.org/operators.html#_spread_operator) - 详情请参考文档

The Spread-dot Operator (`*.`), often abbreviated to just Spread Operator, is used to invoke an
action on all items of an aggregate object. It is equivalent to calling the action on each item and
collecting the result into a list:

```groovy
class Car {
    String make
    String model
}
def cars = [
       new Car(make: 'Peugeot', model: '508'),
       new Car(make: 'Renault', model: 'Clio')]
def makes = cars*.make
assert makes == ['Peugeot', 'Renault']
```

The spread operator is null-safe, meaning that if an element of the collection is null, it will
return null instead of throwing a `NullPointerException`:

```groovy
cars = [
   new Car(make: 'Peugeot', model: '508'),
   null,
   new Car(make: 'Renault', model: 'Clio')]
assert cars*.make == ['Peugeot', null, 'Renault']
assert null*.make == null
```

以下功能请参考官方文档：
* Spreading method arguments
* Spread list elements
* Spread map elements

### Identity operator

In Groovy, using `==` to test equality is different from using the same operator in Java. In Groovy,
it is calling `equals`. If you want to compare reference equality, you should use `is` like in the
following example:

```groovy
// Create a list of strings
def list1 = ['Groovy 1.8','Groovy 2.0','Groovy 2.3']
// Create another list of strings containing the same elements
def list2 = ['Groovy 1.8','Groovy 2.0','Groovy 2.3']
// using `==`, we test object equality
assert list1 == list2
// but using `is`, we can check that references are distinct
assert !list1.is(list2)
```

### [Coercion operator](http://groovy-lang.org/operators.html#_coercion_operator)

The coercion operator (`as`) is a variant of casting. Coercion converts object from one type to
another without them being compatible for assignment. Let’s take an example:

```groovy
Integer x = 123
// `Integer` is not assignable to a `String`, so it will produce a `ClassCastException` at runtime
String s = (String) x
```

This can be fixed by using coercion instead:

```groovy
Integer x = 123
// `Integer` is not assignable to a `String`, but use of `as` will coerce it to a `String`
String s = x as String
```

When an object is coerced into another, unless the target type is the same as the source type,
coercion will return a new object. The rules of coercion differ depending on the source and target
types, and coercion may fail if no conversion rules are found. Custom conversion rules may be
implemented thanks to the `asType` method:

```groovy
class Identifiable {
    String name
}
class User {
    Long id
    String name
    def asType(Class target) {
        if (target == Identifiable) {
            return new Identifiable(name: name)
        }
        throw new ClassCastException("User cannot be coerced into $target")
    }
}
def u = new User(name: 'Xavier')
def p = u as Identifiable
assert p instanceof Identifiable
assert !(p instanceof User)
```

### Call operator

The call operator `()` is used to call a method named `call` implicitly. For any object which
defines a `call` method, you can omit the `.call` part and use the call operator instead:

```groovy
class MyCallable {
    //`MyCallable` defines a method named `call`. Note that it doesn’t need to implement `java.util.concurrent.Callable`
    int call(int x) {
        2*x
    }
}

def mc = new MyCallable()
// we can call the method using the classic method call syntax
assert mc.call(2) == 4
// or we can omit `.call` thanks to the call operator
assert mc(2) == 4
```

### Operator overloading

Groovy allows you to overload the various operators so that they can be used with your own classes. Consider this simple class:

```groovy
class Bucket {
    int size

    Bucket(int size) { this.size = size }

    // `Bucket` implements a special method called `plus()`
    Bucket plus(Bucket other) {
        return new Bucket(this.size + other.size)
    }
}
```

Just by implementing the `plus()` method, the `Bucket` class can now be used with the + operator
like so:

```groovy
def b1 = new Bucket(4)
def b2 = new Bucket(11)
// The two `Bucket` objects can be added together with the `+` operator
assert (b1 + b2).size == 15
```

All (non-comparator) Groovy operators have a corresponding method that you can implement in your own
classes. The only requirements are that your method is public, has the correct name, and has the
correct number of arguments. The argument types depend on what types you want to support on the
right hand side of the operator. For example, you could support the statement

```groovy
assert (b1 + 11).size == 15
```
by implementing the `plus()` method with this signature:

```groovy
Bucket plus(int capacity) {
    return new Bucket(this.size + capacity)
}
```

Here is a complete list of the operators and their corresponding methods:

| Operator   |  Method  |  Operator  |  Method  |
|:---|:---|:---|:---|
|  `+`  |  `a.plus(b)`  |  `a[b]`  |  `a.getAt(b)`  |
|  `-`  |  `a.minus(b)`  |  `a[b] = c`  |  `a.putAt(b, c)`  |
|  `*`  |  `a.multiply(b)`  |  `a in b`  |  `b.isCase(a)`  |
|  `/`  |  `a.div(b)`  |  `<<`  |  `a.leftShift(b)`  |
|  `%`  |  `a.mod(b)`  |  `>>`  |  `a.rightShift(b)`  |
|  `**`  |  `a.power(b)`  |  `>>>`  |  `a.rightShiftUnsigned(b)`  |
|  `|`  |  `a.or(b)`  |  `++`  |  `a.next()`  |
|  `&`  |  `a.and(b)`  |  `--`  |  `a.previous()`  |
|  `^`  |  `a.xor(b)`  |  `+a`  |  `a.positive()`  |
|  `as`  |  `a.asType(b)`  |  `-a`  |  `a.negative()`  |
|  `a()`  |  `a.call()`  |  `~a`  |  `a.bitwiseNegate()`  |

## 文档

* [官方文档](http://groovy-lang.org/documentation.html)
  * [System requirements](http://groovy-lang.org/download.html#requirements)
  * [IDE integration](http://docs.groovy-lang.org/latest/html/documentation/tools-ide.html)

  * [Differences with Java -【重要】](http://groovy-lang.org/differences.html)

  * Language Specification
    * Syntax
      * [Shebang line](http://groovy-lang.org/syntax.html#_shebang_line) - Shell脚本
      * [Quoted identifiers](http://groovy-lang.org/syntax.html#_quoted_identifiers) -
        引号包裹的标识符，引号中可包含Java非法标识符
      * [Strings](http://groovy-lang.org/syntax.html#all-strings)
        * `Single-quoted string` - 等效于`java.lang.String`，不支持插值操作。
        * `Triple-single-quoted string` - 和`Single-quoted string`一样，且支持多行字符窜。怎么处理开头结尾换行及缩进参考文档。
        * `Escaping special characters` - `\`
        * `Unicode escape sequence`
        * `Double-quoted string` - Double-quoted strings are plain `java.lang.String` if there’s no
          interpolated expression, but are `groovy.lang.GString` instances if interpolation is
          present. 支持插值操作，详情请参考文档。
        * `Triple-double-quoted string` - 和`Double-quoted string`一样，且支持多行字符窜。
        * `Slashy string` - 简化定义正则表达式
        * `Dollar slashy string`
        * [String summary table](http://groovy-lang.org/syntax.html#_string_summary_table)
      * [Characters](http://groovy-lang.org/syntax.html#_characters)
      * [Numbers](http://groovy-lang.org/syntax.html#_numbers)
      * [Lists](http://groovy-lang.org/syntax.html#_lists)
      * [Arrays](http://groovy-lang.org/syntax.html#_arrays)
      * [Maps](http://groovy-lang.org/syntax.html#_maps)

    * [Operators](http://groovy-lang.org/operators.html)
      * `Elvis operator`
      * `Safe navigation operator`
      * `Direct field access operator` - use of `.@` forces usage of the field instead of the
        getter: `user.@name == 'Bob'`
      * `Method pointer operator`
      * `Regular expression operators`
      * `Spread operator`
      * `Range operator`
      * `Spaceship operator` - The spaceship operator (`<=>`) delegates to the `compareTo` method
      * `Subscript operator`
      * `Membership operator` - he membership operator (`in`) is equivalent to calling the `isCase`
        method. In the context of a `List`, it is equivalent to calling `contains`.
      * `Coercion operator`
      * `Call operator`
      * [`Operator precedence`](http://groovy-lang.org/operators.html#_operator_precedence)
      * `Operator overloading`

    * [Program structure](http://groovy-lang.org/structure.html) - 讲解程序整体结构
      * Scripts versus classes - 简易说明Groovy怎么转变Script为Class

    * Object orientation - 讲解Groovy面向对象编程的语法及概念
      * [Primitive types](http://groovy-lang.org/objectorientation.html#_primitive_types) - 自动拆箱/装箱
      * [Meta-annotations](http://groovy-lang.org/objectorientation.html#_meta_annotations) -
        给多个注解起别名，便于开发及维护：`@AnnotationCollector`
      * [Traits](http://groovy-lang.org/objectorientation.html#_traits) - 有点类似JDK8接口的默认实现功能

    * [Closures](http://groovy-lang.org/closures.html) - Groovy闭包

    * [Semantics](http://groovy-lang.org/semantics.html) - Groovy语法
      * `Statements`
      * `GPath expressions`
      * `Promotion and coercion`
      * `Optionality`
      * `The Groovy Truth`
      * `Typing`
      * `Type checking extensions`

  * Tools
    * [groovyc - the Groovy compiler](http://groovy-lang.org/groovyc.html)
      * `groovyc`
      * `Ant task`
      * `Gant`
      * `Maven integration`
      * `GMaven` - 不在支持，转用`GMavenPlus`
      * `GMaven 2` -
        [Groovy Maven Plugin](http://groovy.github.io/gmaven/groovy-maven-plugin/index.html) -
        不是`GMaven`升级版，不是为了替换`GMaven`，它删除了`GMaven`非脚本功能。
        * `groovy:console` - Open a Groovy console window.
        * `groovy:execute` - Execute a Groovy script.
        * `groovy:shell` - Run `groovysh` shell.
      * `GMavenPlus`
        * [GMavenPlus - 插件配置详解](http://groovy.github.io/GMavenPlus/plugin-info.html)
        * [About GMavenPlus](https://github.com/groovy/GMavenPlus/wiki/About)
          * Why? - These were some of my goals in creating this project.
          * Why not patch GMaven?
          * What's so different?
          * Why not just use groovyc in the AntRun Plugin?
          * Why not just use the Groovy-Eclipse Compiler Plugin for Maven?
        * [Choosing Your Build Tool](https://github.com/groovy/GMavenPlus/wiki/Choosing-Your-Build-Tool)
          - 怎样选择适合你的构建工具
        * [Examples](https://github.com/groovy/GMavenPlus/wiki/Examples)
        * [Known Issues](https://github.com/groovy/GMavenPlus/wiki/Known-Issues)
        * [Usage](https://github.com/groovy/GMavenPlus/wiki/Usage)
      * `The Groovy Eclipse Maven plugin`
        * [Catalog of Features](https://github.com/groovy/groovy-eclipse/wiki/Catalog-of-Features)
        * [DSL Descriptors](https://github.com/groovy/groovy-eclipse/wiki/DSL-Descriptors)
        * [Groovy Eclipse Architecture](https://github.com/groovy/groovy-eclipse/wiki/Groovy-Eclipse-Architecture)
        * [A Groovier Eclipse experience](https://spring.io/blog/2009/07/30/a-groovier-eclipse-experience)
        * [Groovy Eclipse Maven plugin](https://github.com/groovy/groovy-eclipse/wiki/Groovy-Eclipse-Maven-plugin)
          * [Examples](https://github.com/groovy/groovy-eclipse/tree/master/extras/groovy-eclipse-compiler-tests/src/it)
      * `Joint compilation`
      * `Android support`

    * [groovysh - the Groovy repl-like shell](http://groovy-lang.org/groovysh.html)

    * [groovyConsole - the Groovy Swing console](http://groovy-lang.org/groovyconsole.html)
      * `Groovy Console` 可以查看 `AST`(`Abstract Syntax Tree`) 及 `Class Generation`

    * [IDE integration](http://groovy-lang.org/ides.html)

  * [The Groovy Development Kit](http://groovy-lang.org/groovy-dev-kit.html)
    * [Working with IO](http://groovy-lang.org/groovy-dev-kit.html#_working_with_io) - 各种文件操作
    * [Lists](http://groovy-lang.org/groovy-dev-kit.html#Collections-Lists) - 操作List
    * [Maps](http://groovy-lang.org/groovy-dev-kit.html#Collections-Maps) - 操作Map
    * [Ranges](http://groovy-lang.org/groovy-dev-kit.html#Collections-Ranges) - 快速创建范围List
    * [Syntax enhancements for collections](http://groovy-lang.org/groovy-dev-kit.html#_syntax_enhancements_for_collections)
      * GPath support
      * Spread operator
      * The star-dot `*.` operator
      * Slicing with the subscript operator
    * [Working with legacy Date/Calendar types](http://groovy-lang.org/groovy-dev-kit.html#_working_with_legacy_date_calendar_types)
    * [Working with Date/Time types](http://groovy-lang.org/groovy-dev-kit.html#_working_with_date_time_types)
    * [Handy utilities](http://groovy-lang.org/groovy-dev-kit.html#_handy_utilities)
      * ConfigSlurper - 读配置文件的工具类
      * Expando - 动态扩展对象
      * Observable list, map and set - 观察list、map和set集合的变动

  * Runtime and compile-time metaprogramming -【重要】
    * [Runtime metaprogramming](http://groovy-lang.org/metaprogramming.html#_runtime_metaprogramming)
      -【重要】运行时元编程
    * [Compile-time metaprogramming](http://groovy-lang.org/metaprogramming.html#_compile_time_metaprogramming)
      -【重要】编译时元编程，通常使用注解在编译时修改AST
    * [Groovy interception mechanism](http://groovy-lang.org/metaprogramming.html#_runtime_metaprogramming)
      -【重要】POGO类方法调用过程
    * [Compilation phases guide](http://groovy-lang.org/metaprogramming.html#_compilation_phases_guide)
    * [Developing AST transformations](http://groovy-lang.org/metaprogramming.html#developing-ast-xforms)
      -【重要】自定义开发AST转换规则
    * [Unleashing the power of AST transformations](http://melix.github.io/ast-workshop/) - 非官方文档

  * [The Grape dependency manager](http://groovy-lang.org/grape.html) -【重要】

    通过`@Grab`注解或`Grape.grab()`下载所依赖的Jar：
    ```groovy
    @Grab(group='org.springframework', module='spring-orm', version='3.2.5.RELEASE')

    Grape.grab(group:'com.jidesoft', module:'jide-oss', version:'[2.2.0,)')
    ```

  * [Testing guide - 编写单元测试](http://groovy-lang.org/testing.html)
    * `assert` - 扩展了Java的assert功能，且默认启用
    * `Mocking` and `Stubbing` - Groovy内置功能
    * Testing with `JUnit`
    * Testing with `Spock`
    * Functional Tests with `Geb`

  * [Domain-Specific Languages](http://groovy-lang.org/dsls.html) -【重要】
    * `Command chains`
    * `Operator overloading`
    * `Script base classes`
    * `Adding properties to numbers`
    * `@DelegatesTo`
    * `Compilation customizers`
    * `Builders` - `MarkupBuilder`、`StreamingMarkupBuilder`、`SaxBuilder`、`StaxBuilder`、
      `DOMBuilder`、`NodeBuilder`、`JsonBuilder`、`StreamingJsonBuilder`、`SwingBuilder`、
      `AntBuilder`、`CliBuilder`、`ObjectGraphBuilder`、`JmxBuilder`、`FileTreeBuilder`

  * [Type checking extensions](http://docs.groovy-lang.org/latest/html/documentation/type-checking-extensions.html) -【重要】

    The DSL relies on a support class called `org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport`

  * [Integrating Groovy into applications](http://groovy-lang.org/integrating.html) -【重要】
    * `Eval`
    * `GroovyShell`
    * `GroovyClassLoader`
    * `GroovyScriptEngine`
    * `JSR 223 javax.script API`

  * [Design patterns in Groovy](http://groovy-lang.org/design-patterns.html)

  * [Style guide](http://groovy-lang.org/style-guide.html) -【重要】列出了部分Groovy语言特色，和Java形成对比
    * `No semicolons`
    * `Return keyword optional`
    * `Def and type`
    * `Public by default`
    * `Omitting parentheses`
    * `Classes as first-class citizens`
    * `Getters and Setters`
    * `Initializing beans with named parameters and the default constructor`
    * Using `with()` and `tap()` for repeated operations on the same bean
    * `Equals` and `==`
    * `GStrings` (interpolation, multiline)
    * `Native syntax for data structures`
    * `The Groovy Development Kit`
    * The power of `switch`
    * `Import aliasing`
    * `Groovy Truth`
    * `Safe graph navigation`
    * `Assert`
    * `Elvis operator` for default values
    * `Catch any exception`
    * Optional typing advice

  * Groovy module guides
    * [Parsing and producing JSON](http://groovy-lang.org/json.html)
    * [Working with a relational database](http://groovy-lang.org/databases.html)
    * [Processing XML](http://groovy-lang.org/processing-xml.html)
    * [Scripting Ant tasks](http://groovy-lang.org/scripting-ant.html)
    * [Template engines](http://groovy-lang.org/templating.html) -【重要】
    * [Creating Swing UIs](http://groovy-lang.org/swing.html)
    * [Servlet support](http://groovy-lang.org/servlet.html)
    * [Working with JMX](http://groovy-lang.org/jmx.html) -【重要】

  * API documentation
    * [GroovyDoc documentation of the Groovy APIs](http://groovy-lang.org/api.html)
    * [The Groovy Development Kit enhancements](http://groovy-lang.org/gdk.html) -【重要】可查看哪些Java类被增强了

repository: WangXiaoJin/docs

repo_name: WangXiaoJin/docs


text:
### Import Engine
This project provides a client library for the Advantage Navigator import engine. Advantage Navigator is an online tool for energy monitoring provided by Siemens, see https://eadvantage.siemens.com/. The import engine allows to transfer data like meter readings to the online tool by sending messages using HTTPS. Note that for all operations, a valid device user account from Siemens is necessary. The library is licensed under Apache License 2.0.

The following example shows how the library is used. In the example, a new device status is sent to the import engine.

```java
ImportEngineClient client = new ImportEngineClient("user", "secret");

DeviceStatus status = new DeviceStatus(DeviceStatusClass.OK, "Device up and running", "1.1");
DeviceStatusCommand command = new DeviceStatusCommand(status);

String result = client.executeCommand(command);
```

More examples can be found in the project's wiki.

repository: AdvantageNavigator/ImportEngine

repo_name: AdvantageNavigator/ImportEngine


text:
# eloc

[![npm version][npm-src]][npm-href]
[![Install size][packagephobia-src]][packagephobia-href]
[![License][license-src]][license-href]

Eloquence cli. For presenters who (1) focus on writing, (2) present in a concise style.

- Serve markdown as presentation
- Live editor
- Static export
- Print view / Mobile view / Dark mode
- Customizable with web standard

All of this in a [1MB][packagephobia-href] cli. Check out https://eloc.now.sh

### Presentation in Markdown ABC

Break markdown into slides with `---` (horizontal rule), and that's all. e.g. `slides.md`:

```
# Hello World
---
Brown fox jumps over the lazy dog.
---
## Thanks
```

then `eloc slides.md` gives you:

## Install

```bash
npm install -g eloc
```

## Usage

```
  eloc - The eloquent cli

  Usage

    $ eloc <markdown-file>        Serve markdown file as presentation
    $ eloc open <markdown-file>   Open markdown file as presention in browser
    $ eloc build <markdown-file>  Export presentation to directory

  Options

    -p, --port <number>     Port (default: 5000)
    -c, --css <file>        External css for customization
    -i, --include <globs>   Files for referencing in markdown
    -o, --out-dir <dir>     Output directory for build (default: public)
    -t, --title <string>    HTML title (default: <markdown-filename>)
    -b, --progress-bar      Enable progress bar
    -d, --dark              Enable dark theme

    -q, --quiet             Mute verbose logs
    -v, --version           Display version number
    -h, --help              Display usage information

  Examples

    # Serve "deck.md" as presentation
    $ eloc deck.md

    # Create & open "new-deck.md" as presentation in browser
    $ eloc open new-deck.md

    # Export presentation with images
    $ eloc build deck.md --include "*.jpg"
```

### Customization & Tips

- Use `--css` arg with an external stylesheet, which will be applied on every slide.

- Use inline `<style />` for [per-slide customization](https://eloc.now.sh/#6):

  ```
  _write style tag within markdown_

  <style>
    .slide { background: url(...) }
    .content { filter: invert() }
    code { opacity: 0.8 }
  </style>
  ```

- https://math.vercel.app/ is your friend for embedding math equations.

## See Also

- [markdown-deck](https://github.com/amio/markdown-deck): a web component for presenters

## Prior Art

- [mdx-deck](https://github.com/jxnblk/mdx-deck) - If you want to enhance slides with React, this is the one.
- [slides.com](https://slides.com) - Beautiful and powerful, the final choice for full featured presentation.
- [big](https://github.com/tmcw/big) - The boldest style, for fan of [Takahashi method](https://en.wikipedia.org/wiki/Takahashi_method).

[npm-src]: https://badgen.net/npm/v/eloc
[npm-href]: https://www.npmjs.com/package/eloc
[coverage-src]: https://badgen.net/codecov/c/github/amio/eloc
[coverage-href]: https://codecov.io/gh/amio/eloc
[packagephobia-src]: https://badgen.net/packagephobia/install/eloc
[packagephobia-href]: https://packagephobia.now.sh/result?p=eloc
[license-src]: https://badgen.net/badge/license/MIT
[license-href]: LICENSE.md

repository: amio/eloc

gha_language: TypeScript

repo_name: amio/eloc


text:
> [Go to French version](/fr/Lois/Lois%20révisées%20du%20Canada/N/N-23.md)

# Newfoundland and Labrador Additional Financial Assistance Act

**R.S.C. 1985, c. N-23**

----------

**Short title**

**1** This Act may be cited as the Newfoundland and Labrador Additional Financial Assistance Act.
> R.S., 1985, c. N-23, s. 1; 2015, c. 3, s. 135.

**Annual payment to Newfoundland and Labrador by way of additional financial assistance**

**2** In addition to all other payments, grants, subsidies and allowances payable to the Province of Newfoundland and Labrador, the Minister of Finance, on behalf of the Government of Canada, shall, out of the Consolidated Revenue Fund, cause to be paid to the Province of Newfoundland and Labrador in each and every fiscal year, until otherwise provided by any agreement in that behalf entered into between the Government of Canada and the Government of Newfoundland and Labrador, an annual amount, by way of additional financial assistance as contemplated by Term 29 of the Terms of Union of Newfoundland with Canada, of eight million dollars.
> R.S., 1985, c. N-23, s. 2; 2015, c. 3, s. 135.

repository: TravisMadill/CanadianLaws

path: /en/Acts/Revised Statutes of Canada/N/N-23.md

repo_name: TravisMadill/CanadianLaws


text:
# Databases With R

This repository contains the material for my talk 'Databases With R' at the
  combined San Diego/Boston/South Coast MA useR and San Diego R-Ladies meeting on July 30, 2020.
I show a few basic examples of using databases from within R, provide a few
  tips for effectively incorporating databases in your R workflow, and point
  to a few resources to learn more.

# Data

The data used in the examples comes from the [PokeAPI](https://pokeapi.co/), an
  API for accessing information on pokemon.
The file `data/get-data.R` pulls data from the PokeAPI and creates a local
  [SQLite](https://www.sqlite.org/index.html) database.

# Slides

The slides from the talk are in the `slides.html` file.
They are generated from `slides.Rmd` with the R package [xaringan](https://github.com/yihui/xaringan).
Note that you need to also have the `libs` folder in the same directory as
  `slides.html` in order to view the slides.

# Usage

If you want to run any of the files, the easiest thing is to dowload the
  entire repository (fork, clone, or as a zip).
This of course requires that you have all the required software installed.

# Dependencies

Since a SQLite database is used, you need to have SQLite installed, which it
  may already be.
I won't go into details of that here as this depends on your system.

To get the data and create the database, you will need the following R packages:

* tidyverse
* DBI
* RSQLite

Doing this in conjuction with the slides should be enough to start playing
  around in R.
If you also want to generate the slides, you will also need the xaringan
  package.

repository: asbates/databases-with-r

repo_name: asbates/databases-with-r


text:
# Gatsby Theme Portfolio Starter

A Gatsby theme for creating Superfast, SEO optimized Portfolio powered by `Material UI` and `MDX`
- [Live demo](https://gatsby-theme-portfolio-starter.netlify.com/)
- [My Portfolio Site](https://kamranali.in/)

## Performance
### Desktop

### Mobile

## ✨Features

It provides following functionality out of box

- Fully optimized for Lighthouse audit
- Responsive
- Pagination for projects
- Tags for browsing the projects
- Google Structured Data
- Google Analytics
- Sitemap

## Usage
### Install
Manually add to you site

`npm install --save gatsby-theme-portfolio-starter`

### Theme options

| Key              | Default value    | Description                                                                                |
| ---------------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
| `trackingId`     | `UA-27634418-4`  | Google Analytics Tracking ID                                                                               |
| `projectsPath`   | `projects`       | Location of Projects                                                                                |
| `imagesPath`     | `images`         | Location of cover image and icon                                                                                |
| `projectsPerPage`| `12`             | Number of Projects to be displayed on a single page |

#### Example usage

```js
// gatsby-config.js
module.exports = {
  plugins: [
        {
      resolve: "gatsby-theme-portfolio-starter",
      options: {
        trackingId: "UA-27634418-4",
        projectsPath: "projects",
        imagesPath: "images",
        projectsPerPage: "12"
      },
    },
  ],
}
```

### Additional configuration
In addition to the theme options, there are a handful of items you can customize via the siteMetadata object in your site's gatsby-config.js
```
// gatsby-config.js
module.exports = {
  siteMetadata: {
    title: `My Portfolio Title`,
    description: `My Portfolio Description`,
    author: `Author Name`,
    headline: `My Introduction`, // One liner Introduction
    focusArea: `Tech focus Area`, // Technologies currently working on / Knowledge of Tools, expertise etc
    twitterId: `@twitterHandle`,
    linkedInId: `linkedInID`,
    siteUrl: `site domain name`,
    keywords: [`Technology Blog`], // Used for SEO and Google Structured Data
    email<EMAIL_ADDRESS>// Contact email Used for Google Structured Data
    social: [
      'https://www.facebook.com/aTechGuide/'  // Social link used in site schema for Google Structured Data
    ],
    contactSupport: 'https://www.site.com/support/', // Contact link used in site schema for Google Structured Data
    bingId: '', // Support for Bing
    menuLinks: [{name: 'Projects', link: '/page/1'}], // Adding Menu bar links
  },
}
```

## 🚀Getting Started

- Create `projects` directory and add projects into it as Markdown files
- Create `images` directory and add images into it to be used by queries directly
  - Add icon under `images` by the name `icon.png`
  - Add cover image under `images` by the name `cover.svg` You may download your SVG from [undraw.co](https://undraw.co/) as per theme color

## Shadowing
Please read the guide [Shadowing in Gatsby Themes](https://www.gatsbyjs.org/docs/themes/shadowing/) to understand how to customize the theme. Basically you should place your files into src/gatsby-theme-portfolio-starter/ to shadow/override files.

### Editing the theme
- Shadow `src/styles/themeColors.js` to override the primary, secondary colors

**themeColors.js**
```
import {blueGrey, cyan} from '@material-ui/core/colors/';

const primary = blueGrey
const secondary = cyan

export {primary, secondary} //<- Exporting an object
```

- Shadow `src/styles/theme.js` to override rest of the defaults

**theme.js**
```
import {primary, secondary} from './themeColors'; //<- Destructuring the imported object

const theme = {
  palette: {
    primary: primary,
    secondary: secondary
  },
  typography: {
    fontSize: 16,
    h1 : {
      fontSize: "3rem",
      fontWeight: 500,
      color: primary[500]
    },
    h5 : {
      color: secondary[900]
    }
  },
  button: {
    color: "primary",
    variant: "contained"
  }
}

export default theme
```

### Projects
Project cards are created from MDX. Its content is picked from the frontmatter as follows

```
---
dataType: project // <- This is added to filter markdown files for projects
title: Project Title
description: Project Description
date: '2019-05-28'
tags:
  - Node // Tech stack
projectLink: https://github.com/aTechGuide/
published: true
---
```


text:
---
layout: default
---

# 1997-07-17 - Family values

## Header Data

From: Martin Pool<EMAIL_ADDRESS>To<EMAIL_ADDRESS>Message Hash:<PHONE_NUMBER>4c1fefa1f8fc1271eddf310bef021945cc9f8a69fcefadcc7708d1

Message ID<EMAIL_ADDRESS>Reply To<EMAIL_ADDRESS>UTC Datetime: 1997-07-17 05:06:26 UTC

Raw Date: Thu, 17 Jul 1997 13:06:26 +0800

## Raw message

```
{% raw  %}From: Martin Pool<EMAIL_ADDRESS>Date: Thu, 17 Jul 1997 13:06:26 +0800
To<EMAIL_ADDRESS>Subject: Family values
In-Reply-To<EMAIL_ADDRESS>Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

I'd rather accept the fact that teenagers might look at porn (shock!)
than bring children up in a police state.  Anyhow, vaguely relevant to
this hypocrisy is

http://www.gmcclel.bossnt.com/kk/kk970708.html

--
Martin Pool<EMAIL_ADDRESS>Pharos Business Solutions

{% endraw %}
```

## Thread

+ Return to [July 1997](/archive/1997/07)

+ Return to "[Declan McCullagh <declan@well.com>](/authors/declan_mccullagh_declan_at_well_com_)"
+ Return to "[Marshall Clow <mclow@owl.csusm.edu>](/authors/marshall_clow_mclow_at_owl_csusm_edu_)"
+ Return to "[Martin Pool <m.pool@pharos.com.au>](/authors/martin_pool_m_pool_at_pharos_com_au_)"
+ Return to "[Michael C Taylor <mctaylor@mta.ca>](/authors/michael_c_taylor_mctaylor_at_mta_ca_)"

+ 1997-07-16 (Wed, 16 Jul 1997 23:38:26 +0800) - [SPA statement and RSAC release](/archive/1997/07/49c8f206b6c849401d3275d98c4a227eace463fc5ff63aaf94df77313e6817b9) - _Declan McCullagh<EMAIL_ADDRESS>  + 1997-07-16 (Thu, 17 Jul 1997 03:55:37 +0800) - [Re: SPA statement and RSAC release](/archive/1997/07/8366d3cc1be1fd1fdcd383dcfe9c7c858ddc0d10f326090f8f0a5cb9aef46060) - _Marshall Clow<EMAIL_ADDRESS>  + 1997-07-16 (Thu, 17 Jul 1997 04:48:25 +0800) - [Re: SPA statement and RSAC release](/archive/1997/07/347b2971583b7f858c2c7e56dae53f6ae98a5390722710ca45d7a92ce7377284) - _Michael C Taylor<EMAIL_ADDRESS>  + 1997-07-17 (Thu, 17 Jul 1997 13:06:26 +0800) - Family values - _Martin Pool<EMAIL_ADDRESS>