diff --git a/.github/actions/glob/entrypoint.sh b/.github/actions/glob/entrypoint.sh deleted file mode 100755 index 7428213a5..000000000 --- a/.github/actions/glob/entrypoint.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -cd "$GITHUB_WORKSPACE" || exit - -echo "$2" | base64 -d > service-account -echo "$3" | base64 -d > id_ssh -echo "$4" | base64 -d > id_ssh.pub - -chmod 600 service-account -chmod 600 id_ssh -chmod 600 id_ssh.pub - -janeway release glob-all --dev --no-pill \ - --credentials service-account \ - --ssh-key id_ssh \ - --ci \ - | bash - -SHORTHASH=$(git rev-parse --short HEAD) - -janeway release prepare-ota arvo-glob-"$SHORTHASH" "$1" \ - --credentials service-account \ - --ssh-key id_ssh \ - --ci \ - | bash - -janeway release perform-ota "$1" \ - --credentials service-account \ - --ssh-key id_ssh \ - --ci \ - | bash - diff --git a/.github/actions/glob/Dockerfile b/.github/actions/ota/Dockerfile similarity index 72% rename from .github/actions/glob/Dockerfile rename to .github/actions/ota/Dockerfile index e372532ac..bee188917 100644 --- a/.github/actions/glob/Dockerfile +++ b/.github/actions/ota/Dockerfile @@ -1,4 +1,4 @@ -FROM tloncorp/janeway:v0.15.4 +FROM tloncorp/janeway:v0.17.0 COPY entrypoint.sh /entrypoint.sh EXPOSE 22/tcp ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/glob/action.yml b/.github/actions/ota/action.yml similarity index 52% rename from .github/actions/glob/action.yml rename to .github/actions/ota/action.yml index 4617e3d49..f9b0d027e 100644 --- a/.github/actions/glob/action.yml +++ b/.github/actions/ota/action.yml @@ -1,18 +1,21 @@ -name: 'glob' -description: 'Create a glob and deploy it to a moon' +name: 'ota' +description: 'perform an OTA update of arvo on a remote ship' inputs: ship: - description: "Ship to deploy to" + description: "target ship" required: true credentials: description: "base64-encoded GCP Service Account credentials" required: true ssh-sec-key: - description: "A base64-encoded SSH secret key for the container to use" + description: "base64-encoded SSH secret key for the container to use" required: true ssh-pub-key: - description: "The corresponding base64-encoded SSH public key" + description: "base64-encoded corresponding SSH public key" required: true + ref: + description: "git ref of arvo source to check out" + required: false runs: using: 'docker' @@ -22,4 +25,4 @@ runs: - ${{ inputs.credentials }} - ${{ inputs.ssh-sec-key }} - ${{ inputs.ssh-pub-key }} - + - ${{ inputs.ref }} diff --git a/.github/actions/ota/entrypoint.sh b/.github/actions/ota/entrypoint.sh new file mode 100755 index 000000000..5839a49f4 --- /dev/null +++ b/.github/actions/ota/entrypoint.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +echo "$2" | base64 -d > /service-account +echo "$3" | base64 -d > /id_ssh +echo "$4" | base64 -d > /id_ssh.pub + +chmod 600 /service-account +chmod 600 /id_ssh +chmod 600 /id_ssh.pub + +janeway \ + --ci \ + --verbose \ + --credentials /service-account \ + --ssh-key /id_ssh \ + release ota \ + arvo \ + "$1" \ + ${5:+"--ref"} ${5:+"$5"} \ + | bash diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml deleted file mode 100644 index 1d8711f7f..000000000 --- a/.github/workflows/chromatic.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Chromatic Deployment - -on: - pull_request: - paths: - - 'pkg/interface/**' - push: - paths: - - 'pkg/interface/**' - branches: - - 'release/next-userspace' - -jobs: - chromatic-deployment: - runs-on: ubuntu-latest - name: "Deploy Chromatic" - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - run: npm i && npm run bootstrap - - name: Publish to Chromatic - uses: chromaui/action@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - workingDir: pkg/interface diff --git a/.github/workflows/glob.yml b/.github/workflows/glob.yml deleted file mode 100644 index be5d77115..000000000 --- a/.github/workflows/glob.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: glob -on: - push: - branches: - - 'release/next-userspace' -jobs: - glob: - runs-on: ubuntu-latest - name: "Create and deploy a glob to ~hanruc-nalfus-nidsut-tomdun" - steps: - - uses: actions/checkout@v2 - with: - lfs: true - - uses: ./.github/actions/glob - with: - ship: 'hanruc-nalfus-nidsut-tomdun' - credentials: ${{ secrets.JANEWAY_SERVICE_KEY }} - ssh-sec-key: ${{ secrets.JANEWAY_SSH_SEC_KEY }} - ssh-pub-key: ${{ secrets.JANEWAY_SSH_PUB_KEY }} - diff --git a/.github/workflows/merge-master.yml b/.github/workflows/merge-master.yml deleted file mode 100644 index 48d0abf9f..000000000 --- a/.github/workflows/merge-master.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: merge -on: - push: - branches: - - 'master' -jobs: - merge-to-next-js: - runs-on: ubuntu-latest - name: "Merge master to release/next-userspace" - steps: - - uses: actions/checkout@v2 - - uses: devmasx/merge-branch@v1.3.1 - with: - type: now - target_branch: release/next-userspace - github_token: ${{ secrets.JANEWAY_BOT_TOKEN }} - - merge-to-group-timer: - runs-on: ubuntu-latest - name: "Merge master to ops/group-timer" - steps: - - uses: actions/checkout@v2 - - uses: devmasx/merge-branch@v1.3.1 - with: - type: now - target_branch: ops/group-timer - github_token: ${{ secrets.JANEWAY_BOT_TOKEN }} diff --git a/.github/workflows/merge-release.yml b/.github/workflows/merge-release.yml deleted file mode 100644 index eb7df325a..000000000 --- a/.github/workflows/merge-release.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: ops-merge -on: - push: - branches: - - 'release/*' -jobs: - merge-release-to-ops: - runs-on: ubuntu-latest - name: "Merge to ops-tlon" - steps: - - uses: actions/checkout@v2 - - uses: devmasx/merge-branch@v1.3.1 - with: - type: now - target_branch: ops-tlon - github_token: ${{ secrets.JANEWAY_BOT_TOKEN }} - diff --git a/.github/workflows/ota.yml b/.github/workflows/ota.yml new file mode 100644 index 000000000..d4742e478 --- /dev/null +++ b/.github/workflows/ota.yml @@ -0,0 +1,19 @@ +name: ota +on: + workflow_dispatch: + push: + branches: + - 'next/arvo' +jobs: + deploy: + runs-on: ubuntu-latest + name: "make an OTA update to arvo on ~binnec-dozzod-marzod" + steps: + - uses: actions/checkout@v3 + - uses: ./.github/actions/ota + with: + ship: 'canary' + credentials: ${{ secrets.JANEWAY_SERVICE_KEY }} + ssh-sec-key: ${{ secrets.JANEWAY_SSH_SEC_KEY }} + ssh-pub-key: ${{ secrets.JANEWAY_SSH_PUB_KEY }} + ref: 'next/arvo' diff --git a/bin/brass.pill b/bin/brass.pill index ad7da6640..a6baa096b 100644 --- a/bin/brass.pill +++ b/bin/brass.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4247c64a7d9fc0c0f1d2f017c21dd3464ddfe56529c7d6eef0e64554bd453e8 -size 7611162 +oid sha256:bd487cdb8294fdef6878f623bceb893553b36b2a616d22d30017b430361586fb +size 3889185 diff --git a/bin/ivory.pill b/bin/ivory.pill index c782fb725..3a6b06922 100644 --- a/bin/ivory.pill +++ b/bin/ivory.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5123a1ac30b83ec026587574df1ce13a73e72d06588ff68b5c41c09e1bebb5b7 -size 949962 +oid sha256:26ff86808886beb831e4a135f478e42ce83ef4a09ad24808b3fe97248ce7a6b7 +size 1136643 diff --git a/bin/solid.pill b/bin/solid.pill index c8d27030b..b07edcafd 100644 --- a/bin/solid.pill +++ b/bin/solid.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40bc203b8a2d2ebad81723da6fc946ee32d2f8a204884f50f9710177ae257d08 -size 5712264 +oid sha256:dfceb32839ee1444325c070397724d42773b352ae006da148e5bb98d408c4be5 +size 5924071 diff --git a/doc/spec/nock/10.txt b/doc/spec/nock/10.txt new file mode 100644 index 000000000..27d1e8c73 --- /dev/null +++ b/doc/spec/nock/10.txt @@ -0,0 +1,70 @@ +Author: Mencius Moldbug [moldbug@gmail.com] +Date: 9/15/2008 +Version: 10K + +1. Introduction + + This file defines one function, "nock." + + nock is in the public domain. + +2. Data + + A "noun" is either an "atom" or a "cell." An "atom" is an unsigned + integer of any size. A "cell" is an ordered pair of any two nouns, + the "head" and "tail." + +3. Semantics + + nock maps one noun to another. It doesn't always terminate. + +4. Pseudocode + + nock is defined in a pattern-matching pseudocode, below. + + Brackets enclose cells. [a b c] is [a [b c]]. + +5. Definition + +5.1 Transformations + + *[a [b c] d] => [*[a b c] *[a d]] + *[a 0 b] => /[b a] + *[a 1 b] => [b] + *[a 2 b c d] => *[a 3 [0 1] 3 [1 c d] [1 0] 3 [1 2 3] [1 0] 5 5 b] + *[a 3 b] => **[a b] + *[a 4 b] => &*[a b] + *[a 5 b] => ^*[a b] + *[a 6 b] => =*[a b] + *[a] => *[a] + +5.2 Operators + +5.2.1 Goto [*] + + *[a] -> nock[a] + +5.2.2 Deep [&] + + &[a b] -> 0 + &[a] -> 1 + +5.2.4 Bump [^] + + ^[a b] -> ^[a b] + ^[a] -> (a + 1) + +5.2.5 Like [=] + + =[a a] -> 0 + =[a b] -> 1 + =[a] -> =[a] + +5.2.6 Snip [/] + + /[1 a] -> a + /[2 a b] -> a + /[3 a b] -> b + /[(a + a) b] -> /[2 /[a b]] + /[(a + a + 1) b] -> /[3 /[a b]] + /[a] -> /[a] diff --git a/doc/spec/nock/11.txt b/doc/spec/nock/11.txt new file mode 100644 index 000000000..da9dafb91 --- /dev/null +++ b/doc/spec/nock/11.txt @@ -0,0 +1,74 @@ +Author: Mencius Moldbug (moldbug@gmail.com) +Date: 5/25/2008 +Version: 11K + +1. Introduction + + This file defines one function, "nock." + + nock is in the public domain. + +2. Data + + A "noun" is either an "atom" or a "cell." An "atom" is an unsigned + integer of any size. A "cell" is an ordered pair of any two nouns, + the "head" and "tail." + +3. Semantics + + nock maps one noun to another. It doesn't always terminate. + +4. Pseudocode + + nock is defined in a pattern-matching pseudocode, below. + + Parentheses enclose cells. (a b c) is (a (b c)). + +5. Definition + +5.1 Transformations + + *(a (b c) d) => (*(a b c) *(a d)) + *(a 0 b) => /(b a) + *(a 1 b) => (b) + *(a 2 b c d) => *(a 3 (0 1) 3 (1 c d) (1 0) 3 (1 2 3) (1 0) 5 5 b) + *(a 3 b) => **(a b) + *(a 4 b) => &*(a b) + *(a 5 b) => ^*(a b) + *(a 6 b) => =*(a b) + + *(a 7 b c) => *(a 3 (((1 0) b) c) 1 0 3) + *(a 8 b c) => *(a c) + + *(a) => *(a) + +5.2 Operators + +5.2.1 Goto (*) + + *(a) -> nock(a) + +5.2.2 Deep (&) + + &(a b) -> 0 + &(a) -> 1 + +5.2.4 Bump (^) + + ^(a b) -> ^(a b) + ^(a) -> a + 1 + +5.2.5 Same (=) + + =(a a) -> 0 + =(a b) -> 1 + =(a) -> =(a) + +5.2.6 Snip (/) + + /(1 a) -> a + /(2 a b) -> a + /(3 a b) -> b + /((a + a) b) -> /(2 /(a b)) + /((a + a + 1) b) -> /(3 /(a b)) + /(a) -> /(a) diff --git a/doc/spec/nock/12.txt b/doc/spec/nock/12.txt new file mode 100644 index 000000000..d3762e855 --- /dev/null +++ b/doc/spec/nock/12.txt @@ -0,0 +1,75 @@ +Author: Curtis Yarvin (curtis.yarvin@gmail.com) +Date: 3/28/2008 +Version: 0.12 + +1. Introduction + + This file defines one function, "nock." + + nock is in the public domain. + +2. Data + + A "noun" is either an "atom" or a "cell." An "atom" is an unsigned + integer of any size. A "cell" is an ordered pair of any two nouns, + the "head" and "tail." + +3. Semantics + + nock maps one noun to another. It doesn't always terminate. + +4. Pseudocode + + nock is defined in a pattern-matching pseudocode, below. + + Parentheses enclose cells. (a b c) is (a (b c)). + +5. Definition + +5.1 Transformations + + *(a (b c) d) => (*(a b c) *(a d)) + *(a 0 b) => /(b a) + *(a 1 b) => (b) + *(a 2 b c) => *(*(a b) c) + *(a 3 b) => **(a b) + *(a 4 b) => &*(a b) + *(a 5 b) => ^*(a b) + *(a 6 b) => =*(a b) + + *(a 7 b c d) => *(a 3 (0 1) 3 (1 c d) (1 0) 3 (1 2 3) (1 0) 5 5 b) + *(a 8 b c) => *(a 2 (((1 0) b) c) 0 3) + *(a 9 b c) => *(a c) + + *(a) => *(a) + +5.2 Operators + +5.2.1 Goto (*) + + *(a) -> nock(a) + +5.2.2 Deep (&) + + &(a b) -> 0 + &(a) -> 1 + +5.2.4 Bump (^) + + ^(a b) -> ^(a b) + ^(a) -> a + 1 + +5.2.5 Same (=) + + =(a a) -> 0 + =(a b) -> 1 + =(a) -> =(a) + +5.2.6 Snip (/) + + /(1 a) -> a + /(2 a b) -> a + /(3 a b) -> b + /((a + a) b) -> /(2 /(a b)) + /((a + a + 1) b) -> /(3 /(a b)) + /(a) -> /(a) diff --git a/doc/spec/nock/13.txt b/doc/spec/nock/13.txt new file mode 100644 index 000000000..2295e5ead --- /dev/null +++ b/doc/spec/nock/13.txt @@ -0,0 +1,71 @@ +Author: Curtis Yarvin (curtis.yarvin@gmail.com) +Date: 3/8/2008 +Version: 0.13 + +1. Manifest + + This file defines one Turing-complete function, "nock." + + nock is in the public domain. So far as I know, it is + neither patentable nor patented. Use it at your own risk. + +2. Data + + Both the domain and range of nock are "nouns." + + A "noun" is either an "atom" or a "cell." An "atom" is an unsigned + integer of any size. A "cell" is an ordered pair of any two nouns, + the "head" and "tail." + +3. Pseudocode + + nock is defined in a pattern-matching pseudocode. + + Match precedence is top-down. Operators are prefix. Parens + denote cells, and group right: (a b c) is (a (b c)). + +4. Definition + +4.1 Transformations + + *(a 0 b c) => *(*(a b) c) + *(a 0 b) => /(b a) + *(a 1 b) => (b) + *(a 2 b) => **(a b) + *(a 3 b) => &*(a b) + *(a 4 b) => ^*(a b) + *(a 5 b) => =*(a b) + *(a 6 b c d) => *(a 2 (0 1) 2 (1 c d) (1 0) 2 (1 2 3) (1 0) 4 4 b) + *(a b c) => (*(a b) *(a c)) + *(a) => *(a) + +4.2 Operators + +4.2.1 Goto (*) + + *(a) -> nock(a) + +4.2.2 Deep (&) + + &(a b) -> 0 + &(a) -> 1 + +4.2.3 Bump (^) + + ^(a b) -> ^(a b) + ^(a) -> a + 1 + +4.2.4 Same (=) + + =(a a) -> 0 + =(a b) -> 1 + =(a) -> =(a) + +4.2.5 Snip (/) + + /(1 a) -> a + /(2 a b) -> a + /(3 a b) -> b + /((a + a) b) -> /(2 /(a b)) + /((a + a + 1) b) -> /(3 /(a b)) + /(a) -> /(a) diff --git a/doc/spec/nock/6.txt b/doc/spec/nock/6.txt new file mode 100644 index 000000000..1dbd59958 --- /dev/null +++ b/doc/spec/nock/6.txt @@ -0,0 +1,42 @@ +1 Structures + + A noun is an atom or a cell. An atom is any natural number. + A cell is an ordered pair of nouns. + +2 Reductions + + nock(a) *a + [a b c] [a [b c]] + + ?[a b] 0 + ?a 1 + +a 1 + a + =[a a] 0 + =[a b] 1 + + /[1 a] a + /[2 a b] a + /[3 a b] b + /[(a + a) b] /[2 /[a b]] + /[(a + a + 1) b] /[3 /[a b]] + + *[a [b c] d] [*[a b c] *[a d]] + + *[a 0 b] /[b a] + *[a 1 b] b + *[a 2 b c] *[*[a b] *[a c]] + *[a 3 b] ?*[a b] + *[a 4 b] +*[a b] + *[a 5 b] =*[a b] + + *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b] + *[a 7 b c] *[a 2 b 1 c] + *[a 8 b c] *[a 7 [[0 1] b] c] + *[a 9 b c] *[a 7 c 0 b] + *[a 10 b c] *[a c] + *[a 10 [b c] d] *[a 8 c 7 [0 2] d] + + +[a b] +[a b] + =a =a + /a /a + *a *a diff --git a/doc/spec/nock/7.txt b/doc/spec/nock/7.txt new file mode 100644 index 000000000..bd3e29508 --- /dev/null +++ b/doc/spec/nock/7.txt @@ -0,0 +1,42 @@ +1 Structures + + A noun is an atom or a cell. An atom is any natural number. + A cell is any ordered pair of nouns. + +2 Pseudocode + + [a b c] [a [b c]] + nock(a) *a + + ?[a b] 0 + ?a 1 + ^a 1 + a + =[a a] 0 + =[a b] 1 + + /[1 a] a + /[2 a b] a + /[3 a b] b + /[(a + a) b] /[2 /[a b]] + /[(a + a + 1) b] /[3 /[a b]] + + *[a [b c] d] [*[a b c] *[a d]] + + *[a 0 b] /[b a] + *[a 1 b] b + *[a 2 b c] *[*[a b] *[a c]] + *[a 3 b] ?*[a b] + *[a 4 b] ^*[a b] + *[a 5 b] =*[a b] + + *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b] + *[a 7 b c] *[a 2 b 1 c] + *[a 8 b c] *[a 7 [[7 [0 1] b] 0 1] c] + *[a 9 b c] *[a 7 c 0 b] + *[a 10 b c] *[a c] + *[a 10 [b c] d] *[a 8 c 7 [0 3] d] + + ^[a b] ^[a b] + =a =a + /a /a + *a *a diff --git a/doc/spec/nock/8.txt b/doc/spec/nock/8.txt new file mode 100644 index 000000000..2981d6c5f --- /dev/null +++ b/doc/spec/nock/8.txt @@ -0,0 +1,45 @@ +1 Structures + + A noun is an atom or a cell. An atom is any unsigned integer. + A cell is an ordered pair of nouns. + +2 Pseudocode + + [a b c] is [a [b c]]; *a is nock(a). Reductions match top-down. + +3 Reductions + + ?[a b] 0 + ?a 1 + ^a (a + 1) + =[a a] 0 + =[a b] 1 + + /[1 a] a + /[2 a b] a + /[3 a b] b + /[(a + a) b] /[2 /[a b]] + /[(a + a + 1) b] /[3 /[a b]] + + *[a [b c] d] [*[a b c] *[a d]] + *[a 0 b] /[b a] + *[a 1 b] b + *[a 2 b c] *[*[a b] *[a c]] + *[a 3 b] ?*[a b] + *[a 4 b] ^*[a b] + *[a 5 b] =*[a b] + + *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b] + *[a 7 b c] *[a 2 b 1 c] + *[a 8 b c] *[a 7 [7 b [0 1]] c] + *[a 9 b c] *[a 8 b 2 [[7 [0 3] d] [0 5]] 0 5] + *[a 10 b c] *[a 8 b 8 [7 [0 3] c] 0 2] + *[a 11 b c] *[a 8 b 7 [0 3] c] + *[a 12 b c] *[a [1 0] 1 c] + + ^[a b] ^[a b] + =a =a + /a /a + *a *a + + diff --git a/doc/spec/nock/9.txt b/doc/spec/nock/9.txt new file mode 100644 index 000000000..b6aabad76 --- /dev/null +++ b/doc/spec/nock/9.txt @@ -0,0 +1,43 @@ +1 Context + + This spec defines one function, Nock. + +2 Structures + + A noun is an atom or a cell. An atom is any unsigned integer. + A cell is an ordered pair of any two nouns. + +3 Pseudocode + + Brackets enclose cells. [a b c] is [a [b c]]. + + *a is Nock(a). Reductions match top-down. + +4 Reductions + + ?[a b] => 0 + ?a => 1 + + ^[a b] => ^[a b] + ^a => (a + 1) + + =[a a] => 0 + =[a b] => 1 + =a => =a + + /[1 a] => a + /[2 a b] => a + /[3 a b] => b + /[(a + a) b] => /[2 /[a b]] + /[(a + a + 1) b] => /[3 /[a b]] + /a => /a + + *[a 0 b] => /[b a] + *[a 1 b] => b + *[a 2 b c d] => *[a 3 [0 1] 3 [1 c d] [1 0] 3 [1 2 3] [1 0] 5 5 b] + *[a 3 b] => **[a b] + *[a 4 b] => ?*[a b] + *[a 5 b] => ^*[a b] + *[a 6 b] => =*[a b] + *[a [b c] d] => [*[a b c] *[a d]] + *a => *a diff --git a/pkg/arvo/app/dbug.hoon b/pkg/arvo/app/dbug.hoon index fbec14e29..90c17c22d 100644 --- a/pkg/arvo/app/dbug.hoon +++ b/pkg/arvo/app/dbug.hoon @@ -716,7 +716,7 @@ 'rtt'^(numb (div rtt ~s1)) 'rttvar'^(numb (div rttvar ~s1)) 'ssthresh'^(numb ssthresh) - 'num-live'^(numb num-live) + 'num-live'^(numb ~(wyt by live)) 'cwnd'^(numb cwnd) 'counter'^(numb counter) == diff --git a/pkg/arvo/app/debug/css/index.css b/pkg/arvo/app/debug/css/index.css index 2be3ef081..1121ba3f8 100644 Binary files a/pkg/arvo/app/debug/css/index.css and b/pkg/arvo/app/debug/css/index.css differ diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index b24c681da..dd2600d80 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -3,16 +3,16 @@ :: :: :: /? 309 :: arvo kelvin /- *sole, lens :: console structures -/+ sole, pprint, :: +/+ sole, pprint, dprint, :: auto=language-server-complete, :: easy-print=language-server-easy-print :: :: :: :: :::: :: :::: :: :: :: => |% :: external structures - +$ id @tasession :: session id + +$ id sole-id :: session id +$ house :: all state - $: %8 + $: %9 egg=@u :: command count hoc=(map id session) :: conversations acl=(set ship) :: remote access whitelist @@ -54,6 +54,7 @@ r=@t == [%poke p=goal] :: poke app + [%help p=(list term)] :: doccords [%show p=?(%0 %1 %2 %3 %4 %5)] :: val/type/hoon/xray [%verb p=term] :: store variable == :: @@ -180,6 +181,18 @@ ;~(pfix cen gap (parse-variable sym ;~(pfix gap parse-mark))) == == + :: + ;~ pfix hax + ;~ pose + ;~ pfix ace + %+ cook + |= a=(list term) + [[%help (flop a)] 0 %ex [%cnts p=~[[%.y p=1]] q=~]] + (most fas sym) + == + (easy [[%help ~[%$]] 0 %ex [%cnts p=~[[%.y p=1]] q=~]]) + == + == :: ;~((glue ace) parse-sink parse-source) (stag [%show %0] parse-source) @@ -621,6 +634,9 @@ ++ maar ?: =(%noun p.cay) ~ [[%rose [~ " " ~] >p.cay< ~] ~] -- + :: + %help + (dy-inspect p.p.mad p.q.cay) == :: ++ dy-show |=(cay=cage (dy-print cay ~)) @@ -660,6 +676,20 @@ :- i="" t=(turn `wain`?~(r.hit ~ (to-wain:format q.u.r.hit)) trip) == + :: + ++ dy-inspect + |= [topics=(list term) sut=type] + %+ dy-rash %mor + =+ to-display=(mule |.((find-item-in-type:dprint (flop topics) sut))) + ?: ?=(%| -.to-display) + [%tan [%leaf "Could not find help A"] p.to-display]~ + ?~ p.to-display + [%tan [%leaf "Could not find help B"]~]~ + =/ item (mule |.((print-item:dprint u.p.to-display))) + ?: ?=(%| -.item) + [%tan [%leaf "Could not find help C"] p.item]~ + p.item + :: ++ dy-show-type-noun |= a=type ^- tank =- >[-]< @@ -676,11 +706,16 @@ [%face ^] a(q $(a q.a)) [%cell ^] a(p $(a p.a), q $(a q.a)) [%fork *] a(p (silt (turn ~(tap in p.a) |=(b=type ^$(a b))))) - [%hint *] ?. ?=(%know -.q.p.a) $(a q.a) - ?@ p.q.p.a [(cat 3 '#' mark.p.q.p.a)]~ - [(rap 3 '#' auth.p.q.p.a (spat type.p.q.p.a) ~)]~ + [%hint *] ?+ q.p.a $(a q.a) + [%know *] + ?@ p.q.p.a [(cat 3 '#' mark.p.q.p.a)]~ + [(rap 3 '#' auth.p.q.p.a (spat type.p.q.p.a) ~)]~ + :: + [%help *] + [summary.crib.p.q.p.a]~ + == [%core ^] `wain`/core - [%hold *] a(p $(a p.a)) + [%hold *] $(a (~(play ut p.a) q.a)) == :: :: XX needs filter @@ -820,12 +855,23 @@ =/ poz=vase (dy-sore p.cig) =/ kev=vase =/ kuv=(unit vase) (slew 7 som) - ?: =(~ q.cig) - (fall kuv !>(~)) =/ soz=(list [var=term vax=vase]) %~ tap by %- ~(run by q.cig) |=(val=(unit dojo-source) ?~(val !>([~ ~]) (dy-vase p.u.val))) + :: if the generator takes a named argument "drum-session", + :: then if a value isn't already supplied, we set it to the session + :: that this dojo instance is being run in. + :: (dojo is, indeed, quite coupled with drum.) + :: + =? soz + ?& ?=(^ kuv) + (slab %both %drum-session p.u.kuv) + !(~(has by q.cig) %drum-session) + == + [[%drum-session !>(ses.id)] soz] ::TODO does the who matter? + ?: =(~ soz) + (fall kuv !>(~)) ~| keyword-arg-failure+~(key by q.cig) %+ slap (with-faces kuv+(need kuv) rep+(with-faces soz) ~) @@ -1018,13 +1064,14 @@ |= =card:agent:gall ^+ +> =? card ?=(%pass -.card) - card(p [id p.card]) + ^- card:agent:gall + card(p [(scot %p who.id) ses.id p.card]) %_(+> moz [card moz]) :: ++ he-diff :: emit update |= fec=sole-effect ^+ +> - (he-card %give %fact ~[/sole/[id]] %sole-effect !>(fec)) + (he-card %give %fact ~[(id-to-path:sole id)] %sole-effect !>(fec)) :: ++ he-stop :: abort work ^+ . @@ -1532,21 +1579,47 @@ :: ++ on-load |= ole=vase + ^- (quip card:agent:gall _..on-init) |^ =+ old=!<(house-any ole) =? old ?=(%5 -.old) + ^- house-any + ^- house-6 (house-5-to-6 old) =? old ?=(?(%6 %7) -.old) (house-6-7-to-8 +.old) - ?> ?=(%8 -.old) - `..on-init(state old) + =^ caz old + ?. ?=(%8 -.old) [~ old] + (house-8-to-9 old) + ?> ?=(%9 -.old) + [caz ..on-init(state old)] :: - +$ house-any $%(house house-7 house-6 house-5) + +$ house-any $%(house house-8 house-7 house-6 house-5) + :: + +$ id-8 @tasession + +$ house-8 + $: %8 + egg=@u + hoc=(map id-8 session) + acl=(set ship) + == + ++ house-8-to-9 + |= old=house-8 + ^- (quip card:agent:gall house) + :- %+ turn ~(tap in ~(key by hoc.old)) + |= id=@ta + ^- card:agent:gall + [%give %kick ~[/sole/[id]] ~] + =- [%9 egg.old - acl.old] + %- ~(gas by *(map sole-id session)) + %+ murn ~(tap by hoc.old) + |= [id=@ta s=session] + (bind (upgrade-id:sole id) (late s)) :: +$ house-7 [%7 house-6-7] +$ house-6 [%6 house-6-7] +$ house-6-7 $: egg=@u :: command count - hoc=(map id session-6) :: conversations + hoc=(map id-8 session-6) :: conversations acl=(set ship) :: remote access whitelist == :: +$ session-6 :: per conversation @@ -1573,9 +1646,10 @@ old(poy ~, -.dir [our.hid %base ud+0]) :: +$ house-5 - [%5 egg=@u hoc=(map id session)] + [%5 egg=@u hoc=(map id-8 session-6)] ++ house-5-to-6 |= old=house-5 + ^- house-6 [%6 egg.old hoc.old *(set ship)] -- :: @@ -1591,7 +1665,8 @@ he-abet:(~(he-type he hid id.act ~ (~(got by hoc) id.act)) act) :: %lens-command - =+ !<([=id =command:lens] vase) + =+ !<([ses=@ta =command:lens] vase) + =/ =id [our.hid ses] he-abet:(~(he-lens he hid id ~ (~(got by hoc) id)) command) :: %allow-remote-login @@ -1629,8 +1704,7 @@ ?> ?| (team:title our.hid src.hid) (~(has in acl) src.hid) == - ?> ?=([%sole @ ~] path) - =/ id i.t.path + =/ =id (need (path-to-id:sole path)) =? hoc (~(has by hoc) id) ~& [%dojo-peer-replaced id] (~(del by hoc) id) @@ -1642,7 +1716,7 @@ ++ on-leave |= =path ?> ?=([%sole *] path) - =. hoc (~(del by hoc) t.path) + =. hoc (~(del by hoc) (need (path-to-id:sole path))) [~ ..on-init] :: ++ on-peek @@ -1651,13 +1725,15 @@ :: ++ on-agent |= [=wire =sign:agent:gall] - ?> ?=([@ @ *] wire) - =/ =session (~(got by hoc) i.wire) - =/ he-full ~(. he hid i.wire ~ session) + ^- (quip card:agent:gall _..on-init) + ?> ?=([@ @ @ *] wire) + =/ =id [(slav %p i.wire) i.t.wire] + =/ =session (~(got by hoc) id) + =/ he-full ~(. he hid id ~ session) =^ moves state =< he-abet ^+ he - ?+ i.t.wire ~|([%dojo-bad-on-agent wire -.sign] !!) + ?+ i.t.t.wire ~|([%dojo-bad-on-agent wire -.sign] !!) %poke (he-unto:he-full t.wire sign) %wool (he-wool:he-full t.wire sign) == @@ -1665,14 +1741,16 @@ :: ++ on-arvo |= [=wire =sign-arvo] - ?> ?=([@ *] wire) - =/ =session (~(got by hoc) i.wire) - =/ he-full ~(. he hid i.wire ~ session) + ^- (quip card:agent:gall _..on-init) + ?> ?=([@ @ *] wire) + =/ =id [(slav %p i.wire) i.t.wire] + =/ =session (~(got by hoc) id) + =/ he-full ~(. he hid id ~ session) =^ moves state =< he-abet ?+ +<.sign-arvo ~|([%dojo-bad-take +<.sign-arvo] !!) - %writ (he-writ:he-full t.wire +>.sign-arvo) - %http-response (he-http-response:he-full t.wire +>.sign-arvo) + %writ (he-writ:he-full t.t.wire +>.sign-arvo) + %http-response (he-http-response:he-full t.t.wire +>.sign-arvo) == [moves ..on-init] :: if dojo fails unexpectedly, kill whatever each session is working on diff --git a/pkg/arvo/app/herm.hoon b/pkg/arvo/app/herm.hoon index d19c92778..aefe6c8df 100644 --- a/pkg/arvo/app/herm.hoon +++ b/pkg/arvo/app/herm.hoon @@ -1,8 +1,13 @@ :: herm: stand-in for term.c with http interface :: +/- herm /+ default-agent, dbug, verb +:: keep relevant mark conversions in cache for performance +:: /$ blit-to-json %blit %json /$ json-to-blit %json %blit +/$ json-to-task %json %herm-task +:: =, jael |% +$ state-0 [%0 ~] @@ -13,15 +18,18 @@ %+ verb | %- agent:dbug ^- agent:gall +=> |% + ++ pass-session + |= [ses=@tas tas=session-task:dill] + [%pass /dill/[ses] %arvo %d %shot ses tas] + -- |_ =bowl:gall +* this . def ~(. (default-agent this %|) bowl) :: ++ on-init ^- (quip card:agent:gall _this) - :: set up dill session subscription - :: - [[%pass [%view %$ ~] %arvo %d %view ~]~ this] + [~ this] :: ++ on-save !>([%0 ~]) ++ on-load @@ -32,47 +40,68 @@ ++ on-watch |= =path ^- (quip card:agent:gall _this) - ?> =(our src):bowl - ?> ?=([%session @ %view ~] path) :_ this - :: scry prompt and cursor position out of dill for initial response + ~| path + ?> ?=([%session @ %view ~] path) + =* ses i.t.path + :: subscribe to the requested session :: - =/ base=^path - /dx/(scot %p our.bowl)//(scot %da now.bowl)/sessions - :~ [%give %fact ~ %blit !>(.^(blit:dill (weld base //line)))] - [%give %fact ~ %blit !>(`blit:dill`hop+.^(@ud (weld base //cursor)))] - == + ::NOTE multiple views do not result in multiple subscriptions + :: because they go over the same wire/duct + :: + [(pass-session ses %view ~)]~ :: ++ on-arvo |= [=wire =sign-arvo] ^- (quip card:agent:gall _this) + ~| wire ?+ wire (on-arvo:def wire sign-arvo) [%tube *] [~ this] :: we no longer care about these :: :: pass on dill blits for the session :: - [%view %$ ~] + [%dill @ ~] + =* ses i.t.wire ?. ?=([%dill %blit *] sign-arvo) ~| [%unexpected-sign [- +<]:sign-arvo] !! :_ this %+ turn p.sign-arvo |= =blit:dill - [%give %fact [%session %$ %view ~]~ %blit !>(blit)] + [%give %fact [%session ses %view ~]~ %blit !>(blit)] + :: + :: clean up old-style subscriptions + :: + [%view @ ~] + =* ses i.t.wire + :_ this + [%pass wire %arvo %d %shot ses %flee ~]~ == :: ++ on-poke |= [=mark =vase] ^- (quip card:agent:gall _this) - ?> =(our src):bowl - ?. ?=(%belt mark) - ~| [%unexpected-mark mark] - !! :_ this - [%pass [%belt %$ ~] %arvo %d %belt !<(belt:dill vase)]~ + :_ ~ + ?+ mark ~|([%unexpected-mark mark] !!) + %belt (pass-session %$ %belt !<(belt:dill vase)) + %herm-task (pass-session !<(task:herm vase)) + == +:: +++ on-peek + |= =path + ^- (unit (unit cage)) + ?+ path ~ + [%x %sessions ~] + :+ ~ ~ + :- %json + !> ^- json + =- a+(turn ~(tap in -) (lead %s)) + .^((set @tas) %dy /(scot %p our.bowl)//(scot %da now.bowl)/sessions) + == :: ++ on-leave on-leave:def -++ on-peek on-peek:def +:: ++ on-agent on-agent:def ++ on-fail on-fail:def -- diff --git a/pkg/arvo/app/hood.hoon b/pkg/arvo/app/hood.hoon index 4866ce439..41a1eb5d8 100644 --- a/pkg/arvo/app/hood.hoon +++ b/pkg/arvo/app/hood.hoon @@ -2,8 +2,8 @@ /+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln |% +$ state - $~ [%24 *state:drum *state:helm *state:kiln] - $>(%24 any-state) + $~ [%25 *state:drum *state:helm *state:kiln] + $>(%25 any-state) :: +$ any-state $% [ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)] @@ -25,6 +25,7 @@ [%22 drum=state-4:drum helm=state-1:helm kiln=state-9:kiln] [%23 drum=state-4:drum helm=state-2:helm kiln=state-9:kiln] [%24 drum=state-4:drum helm=state-2:helm kiln=state-10:kiln] + [%25 drum=state-5:drum helm=state-2:helm kiln=state-10:kiln] == +$ any-state-tuple $: drum=any-state:drum @@ -92,8 +93,7 @@ :: ?+ mark (on-poke:def mark vase) %atom poke-helm(mark %helm-atom) - %dill-belt poke-drum(mark %drum-dill-belt) - %dill-blit poke-drum(mark %drum-dill-blit) + %dill-poke poke-drum %hood-sync poke-kiln(mark %kiln-sync) %write-sec-atom poke-helm(mark %helm-write-sec-atom) == @@ -108,6 +108,7 @@ ?+ path (on-watch:def +<) [%drum *] =^(c drum.state (peer:drum-core t.path) [c this]) [%kiln *] =^(c kiln.state (peer:kiln-core t.path) [c this]) + [%dill *] =^(c drum.state (peer:drum-core +<) [c this]) == :: ++ on-agent diff --git a/pkg/arvo/app/lens.hoon b/pkg/arvo/app/lens.hoon index 74734f42e..3969a65d4 100644 --- a/pkg/arvo/app/lens.hoon +++ b/pkg/arvo/app/lens.hoon @@ -83,7 +83,8 @@ :: ?+ -.source.com :_ this(job.state (some [eyre-id com])) - [%pass /sole %agent [our.bowl %dojo] %watch /sole/[eyre-id]]~ + =/ =path /sole/(scot %p our.bowl)/[eyre-id] + [%pass /sole %agent [our.bowl %dojo] %watch path]~ :: %export :_ this(job.state (some [eyre-id com])) diff --git a/pkg/arvo/app/shoe.hoon b/pkg/arvo/app/shoe.hoon index 4b0538ad3..0e827f57c 100644 --- a/pkg/arvo/app/shoe.hoon +++ b/pkg/arvo/app/shoe.hoon @@ -43,13 +43,13 @@ ++ on-fail on-fail:def :: ++ command-parser - |= sole-id=@ta + |= =sole-id:shoe ^+ |~(nail *(like [? command])) %+ stag & (perk %demo %row %table ~) :: ++ tab-list - |= sole-id=@ta + |= =sole-id:shoe ^- (list [@t tank]) :~ ['demo' leaf+"run example command"] ['row' leaf+"print a row"] @@ -57,7 +57,7 @@ == :: ++ on-command - |= [sole-id=@ta =command] + |= [=sole-id:shoe =command] ^- (quip card _this) =; [to=(list _sole-id) fec=shoe-effect:shoe] [[%shoe to fec]~ this] @@ -87,7 +87,7 @@ == :: ++ can-connect - |= sole-id=@ta + |= =sole-id:shoe ^- ? ?| =(~zod src.bowl) (team:title [our src]:bowl) diff --git a/pkg/arvo/gen/aqua/dojo.hoon b/pkg/arvo/gen/aqua/dojo.hoon index 03d63f505..d9ef58a1d 100644 --- a/pkg/arvo/gen/aqua/dojo.hoon +++ b/pkg/arvo/gen/aqua/dojo.hoon @@ -5,8 +5,8 @@ :- %aqua-events %+ turn ^- (list unix-event) - :~ [/d/term/1 %belt %ctl `@c`%e] - [/d/term/1 %belt %ctl `@c`%u] + :~ [/d/term/1 %belt %mod %ctl `@c`%e] + [/d/term/1 %belt %mod %ctl `@c`%u] [/d/term/1 %belt %txt ((list @c) command)] [/d/term/1 %belt %ret ~] == diff --git a/pkg/arvo/gen/help.hoon b/pkg/arvo/gen/help.hoon index 277b41e93..2446943e5 100644 --- a/pkg/arvo/gen/help.hoon +++ b/pkg/arvo/gen/help.hoon @@ -39,7 +39,7 @@ |= a=* ^- [cord path] [;;(@t a) (welp (slag len pax) /[nam])] -- -:: +::TODO: make this work with doccords :- %say |= [[now=time @ our=ship ^] typ=$@(~ [p=term ~]) ~] =/ pax=path /(scot %p our)/base/(scot %da now)/gen :: XX hardcoded diff --git a/pkg/arvo/gen/hood/ames-snub.hoon b/pkg/arvo/gen/hood/ames-snub.hoon new file mode 100644 index 000000000..575e29c9d --- /dev/null +++ b/pkg/arvo/gen/hood/ames-snub.hoon @@ -0,0 +1,10 @@ +:: Helm: Set Ames Blocklist +:: +/? 310 +:: +:::: + :: +:- %say +|= [^ ships=(list ship) ~] +:- %helm-ames-snub +ships diff --git a/pkg/arvo/gen/hood/install.hoon b/pkg/arvo/gen/hood/install.hoon index c243cf90a..723d02a6d 100644 --- a/pkg/arvo/gen/hood/install.hoon +++ b/pkg/arvo/gen/hood/install.hoon @@ -8,7 +8,7 @@ :: :- %say |= $: [now=@da eny=@uvJ bec=beak] - [[her=@p rem=desk ~] local=@tas] + [[her=@p rem=desk ~] local=@tas once=_|] == =/ loc=desk ?:(=(%$ local) rem local) -[%kiln-install loc her rem] +[%kiln-install loc her rem once] diff --git a/pkg/arvo/gen/hood/link.hoon b/pkg/arvo/gen/hood/link.hoon index 5fe183279..5e14126a1 100644 --- a/pkg/arvo/gen/hood/link.hoon +++ b/pkg/arvo/gen/hood/link.hoon @@ -8,9 +8,11 @@ :: :- %say |= $: [now=@da eny=@uvJ byk=beak] - [arg=$?([dap=term ~] [who=ship dap=term ~]) ~] + arg=$?([dap=term ~] [who=ship dap=term ~]) + drum-session=@ta == :- %drum-link +:- drum-session ?~ +.arg [p.byk dap.arg] [who.arg dap.arg] diff --git a/pkg/arvo/gen/hood/unlink.hoon b/pkg/arvo/gen/hood/unlink.hoon index d7bc509b0..fc6e1fb01 100644 --- a/pkg/arvo/gen/hood/unlink.hoon +++ b/pkg/arvo/gen/hood/unlink.hoon @@ -8,9 +8,11 @@ :: :- %say |= $: [now=@da eny=@uvJ byk=beak] - [arg=$?([dap=term ~] [who=ship dap=term ~]) ~] + arg=$?([dap=term ~] [who=ship dap=term ~]) + drum-session=@ta == :- %drum-unlink +:- drum-session ?~ +.arg [p.byk dap.arg] [who.arg dap.arg] diff --git a/pkg/arvo/lib/deco.hoon b/pkg/arvo/lib/deco.hoon new file mode 100644 index 000000000..0773c879a --- /dev/null +++ b/pkg/arvo/lib/deco.hoon @@ -0,0 +1,189 @@ +:: Hoon doccords sample +:: +:: this is a sample file designed to explain syntax and conventions +:: for doccords +:: +:: all lines must be under 80 characters. no blank lines. +:: any line longer than 60 characters is probably too long. +:: uppercase or non-ascii letters are strongly discouraged. +:: +:: whenever possible, use formal decorations. {::} decorates +:: the next expression when put on its own line, and the previous +:: expression if written on the same line +:: +:: there are two places to put decorations: in line with the +:: code, and on the right margin. +:: +:: the file below is a well-commented library, built around +:: a typical two-core structure. the cores are labeled {%arch} +:: (structures) and {%work} (productions). +:: +:: this code is written to display the variety of formatting +:: options the parser allows. a specific convention should pick +:: one of these styles and stick to it. +:: +:: there are three ways to mark the beginning of a formal comment: +:: 1- {:: $foo:} +:: 2- {:: +bar:} +:: 3- {:: } +:: +:: style 1 may optionally be followed by a series of paragraphs, where each +:: paragraph is preceded by a line containing only {::} and whitespace, and +:: each line of a given paragraph is preceded by four aces. +:: {::} +:: {:: more text} +:: {:: even more text} +:: {::} +:: {:: |=(code=hoon !!)} +:: +:: style 2 is much like style 1, but paragraphs are indented by two spaces +:: instead of four. +:: {::} +:: {:: more text} +:: {:: even more text} +:: {::} +:: {:: |=(code=hoon !!)} +:: +:: code is indented a total of six aces, for either style. +:: +:: style 3 is used to annotate the hoon or spec that immediately follows +:: the comment. paragraphs are written with style 2. +:: +:: the $foo and +bar above are examples of *lexical locations* for +:: style and batch-commenting purposes. this tells the parser to attempt +:: to attach the comment to the specified location. these locations +:: may be written as follows: +:: - `|foo` means a chapter +:: - `%foo` means a constant +:: - `.foo` means a face +:: - `+foo` means an arm +:: - `$foo` means a spec +:: - `^foo` means a core +:: - `_foo` means a door +:: - `=foo` means a gate +:: - `/foo` means a file path segment +:: +:: thus /lib/foo^widget|initial=open means the =open gate in the |initial +:: chapter of the ^widget core in the /foo library +:: +:: at present, doccords does not support lexical locations in full. +:: only single-element locations of the form `$foo` and `+foo` are supported, +:: and must be written above an arm in the core to which they are to be +:: attached, and after the chapter they are in (if the core has chapters). +:: you may still write doccords for other locations in anticipation of the +:: fully supported lexical location, but they will be thrown away before they +:: make it to the compiler. +:: +:: a postfix formal comment will either attach to hoon or spec on the +:: current line, or the arm name if there is no hoon or spec on the +:: line. the convention for +$ arms is that the comment attached to the +:: arm is about the mold itself, while the comment attached to the spec +:: is about the output type of the mold. +:: +:: to inspect doccords in this file from dojo, try the following: +:: +:: > =deco -build-file %/lib/deco/hoon +:: > # deco +:: > # deco/arch +:: > # deco/arch/molds +:: > # deco/arch/molds/goof +:: +:: > ?? *goof:deco +:: +=> :: + :: structures for our imaginary hello, world generator. + :: + :: nothing forces us to put structures in a separate core. + :: but compile-time evaluation doesnt work in the current + :: core; we often want to statically evaluate structures. + :: + :: there are three kinds of structures: moldss (normalizing + :: functions), mold builders (functions that build molds), and + :: constants (static data). + :: + :: most code will not need its own mold builders. but put them + :: in a separate chapter (separated by {+|}). + |% + :: molds are functions that normalize nouns. + :: + :: arms producing molds are introduced with {+$}. the + :: compiler will copy the arm decoration onto its product + +| %molds + :: $jam: some delicious jam + :: $jelly: different from jam? + +$ spot [p=@ q=@] :: a coordinate + +$ tops :: mold for coordinate + [p=@ q=@] :: another coordinate + +$ goof :: a simple tuple mold + $: foo=@ :: something mysterious + bar=@ :: go here for drink + moo=(binary-tree juice) :: cows do this + == + +$ juice :: fruity beverage mold + $% [%plum p=@] :: fresh prune + [%pear p=@ q=@] :: good for cider + [%acai p=@] :: aztec superfood + == + +$ jam @tas + +$ jelly @tas + :: mold builders are functions that build molds from other molds + :: + :: other languages might call these "type constructors" + :: or "higher-kinded types". + +| %mold-builders + ++ binary-tree :: tree mold builder + |* a=$-(* *) + $@(~ [n=a l=(binary-tree a) r=(binary-tree a)]) + :: + :: if you have constants, put them in their own chapter. + +| %constant + ++ answer :: answer to everything + 42 + -- +:: engines for our imaginary hello, world app. +:: +|% +:: +default-jam: bunts $jam +:: +default-juice: bunts $juice +++ say-hello :: say hi to someone + :: friendly welcome message + :: + |= + :: .txt: friend to say hi to + :: + txt=term + ^- tape + "hello, {(rip 3 txt)}" +:: +say-goodbye: say a really proper goodbye +:: +:: some paragraphs about the goodbye algorithm, possibly +:: including code indented by four extra spaces: +:: +:: ?: =(%hello %world) +:: %hello +:: %world +:: +++ say-goodbye + :: describe product of function + :: + |= + :: .txt: departing friend + :: .num: number of friends + $: txt=term + num=@ + == + ^- tape + :: .foo: four + :: .bar: forty-two + =/ foo (add 2 2) + =/ bar (add (mul num foo) 2) + =/ moo (mul num bar) :: for all the cows + "goodbye and {(scow %ud moo)}, {(rip 3 txt)}" +:: +++ say-minimum :: minimal decoration + |= txt=term + "nothing to say to {(rip 3 txt)}" +:: +++ default-jam *jam +++ default-juice *juice +-- diff --git a/pkg/arvo/lib/dill.hoon b/pkg/arvo/lib/dill.hoon new file mode 120000 index 000000000..f9c2362f0 --- /dev/null +++ b/pkg/arvo/lib/dill.hoon @@ -0,0 +1 @@ +../../base-dev/lib/dill.hoon \ No newline at end of file diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon new file mode 100644 index 000000000..68d36fa6e --- /dev/null +++ b/pkg/arvo/lib/dprint.hoon @@ -0,0 +1,773 @@ +/- *sole +/+ easy-print=language-server-easy-print +:: a library for printing doccords +=/ debug | +=> + :: dprint-types + |% + :: $overview: an overview of all named things in the type. + :: + :: each element in the overview list is either a documentation for a sublist + :: or an association betwen a term and documentation for it + +$ overview (list overview-item) + :: + :: $overview-item: an element of an overview + +$ overview-item + $% [%header doc=what children=overview] + [%item name=tape doc=what] + == + :: + :: $item: the part of a type being inspected + +$ item + $% + :: overview of a type + :: + [%view items=overview] + :: inspecting a full core + $: %core + name=tape :: arm that built it + docs=what :: + sut=type :: [%core *] + children=(unit item) :: compiled against + == + :: inspecting a single arm on a core + $: %arm + name=tape :: arm name + adoc=what :: arm doc + pdoc=what :: product doc + cdoc=what :: $ arm/prod doc + gen=hoon :: arm hoon AST + sut=type :: subject of arm + == + :: inspecting a face and what's behind it + $: %face + name=tape :: name of face + docs=what :: + children=(unit item) :: face referent + == + :: inspecting a single chapter on a core + $: %chapter + name=tape :: name of chapter + docs=what :: + sut=type :: [%core *] + tom=tome :: tome of chapter + == + == + :: + -- +:: dprint +:: +:: core containing doccords search and printing utilities +|% +:: contains arms used for looking for docs inside of a type +:: +:: the entrypoint for finding docs within a type is +find-item-in-type. ++| %searching +:: +find-item-in-type: returns the item to print while searching through topic +:: +:: this gate is a thin wrapper around _hunt for usability, since the only entry +:: point most users should care about is find-item:hunt +:: +++ find-item-in-type + |= [topics=(list term) sut=type] + ?~ topics !! + =/ top=(lest term) topics + ~(find-item hunt [top sut]) +:: +:: +hunt: door used for refining the type while searching for doccords +:: +++ hunt + |_ [topics=(lest term) sut=type] + +* this . + :: + +| %find + :: + ++ find-item + ~? >> debug %find-item + ^- (unit item) + ?- sut + %noun ~ + %void ~ + [%atom *] ~ + [%cell *] find-cell + [%core *] find-core + [%face *] find-face + [%fork *] find-fork + [%hint *] find-hint + [%hold *] find-item:this(sut (~(play ut p.sut) q.sut)) + == + :: + ++ find-cell + ~? >> debug %find-cell + ^- (unit item) + ?> ?=([%cell *] sut) + =/ lhs find-item:this(sut p.sut) + ?~ lhs + find-item:this(sut q.sut) + lhs + :: + ++ find-core + ~? >> debug %find-core + ^- (unit item) + ?> ?=([%core *] sut) + ?: check-arm + ?: check-search + ?: check-arm-core + return-arm-core + return-arm + recurse-arm-core + ?: check-chap + ?: check-search + return-chap + recurse-chap + recurse-core + :: + ++ find-face + ~? >> debug %find-face + ^- (unit item) + ?> ?=([%face *] sut) + ?. ?=(term p.sut) + ::TODO: handle $tune case + find-item:this(sut q.sut) + ?. =(i.topics p.sut) + ~ + ?~ t.topics + return-face + find-item:this(sut q.sut, topics t.topics) + :: + ++ find-fork + ~? >> debug %find-fork + ^- (unit item) + ?> ?=([%fork *] sut) + =/ types=(list type) ~(tap in p.sut) + |- + ?~ types ~ + =+ res=find-item:this(sut i.types) + ?~ res + $(types t.types) + res + :: + ++ find-hint + ~? >> debug %find-hint + ^- (unit item) + |^ + ?> ?=([%hint *] sut) + ?. ?=([%help *] q.p.sut) + find-item:this(sut q.sut) + ?+ q.sut ~ + [%cell *] find-cell:this(sut q.sut) + [%core *] find-hint-core + [%face *] find-hint-face + [%fork *] find-fork:this(sut q.sut) + [%hint *] find-hint:this(sut q.sut) + [%hold *] find-hint:this(q.sut (~(play ut p.q.sut) q.q.sut)) + == + :: + ++ find-hint-core + ~? >> debug %find-hint-core + ^- (unit item) + ?> &(?=([%hint *] sut) ?=([%help *] q.p.sut) ?=([%core *] q.sut)) + :: + ?. ?& ((sane %tas) summary.crib.p.q.p.sut) + =(summary.crib.p.q.p.sut i.topics) + == + find-core:this(sut q.sut) + ?~ t.topics + return-hint-core + find-item:this(sut q.sut, topics t.topics) + :: + ++ find-hint-face + ~? >> debug %find-hint-face + ^- (unit item) + ?> &(?=([%hint *] sut) ?=([%help *] q.p.sut) ?=([%face *] q.sut)) + ?: check-face:this(sut q.sut) + ?~ t.topics + return-hint-face + find-item:this(sut q.q.sut, topics t.topics) + find-item:this(sut q.q.sut) + -- + :: + ::+| %recurse + ++ recurse-core + ~? >> debug %recurse-core + ^- (unit item) + ?> ?=([%core *] sut) + find-item:this(sut p.sut) + ++ recurse-chap + ~? >> debug %recurse-chap + ^- (unit item) + ?> ?=([%core *] sut) + ?~ t.topics !! + find-item:this(topics t.topics) + ++ recurse-arm-core + ~? >> debug %recurse-arm-core + ^- (unit item) + ?> ?=([%core *] sut) + ?~ t.topics !! + find-item:this(sut arm-type, topics t.topics) + :: + +| %check + :: + ++ check-arm + ~? >> debug %recurse-core + ^- ? + !=(~ (find ~[i.topics] (sloe sut))) + ++ check-chap + ~? >> debug %check-chap + ^- ? + ?> ?=([%core *] sut) + (~(has by q.r.q.sut) i.topics) + ++ check-face + ~? >> debug %check-face + ^- ? + ?> ?=([%face *] sut) + ?. ?=(term p.sut) + ::TODO: handle $tune case + %.n + =(p.sut i.topics) + ++ check-search + ~? >> debug %check-search + ^- ? + =(~ t.topics) + ++ check-arm-core + ~? >> debug %check-arm-core + ^- ? + =+ arm-list=(sloe (~(play ut sut) arm-hoon)) + &(!=(arm-list ~) !=(arm-list ~[%$]) ?=([%core *] arm-type)) + :: + +| %return + :: + ++ return-cell + ~? >>> debug %return-cell + ^- (unit item) + ?> ?=([%cell *] sut) + (join-items return-item:this(sut p.sut) return-item:this(sut q.sut)) + :: + ++ return-core + ~? >>> debug %return-core + ^- (unit item) + ?> ?=([%core *] sut) + =* compiled-against return-item:this(sut p.sut) + `[%core (trip i.topics) *what sut compiled-against] + :: + ++ return-face + ~? >>> debug %return-face + ^- (unit item) + ?> ?=([%face *] sut) + :: TODO: handle tune case + ?> ?=(term p.sut) + =* compiled-against return-item:this(sut q.sut) + `[%face (trip p.sut) *what compiled-against] + :: + ++ return-fork + ~? >>> debug %return-fork + ^- (unit item) + ?> ?=([%fork *] sut) + =* types ~(tap in p.sut) + =* items (turn types |=(a=type return-item:this(sut a))) + (roll items join-items) + :: + ++ return-hint + ~? >>> debug %return-hint + ^- (unit item) + ?> ?=([%hint *] sut) + =* res return-item:this(sut q.sut) + ?. ?=([%help *] q.p.sut) + ~ + ?: ?=([%core *] q.sut) + return-hint-core + ?: ?=([%face *] q.sut) + return-hint-face + `[%view [%header `crib.p.q.p.sut (item-as-overview res)]~] + :: + ++ return-arm + ~? >>> debug %return-arm + ^- (unit item) + ?> ?=([%core *] sut) + =+ [adoc pdoc cdoc]=(arm-docs i.topics sut) + ::TODO: should this p.sut be sut? or the compiled type of the arm? + `[%arm (trip i.topics) adoc pdoc cdoc arm-hoon sut] + :: + ++ return-chap + ~? >>> debug %return-chap + ^- (unit item) + ?> ?=([%core *] sut) + =/ tom=tome (~(got by q.r.q.sut) i.topics) + `[%chapter (trip i.topics) p.tom sut (~(got by q.r.q.sut) i.topics)] + :: + ++ return-arm-core + ~? >>> debug %return-arm-core + ^- (unit item) + ?> ?=([%core *] sut) + =+ [adoc pdoc cdoc]=(arm-docs i.topics sut) + =/ dox=what ?~(adoc ?~(pdoc ~ pdoc) adoc) + =/ at arm-type + ?> ?=([%core *] at) + =* compiled-against return-item:this(sut p.sut) + `[%core (trip i.topics) dox at compiled-against] + :: + ++ return-item + ~? >>> debug %return-item + ^- (unit item) + ?- sut + %noun ~ + %void ~ + [%atom *] ~ + [%cell *] return-cell + [%core *] return-core + [%face *] return-face + [%fork *] return-fork + [%hint *] return-hint + [%hold *] return-item:this(sut (~(play ut p.sut) q.sut)) + == + :: + ++ return-hint-core + ~? >>> debug %return-hint-core + ^- (unit item) + ?> &(?=([%hint *] sut) ?=([%core *] q.sut)) + (apply-hint return-core:this(sut q.sut)) + :: + ++ return-hint-face + ~? >>> debug %return-hint-face + ^- (unit item) + ?> &(?=([%hint *] sut) ?=([%face *] q.sut)) + (apply-hint return-face:this(sut q.sut)) + :: + ++ apply-hint + ~? >> debug %apply-hint + |= uit=(unit item) + ^- (unit item) + ?~ uit ~ + ?> &(?=([%hint *] sut) ?=([%help *] q.p.sut)) + ?+ u.uit ~ + ?([%core *] [%face *]) (some u.uit(docs `crib.p.q.p.sut)) + == + :: + +| %misc + ++ arm-hoon + ^- hoon + ?> ?=([%core *] sut) + (^arm-hoon i.topics sut) + :: + ++ arm-type + ^- type + ?> ?=([%core *] sut) + (^arm-type i.topics sut) + -- +:: +:: +arm-hoon: looks for an arm in a core type and returns its hoon +++ arm-hoon + |= [nom=term sut=type] + ^- hoon + ?> ?=([%core *] sut) + =/ tomes=(list [p=term q=tome]) ~(tap by q.r.q.sut) + |- + ?~ tomes !! + =+ gen=(~(get by q.q.i.tomes) nom) + ?~ gen + $(tomes t.tomes) + u.gen +:: +:: +arm-type: looks for an arm in a core type and returns its type +++ arm-type + |= [nom=term sut=type] + ^- type + ?> ?=([%core *] sut) + (~(play ut sut) (arm-hoon nom sut)) +:: +:: +hint-doc: returns docs if type is %help $hint w/ matching cuff +++ hint-doc + |= [=cuff sut=type] + ^- what + ?. &(?=([%hint *] sut) ?=([%help *] q.p.sut) =(cuff cuff.p.q.p.sut)) + ~ + `crib.p.q.p.sut +:: +:: +arm-doc: returns arm doc of an arm +:: +:: we just check if the $cuff is from a ++ or +$ arm but this will +:: probably need to be revisited once more sophisticated cuffs are used +++ arm-doc + |= [nom=term sut=type] + ^- what + ?~ (hint-doc [%funk nom]~ sut) + (hint-doc [%plan nom]~ sut) + (hint-doc [%funk nom]~ sut) +:: +:: +prod-doc: wrapper for +hint-doc with empty cuff +++ prod-doc + |= sut=type + ^- what + (hint-doc ~ sut) +:: +:: +buc-doc: checks if type is core and returns docs on $ arm if it exists +++ buc-doc + |= sut=type + ^- what + ?. ?=([%core *] sut) + ~ + ?~ (find [%$]~ (sloe sut)) + ~ + =/ sat=type (arm-type %$ sut) + ?~ (arm-doc %$ sat) + (prod-doc sat) + (arm-doc %$ sat) +:: +:: +arm-docs: grabs the docs for an arm. +:: +:: there are three possible places with relevant docs for an arm: +:: docs for the arm itself, docs for the product of the arm, and +:: if the arm builds a core, docs for the default arm of that core. +:: +:: .adoc: docs written above the the arm +:: .pdoc: docs for the product of the arm +:: .cdoc: docs for the default arm of the core produced by the arm +++ arm-docs + |= [nom=term sut=type] + ^- [what what what] + ?> ?=([%core *] sut) + =/ sat=type (~(play ut sut) (arm-hoon nom sut)) + =/ adoc=what (arm-doc nom sat) + =/ pdoc=what + ?~ adoc + (prod-doc sat) + ?> ?=([%hint *] sat) + (prod-doc q.sat) + =/ cdoc=what + ?~ adoc + ?~ pdoc + (buc-doc sat) + ?> ?=([%hint *] sat) + (buc-doc q.sat) + ?~ pdoc + ?> ?=([%hint *] sat) + (buc-doc q.sat) + ?> &(?=([%hint *] sat) ?=([%hint *] q.sat)) + (buc-doc q.q.sat) + [adoc pdoc cdoc] +:: +:: +arm-and-chapter-overviews: returns an overview of a core's contents +:: +:: returns an overview for arms which are part of unnamed chapters, and +:: an overview of the named chapters +:: +++ arm-and-chapter-overviews + |= =item + ^- [overview overview] + ?> &(?=([%core *] item) ?=([%core *] sut.item)) + =| [adocs=overview cdocs=overview] + =/ tomes ~(tap by q.r.q.sut.item) + |- + ?~ tomes + [(sort-overview adocs) (sort-overview cdocs)] + ?~ p.i.tomes + :: chapter has no name. add documentation for its arms to arm-docs + =. adocs (weld adocs (tome-as-overview q.i.tomes sut.item)) + $(tomes t.tomes) + :: chapter has a name. add to list of chapters + =. cdocs + %+ weld cdocs + ^- overview + [%item :(weld "^" name.item "|" (trip -.i.tomes)) p.q.i.tomes]~ + $(tomes t.tomes) +:: +:: +arms-in-chapter: returns an overview of the arms in a specific chapter +++ arms-in-chapter + |= [sut=type tom=tome] + ^- overview + (sort-overview (tome-as-overview tom sut)) +:: +:: +sort-overview: sort items in an overview in alphabetical order +++ sort-overview + |= ovr=overview + ^- overview + %+ sort ovr + |= [lhs=overview-item rhs=overview-item] + (aor (get-overview-name lhs) (get-overview-name rhs)) +:: +:: +get-overview-name: returns the name of an overview +++ get-overview-name + |= ovr=overview-item + ?- ovr + [%header *] "" + [%item *] name.ovr + == +:: +:: +tome-as-overview: translate a tome into an overview +++ tome-as-overview + |= [tom=tome sut=type] + ^- overview + %+ turn ~(tap by q.tom) + |= ar=(pair term hoon) + :* %item + ::TODO make this distinguish between ++ and +$ arms + (weld "+" (trip p.ar)) + =/ adoc (arm-doc p.ar (~(play ut sut) q.ar)) + =/ pdoc (prod-doc (~(play ut sut) q.ar)) + ?~ adoc + pdoc + adoc + == +:: +:: +item-as-overview: changes an item into an overview +++ item-as-overview + |= uit=(unit item) + ~? >> debug %item-as-overview + ^- overview + ?~ uit ~ + =+ itm=(need uit) + ?- itm + [%view *] items.itm + :: + [%core *] + ?~ name.itm + (item-as-overview children.itm) + :- [%item (weld "^" name.itm) docs.itm] + (item-as-overview children.itm) + :: + [%arm *] + :_ ~ + ::TODO make this distinguish between ++ and +$ arms + :* %item (weld "+" name.itm) + ?~ adoc.itm + ?~ pdoc.itm + cdoc.itm + pdoc.itm + adoc.itm + == + :: + [%chapter *] + [%item (weld "|" name.itm) docs.itm]~ + :: + [%face *] + ?~ name.itm + ~ + [%item (weld "." name.itm) docs.itm]~ + == +:: +:: +join-items: combines two (unit items) together +++ join-items + |= [lhs=(unit item) rhs=(unit item)] + ^- (unit item) + ?~ lhs rhs + ?~ rhs lhs + `[%view (weld (item-as-overview lhs) (item-as-overview rhs))] +:: +:: contains arms using for printing doccords items ++| %printing +:: +print-item: prints a doccords item +++ print-item + |= =item + ~? >> debug %print-item + ^- (list sole-effect) + ?- item + [%view *] (print-overview item *(pair styl styl)) + [%core *] (print-core item) + [%arm *] (print-arm item) + [%chapter *] (print-chapter item) + [%face *] (print-face item) + == +:: +:: +print-core: renders documentation for a full core +++ print-core + |= =item + ^- (list sole-effect) + ?> ?=([%core *] item) + =+ [arms chapters]=(arm-and-chapter-overviews item) + =/ styles=(pair styl styl) [[`%br ~ `%b] [`%br ~ `%m]] + ;: weld + (print-header (weld "^" name.item) docs.item) + :: + [%txt ""]~ + :: + (print-signature ~(duck easy-print sut.item)) + :: + [%txt ""]~ + :: + ?~ arms + ~ + (print-overview [%view [%header `['arms:' ~] arms]~] styles) + :: + ?~ chapters + ~ + (print-overview [%view [%header `['chapters:' ~] chapters]~] styles) + :: + ?~ children.item + ~ + =/ child ?: ?=([%core *] u.children.item) + u.children.item(children ~) + ?: ?=([%face *] u.children.item) + u.children.item(children ~) + u.children.item + =+ compiled=(item-as-overview `child) + ?~ compiled + ~ + (print-overview [%view [%header `['compiled against: ' ~] [i.compiled]~]~] styles) + == +:: +:: +print-chapter: renders documentation for a single chapter +++ print-chapter + |= =item + ^- (list sole-effect) + ?> ?=([%chapter *] item) + ~? > debug %print-chapter + =/ styles=(pair styl styl) [[`%br ~ `%b] [`%br ~ `%m]] + ;: weld + (print-header (weld "|" name.item) docs.item) + :: + =+ arms=(arms-in-chapter sut.item tom.item) + ?~ arms + ~ + (print-overview [%view [%header `['arms:' ~] arms]~] styles) + == +:: +:: +print-signature: turns product of duck:easy-print into a (list sole-effect) +++ print-signature + |= =tank + ^- (list sole-effect) + =/ tan (wash [3 80] tank) + ?. (gte (lent tan) 3) + (turn tan |=(a=tape [%txt a])) + %+ weld + (turn (scag 3 tan) |=(a=tape [%txt a])) + (styled [[`%br ~ `%g] ' ...']~) +:: +:: +print-arm: renders documentation for a single arm in a core +++ print-arm + |= =item + ^- (list sole-effect) + ?> ?=([%arm *] item) + ~? >> debug %print-arm + ;: weld + (print-header (weld "+" name.item) adoc.item) + [%txt ""]~ + :: + (print-signature ~(duck easy-print (~(play ut sut.item) gen.item))) + :: + [%txt ""]~ + :: + ?~ pdoc.item + *(list sole-effect) + %- zing :~ (styled [[`%br ~ `%b] 'product:']~) + (print-header "" pdoc.item) + [%txt ""]~ + == + :: + ?~ cdoc.item + *(list sole-effect) + %- zing :~ (styled [[`%br ~ `%b] '$:']~) + (print-header "" cdoc.item) + == + == +:: +:: +print-face: renders documentation for a face +++ print-face + |= =item + ^- (list sole-effect) + ?> ?=([%face *] item) + ~? >> debug %print-face + ;: weld + (print-header (weld "." name.item) docs.item) + [%txt ""]~ + :: + ?~ children.item + ~ + (print-item u.children.item) + == +:: +:: +print-header: prints name and docs only +++ print-header + |= [name=tape doc=what] + ^- (list sole-effect) + ~? >> debug %print-header + ;: weld + (styled [[`%br ~ `%g] (crip name)]~) + ?~ doc *(list sole-effect) +:: (styled [[`%br ~ `%r] '(undocumented)']~) + :~ :- %tan + %- flop + ;: weld + [%leaf "{(trip p.u.doc)}"]~ + (print-sections q.u.doc) + == == + == +:: +:: +print-overview: prints summaries of several items +:: +:: the (pair styl styl) provides styles for each generation of child items +++ print-overview + |= [view=item styles=(pair styl styl)] + ?> ?=([%view *] view) + ~? >> debug %print-overview + =| out=(list sole-effect) + |- ^- (list sole-effect) + ?~ items.view out + =/ oitem i.items.view + ?- oitem + [%header *] + %= $ + items.view t.items.view + out ;: weld + out + ?~ doc.oitem ~ + (styled [p.styles (crip "{(trip p.u.doc.oitem)}")]~) + ^$(view [%view children.oitem]) + == == + :: + [%item *] + %= $ + items.view t.items.view + out ;: weld + out + (styled [q.styles (crip name.oitem)]~) + ?~ doc.oitem + %- styled + :~ [[`%br ~ `%r] '(undocumented)'] + [[~ ~ ~] ''] + == + ^- (list sole-effect) + [%tan [[%leaf ""] [%leaf "{(trip p.u.doc.oitem)}"] ~]]~ + == == + == +:: +:: +print-sections: renders a list of sections as tang +:: +:: prints the longform documentation +++ print-sections + |= sections=(list sect) + ^- tang + =| out=tang + |- + ?~ sections out + =. out + ;: weld + out + `tang`[%leaf ""]~ + (print-section i.sections) + == + $(sections t.sections) +:: +:: +print-section: renders a sect as a tang +++ print-section + |= section=sect + ^- tang + %+ turn section + |= =pica + ^- tank + ?: p.pica + [%leaf (trip q.pica)] + [%leaf " {(trip q.pica)}"] +:: +:: +styled: makes $sole-effects out of $styls and $cords +++ styled + |= [in=(list (pair styl cord))] + ^- (list sole-effect) + =| out=(list sole-effect) + |- + ?~ in out + =/ eff=styx [p.i.in [q.i.in]~]~ + %= $ + in t.in + out (snoc out [%klr eff]) + == +-- diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 649e48e25..68778475d 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -1,34 +1,66 @@ /- *sole /+ sole |% -+$ state state-4 ++$ state state-5 +$ any-state $~ *state - $% state-4 + $% state-5 + state-4 state-3 state-2 == ++$ state-5 [%5 pith-5] +$ state-4 [%4 pith-4] +$ state-3 [%3 pith-3] +$ state-2 [%2 pith-2] :: ++$ pith-5 + $: bin=(map @ source) :: terminals + == +:: +$ pith-4 $: eel=(set gill:gall) :: connect to - bin=(map bone source) :: terminals + bin=(map bone source-4) :: terminals == :: :: ++$ source-4 + $: edg=_80 + off=@ud + kil=kill + inx=@ud + fug=(map gill:gall (unit target-4)) + mir=(pair @ud stub) + == +:: ++$ target-4 + $: $= blt + %+ pair + (unit dill-belt-4) + (unit dill-belt-4) + ris=(unit search) + hit=history + pom=sole-prompt + inp=sole-command + == +:: ++$ dill-belt-4 + $% [%ctl p=@c] + [%met p=@c] + dill-belt:dill + == +:: ++ pith-3 :: $: eel=(set gill:gall) :: connect to ray=(map dude:gall desk) :: fur=(map dude:gall (unit *)) :: servers - bin=(map bone source) :: terminals + bin=(map bone source-4) :: terminals == :: :: :: ++ pith-2 :: $: eel=(set gill:gall) :: connect to ray=(set well:gall) :: fur=(map dude:gall (unit *)) :: servers - bin=(map bone source) :: terminals + bin=(map bone source-4) :: terminals == :: :: :: ++ kill :: kill ring @@ -42,6 +74,7 @@ off=@ud :: window offset kil=kill :: kill buffer inx=@ud :: ring index + eel=(set gill:gall) :: connect to fug=(map gill:gall (unit target)) :: connections mir=(pair @ud stub) :: mirrored terminal == :: @@ -65,52 +98,74 @@ pom=sole-prompt :: static prompt inp=sole-command :: input state == :: +:: -- :: :: :: :::: :: :: :: :: :: |% ++ en-gill :: gill to wire - |= gyl=gill:gall + |= [ses=@tas gyl=gill:gall] ^- wire - [%drum %phat (scot %p p.gyl) q.gyl ~] + [%drum %phat (scot %p p.gyl) q.gyl ?:(=(%$ ses) ~ [ses ~])] :: ++ de-gill :: gill from wire - |= way=wire ^- gill:gall - ~| way - ?>(?=([@ @ *] way) [(slav %p i.way) i.t.way]) + |= way=wire + ^- [@tas gill:gall] + ~| wire=way + ?> ?=([@ @ ?(~ [@ ~])] way) + :- ?~(t.t.way %$ i.t.t.way) + [(slav %p i.way) i.t.way] -- -:: TODO: remove .ost :: |= [hid=bowl:gall state] =* sat +<+ -=/ ost 0 -=+ (~(gut by bin) ost *source) +=/ ses=@tas %$ +=+ (~(gut by bin) ses *source) =* dev - =| moz=(list card:agent:gall) -=| biz=(list dill-blit:dill) +=| biz=(list blit:dill) ::TODO should be per-session |% ++ this . +++ klr klr:format +$ state ^state :: proxy +$ any-state ^any-state :: proxy -++ on-init (poke-link our.hid %dojo) +++ on-init (poke-link %$ our.hid %dojo) +:: +++ prep + |= s=@tas + =. ses s + =. dev (~(gut by bin) ses *source) + this +:: +++ open + %+ cork de-gill + |= [s=@tas g=gill:gall] + [g (prep s)] +:: ++ diff-sole-effect-phat :: app event |= [way=wire fec=sole-effect] - =< se-abet =< se-view - =+ gyl=(de-gill way) + =< se-abet + =^ gyl this (open way) ?: (se-aint gyl) +>.$ (se-diff gyl fec) :: ++ peer :: |= pax=path + =? this ?=([%dill @ ~] pax) + (prep i.t.pax) ~| [%drum-unauthorized our+our.hid src+src.hid] :: ourself ?> (team:title our.hid src.hid) :: or our own moon - =< se-abet =< se-view + =< se-abet (se-text "[{}, driving {}]") :: +++ poke-dill + |= [ses=@tas bet=dill-belt:dill] + (poke-dill-belt:(prep ses) bet) +:: ++ poke-dill-belt :: terminal event |= bet=dill-belt:dill - =< se-abet =< se-view + =< se-abet (se-belt bet) :: ++ poke-dill-blit :: terminal output @@ -118,29 +173,29 @@ se-abet:(se-blit-sys bit) :: ++ poke-link :: connect app - |= gyl=gill:gall - =< se-abet =< se-view - (se-link gyl) + |= [ses=@tas gyl=gill:gall] + =< se-abet + (se-link:(prep ses) gyl) :: ++ poke-unlink :: disconnect app - |= gyl=gill:gall - =< se-abet =< se-view - (se-drop:(se-pull gyl) & gyl) + |= [ses=@ta gyl=gill:gall] + =< se-abet + (se-drop:(se-pull:(prep ses) gyl) & gyl) :: ++ poke-exit :: shutdown |= ~ se-abet:(se-blit-sys `dill-blit:dill`[%qit ~]) :: ++ poke-put :: write file - |= [pax=path txt=@] + |= [pax=path arg=$@(@ [@tas @])] + =^ txt +> ?@(arg [arg +>] [+.arg (prep -.arg)]) se-abet:(se-blit-sys [%sav pax txt]) :: :: ++ poke |= [=mark =vase] ?> =(our src):hid ?+ mark ~|([%poke-drum-bad-mark mark] !!) - %drum-dill-belt =;(f (f !<(_+<.f vase)) poke-dill-belt) - %drum-dill-blit =;(f (f !<(_+<.f vase)) poke-dill-blit) + %dill-poke =;(f (f !<(_+<.f vase)) poke-dill) %drum-exit =;(f (f !<(_+<.f vase)) poke-exit) %drum-link =;(f (f !<(_+<.f vase)) poke-link) %drum-put =;(f (f !<(_+<.f vase)) poke-put) @@ -149,19 +204,40 @@ :: ++ on-load |= [hood-version=@ud old=any-state] - =< se-abet =< se-view + =< se-abet =? old ?=(%2 -.old) [%4 [eel bin]:old] =? old ?=(%3 -.old) [%4 [eel bin]:old] + =? old ?=(%4 -.old) + |^ 5+(~(run by bin.old) source-4-to-5) + ++ source-4-to-5 + |= source-4 + ^- source + =; fug [edg off kil inx eel.old fug mir] + (~(run by fug) |=(t=(unit target-4) (bind t target-4-to-5))) + :: + ++ target-4-to-5 + |= t=target-4 + ^- target + :_ +.t + :- (bind p.blt.t belt-4-to-5) + (bind q.blt.t belt-4-to-5) + :: + ++ belt-4-to-5 + |= b=dill-belt-4 + ^- dill-belt:dill + ?. ?=(?(%ctl %met) -.b) b + [%mod -.b p.b] + -- :: - ?> ?=(%4 -.old) + ?> ?=(%5 -.old) =. sat old - =. dev (~(gut by bin) ost *source) + =. dev (~(gut by bin) ses *source) this :: ++ reap-phat :: ack connect |= [way=wire saw=(unit tang)] - =< se-abet =< se-view - =+ gyl=(de-gill way) + =< se-abet + =^ gyl this (open way) ?~ saw (se-join gyl) :: Don't print stack trace because we probably just crashed to @@ -171,9 +247,9 @@ :: ++ take-coup-phat :: ack poke |= [way=wire saw=(unit tang)] - =< se-abet =< se-view + =< se-abet ?~ saw +> - =+ gyl=(de-gill way) + =^ gyl this (open way) ?: (se-aint gyl) +>.$ %- se-dump:(se-drop:(se-pull gyl) & gyl) :_ u.saw @@ -196,8 +272,8 @@ :: ++ quit-phat :: |= way=wire - =< se-abet =< se-view - =+ gyl=(de-gill way) + =< se-abet + =^ gyl this (open way) ~& [%drum-quit src.hid gyl] (se-drop %| gyl) :: :: :: @@ -205,13 +281,18 @@ :: :: :: ++ se-abet :: resolve ^- (quip card:agent:gall state) - =. . se-subze:se-adze - :_ sat(bin (~(put by bin) ost dev)) + =. . se-view:se-subze:se-adze + :_ sat(bin (~(put by bin) ses dev)) ^- (list card:agent:gall) ?~ biz (flop moz) :_ (flop moz) - =/ =dill-blit:dill ?~(t.biz i.biz [%mor (flop biz)]) - [%give %fact ~[/drum] %dill-blit !>(dill-blit)] + =/ =blit:dill ?~(t.biz i.biz [%mor (flop biz)]) + ::TODO remove /drum after dill cleans up + ::TODO but once we remove it, the empty trailing segment of + :: /dill/[ses] would prevent outsiders from subscribing + :: to the default session... + =/ to=(list path) [/dill/[ses] ?~(ses ~[/drum] ~)] + [%give %fact to %dill-blit !>(blit)] :: ++ se-adze :: update connections ^+ . @@ -230,14 +311,14 @@ (se-peer gil) :: ++ se-subze :: downdate connections - =< .(dev (~(got by bin) ost)) - =. bin (~(put by bin) ost dev) + =< .(dev (~(got by bin) ses)) + =. bin (~(put by bin) ses dev) ^+ . %- ~(rep by bin) =< .(con +>) - |: $:,[[ost=bone dev=source] con=_.] ^+ con - =+ xeno=se-subze-local:%_(con ost ost, dev dev) - xeno(ost ost.con, dev dev.con, bin (~(put by bin) ost dev.xeno)) + |: $:,[[ses=@tas dev=source] con=_.] ^+ con + =+ xeno=se-subze-local:%_(con ses ses, dev dev) + xeno(ses ses.con, dev dev.con, bin (~(put by bin.xeno) ses dev.xeno)) :: ++ se-subze-local ^+ . @@ -252,7 +333,7 @@ ++ se-aint :: ignore result |= gyl=gill:gall ^- ? - ?. (~(has by bin) ost) & + ?. (~(has by bin) ses) & =+ gyr=(~(get by fug) gyl) |(?=(~ gyr) ?=(~ u.gyr)) :: @@ -290,7 +371,7 @@ [%cru *] (se-dump:(se-text (trip p.bet)) q.bet) [%hey *] +>(mir [0 ~]) :: refresh [%rez *] +>(edg (dec p.bet)) :: resize window - [%yow *] ~&([%no-yow -.bet] +>) + [%yow *] (se-link p.bet) == =+ gul=se-agon ?: |(?=(~ gul) (se-aint u.gul)) @@ -341,6 +422,21 @@ leaf+(weld (scag (sub edg 3) tape) "...") leaf+tape :: +++ se-blin :: print and newline + |= $= lin + $~ [%put ~] + $>(?(%put %klr) dill-blit:dill) + ^+ +> + :: newline means we need to redraw the prompt, + :: so update the prompt mirror accordingly. + :: + =. mir [0 ~] + ::TODO doing hops and wyps conditionally based on the mirror state seems + :: better, but doesn't cover edge cases. results in dojo's ">=" being + :: rendered alongside the prompt in scrollback, for example. + :: figure out a way to make that work! + (se-blit %mor [%hop 0] [%wyp ~] lin [%nel ~] ~) +:: ++ se-dump :: print tanks |= tac=(list tank) ^+ +> @@ -351,7 +447,7 @@ ?. ((sane %t) (crip i.wol)) :: XX upstream validation ~& bad-text+<`*`i.wol> $(wol t.wol) - $(wol t.wol, +>.^$ (se-blit %out (tuba i.wol))) + $(wol t.wol, +>.^$ (se-blin %put (tuba i.wol))) :: ++ se-join :: confirm connection |= gyl=gill:gall @@ -379,20 +475,21 @@ +>(eel (~(put in eel) gyl)) :: ++ se-blit :: give output - |= bil=dill-blit:dill + |= bil=blit:dill +>(biz [bil biz]) :: ++ se-blit-sys :: output to system |= bil=dill-blit:dill ^+ +> - (se-emit %give %fact ~[/drum] %dill-blit !>(bil)) + ::TODO remove /drum after dill cleans up + (se-emit %give %fact ~[/drum /dill/[ses]] %dill-blit !>(bil)) :: ++ se-show :: show buffer, raw |= lin=(pair @ud stub) ^+ +> ?: =(mir lin) +> - =. +> ?:(=(p.mir p.lin) +> (se-blit %hop p.lin)) - =. +> ?:(=(q.mir q.lin) +> (se-blit %pom q.lin)) - +>(mir lin) + %- se-blit(mir lin) + ?: =(q.mir q.lin) [%hop p.lin] + mor+[[%hop 0] [%wyp ~] [%klr q.lin] [%hop p.lin] ~] :: ++ se-just :: adjusted buffer |= [pom=stub lin=(pair @ud (list @c))] @@ -430,22 +527,22 @@ ?. ((sane %t) (crip txt)) :: XX upstream validation ~& bad-text+<`*`txt> +> - (se-blit %out (tuba txt)) + (se-blin %put (tuba txt)) :: ++ se-poke :: send a poke |= [gyl=gill:gall par=cage] - (se-emit %pass (en-gill gyl) %agent gyl %poke par) + (se-emit %pass (en-gill ses gyl) %agent gyl %poke par) :: ++ se-peer :: send a peer |= gyl=gill:gall ~> %slog.0^leaf/"drum: link {<[p q]:gyl>}" - =/ =path /sole/(cat 3 'drum_' (scot %p our.hid)) + =/ =path (id-to-path:sole our.hid ses) %- se-emit(fug (~(put by fug) gyl ~)) - [%pass (en-gill gyl) %agent gyl %watch path] + [%pass (en-gill ses gyl) %agent gyl %watch path] :: ++ se-pull :: cancel subscription |= gyl=gill:gall - (se-emit %pass (en-gill gyl) %agent gyl %leave ~) + (se-emit %pass (en-gill ses gyl) %agent gyl %leave ~) :: ++ se-tame :: switch connection |= gyl=gill:gall @@ -470,7 +567,7 @@ ^+ +> (ta-poke %sole-action !>(act)) :: - ++ ta-id (cat 3 'drum_' (scot %p our.hid)) :: per-ship duct id + ++ ta-id [our.hid ses] :: per-ship-session id :: ++ ta-aro :: hear arrow |= key=?(%d %l %r %u) @@ -499,13 +596,19 @@ ?< ?=([?(%cru %hey %rez %yow) *] bet) :: target-specific =. blt [q.blt `bet] :: remember belt ?- bet + @ (ta-txt bet ~) [%aro *] (ta-aro p.bet) [%bac *] ta-bac - [%ctl *] (ta-ctl p.bet) [%del *] ta-del - [%met *] (ta-met p.bet) + [%hit *] (ta-hit +.bet) [%ret *] ta-ret [%txt *] (ta-txt p.bet) + :: + [%mod *] + ?+ mod.bet $(bet key.bet) + %ctl (ta-ctl key.bet) + %met (ta-met key.bet) + == == :: ++ ta-det :: send edit @@ -529,7 +632,7 @@ (ta-hom %del (dec pos.inp)) :: ++ ta-ctl :: hear control - |= key=@ud + |= key=bolt:dill ^+ +> =. ris ?.(?=(?(%g %r) key) ~ ris) ?+ key ta-bel @@ -539,7 +642,7 @@ %d ?^ buf.say.inp ta-del ?: =([our.hid %dojo] gyl) - +>(..ta (se-blit qit+~)) :: quit pier + +>(..ta (se-blit-sys %qit ~)) :: quit pier +>(..ta (se-klin gyl)) :: unlink app %e +>(pos.inp (lent buf.say.inp)) %f (ta-aro %r) @@ -550,7 +653,7 @@ ?: =(pos.inp len) ta-bel (ta-kil %r [pos.inp (sub len pos.inp)]) - %l +>(..ta (se-blit %clr ~)) + %l +>(..ta (se-blit(q.mir ~) %clr ~)) %n (ta-aro %d) %p (ta-aro %u) %r ?~ ris @@ -583,6 +686,14 @@ ta-bel (ta-hom %del pos.inp) :: + ++ ta-hit :: hear click + |= [x=@ud y=@ud] + ^+ +> + =/ pol=@ud + (lent-char:klr (make:klr cad.pom)) + =? x (lth x pol) pol + +>.$(pos.inp (min (sub x pol) (lent buf.say.inp))) + :: ++ ta-erl :: hear local error |= pos=@ud ta-bel(pos.inp (min pos (lent buf.say.inp))) @@ -594,14 +705,13 @@ ++ ta-fec :: apply effect |= fec=sole-effect ^+ +> - ?- fec + ?+ fec +>(..ta (se-blit fec)) [%bel *] ta-bel [%blk *] +> [%bye *] +>(..ta (se-klin gyl)) - [%clr *] +>(..ta (se-blit fec)) [%det *] (ta-got +.fec) [%err *] (ta-err p.fec) - [%klr *] +>(..ta (se-blit %klr (make:klr p.fec))) + [%klr *] +>(..ta (se-blin %klr (make:klr p.fec))) [%mor *] |- ^+ +>.^$ ?~ p.fec +>.^$ $(p.fec t.p.fec, +>.^$ ^$(fec i.p.fec)) @@ -609,10 +719,8 @@ [%pro *] (ta-pro +.fec) [%tab *] +>(..ta (se-tab p.fec)) [%tan *] +>(..ta (se-dump p.fec)) - [%sag *] +>(..ta (se-blit fec)) - [%sav *] +>(..ta (se-blit fec)) [%txt *] +>(..ta (se-text p.fec)) - [%url *] +>(..ta (se-blit fec)) + [%url *] +>(..ta (se-text:(se-blit fec) (trip p.fec))) == :: ++ ta-dog :: change cursor @@ -664,8 +772,8 @@ kil ?. ?& ?=(^ old.kil) ?=(^ p.blt) - ?| ?=([%ctl ?(%k %u %w)] u.p.blt) - ?=([%met ?(%d %bac)] u.p.blt) + ?| ?=([%mod %ctl ?(%k %u %w)] u.p.blt) + ?=([%mod %met ?(%d [%bac ~])] u.p.blt) == == %= kil :: prepend num +(num.kil) @@ -682,17 +790,18 @@ == :: ++ ta-met :: meta key - |= key=@ud + |= key=bolt:dill ^+ +> =. ris ~ ?+ key ta-bel - %dot ?. &(?=(^ old.hit) ?=(^ i.old.hit)) :: last "arg" from hist + %'.' ?. &(?=(^ old.hit) ?=(^ i.old.hit)) :: last "arg" from hist ta-bel =+ old=`(list @c)`i.old.hit =+ sop=(ta-jump(buf.say.inp old) %l %ace (lent old)) (ta-hom (cat:edit pos.inp (slag sop old))) :: - %bac ?: =(0 pos.inp) :: kill left-word + [%bac ~] + ?: =(0 pos.inp) :: kill left-word ta-bel =+ sop=(ta-pos %l %edg pos.inp) (ta-kil %l [(sub pos.inp sop) sop]) @@ -748,8 +857,8 @@ :: %y ?. ?& ?=(^ old.kil) :: rotate & yank ?=(^ p.blt) - ?| ?=([%ctl %y] u.p.blt) - ?=([%met %y] u.p.blt) + ?| ?=([%mod %ctl %y] u.p.blt) + ?=([%mod %met %y] u.p.blt) == == ta-bel =+ las=(lent ta-yan) @@ -927,82 +1036,4 @@ ?: |(?=(~ a) (alnm i.a)) i $(i +(i), a t.a) -- -:: -++ klr :: styx/stub engine - =, dill - |% - ++ make :: stub from styx - |= a=styx ^- stub - =| b=stye - %+ reel - |- ^- stub - %- zing %+ turn a - |= a=$@(@t (pair styl styx)) - ?@ a [b (tuba (trip a))]~ - ^$(a q.a, b (styd p.a b)) - :: - |= [a=(pair stye (list @c)) b=stub] - ?~ b [a ~] - ?. =(p.a p.i.b) [a b] - [[p.a (weld q.a q.i.b)] t.b] - :: - ++ styd :: stye from styl - |= [a=styl b=stye] ^+ b :: with inheritance - :+ ?~ p.a p.b - ?~ u.p.a ~ - (~(put in p.b) u.p.a) - (fall p.q.a p.q.b) - (fall q.q.a q.q.b) - :: - ++ lent-char - |= a=stub ^- @ - (roll (lnts-char a) add) - :: - ++ lnts-char :: stub pair tail lengths - |= a=stub ^- (list @) - %+ turn a - |= a=(pair stye (list @c)) - (lent q.a) - :: - ++ brek :: index + incl-len of - |= [a=@ b=(list @)] :: stub pair w= idx a - =| [c=@ i=@] - |- ^- (unit (pair @ @)) - ?~ b ~ - =. c (add c i.b) - ?: (gte c a) - `[i c] - $(i +(i), b t.b) - :: - ++ slag :: slag stub, keep stye - |= [a=@ b=stub] - ^- stub - =+ c=(lnts-char b) - =+ i=(brek a c) - ?~ i b - =+ r=(^slag +(p.u.i) b) - ?: =(a q.u.i) - r - =+ n=(snag p.u.i b) - :_ r :- p.n - (^slag (sub (snag p.u.i c) (sub q.u.i a)) q.n) - :: - ++ scag :: scag stub, keep stye - |= [a=@ b=stub] - ^- stub - =+ c=(lnts-char b) - =+ i=(brek a c) - ?~ i b - ?: =(a q.u.i) - (^scag +(p.u.i) b) - %+ welp - (^scag p.u.i b) - =+ n=(snag p.u.i b) - :_ ~ :- p.n - (^scag (sub (snag p.u.i c) (sub q.u.i a)) q.n) - :: - ++ swag :: swag stub, keep stye - |= [[a=@ b=@] c=stub] - (scag b (slag a c)) - -- -- diff --git a/pkg/arvo/lib/hood/helm.hoon b/pkg/arvo/lib/hood/helm.hoon index aecb91c20..6b29348a2 100644 --- a/pkg/arvo/lib/hood/helm.hoon +++ b/pkg/arvo/lib/hood/helm.hoon @@ -202,6 +202,10 @@ |= ships=(list ship) abet:(emit %pass /helm/prod %arvo %a %prod ships) :: +++ poke-ames-snub + |= ships=(list ship) + abet:(emit %pass /helm/snub %arvo %a %snub ships) +:: ++ poke-atom |= ato=@ =+ len=(scow %ud (met 3 ato)) @@ -273,6 +277,7 @@ == ?+ mark ~|([%poke-helm-bad-mark mark] !!) %helm-ames-prod =;(f (f !<(_+<.f vase)) poke-ames-prod) + %helm-ames-snub =;(f (f !<(_+<.f vase)) poke-ames-snub) %helm-ames-sift =;(f (f !<(_+<.f vase)) poke-ames-sift) %helm-ames-verb =;(f (f !<(_+<.f vase)) poke-ames-verb) %helm-ames-wake =;(f (f !<(_+<.f vase)) poke-ames-wake) diff --git a/pkg/arvo/lib/hood/kiln.hoon b/pkg/arvo/lib/hood/kiln.hoon index d8fac70f7..705f961a9 100644 --- a/pkg/arvo/lib/hood/kiln.hoon +++ b/pkg/arvo/lib/hood/kiln.hoon @@ -504,7 +504,7 @@ [%x %kiln %pikes ~] =+ .^(=rock:tire %cx /(scot %p our)//(scot %da now)/tire) :^ ~ ~ %kiln-pikes - !> ^- pikes + !> ^- pikes %- ~(rut by rock) |= [=desk =zest wic=(set weft)] ^- pike @@ -687,7 +687,7 @@ abet:(emit:(spam leaf+mez ~) %pass /kiln %arvo %c [%info u.tor]) :: ++ poke-install - |= [loc=desk her=ship rem=desk] + |= [loc=desk her=ship rem=desk once=?] =+ .^(=rock:tire %cx /(scot %p our)//(scot %da now)/tire) =/ =zest ?~ got=(~(get by rock) loc) @@ -703,6 +703,8 @@ abet:(spam (render "already syncing" loc her rem ~) ~) ?: =([our loc] [her rem]) abet + ?: once + abet:abet:(merge:(work loc) her rem da+now %only-that) =/ sun (sync loc her rem) ~> %slog.(fmt "beginning install into {here:sun}") =< abet:abet:init @@ -764,11 +766,19 @@ :: ++ poke-rm |= a=path + =| c=(list (unit toro)) + %+ poke-info "removed: {}" + =- %+ roll - + |= [a=(unit toro) b=(unit toro)] + (clap a b furl) + |- ^- (list (unit toro)) =+ b=.^(arch %cy a) - ?~ fil.b - =+ ~[leaf+"No such file:" leaf+"{}"] - abet:(spam -) - (poke-info "removed" `(fray a)) + ?: ?=([^ ~] b) (snoc c `(fray a)) + =? c ?=(^ fil.b) (snoc c `(fray a)) + %- zing + %+ turn ~(tap by dir.b) + |= [kid=@ta ~] + ^$(a (weld a /[kid])) :: ++ poke-schedule |= [where=path tym=@da eve=@t] diff --git a/pkg/arvo/lib/pprint.hoon b/pkg/arvo/lib/pprint.hoon index 310c0f640..3eab077ad 100644 --- a/pkg/arvo/lib/pprint.hoon +++ b/pkg/arvo/lib/pprint.hoon @@ -632,6 +632,7 @@ [%atom *] (cat 3 '@' p.p.spec) == %dbug $(spec q.spec) + %gist $(spec q.spec) %leaf =+((scot p.spec q.spec) ?:(=('~' -) - (cat 3 '%' -))) %like tree/[[`[':' ~] ~] (turn `(list wing)`+.spec wing-to-plum)] %loop (cat 3 '$' p.spec) diff --git a/pkg/arvo/mar/dill/belt.hoon b/pkg/arvo/mar/dill/belt.hoon index 1677b6ef1..5d50dcd98 100644 --- a/pkg/arvo/mar/dill/belt.hoon +++ b/pkg/arvo/mar/dill/belt.hoon @@ -45,8 +45,8 @@ =+ cha=(tuba (trip q.kev)) ?> ?=([@ ~] cha) :: of a single character ?+ mod !! :: modified by one buckykey - [%ctrl ~ ~] [%ctl i.cha] - [%alt ~ ~] [%met i.cha] + [%ctrl ~ ~] [%mod %ctl i.cha] + [%alt ~ ~] [%mod %met i.cha] == ?@ q.kev [%txt (tuba (trip q.kev))] diff --git a/pkg/arvo/mar/dill/blit.hoon b/pkg/arvo/mar/dill/blit.hoon index 77e5cecf4..3ba85e3dc 100644 --- a/pkg/arvo/mar/dill/blit.hoon +++ b/pkg/arvo/mar/dill/blit.hoon @@ -19,8 +19,10 @@ ^- ^json ?+ -.dib ~|(unsupported-blit+-.dib !!) %mor [%a (turn p.dib |=(a=dill-blit:dill json(dib a)))] - %hop (frond %hop (numb p.dib)) - ?(%pro %out) (frond -.dib (tape (tufa p.dib))) + %hop %+ frond %hop + ?@ p.dib (numb p.dib) + (pairs 'x'^(numb x.p.dib) 'y'^(numb y.p.dib) ~) + %put (frond -.dib (tape (tufa p.dib))) ?(%bel %clr) (frond %act %s -.dib) == -- diff --git a/pkg/arvo/mar/drum-put.hoon b/pkg/arvo/mar/drum-put.hoon index e6094158e..8fa3773c0 100644 --- a/pkg/arvo/mar/drum-put.hoon +++ b/pkg/arvo/mar/drum-put.hoon @@ -1,8 +1,7 @@ +:: %drum-put: download into host system :: -:::: /hoon/do-claim/womb/mar - :: /? 310 -|_ [path @] +|_ [path $@(@ [@ta @])] :: ++ grad %noun ++ grow @@ -11,6 +10,6 @@ -- ++ grab :: convert from |% - +$ noun [path @] :: clam from %noun + +$ noun [path $@(@ [@ta @])] :: clam from %noun -- -- diff --git a/pkg/arvo/mar/herm/task.hoon b/pkg/arvo/mar/herm/task.hoon new file mode 100644 index 000000000..93757418e --- /dev/null +++ b/pkg/arvo/mar/herm/task.hoon @@ -0,0 +1,46 @@ +:: task: herm task for passthrough to dill +:: +/- herm +/+ dill +:: +|_ =task:herm +++ grad %noun +:: +grab: convert from +:: +++ grab + |% + ++ noun task:herm + :: + ++ json + |= jon=^json + ^+ task + ~| jon + ?> ?=([%o *] jon) + =+ ses=(~(got by p.jon) 'session') + ?> ?=([%s *] ses) + :- ?: =('' p.ses) %$ + (slav %tas p.ses) + =. p.jon (~(del by p.jon) 'session') + %. jon + =, dejs:format + |^ task + ++ task + %- of + :~ belt+belt:dejs:^dill + blew+(ot 'w'^ni 'h'^ni ~) + hail+ul + open+(ot 'term'^(se %tas) 'apps'^(ar gill) ~) + shut+ul + == + :: + ++ gill + (ot 'who'^(se %p) 'app'^(se %tas) ~) + -- + -- +:: +grow: convert to +:: +++ grow + |% + ++ noun task + -- +-- diff --git a/pkg/arvo/sur/herm.hoon b/pkg/arvo/sur/herm.hoon new file mode 100644 index 000000000..eab8cbb1b --- /dev/null +++ b/pkg/arvo/sur/herm.hoon @@ -0,0 +1,9 @@ +:: herm: stand-in for term.c with http interface +:: +|% ++$ task + $~ [%$ %hail ~] + $: session=@tas + task=$>(?(%open %shut %belt %blew %hail) session-task:dill) + == +-- diff --git a/pkg/arvo/sys.kelvin b/pkg/arvo/sys.kelvin index b7bcb9ecd..5bd0cc68f 100644 --- a/pkg/arvo/sys.kelvin +++ b/pkg/arvo/sys.kelvin @@ -1 +1 @@ -[%zuse 417] +[%zuse 415] diff --git a/pkg/arvo/sys/arvo.hoon b/pkg/arvo/sys/arvo.hoon index 7dbbb0a23..9d97a1d9c 100644 --- a/pkg/arvo/sys/arvo.hoon +++ b/pkg/arvo/sys/arvo.hoon @@ -3,7 +3,7 @@ |% +| %global :: -++ arvo %240 +++ arvo %239 :: :: $arch: node identity :: $axal: fundamental node, recursive (trie) @@ -415,7 +415,7 @@ == -- :: -:: |de: axal engine +:: |of: axal engine :: ++ of =| fat=(axal) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 24c746d8a..0def504fb 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -2,25 +2,24 @@ :::: /sys/hoon :: :: :: =< ride -=> %140 => +=> %139 => :: :: :::: 0: version stub :: :: :: -~% %k.140 ~ ~ :: +~% %k.139 ~ ~ :: |% ++ hoon-version + -- => ~% %one + ~ -:: # %base +:: layer-1 :: -:: basic mathematical operations +:: basic mathematical operations |% -:: # %math :: unsigned arithmetic +| %math ++ add ~/ %add - :: unsigned addition + :: unsigned addition :: :: a: augend :: b: addend @@ -32,7 +31,7 @@ :: ++ dec ~/ %dec - :: unsigned decrement by one. + :: unsigned decrement by one. |= a=@ ~_ leaf+"decrement-underflow" ?< =(0 a) @@ -44,7 +43,7 @@ :: ++ div ~/ %div - :: unsigned divide + :: unsigned divide :: :: a: dividend :: b: divisor @@ -60,7 +59,7 @@ :: ++ dvr ~/ %dvr - :: unsigned divide with remainder + :: unsigned divide with remainder :: :: a: dividend :: b: divisor @@ -126,7 +125,7 @@ :: ++ max ~/ %max - :: unsigned maximum + :: unsigned maximum |= [a=@ b=@] :: the maximum ^- @ @@ -135,7 +134,7 @@ :: ++ min ~/ %min - :: unsigned minimum + :: unsigned minimum |= [a=@ b=@] :: the minimum ^- @ @@ -144,7 +143,7 @@ :: ++ mod ~/ %mod - :: unsigned modulus + :: unsigned modulus :: :: a: dividend :: b: divisor @@ -156,7 +155,7 @@ :: ++ mul ~/ %mul - :: unsigned multiplication + :: unsigned multiplication :: :: a: multiplicand :: b: multiplier @@ -170,7 +169,7 @@ :: ++ sub ~/ %sub - :: unsigned subtraction + :: unsigned subtraction :: :: a: minuend :: b: subtrahend @@ -181,8 +180,6 @@ ?: =(0 b) a $(a (dec a), b (dec b)) :: -:: # %tree -:: :: tree addressing +| %tree ++ cap @@ -229,43 +226,6 @@ %3 +((mul a 2)) * (add (mod b 2) (mul $(b (div b 2)) 2)) == -:: :: -:::: 2n: functional hacks :: - :: :: - :: -++ aftr |*(a=$-(* *) |*(b=$-(* *) (pair b a))) :: pair after -++ cork |*([a=$-(* *) b=$-(* *)] (corl b a)) :: compose forward -++ corl :: compose backwards - |* [a=$-(* *) b=$-(* *)] - =< +:|.((a (b))) :: type check - =+ c=+<.b - |@ ++ $ (a (b c)) - -- -:: -++ cury :: curry left - |* [a=$-(^ *) b=*] - =+ c=+<+.a - |@ ++ $ (a b c) - -- -:: -++ curr :: curry right - |* [a=$-(^ *) c=*] - =+ b=+<+.a - |@ ++ $ (a b c) - -- -:: -++ fore |*(a=$-(* *) |*(b=$-(* *) (pair a b))) :: pair before -:: -++ head |*(^ ,:+<-) :: get head -++ same |*(* +<) :: identity -:: -++ succ |=(@ +(+<)) :: successor -:: -++ tail |*(^ ,:+<+) :: get tail -++ test |=(^ =(+<- +<+)) :: equality -:: -++ lead |*(* |*(* [+>+< +<])) :: put head -++ late |*(* |*(* [+< +>+<])) :: put tail :: :: # %containers :: @@ -413,35 +373,14 @@ :: $@(~ [~ u=item]) -- => -:: :: -:::: 2: layer two :: - :: :: - :: 2a: unit logic :: - :: 2b: list logic :: - :: 2c: bit arithmetic :: - :: 2d: bit logic :: - :: 2e: insecure hashing :: - :: 2f: noun ordering :: - :: 2g: unsigned powers :: - :: 2h: set logic :: - :: 2i: map logic :: - :: 2j: jar and jug logic :: - :: 2k: queue logic :: - :: 2l: container from container :: - :: 2m: container from noun :: - :: 2n: functional hacks :: - :: 2o: normalizing containers :: - :: 2p: serialization :: - :: 2q: molds and mold builders :: - :: +:: ~% %two + ~ +:: layer-2 +:: |% -:: :: -:::: 2a: unit logic :: - :: :: - :: biff, bind, bond, both, clap, drop, :: - :: fall, flit, lift, mate, need, some :: - :: +:: 2a: unit logic ++| %unit-logc +:: ++ biff :: apply |* [a=(unit) b=$-(* (unit))] ?~ a ~ @@ -521,16 +460,19 @@ |* a=* [~ u=a] :: -:::: 2b: list logic :: - :: :: - :: :: -:: +:: 2b: list logic ++| %list-logic :: +snoc: append an element to the end of a list :: ++ snoc |* [a=(list) b=*] (weld a ^+(a [b]~)) :: +:: +lure: List pURE +++ lure + |* a=* + [i=a t=~] +:: ++ fand :: all indices ~/ %fand |= [nedl=(list) hstk=(list)] @@ -811,27 +753,21 @@ :: ++ welp :: faceless weld ~/ %welp - =| [* *] - |@ - ++ $ - ?~ +<- - +<-(. +<+) - +<-(+ $(+<- +<->)) - -- + |* [* *] + ?~ +<- + +<-(. +<+) + +<-(+ $(+<- +<->)) :: ++ zing :: promote ~/ %zing - =| * - |@ - ++ $ - ?~ +< - +< - (welp +<- $(+< +<+)) - -- -:: :: -:::: 2c: bit arithmetic :: - :: :: - :: + |* * + ?~ +< + +< + (welp +<- $(+< +<+)) +:: +:: 2c: bit arithmetic ++| %bit-arithmetic +:: ++ bex :: binary exponent ~/ %bex |= a=bloq @@ -906,7 +842,7 @@ (lsh [bloq (mul step i)] (end [bloq step] i.b)) :: ++ rev - :: reverses block order, accounting for leading zeroes + :: reverses block order, accounting for leading zeroes :: :: boz: block size :: len: size of dat, in boz @@ -989,10 +925,10 @@ ++ sum |=([b=@ c=@] (sit (add b c))) :: wrapping add ++ sit |=(b=@ (end a b)) :: enforce modulo -- -:: :: -:::: 2d: bit logic :: - :: :: - :: +:: +:: 2d: bit logic ++| %bit-logic +:: ++ con :: binary or ~/ %con |= [a=@ b=@] @@ -1043,10 +979,10 @@ :: ++ not |= [a=bloq b=@ c=@] :: binary not (sized) (mix c (dec (bex (mul b (bex a))))) -:: :: -:::: 2e: insecure hashing :: - :: :: - :: +:: +:: 2e: insecure hashing ++| %insecure-hashing +:: ++ muk :: standard murmur3 ~% %muk ..muk ~ =+ ~(. fe 5) @@ -1123,10 +1059,9 @@ ?.(=(0 ham) ham $(i +(i), syd +(syd))) -- :: :: -:::: 2f: noun ordering :: - :: :: - :: aor, dor, gor, mor :: - :: +:: 2f: noun ordering ++| %noun-ordering +:: :: +aor: alphabetical order :: :: Orders atoms before cells, and atoms in ascending LSB order. @@ -1187,11 +1122,10 @@ ?: =(c d) (dor a b) (lth c d) -:: :: -:::: :: - :: 2g: unsigned powers :: - :: :: - :: +:: +:: 2g: unsigned powers ++| %unsigned-powers +:: ++ pow :: unsigned exponent ~/ %pow |= [a=@ b=@] @@ -1215,12 +1149,10 @@ ?: (lte t a) $(r s, q (dec q)) $(q (dec q)) -:: :: -:::: :: - :: :: - :: 2h: set logic :: - :: :: - :: +:: +:: 2h: set logic ++| %set-logic +:: ++ in :: set engine ~/ %in =| a=(tree) :: (set) @@ -1247,10 +1179,10 @@ =| [l=(unit) r=(unit)] |. ^- ? ?~ a & - ?& ?~(l & (gor n.a u.l)) - ?~(r & (gor u.r n.a)) - ?~(l.a & ?&((mor n.a n.l.a) $(a l.a, l `n.a))) - ?~(r.a & ?&((mor n.a n.r.a) $(a r.a, r `n.a))) + ?& ?~(l & &((gor n.a u.l) !=(n.a u.l))) + ?~(r & &((gor u.r n.a) !=(u.r n.a))) + ?~(l.a & ?&((mor n.a n.l.a) !=(n.a n.l.a) $(a l.a, l `n.a))) + ?~(r.a & ?&((mor n.a n.r.a) !=(n.a n.r.a) $(a r.a, r `n.a))) == :: ++ bif :: splits a by b @@ -1290,23 +1222,20 @@ :: ++ dif :: difference ~/ %dif - =+ b=a - |@ - ++ $ - |- ^+ a - ?~ b - a - =+ c=(bif n.b) - ?> ?=(^ c) - =+ d=$(a l.c, b l.b) - =+ e=$(a r.c, b r.b) - |- ^- [$?(~ _a)] - ?~ d e - ?~ e d - ?: (mor n.d n.e) - d(r $(d r.d)) - e(l $(e l.e)) - -- + |* b=_a + |- ^+ a + ?~ b + a + =+ c=(bif n.b) + ?> ?=(^ c) + =+ d=$(a l.c, b l.b) + =+ e=$(a r.c, b r.b) + |- ^- [$?(~ _a)] + ?~ d e + ?~ e d + ?: (mor n.d n.e) + d(r $(d r.d)) + e(l $(e l.e)) :: ++ dig :: axis of a in b |= b=* @@ -1331,16 +1260,16 @@ ~/ %has |* b=* ^- ? - :: wrap extracted item type in a unit because bunting fails + :: wrap extracted item type in a unit because bunting fails :: - :: If we used the real item type of _?^(a n.a !!) as the sample type, - :: then hoon would bunt it to create the default sample for the gate. + :: If we used the real item type of _?^(a n.a !!) as the sample type, + :: then hoon would bunt it to create the default sample for the gate. :: - :: However, bunting that expression fails if :a is ~. If we wrap it - :: in a unit, the bunted unit doesn't include the bunted item type. + :: However, bunting that expression fails if :a is ~. If we wrap it + :: in a unit, the bunted unit doesn't include the bunted item type. :: - :: This way we can ensure type safety of :b without needing to perform - :: this failing bunt. It's a hack. + :: This way we can ensure type safety of :b without needing to perform + :: this failing bunt. It's a hack. :: %. [~ b] |= b=(unit _?>(?=(^ a) n.a)) @@ -1356,22 +1285,19 @@ :: ++ int :: intersection ~/ %int - =+ b=a - |@ - ++ $ - |- ^+ a - ?~ b - ~ - ?~ a - ~ - ?. (mor n.a n.b) - $(a b, b a) - ?: =(n.b n.a) - a(l $(a l.a, b l.b), r $(a r.a, b r.b)) - ?: (gor n.b n.a) - %- uni(a $(a l.a, r.b ~)) $(b r.b) - %- uni(a $(a r.a, l.b ~)) $(b l.b) - -- + |* b=_a + |- ^+ a + ?~ b + ~ + ?~ a + ~ + ?. (mor n.a n.b) + $(a b, b a) + ?: =(n.b n.a) + a(l $(a l.a, b l.b), r $(a r.a, b r.b)) + ?: (gor n.b n.a) + %- uni(a $(a l.a, r.b ~)) $(b r.b) + %- uni(a $(a r.a, l.b ~)) $(b l.b) :: ++ put :: puts b in a, sorted ~/ %put @@ -1420,25 +1346,22 @@ :: ++ uni :: union ~/ %uni - =+ b=a - |@ - ++ $ - ?: =(a b) a - |- ^+ a - ?~ b - a - ?~ a - b - ?: =(n.b n.a) - b(l $(a l.a, b l.b), r $(a r.a, b r.b)) - ?: (mor n.a n.b) - ?: (gor n.b n.a) - $(l.a $(a l.a, r.b ~), b r.b) - $(r.a $(a r.a, l.b ~), b l.b) - ?: (gor n.a n.b) - $(l.b $(b l.b, r.a ~), a r.a) - $(r.b $(b r.b, l.a ~), a l.a) - -- + |* b=_a + ?: =(a b) a + |- ^+ a + ?~ b + a + ?~ a + b + ?: =(n.b n.a) + b(l $(a l.a, b l.b), r $(a r.a, b r.b)) + ?: (mor n.a n.b) + ?: (gor n.b n.a) + $(l.a $(a l.a, r.b ~), b r.b) + $(r.a $(a r.a, l.b ~), b l.b) + ?: (gor n.a n.b) + $(l.b $(b l.b, r.a ~), a r.a) + $(r.b $(b r.b, l.a ~), a l.a) :: ++ wyt :: size of set =< $ @@ -1446,10 +1369,10 @@ |. ^- @ ?~(a 0 +((add $(a l.a) $(a r.a)))) -- -:: :: -:::: 2i: map logic :: - :: :: - :: +:: +:: 2i: map logic ++| %map-logic +:: ++ by :: map engine ~/ %by =| a=(tree (pair)) :: (map) @@ -1509,23 +1432,20 @@ :: ++ dif :: difference ~/ %dif - =+ b=a - |@ - ++ $ - |- ^+ a - ?~ b - a - =+ c=(bif p.n.b q.n.b) - ?> ?=(^ c) - =+ d=$(a l.c, b l.b) - =+ e=$(a r.c, b r.b) - |- ^- [$?(~ _a)] - ?~ d e - ?~ e d - ?: (mor p.n.d p.n.e) - d(r $(d r.d)) - e(l $(e l.e)) - -- + |* b=_a + |- ^+ a + ?~ b + a + =+ c=(bif p.n.b q.n.b) + ?> ?=(^ c) + =+ d=$(a l.c, b l.b) + =+ e=$(a r.c, b r.b) + |- ^- [$?(~ _a)] + ?~ d e + ?~ e d + ?: (mor p.n.d p.n.e) + d(r $(d r.d)) + e(l $(e l.e)) :: ++ dig :: axis of b key |= b=* @@ -1588,26 +1508,23 @@ :: ++ int :: intersection ~/ %int - =+ b=a - |@ - ++ $ - |- ^+ a - ?~ b - ~ - ?~ a - ~ - ?: (mor p.n.a p.n.b) - ?: =(p.n.b p.n.a) - b(l $(a l.a, b l.b), r $(a r.a, b r.b)) - ?: (gor p.n.b p.n.a) - %- uni(a $(a l.a, r.b ~)) $(b r.b) - %- uni(a $(a r.a, l.b ~)) $(b l.b) - ?: =(p.n.a p.n.b) - b(l $(b l.b, a l.a), r $(b r.b, a r.a)) - ?: (gor p.n.a p.n.b) - %- uni(a $(b l.b, r.a ~)) $(a r.a) - %- uni(a $(b r.b, l.a ~)) $(a l.a) - -- + |* b=_a + |- ^+ a + ?~ b + ~ + ?~ a + ~ + ?: (mor p.n.a p.n.b) + ?: =(p.n.b p.n.a) + b(l $(a l.a, b l.b), r $(a r.a, b r.b)) + ?: (gor p.n.b p.n.a) + %- uni(a $(a l.a, r.b ~)) $(b r.b) + %- uni(a $(a r.a, l.b ~)) $(b l.b) + ?: =(p.n.a p.n.b) + b(l $(b l.b, a l.a), r $(b r.b, a r.a)) + ?: (gor p.n.a p.n.b) + %- uni(a $(b l.b, r.a ~)) $(a r.a) + %- uni(a $(b r.b, l.a ~)) $(a l.a) :: ++ jab ~/ %jab @@ -1693,48 +1610,41 @@ :: ++ uni :: union, merge ~/ %uni - =+ b=a - |@ - ++ $ - |- ^+ a - ?~ b - a - ?~ a - b - ?: =(p.n.b p.n.a) - b(l $(a l.a, b l.b), r $(a r.a, b r.b)) - ?: (mor p.n.a p.n.b) - ?: (gor p.n.b p.n.a) - $(l.a $(a l.a, r.b ~), b r.b) - $(r.a $(a r.a, l.b ~), b l.b) - ?: (gor p.n.a p.n.b) - $(l.b $(b l.b, r.a ~), a r.a) - $(r.b $(b r.b, l.a ~), a l.a) - -- + |* b=_a + |- ^+ a + ?~ b + a + ?~ a + b + ?: =(p.n.b p.n.a) + b(l $(a l.a, b l.b), r $(a r.a, b r.b)) + ?: (mor p.n.a p.n.b) + ?: (gor p.n.b p.n.a) + $(l.a $(a l.a, r.b ~), b r.b) + $(r.a $(a r.a, l.b ~), b l.b) + ?: (gor p.n.a p.n.b) + $(l.b $(b l.b, r.a ~), a r.a) + $(r.b $(b r.b, l.a ~), a l.a) :: ++ uno :: general union - =+ b=a - |@ - ++ $ - |* meg=$-([* * *] *) - |- ^+ a - ?~ b - a - ?~ a - b - ?: =(p.n.b p.n.a) - :+ [p.n.a `_?>(?=(^ a) q.n.a)`(meg p.n.a q.n.a q.n.b)] - $(b l.b, a l.a) - $(b r.b, a r.a) - ?: (mor p.n.a p.n.b) - ?: (gor p.n.b p.n.a) - $(l.a $(a l.a, r.b ~), b r.b) - $(r.a $(a r.a, l.b ~), b l.b) - ?: (gor p.n.a p.n.b) - $(l.b $(b l.b, r.a ~), a r.a) - $(r.b $(b r.b, l.a ~), a l.a) - -- - :: + |* b=_a + |* meg=$-([* * *] *) + |- ^+ a + ?~ b + a + ?~ a + b + ?: =(p.n.b p.n.a) + :+ [p.n.a `_?>(?=(^ a) q.n.a)`(meg p.n.a q.n.a q.n.b)] + $(b l.b, a l.a) + $(b r.b, a r.a) + ?: (mor p.n.a p.n.b) + ?: (gor p.n.b p.n.a) + $(l.a $(a l.a, r.b ~), b r.b) + $(r.a $(a r.a, l.b ~), b l.b) + ?: (gor p.n.a p.n.b) + $(l.b $(b l.b, r.a ~), a r.a) + $(r.b $(b r.b, l.a ~), a l.a) :: ++ urn :: apply gate to nodes ~/ %urn @@ -1763,10 +1673,9 @@ ?~ a b $(a r.a, b [q.n.a $(a l.a)]) -- -:: :: -:::: 2j: jar and jug logic :: - :: :: - :: +:: +:: 2j: jar and jug logic ++| %jar-and-jug-logic ++ ja :: jar engine =| a=(tree (pair * (list))) :: (jar) |@ @@ -1816,10 +1725,10 @@ =+ d=(get b) (~(put by a) b (~(put in d) c)) -- -:: :: -:::: 2k: queue logic :: - :: :: - :: +:: +:: 2k: queue logic ++| %queue-logic +:: ++ to :: queue engine =| a=(tree) :: (qeu) |@ @@ -1897,30 +1806,9 @@ ?~(r.a [~ n.a] $(a r.a)) -- :: -:::: 2o: containers :: - :: :: - :: -++ jar |$ [key value] (map key (list value)) :: map of lists -++ jug |$ [key value] (map key (set value)) :: map of sets +:: 2l: container from container ++| %container-from-container :: -++ map - |$ [key value] :: table - $| (tree (pair key value)) - |=(a=(tree (pair)) ?:(=(~ a) & ~(apt by a))) -:: -++ qeu - |$ [item] :: queue - $| (tree item) - |=(a=(tree) ?:(=(~ a) & ~(apt to a))) -:: -++ set - |$ [item] :: set - $| (tree item) - |=(a=(tree) ?:(=(~ a) & ~(apt in a))) -:: -:::: 2l: container from container :: - :: :: - :: ++ malt :: map from list |* a=(list) (molt `(list [p=_-<.a q=_->.a])`a) @@ -1933,10 +1821,10 @@ |* a=(list) :: ^- (set _i.-.a) =+ b=*(tree _?>(?=(^ a) i.a)) (~(gas in b) a) -:: :: -:::: 2m: container from noun :: - :: :: - :: +:: +:: 2m: container from noun ++| %container-from-noun +:: ++ ly :: list from raw noun le:nl :: @@ -1983,53 +1871,63 @@ [i=i.a t=$(a t.a)] -- :: -:::: 2q: molds and mold builders :: - :: :: - :: -+$ axis @ :: tree address -+$ bean ? :: 0=&=yes, 1=|=no -+$ flag ? -+$ char @t :: UTF8 byte -+$ cord @t :: UTF8, LSB first -+$ byts [wid=@ud dat=@] :: bytes, MSB first -+$ date [[a=? y=@ud] m=@ud t=tarp] :: parsed date -+$ knot @ta :: ASCII text -+$ noun * :: any noun -+$ path (list knot) :: like unix path -+$ stud :: standard name - $@ mark=@tas :: auth=urbit - $: auth=@tas :: standards authority - type=path :: standard label - == :: -+$ tang (list tank) :: bottom-first error +:: 2n: functional hacks ++| %functional-hacks :: -:: $tank: formatted print tree +++ aftr |*(a=$-(* *) |*(b=$-(* *) (pair b a))) :: pair after +++ cork |*([a=$-(* *) b=$-(* *)] (corl b a)) :: compose forward +++ corl :: compose backwards + |* [a=$-(* *) b=$-(* *)] + =< +:|.((a (b))) :: type check + |* c=_+<.b + (a (b c)) :: -:: just a cord, or -:: %leaf: just a tape -:: %palm: backstep list -:: flat-mid, open, flat-open, flat-close -:: %rose: flat list -:: flat-mid, open, close +++ cury :: curry left + |* [a=$-(^ *) b=*] + |* c=_+<+.a + (a b c) :: -+$ tank - $~ leaf/~ - $@ cord - $% [%leaf p=tape] - [%palm p=(qual tape tape tape tape) q=(list tank)] - [%rose p=(trel tape tape tape) q=(list tank)] - == +++ curr :: curry right + |* [a=$-(^ *) c=*] + |* b=_+<+.a + (a b c) :: -+$ tape (list @tD) :: utf8 string as list -+$ tour (list @c) :: utf32 clusters -+$ tarp [d=@ud h=@ud m=@ud s=@ud f=(list @ux)] :: parsed time -+$ term @tas :: ascii symbol -+$ wain (list cord) :: text lines -+$ wall (list tape) :: text lines +++ fore |*(a=$-(* *) |*(b=$-(* *) (pair a b))) :: pair before +:: +++ head |*(^ ,:+<-) :: get head +++ same |*(* +<) :: identity +:: +++ succ |=(@ +(+<)) :: successor +:: +++ tail |*(^ ,:+<+) :: get tail +++ test |=(^ =(+<- +<+)) :: equality +:: +++ lead |*(* |*(* [+>+< +<])) :: put head +++ late |*(* |*(* [+< +>+<])) :: put tail +:: +:: 2o: containers ++| %containers +++ jar |$ [key value] (map key (list value)) :: map of lists +++ jug |$ [key value] (map key (set value)) :: map of sets +:: +++ map + |$ [key value] :: table + $| (tree (pair key value)) + |=(a=(tree (pair)) ?:(=(~ a) & ~(apt by a))) +:: +++ qeu + |$ [item] :: queue + $| (tree item) + |=(a=(tree) ?:(=(~ a) & ~(apt to a))) +:: +++ set + |$ [item] :: set + $| (tree item) + |=(a=(tree) ?:(=(~ a) & ~(apt in a))) +:: +:: 2p: serialization ++| %serialization :: -:::: 2p: serialization :: - :: :: - :: ++ cue :: unpack ~/ %cue |= a=@ @@ -2101,7 +1999,8 @@ =+ e=(add (bex (dec c)) (cut 0 [d (dec c)] b)) [(add (add c c) e) (cut 0 [(add d (dec c)) e] b)] :: -++ fn :: float, infinity, or NaN +++ fn :: float, infinity, or NaN + :: :: s=sign, e=exponent, a=arithmetic form :: (-1)^s * a * 2^e $% [%f s=? e=@s a=@u] @@ -2109,42 +2008,79 @@ [%n ~] == :: -++ dn :: decimal float, infinity, or NaN +++ dn :: decimal float, infinity, or NaN + :: :: (-1)^s * a * 10^e $% [%d s=? e=@s a=@u] [%i s=?] [%n ~] == :: -++ rn :: parsed decimal float +++ rn :: parsed decimal float :: $% [%d a=? b=[c=@ [d=@ e=@] f=? i=@]] [%i a=?] [%n ~] == +:: +:: 2q: molds and mold builders ++| %molds-and-mold-builders +:: ++$ axis @ :: tree address ++$ bean ? :: 0=&=yes, 1=|=no ++$ flag ? ++$ char @t :: UTF8 byte ++$ cord @t :: UTF8, LSB first ++$ byts [wid=@ud dat=@] :: bytes, MSB first ++$ date [[a=? y=@ud] m=@ud t=tarp] :: parsed date ++$ knot @ta :: ASCII text ++$ noun * :: any noun ++$ path (list knot) :: like unix path ++$ stud :: standard name + $@ mark=@tas :: auth=urbit + $: auth=@tas :: standards authority + type=path :: standard label + == :: ++$ tang (list tank) :: bottom-first error +:: +:: $tank: formatted print tree +:: +:: just a cord, or +:: %leaf: just a tape +:: %palm: backstep list +:: flat-mid, open, flat-open, flat-close +:: %rose: flat list +:: flat-mid, open, close +:: ++$ tank + $~ leaf/~ + $@ cord + $% [%leaf p=tape] + [%palm p=(qual tape tape tape tape) q=(list tank)] + [%rose p=(trel tape tape tape) q=(list tank)] + == +:: ++$ tape (list @tD) :: utf8 string as list ++$ tour (list @c) :: utf32 clusters ++$ tarp [d=@ud h=@ud m=@ud s=@ud f=(list @ux)] :: parsed time ++$ term @tas :: ascii symbol ++$ wain (list cord) :: text lines ++$ wall (list tape) :: text lines +:: -- => :: :: -:::: 3: layer three :: - :: :: - :: 3a: signed and modular ints :: - :: 3b: floating point :: - :: 3c: urbit time :: - :: 3d: SHA hash family :: - :: 3e: (reserved) :: - :: 3f: scrambling :: - :: 3g: molds and mold builders :: - :: :: ~% %tri + == %year year %yore yore %ob ob == -|% +:: layer-3 +:: +|% +:: 3a: signed and modular ints ++| %signed-and-modular-ints :: -:::: 3a: signed and modular ints :: - :: :: - :: ++ egcd :: schneier's egcd |= [a=@ b=@] =+ si @@ -2248,10 +2184,9 @@ -1 --1 -- -:: :: -:::: 3b: floating point :: - :: :: - :: +:: +:: 3b: floating point ++| %floating-point :: ++ fl :: arb. precision fp =/ [[p=@u v=@s w=@u] r=$?(%n %u %d %z %a) d=$?(%d %f %i)] @@ -2264,6 +2199,8 @@ :: infinite exponent range => ~% %cofl +> ~ + :: cofl + :: :: internal functions; mostly operating on [e=@s a=@u], in other words :: positive numbers. many of these error out if a=0. |% @@ -2358,19 +2295,21 @@ =((lsh [0 (abs:si (dif:si e.a e.b))] a.b) a.a) =((lsh [0 (abs:si (dif:si e.a e.b))] a.a) a.b) :: - :: integer binary logarithm: 2^ibl(a) <= |a| < 2^(ibl(a)+1) + :: integer binary logarithm: 2^ibl(a) <= |a| < 2^(ibl(a)+1) ++ ibl |= [a=[e=@s a=@u]] ^- @s (sum:si (sun:si (dec (met 0 a.a))) e.a) :: - :: change to a representation where a.a is odd - :: every fn has a unique representation of this kind + :: +uni + :: + :: change to a representation where a.a is odd + :: every fn has a unique representation of this kind ++ uni |= [a=[e=@s a=@u]] |- ?: =((end 0 a.a) 1) a $(a.a (rsh 0 a.a), e.a (sum:si e.a --1)) :: - :: expands to either full precision or to denormalized + :: +xpd: expands to either full precision or to denormalized ++ xpd |= [a=[e=@s a=@u]] =+ ma=(met 0 a.a) @@ -2382,10 +2321,11 @@ (min q (^sub prc ma)) a(e (dif:si e.a (sun:si -)), a (lsh [0 -] a.a)) :: - :: central rounding mechanism - :: can perform: floor, ceiling, smaller, larger, - :: nearest (round ties to: even, away from 0, toward 0) - :: s is sticky bit: represents a value less than ulp(a) = 2^(e.a) + :: +lug: central rounding mechanism + :: + :: can perform: floor, ceiling, smaller, larger, + :: nearest (round ties to: even, away from 0, toward 0) + :: s is sticky bit: represents a value less than ulp(a) = 2^(e.a) :: ++ lug ~/ %lug @@ -2660,8 +2600,8 @@ =+ b=(old:si a) (rou [%f -.b --0 +.b]) :: - :: comparisons return ~ in the event of a NaN ++ lth :: less-than + :: comparisons return ~ in the event of a NaN |= [a=fn b=fn] ^- (unit ?) ?: |(?=([%n *] a) ?=([%n *] b)) ~ :- ~ ?: =(a b) | @@ -2723,16 +2663,17 @@ ?: s.a (^toj +>.a) =.(r swr (fli (^toj +>.a))) -- +:: +ff :: +:: this core has no use outside of the functionality +:: provided to ++rd, ++rs, ++rq, and ++rh +:: +:: w=width: bits in exponent field +:: p=precision: bits in fraction field +:: b=bias: added to exponent when storing +:: r=rounding mode: same as in ++fl ++ ff :: ieee 754 format fp |_ [[w=@u p=@u b=@s] r=$?(%n %u %d %z %a)] - :: this core has no use outside of the functionality - :: provided to ++rd, ++rs, ++rq, and ++rh - :: - :: w=width: bits in exponent field - :: p=precision: bits in fraction field - :: b=bias: added to exponent when storing - :: r=rounding mode: same as in ++fl :: ++ sb (bex (^add w p)) :: sign bit ++ me (dif:si (dif:si --1 b) (sun:si p)) :: minimum exponent @@ -2914,8 +2855,8 @@ ++ rs :: single precision fp ~% %rs +> ~ ^| + :: round to nearest, round up, round down, round to zero |_ r=$?(%n %u %d %z) - :: round to nearest, round up, round down, round to zero :: ++ ma %*(. ff w 8, p 23, b --127, r r) @@ -2993,8 +2934,8 @@ ++ rq :: quad precision fp ~% %rq +> ~ ^| + :: round to nearest, round up, round down, round to zero |_ r=$?(%n %u %d %z) - :: round to nearest, round up, round down, round to zero :: ++ ma %*(. ff w 15, p 112, b --16.383, r r) @@ -3072,8 +3013,8 @@ ++ rh :: half precision fp ~% %rh +> ~ ^| + :: round to nearest, round up, round down, round to zero |_ r=$?(%n %u %d %z) - :: round to nearest, round up, round down, round to zero :: ++ ma %*(. ff w 5, p 10, b --15, r r) @@ -3153,10 +3094,10 @@ ++ drg |= [a=@rh] ^- dn (drg:ma a) :: @rh to decimal float ++ grd |= [a=dn] ^- @rh (grd:ma a) :: decimal float to @rh -- -:: 3c: urbit time :: -:::: :: - :: year, yore, yell, yule, yall, yawn, yelp, yo :: - :: +:: +:: 3c: urbit time ++| %urbit-time +:: ++ year :: date to @d |= det=date ^- @da @@ -3278,10 +3219,10 @@ ++ qad 126.144.001 :: (add 1 (mul 4 yer)) ++ yer 31.536.000 :: (mul 365 day) -- -:: :: -:::: 3d: SHA hash family :: - :: :: - :: +:: +:: 3d: SHA hash family ++| %sha-hash-family +:: ++ shad |=(ruz=@ (shax (shax ruz))) :: double sha-256 ++ shaf :: half sha-256 |= [sal=@ ruz=@] @@ -3700,15 +3641,9 @@ :(sum (rol 0 5 a) fy e (wac 3 kbx) (wac j wox)) $(j +(j), a tem, b a, c (rol 0 30 b), d c, e d) -- -:: :: -:::: 3e: AES encryption (XX removed) :: - :: :: - :: -:: :: -:::: 3f: scrambling :: - :: :: - :: ob :: - :: +:: 3f: scrambling ++| %scrambling +:: ++ un :: =(x (wred (wren x))) |% ++ wren :: conceal structure @@ -4014,8 +3949,9 @@ :: -- :: -:::: 3g: molds and mold builders - :: +:: 3g: molds and mold builders ++| %molds-and-mold-builders +:: +$ coin $~ [%$ %ud 0] :: print format $% [%$ p=dime] :: [%blob p=*] :: @@ -4043,29 +3979,10 @@ [%1 p=*] :: block [%2 p=(list tank)] :: stack trace == :: -++ wonk =+ veq=$:edge :: product from edge - |@ ++ $ ?~(q.veq !! p.u.q.veq) :: - -- :: +++ wonk |* veq=_$:edge :: product from edge + ?~(q.veq !! p.u.q.veq) :: -- => -:: :: -:::: 4: layer four :: - :: :: - :: 4a: exotic bases :: - :: 4b: text processing :: - :: 4c: tank printer :: - :: 4d: parsing (tracing) :: - :: 4e: parsing (combinators) :: - :: 4f: parsing (rule builders) :: - :: 4g: parsing (outside caller) :: - :: 4h: parsing (ascii glyphs) :: - :: 4i: parsing (useful idioms) :: - :: 4j: parsing (bases and base digits) :: - :: 4k: atom printing :: - :: 4l: atom parsing :: - :: 4m: formatting functions :: - :: 4n: virtualization :: - :: 4o: molds and mold builders :: - :: +:: ~% %qua + == @@ -4073,10 +3990,13 @@ %mute mute %show show == +:: layer-4 +:: |% :: -:::: 4a: exotic bases - :: +:: 4a: exotic bases ++| %exotic-bases +:: ++ po :: phonetic base ~/ %po =+ :- ^= sis :: prefix syllables @@ -4154,9 +4074,9 @@ ~ `b -- +:: 4b: text processing ++| %text-processing :: -:::: 4b: text processing - :: ++ at :: basic printing |_ a=@ ++ r @@ -4491,13 +4411,14 @@ %'~' ['~' '~' d] == :: -:::: 4c: tank printer - :: +:: 4c: tank printer ++| %tank-printer +:: ++ wash :: render tank at width |= [[tab=@ edg=@] tac=tank] ^- wall (~(win re tac) tab edg) :: -:: |re: tank renderer +:: +re: tank renderer :: ++ re |_ tac=tank @@ -4732,8 +4653,9 @@ == -- :: -:::: 4d: parsing (tracing) - :: +:: 4d: parsing (tracing) ++| %parsing-tracing +:: ++ last |= [zyc=hair naz=hair] :: farther trace ^- hair ?: =(p.zyc p.naz) @@ -4744,43 +4666,38 @@ ^- hair ?:(=(`@`10 weq) [+(p.naz) 1] [p.naz +(q.naz)]) :: -:::: 4e: parsing (combinators) - :: +:: 4e: parsing (combinators) ++| %parsing-combinators +:: ++ bend :: conditional comp ~/ %bend - =+ raq=|*([a=* b=*] [~ u=[a b]]) - |@ - ++ $ - ~/ %fun - |* [vex=edge sab=rule] - ?~ q.vex - vex - =+ yit=(sab q.u.q.vex) - =+ yur=(last p.vex p.yit) - ?~ q.yit - [p=yur q=q.vex] - =+ vux=(raq p.u.q.vex p.u.q.yit) - ?~ vux - [p=yur q=q.vex] - [p=yur q=[~ u=[p=u.vux q=q.u.q.yit]]] - -- + |* raq=_|*([a=* b=*] [~ u=[a b]]) + ~/ %fun + |* [vex=edge sab=rule] + ?~ q.vex + vex + =+ yit=(sab q.u.q.vex) + =+ yur=(last p.vex p.yit) + ?~ q.yit + [p=yur q=q.vex] + =+ vux=(raq p.u.q.vex p.u.q.yit) + ?~ vux + [p=yur q=q.vex] + [p=yur q=[~ u=[p=u.vux q=q.u.q.yit]]] :: ++ comp ~/ %comp - =+ raq=|*([a=* b=*] [a b]) :: arbitrary compose - |@ - ++ $ - ~/ %fun - |* [vex=edge sab=rule] - ~! +< - ?~ q.vex - vex - =+ yit=(sab q.u.q.vex) - =+ yur=(last p.vex p.yit) - ?~ q.yit - [p=yur q=q.yit] - [p=yur q=[~ u=[p=(raq p.u.q.vex p.u.q.yit) q=q.u.q.yit]]] - -- + |* raq=_|*([a=* b=*] [a b]) :: arbitrary compose + ~/ %fun + |* [vex=edge sab=rule] + ~! +< + ?~ q.vex + vex + =+ yit=(sab q.u.q.vex) + =+ yur=(last p.vex p.yit) + ?~ q.yit + [p=yur q=q.yit] + [p=yur q=[~ u=[p=(raq p.u.q.vex p.u.q.yit) q=q.u.q.yit]]] :: ++ fail |=(tub=nail [p=p.tub q=~]) :: never parse ++ glue :: add rule @@ -4835,8 +4752,9 @@ %. sam (comp |*([a=* b=*] a)) :: -:::: 4f: parsing (rule builders) - :: +:: 4f: parsing (rule builders) ++| %parsing-rule-builders +:: ++ bass :: leftmost base |* [wuc=@ tyd=rule] %+ cook @@ -4900,16 +4818,13 @@ :: ++ here :: place-based apply ~/ %here - =+ [hez=|=([a=pint b=*] [a b]) sef=*rule] - |@ - ++ $ - ~/ %fun - |= tub=nail - =+ vex=(sef tub) - ?~ q.vex - vex - [p=p.vex q=[~ u=[p=(hez [p.tub p.q.u.q.vex] p.u.q.vex) q=q.u.q.vex]]] - -- + |* [hez=_|=([a=pint b=*] [a b]) sef=rule] + ~/ %fun + |= tub=nail + =+ vex=(sef tub) + ?~ q.vex + vex + [p=p.vex q=[~ u=[p=(hez [p.tub p.q.u.q.vex] p.u.q.vex) q=q.u.q.vex]]] :: ++ inde |* sef=rule :: indentation block |= nail ^+ (sef) @@ -4961,12 +4876,10 @@ (next tub) :: ++ knee :: callbacks - =| [gar=* sef=_|.(*rule)] - |@ ++ $ - |= tub=nail - ^- (like _gar) - ((sef) tub) - -- + |* [gar=* sef=_|.(*rule)] + |= tub=nail + ^- (like _gar) + ((sef) tub) :: ++ mask :: match char in set ~/ %mask @@ -5153,8 +5066,9 @@ wag [p.wag [~ [p.u.q.vex p.u.q.wag] q.u.q.wag]] :: -:::: 4g: parsing (outside caller) - :: +:: 4g: parsing (outside caller) ++| %parsing-outside-caller +:: ++ rash |*([naf=@ sab=rule] (scan (trip naf) sab)) ++ rose |* [los=tape sab=rule] =+ vex=(sab [[1 1] los]) @@ -5174,8 +5088,9 @@ ~_(leaf+"syntax error" !!) p.u.q.vex :: -:::: 4h: parsing (ascii glyphs) - :: +:: 4h: parsing (ascii glyphs) ++| %parsing-ascii-glyphs +:: ++ ace (just ' ') :: spACE ++ bar (just '|') :: vertical BAR ++ bas (just '\\') :: Back Slash (escaped) @@ -5210,8 +5125,9 @@ ++ wut (just '?') :: wut, what? ++ zap (just '!') :: zap! bang! crash!! :: -:::: 4i: parsing (useful idioms) - :: +:: 4i: parsing (useful idioms) ++| %parsing-useful-idioms +:: ++ alf ;~(pose low hig) :: alphabetic ++ aln ;~(pose low hig nud) :: alphanumeric ++ alp ;~(pose low hig nud hep) :: alphanumeric and - @@ -5328,8 +5244,9 @@ (just `@`10) == :: -:::: 4j: parsing (bases and base digits) - :: +:: 4j: parsing (bases and base digits) ++| %parsing-bases-and-base-digits +:: ++ ab |% ++ bix (bass 16 (stun [2 2] six)) @@ -5450,8 +5367,9 @@ ++ w ?:(=(tig 63) '~' ?:(=(tig 62) '-' ?:((gte tig 36) (add tig 29) x))) -- :: -:::: 4k: atom printing - :: +:: 4k: atom printing ++| %atom-printing +:: ++ co !: ~% %co ..co ~ @@ -5631,7 +5549,7 @@ |% :: +em-co: format in numeric base :: - :: in .bas, format .min digits of .hol with .par + :: in .bas, format .min digits of .hol with .par :: :: - .hol is processed least-significant digit first :: - all available digits in .hol will be processed, but @@ -5671,8 +5589,8 @@ :: :: +ox-co: format '.'-separated digit sequences in numeric base :: - :: in .bas, format each digit of .hol with .dug, - :: with '.' separators every .gop digits. + :: in .bas, format each digit of .hol with .dug, + :: with '.' separators every .gop digits. :: :: - .hol is processed least-significant digit first :: - .dug handles individual digits, output is prepended @@ -5692,8 +5610,8 @@ :: :: +ro-co: format '.'-prefixed bloqs in numeric base :: - :: in .bas, for .buz bloqs 0 to .dop, format at least one - :: digit of .hol, prefixed with '.' + :: in .bas, for .buz bloqs 0 to .dop, format at least one + :: digit of .hol, prefixed with '.' :: :: - used only for @i* addresses :: @@ -5711,8 +5629,9 @@ |=([? b=@ c=tape] [(dug b) c]) -- :: -:::: 4l: atom parsing - :: +:: 4l: atom parsing ++| %atom-parsing +:: ++ so ~% %so + ~ |% @@ -5901,8 +5820,8 @@ == -- :: -:::: 4m: formatting functions - :: +:: 4m: formatting functions ++| %formatting-functions ++ scot ~/ %scot |=(mol=dime ~(rent co %$ mol)) @@ -5970,8 +5889,9 @@ ~ ;~(pfix fas (most fas urs:ab)) :: -:::: 4n: virtualization - :: +:: 4n: virtualization ++| %virtualization +:: :: +mack: untyped, scry-less, unitary virtualization :: ++ mack @@ -6273,8 +6193,9 @@ |* han=$-(* *) |=(fud=* (mole |.((han fud)))) :: -:::: 4o: molds and mold builders - :: +:: 4o: molds and mold builders ++| %molds-and-mold-builders +:: +$ abel typo :: original sin: type +$ alas (list (pair term hoon)) :: alias list +$ atom @ :: just an atom @@ -6306,11 +6227,13 @@ +$ link :: lexical segment $% [%chat p=term] :: |chapter [%cone p=aura q=atom] :: %constant - [%frag p=term] :: .leg + [%frag p=term] :: .face [%funk p=term] :: +arm + [%plan p=term] :: $spec == :: ++$ cuff (list link) :: parsed lex segments +$ crib [summary=cord details=(list sect)] :: -+$ help [links=(list link) =crib] :: documentation ++$ help [=cuff =crib] :: documentation +$ limb $@ term :: wing element $% [%& p=axis] :: by geometry [%| p=@ud q=(unit term)] :: by name @@ -6325,18 +6248,13 @@ == :: +$ pica (pair ? cord) :: & prose, | code +$ palo (pair vein opal) :: wing trace, match -+$ plat :: - $? %hoon :: - %type :: - %nock :: - %tank :: - == :: +$ pock (pair axis nock) :: changes +$ port (each palo (pair type nock)) :: successful match +$ spec :: structure definition $~ [%base %null] :: $% [%base p=base] :: base type [%dbug p=spot q=spec] :: set debug + [%gist p=[%help p=help] q=spec] :: formal comment [%leaf p=term q=@] :: constant atom [%like p=wing q=(list wing)] :: reference [%loop p=term] :: hygienic reference @@ -6394,23 +6312,23 @@ (pair tope tope) :: cell ++ hoot :: hoon tools |% - +$ beer $@(char [~ p=hoon]) :: simple embed - +$ mane $@(@tas [@tas @tas]) :: XML name+space - +$ manx $~([[%$ ~] ~] [g=marx c=marl]) :: dynamic XML node - +$ marl (list tuna) :: dynamic XML nodes - +$ mart (list [n=mane v=(list beer)]) :: dynamic XML attrs - +$ marx $~([%$ ~] [n=mane a=mart]) :: dynamic XML tag - +$ mare (each manx marl) :: node or nodes - +$ maru (each tuna marl) :: interp or nodes - +$ tuna :: maybe interpolation + +$ beer $@(char [~ p=hoon]) :: simple embed + +$ mane $@(@tas [@tas @tas]) :: XML name+space + +$ manx $~([[%$ ~] ~] [g=marx c=marl]) :: dynamic XML node + +$ marl (list tuna) :: dynamic XML nodes + +$ mart (list [n=mane v=(list beer)]) :: dynamic XML attrs + +$ marx $~([%$ ~] [n=mane a=mart]) :: dynamic XML tag + +$ mare (each manx marl) :: node or nodes + +$ maru (each tuna marl) :: interp or nodes + +$ tuna :: maybe interpolation $~ [[%$ ~] ~] $^ manx $: ?(%tape %manx %marl %call) p=hoon == -- :: -+$ hoon :: - $~ [%zpzp ~] ++$ hoon :: hoon AST + $~ [%zpzp ~] :: $^ [p=hoon q=hoon] :: $% :: [%$ p=axis] :: simple leg @@ -6598,12 +6516,10 @@ +$ vair ?(%gold %iron %lead %zinc) :: in/contra/bi/co +$ vein (list (unit axis)) :: search trace +$ sect (list pica) :: paragraph -+$ whit :: - $: lab=(unit term) :: label - boy=(unit (pair cord (list sect))) :: body - def=(map term (pair cord (list sect))) :: definitions - use=(set term) :: defs used - == :: ++$ whit :: prefix docs parse + $: bat=(map cuff (pair cord (list sect))) :: batch comment + == :: ++$ whiz cord :: postfix doc parse +$ what (unit (pair cord (list sect))) :: help slogan/section +$ wing (list limb) :: search path :: @@ -6682,30 +6598,24 @@ inn=(map path @ud) :: calls into == -- -:: :: -:::: 5: layer five :: - :: :: - :: 5a: compiler utilities :: - :: 5b: macro expansion :: - :: 5c: compiler backend and prettyprinter :: - :: 5d: parser :: - :: 5e: molds and mold builders :: - :: 5f: profiling support (XX remove) :: - :: +:: ~% %pen + == %ap ap %ut ut == +:: layer-5 +:: |% :: -:::: 5aa: new partial nock interpreter - :: +:: 5aa: new partial nock interpreter ++| %new-partial-nock-interpreter +:: ++ musk !. :: nock with block set |% ++ abet - :: simplify raw result + :: simplify raw result :: |= $: :: noy: raw result :: @@ -6728,7 +6638,7 @@ wait/~(tap in blocks) :: ++ araw - :: execute nock on partial subject + :: execute nock on partial subject :: |= $: :: bus: subject, a partial noun :: fol: formula, a complete noun @@ -6964,7 +6874,7 @@ == :: ++ apex - :: execute nock on partial subject + :: execute nock on partial subject :: |= $: :: bus: subject, a partial noun :: fol: formula, a complete noun @@ -6979,7 +6889,7 @@ (abet (araw bus fol)) :: ++ combine - :: combine a pair of seminouns + :: combine a pair of seminouns :: |= $: :: hed: head of pair :: tal: tail of pair @@ -7005,7 +6915,7 @@ [full/(~(uni in blocks.mask.hed) blocks.mask.tal) ~] :: ++ complete - :: complete any laziness + :: complete any laziness :: |= bus=seminoun ^- seminoun @@ -7037,7 +6947,7 @@ == :: ++ fragment - :: seek to an axis in a seminoun + :: seek to an axis in a seminoun :: |= $: :: axe: tree address of subtree :: bus: partial noun @@ -7078,7 +6988,7 @@ == == :: ++ mutate - :: change a single axis in a seminoun + :: change a single axis in a seminoun :: |= $: :: axe: axis within big to change :: lit: (little) seminoun to insert within big at axe @@ -7143,7 +7053,7 @@ (combine hed mut) :: ++ require - :: require complete intermediate step + :: require complete intermediate step :: |= $: noy=result yen=$-(* result) @@ -7167,7 +7077,7 @@ (yen data.bus) :: ++ squash - :: convert stencil to block set + :: convert stencil to block set :: |= tyn=stencil ^- (set block) @@ -7178,8 +7088,9 @@ == -- :: -:::: 5a: compiler utilities - :: +:: 5a: compiler utilities ++| %compiler-utilities +:: ++ bool `type`(fork [%atom %f `0] [%atom %f `1] ~) :: make loobean ++ cell :: make %cell type ~/ %cell @@ -7484,8 +7395,9 @@ $(axe (peg axe 7), dom r.dom) == :: -:::: 5b: macro expansion - :: +:: 5b: macro expansion ++| %macro-expansions +:: ++ ah :: tiki engine |_ tik=tiki ++ blue @@ -7535,11 +7447,12 @@ -- :: ++ ax - =+ :* :: dom: axis to home - :: hay: wing to home - :: cox: hygienic context - :: bug: debug annotations - :: def: default expression + =+ :* :: .dom: axis to home + :: .hay: wing to home + :: .cox: hygienic context + :: .bug: debug annotations + :: .nut: annotations + :: .def: default expression :: dom=`axis`1 hay=*wing @@ -7551,12 +7464,13 @@ |_ mod=spec :: ++ autoname - :: derive name from spec + :: derive name from spec :: |- ^- (unit term) ?- -.mod %base ?.(?=([%atom *] p.mod) ~ ?:(=(%$ p.p.mod) `%atom `p.p.mod)) %dbug $(mod q.mod) + %gist $(mod q.mod) %leaf `p.mod %loop `p.mod %like ?~(p.mod ~ ?^(i.p.mod ?:(?=(%& -.i.p.mod) ~ q.i.p.mod) `i.p.mod)) @@ -7586,13 +7500,9 @@ %bcwt $(mod i.p.mod) %bczp ~ == - ++ hint - |= not=note - ^+ +> - ?>(?=(~ nut) +>.$(nut `not)) :: ++ function - :: construct a function example + :: construct a function example :: |= [fun=spec arg=spec] ^- hoon @@ -7612,7 +7522,7 @@ [%$ 15] :: ++ interface - :: construct a core example + :: construct a core example :: |= [variance=vair payload=spec arms=(map term spec)] ^- hoon @@ -7640,7 +7550,7 @@ [term example:clear(mod spec)] :: ++ home - :: express a hoon against the original subject + :: express a hoon against the original subject :: |= gen=hoon ^- hoon @@ -7652,12 +7562,12 @@ [%tsgr [%wing -] gen] :: ++ clear - :: clear annotations + :: clear annotations ^+ . .(bug ~, def ~, nut ~) :: ++ basal - :: example base case + :: example base case :: |= bas=base ?- bas @@ -7700,30 +7610,29 @@ ?~(res [%wing one] [%tsgl [%wing one] $(one i.res, res t.res)]) :: ++ descend - :: record an axis to original subject + :: record an axis to original subject :: |= axe=axis +>(dom (peg axe dom)) :: ++ decorate - :: apply documentation to expression + :: apply documentation to expression :: |= gen=hoon ^- hoon =- ?~(nut - [%note u.nut -]) - ^- hoon - |- ^- hoon + |- ?~(bug gen [%dbug i.bug $(bug t.bug)]) :: ++ pieces - :: enumerate tuple wings + :: enumerate tuple wings :: |= =(list term) ^- (^list wing) (turn list |=(=term `wing`[term ~])) :: ++ spore - :: build default sample + :: build default sample :: ^- hoon :: sample is always typeless @@ -7754,6 +7663,7 @@ (~(put by ^+(cox (~(uni by cox) q.mod))) %$ p.mod) == [%dbug *] [%dbug p.mod $(mod q.mod)] + [%gist *] $(mod q.mod) [%leaf *] [%rock p.mod q.mod] [%loop *] ~|([%loop p.mod] $(mod (~(got by cox) p.mod))) [%like *] $(mod bcmc/(unreel p.mod q.mod)) @@ -7799,7 +7709,7 @@ == :: ++ example - :: produce a correctly typed default instance + :: produce a correctly typed default instance :: ~+ ^- hoon @@ -7812,6 +7722,7 @@ :: [%base *] (decorate (basal p.mod)) [%dbug *] example(mod q.mod, bug [p.mod bug]) + [%gist *] example(mod q.mod, nut `p.mod) [%leaf *] (decorate [%rock p.mod q.mod]) [%like *] example(mod bcmc/(unreel p.mod q.mod)) [%loop *] [%limb p.mod] @@ -7839,11 +7750,12 @@ == :: ++ factory - :: make a normalizing gate (mold) + :: make a normalizing gate (mold) :: ^- hoon :: process annotations outside construct, to catch default :: + ::TODO: try seeing if putting %gist in here fixes %brbc ?: ?=(%dbug -.mod) factory(mod q.mod, bug [p.mod bug]) ?: ?=(%bcsg -.mod) factory(mod q.mod, def `[%kthp q.mod p.mod]) ^- hoon @@ -7872,7 +7784,7 @@ $/6 :: ++ analyze - :: normalize a fragment of the subject + :: normalize a fragment of the subject :: |_ $: :: axe: axis to fragment :: @@ -7919,19 +7831,19 @@ .(..analyze ^clear) :: ++ fetch - :: load the fragment + :: load the fragment :: ^- hoon [%$ axe] :: ++ fetch-wing - :: load, as a wing + :: load, as a wing :: ^- wing [[%& axe] ~] :: ++ choice - :: match full models, by trying them + :: match full models, by trying them :: |= $: :: one: first option :: rep: other options @@ -7986,7 +7898,7 @@ fin :: ++ relative - :: local constructor + :: local constructor :: ~+ ^- hoon @@ -8002,6 +7914,11 @@ [%dbug *] relative(mod q.mod, bug [p.mod bug]) :: + :: formal comment + :: + [%gist *] + relative(mod q.mod, nut `p.mod) + :: :: constant :: [%leaf *] @@ -8359,6 +8276,7 @@ `[%name term.p.gen skin] == :: + :: +open: desugarer ++ open ^- hoon ?- gen @@ -8411,8 +8329,14 @@ [%yell *] [%cncl [%limb %cain] [%zpgr [%cltr p.gen]] ~] [%note *] q.gen :: + ::TODO: does %gist need to be special cased here? [%brbc *] =- ?~ - !! - [%brtr [%bccl -] [%ktcl body.gen]] + :+ %brtr + [%bccl -] + |- + ?. ?=([%gist *] body.gen) + [%ktcl body.gen] + [%note p.body.gen $(body.gen q.body.gen)] %+ turn `(list term)`sample.gen |= =term ^- spec @@ -8725,8 +8649,9 @@ i.wig -- :: -:::: 5c: compiler backend and prettyprinter - :: +:: 5c: compiler backend and prettyprinter ++| %compiler-backend-and-prettyprinter +:: ++ ut ~% %ut +>+ @@ -8796,7 +8721,7 @@ == |_ [ref=type =skin] :: - :: =fish: make a $nock that tests a .ref at .axis for .skin + :: +fish: make a $nock that tests a .ref at .axis for .skin :: ++ fish |= =axis @@ -8847,7 +8772,7 @@ %wash [%1 1] == :: - :: -gain: make a $type by restricting .ref to .skin + :: +gain: make a $type by restricting .ref to .skin :: ++ gain |- ^- type @@ -8941,7 +8866,7 @@ [[%| 0 ~] $(depth.skin (dec depth.skin))] == :: - :: -lose: make a $type by restricting .ref to exclude .skin + :: +lose: make a $type by restricting .ref to exclude .skin :: ++ lose |- ^- type @@ -9051,7 +8976,7 @@ == :: ++ burp - :: expel undigested seminouns + :: expel undigested seminouns :: ^- type ~+ @@ -9619,7 +9544,7 @@ (chip & gen) :: ++ hemp - :: generate formula from foot + :: generate formula from foot :: |= [hud=poly gol=type gen=hoon] ^- nock @@ -9631,7 +9556,7 @@ == :: ++ laze - :: produce lazy core generator for static execution + :: produce lazy core generator for static execution :: |= [nym=(unit term) hud=poly dom=(map term tome)] ~+ @@ -9760,7 +9685,7 @@ == :: ++ mile - :: mull all chapters and feet in a core + :: mull all chapters and feet in a core :: |= [dox=type mel=vair nym=(unit term) hud=poly dom=(map term tome)] ^- (pair type type) @@ -9770,7 +9695,7 @@ [yet hum] :: ++ mine - :: mint all chapters and feet in a core + :: mint all chapters and feet in a core :: |= [gol=type mel=vair nym=(unit term) hud=poly dom=(map term tome)] ^- (pair type nock) @@ -9808,7 +9733,7 @@ :: all the below arms are used for gol checking and should have no :: effect other than giving more specific errors :: - :: all the possible types we could be expecting. + :: +gol-type: all the possible types we could be expecting. :: +$ gol-type $~ %noun @@ -9817,7 +9742,7 @@ [%core p=type q=coil] [%fork p=(set gol-type)] == - :: check that we're looking for a core + :: +core-check: check that we're looking for a core :: ++ core-check |= log=type @@ -9838,7 +9763,7 @@ =/ b $(tys t.tys) (~(put in b) a) == - :: check we have the expected number of chapters + :: +chapters-check: check we have the expected number of chapters :: ++ chapters-check |= log=gol-type @@ -9857,7 +9782,7 @@ =/ b $(tys t.tys) log == - :: get map of tomes if exists + :: +get-tomes: get map of tomes if exists :: ++ get-tomes |= log=gol-type @@ -9868,7 +9793,7 @@ [%fork *] ~ :: maybe could be more aggressive [%core *] `q.r.q.log == - :: get arms in tome + :: +get-arms: get arms in tome :: ++ get-arms |= [dog=(unit (map term tome)) nam=term] @@ -9877,7 +9802,7 @@ |= a=(map term tome) ~_ leaf+"unexpcted-chapter.{(trip nam)}" q:(~(got by a) nam) - :: check we have the expected number of arms + :: +arms-check: check we have the expected number of arms :: ++ arms-check |= [dab=(map term hoon) dag=(unit (map term hoon))] @@ -9897,7 +9822,7 @@ leaf+"have.{}" (nice dag =(exp hav)) a - :: get expected type of this arm + :: +get-arm-type: get expected type of this arm :: ++ get-arm-type |= [log=gol-type dag=(unit (map term hoon)) nam=term] @@ -11347,7 +11272,7 @@ ++ seem |=(toy=typo `type`toy) :: promote typo ++ seer |=(vix=vise `vase`vix) :: promote vise :: -:: +sell Pretty-print a vase to a tank using `deal`. +:: +sell: pretty-print a vase to a tank using +deal. :: ++ sell ~/ %sell @@ -11356,7 +11281,7 @@ ~| %sell (~(deal us p.vax) q.vax) :: -:: +skol $-(type tank) using `duck`. +:: +skol: $-(type tank) using duck. :: ++ skol |= typ=type @@ -11374,10 +11299,10 @@ :: :: +slab: states whether you can access an arm in a type. :: -:: -- way: the access type ($vial): read, write, or read-and-write. -:: The fourth case of $vial, %free, is not permitted because it would -:: allow you to discover "private" information about a type, -:: information which you could not make use of in (law-abiding) hoon anyway. +:: .way: the access type ($vial): read, write, or read-and-write. +:: The fourth case of $vial, %free, is not permitted because it would +:: allow you to discover "private" information about a type, +:: information which you could not make use of in (law-abiding) hoon anyway. :: ++ slab :: test if contains |= [way=?(%read %rite %both) cog=@tas typ=type] @@ -11488,14 +11413,15 @@ |. ~+ [p.gun .*(q:$:tap q.gun)] :: -:::: 5d: parser - :: +:: 5d: parser ++| %parser +:: ++ vang :: set ++vast params |= [bug=? wer=path] :: bug: debug mode %*(. vast bug bug, wer wer) :: wer: where we are :: ++ vast :: main parsing core - =+ [bug=`?`| wer=*path] + =+ [bug=`?`| wer=*path doc=`?`&] |% ++ gash %+ cook :: parse path |= a=(list tyke) ^- tyke @@ -11529,117 +11455,163 @@ ++ mota %+ cook |=([a=tape b=tape] (rap 3 (weld a b))) ;~(plug (star low) (star hig)) - ++ glom - |= [wit=whit taw=whit] - ^- whit - :* ?~(lab.wit lab.taw lab.wit) - ?~(boy.wit boy.taw boy.wit) - (~(uni by def.wit) def.taw) - (~(uni in use.wit) use.taw) - == ++ docs |% + :: +apex: prefix comment. may contain batch comments. :: - :: above core + :: when a prefix doccord is parsed, it is possible that there is no +gap + :: afterward to be consumed, so we add an additional newline and + :: decrement the line number in the `hair` of the parser :: + :: the reason for this is that the whitespace parsing under +vast seems + :: to factor more cleanly this way, at least compared to the variations + :: tried without the extra newline. this doesn't mean there isn't a + :: better factorization without it, though. ++ apex + ?. doc (easy *whit) + %+ knee *whit |. ~+ ;~ plug - =/ ron (punt (indo noel)) - (punt (ifix [ron ron] (into head))) :: label - :: - =/ ron (punt (indo null)) - (ifix [ron ron] (punt body)) :: body - :: - (cook malt (star fill)) :: definitions - (easy ~) :: defs used (none) + |= tub=nail + =/ vex + %. tub + %- star + %+ cook |*([[a=* b=*] c=*] [a b c]) + ;~(pfix (punt leap) into ;~(pose larg smol)) + ?~ q.vex vex + :- p=p.vex + %- some + ?~ p.u.q.vex + [p=~ q=q.u.q.vex] + :- p=(malt p.u.q.vex) + q=`nail`[[(dec p.p.q.u.q.vex) q.p.q.u.q.vex] ['\0a' q.q.u.q.vex]] == :: - :: backward line + :: +apse: postfix comment. :: + :: a one line comment at the end of a line (typically starting at column + :: 57) that attaches to the expression starting at the beginning of the + :: current line. does not use a $link. ++ apse + ?. doc (easy *whiz) + %+ knee *whiz |. ~+ ;~ pose - %+ cook |=([a=term b=cord] %*(. *whit def (my [a b ~] ~))) - (exit fine) + ;~(less ;~(plug into step en-link col ace) ;~(pfix into step line)) :: - %+ cook |=(a=cord %*(. *whit boy `[a ~])) - (exit line) - :: - (easy *whit) + (easy *whiz) == :: - :: - ++ beer - |= $: lab=(unit term) - boy=(unit (pair cord (list sect))) - def=(list (pair (pair term cord) (list sect))) - == - ^- whit - =; def [lab boy (malt def) ~] - (turn def |=([[a=term b=cord] c=(list sect)] [a [b c]])) - :: - :: - ++ body - ;~ pose - ;~ plug :: can duplicate :: - (into ;~(pfix (punt ;~(plug null col gar step)) line)) - (easy ~) - == - ;~ plug - (into ;~(pfix step line)) - (rant text) - == - == - :: - ++ text (pick line code) :: text line - ++ line ;~(less ace (cook crip (star prn))) :: prose line - ++ code ;~(pfix step step (cook crip (star prn))) :: code line - ++ noel ;~(plug (punt ;~(pfix step hax)) null) :: header padding - ++ head ;~(pfix hax step cen sym) :: header line - ++ null (cold ~ (star ace)) :: blank line - ++ fine :: definition line - ;~ (glue ;~(plug col ace)) - sym - (cook crip (star prn)) - == - :: - :: - :: step: indent - :: into: :: and indent to end of line, consuming following space. - :: indo: :: to end of line, consuming following space. - :: exit: :: to end of line, not consuming following space. - :: - ++ step ;~(plug ace ace) - ++ into |*(bod=rule (indo ;~(pfix step bod))) - :: - ++ indo - |* bod=rule - ;~(pfix col gar ;~(sfix bod (just `@`10) (punt gap))) - :: - ++ exit - |* bod=rule - ;~(pfix (star ace) col gal step bod) - :: - :: fill: full definition - :: - ++ fill - %+ cook |=([[a=term b=cord] c=(list sect) (unit ~)] [a b c]) + ++ leap :: whitespace w/o docs + %+ cold ~ ;~ plug - (into fine) - (rant ;~(pfix step text)) - (punt (indo null)) + ;~ pose + (just '\0a') + ;~(plug gah ;~(pose gah skip)) + skip + == + (star ;~(pose skip gah)) == :: - :: rant: series of sections. + :: +smol: 2 aces then summary, 4 aces then paragraphs. + ++ smol + ;~ pfix + step + ;~ plug + ;~ plug + (plus en-link) + ;~ pose + (ifix [;~(plug col ace) (just '\0a')] (cook crip (plus prn))) + (ifix [(star ace) (just '\0a')] (easy *cord)) + == + == + (rant ;~(pfix step step text)) + == + == + :: + :: +larg: 4 aces then summary, 2 aces then paragraphs. + ++ larg + ;~ pfix + step step + ;~ plug + ;~ sfix + ;~ plug + ;~ pose + ;~(sfix (plus en-link) col ace) + ;~(less ace (easy *cuff)) + == + ;~(less ace (cook crip (plus prn))) + == + (just '\0a') + == + (rant ;~(pfix step teyt)) + == + == :: ++ rant |* sec=rule %- star ;~ pfix - (indo null) - (plus (into sec)) + (ifix [into (just '\0a')] (star ace)) + (plus (ifix [into (just '\0a')] sec)) + == + :: + ++ skip :: non-doccord comment + ;~ plug + col col + ;~(less ;~(pose larg smol) ;~(plug (star prn) (just '\0a'))) + == + :: + ++ null (cold ~ (star ace)) + ++ text (pick line code) + ++ teyt (pick line ;~(pfix step code)) + ++ line ;~(less ace (cook crip (star prn))) + ++ code ;~(pfix step ;~(less ace (cook crip (star prn)))) + ++ step ;~(plug ace ace) + :: + ++ into + ;~(plug (star ace) col col) + :: + ++ en-link + |= a=nail %. a + %+ knee *link |. ~+ + %- stew + ^. stet ^. limo + :~ :- '|' ;~(pfix bar (stag %chat sym)) + :- '.' ;~(pfix dot (stag %frag sym)) + :- '+' ;~(pfix lus (stag %funk sym)) + :- '$' ;~(pfix buc (stag %plan sym)) + :- '%' ;~(pfix cen (stag %cone bisk:so)) == -- :: + ++ clad :: hoon doccords + |* fel=rule + %+ cook + |= [a=whit b=hoon c=whiz] + =? b !=(c *whiz) + [%note help/`[c]~ b] + =+ docs=~(tap by bat.a) + |- + ?~ docs b + $(docs t.docs, b [%note help/i.docs b]) + (seam fel) + ++ coat :: spec doccords + |* fel=rule + %+ cook + |= [a=whit b=spec c=whiz] + =? b !=(c *whiz) + [%gist help/`[c]~ b] + =+ docs=~(tap by bat.a) + |- + ?~ docs b + $(docs t.docs, b [%gist help/i.docs b]) + (seam fel) + ++ scye :: with prefix doccords + |* fel=rule + ;~(pose ;~(plug apex:docs ;~(pfix gap fel)) ;~(plug (easy *whit) fel)) + ++ seam :: with doccords + |* fel=rule + (scye ;~(plug fel apse:docs)) + :: ++ plex :: reparse static path |= gen=hoon ^- (unit path) ?: ?=([%dbug *] gen) :: unwrap %dbug @@ -11869,8 +11841,6 @@ (cook drop-top wide-top) == :: - ::+| - :: ++ a-mane :: mane as hoon %+ cook |= [a=@tas b=(unit @tas)] @@ -11918,8 +11888,6 @@ wide-attrs == :: - ::+| - :: ++ tall-top :: tall top %+ knee *(each manx:hoot marl:hoot) |. ~+ ;~ pose @@ -11946,8 +11914,6 @@ [[p.a (weld q.a b)] c] ;~(plug tag-head tall-attrs tall-tail) :: - ::+| - :: ::REVIEW is there a better way to do this? ++ hopefully-quote :: prefer "quote" form %+ cook |=(a=(list beer:hoot) a) @@ -12050,19 +12016,21 @@ |% ++ main :: - :: state of the parsing loop. we maintain a construction - :: stack for elements and a line stack for lines in the - :: current block. a blank line causes the current block - :: to be parsed and thrown in the current element. when - :: the indent column retreats, the element stack rolls up. + :: state of the parsing loop. :: - :: verbose: debug printing enabled - :: err: error position - :: ind: outer and inner indent level - :: hac: stack of items under construction - :: cur: current item under construction - :: par: current "paragraph" being read in - :: [loc txt]: parsing state + :: we maintain a construction stack for elements and a line + :: stack for lines in the current block. a blank line + :: causes the current block to be parsed and thrown in the + :: current element. when the indent column retreats, the + :: element stack rolls up. + :: + :: .verbose: debug printing enabled + :: .err: error position + :: .ind: outer and inner indent level + :: .hac: stack of items under construction + :: .cur: current item under construction + :: .par: current "paragraph" being read in + :: .[loc txt]: parsing state :: =/ verbose & =| err=(unit hair) @@ -13061,7 +13029,7 @@ [':' (rune col %brcl expb)] ['.' (rune dot %brdt expa)] ['-' (rune hep %brhp expa)] - ['^' (rune ket %brkt expx)] + ['^' (rune ket %brkt expr)] ['~' (rune sig %brsg exqc)] ['*' (rune tar %brtr exqc)] ['=' (rune tis %brts exqc)] @@ -13169,7 +13137,7 @@ ^. stet ^. limo :~ [':' (rune col %mccl expi)] ['/' (rune fas %mcfs expa)] - ['<' (rune gal %mcgl exp1)] + ['<' (rune gal %mcgl expz)] ['~' (rune sig %mcsg expi)] [';' (rune mic %mcmc exqc)] == @@ -13218,63 +13186,52 @@ ;~ pfix zap %- stew ^. stet ^. limo - :~ [':' ;~(pfix col (toad expz))] + :~ [':' ;~(pfix col (toad expy))] ['.' ;~(pfix dot (toad |.(loaf(bug |))))] [',' (rune com %zpcm expb)] [';' (rune mic %zpmc expb)] ['>' (rune gar %zpgr expa)] ['<' (rune gal %zpgl exqc)] - ['@' (rune pat %zppt expy)] + ['@' (rune pat %zppt expx)] ['=' (rune tis %zpts expa)] ['?' (rune wut %zpwt hinh)] == == == :: - ++ boog !: :: core arms - %+ knee [p=*term q=*hoon] |. ~+ - ;~ pose - ;~ pfix (jest '++') - ;~ plug - ;~(pfix gap ;~(pose (cold %$ buc) sym)) - ;~(pfix gap loaf) - == - == - :: - %+ cook - |= [b=term d=spec] - [b [%ktcl [%name b d]]] - ;~ pfix (jest '+$') - ;~ plug - ;~(pfix gap sym) - ;~(pfix gap loan) - == - == - :: - %+ cook - |= [b=term c=(list term) e=spec] - ^- [term hoon] - :- b - :+ %brtr - :- %bccl - =- ?>(?=(^ -) -) - :: for each .term in .c, produce $=(term $~(* $-(* *))) - :: ie {term}=mold - :: - %+ turn c - |= =term - ^- spec - =/ tar [%base %noun] - [%bcts term [%bcsg tar [%bchp tar tar]]] - [%ktcl [%made [b c] e]] - ;~ pfix (jest '+*') - ;~ plug - ;~(pfix gap sym) - ;~(pfix gap (ifix [sel ser] (most ace sym))) - ;~(pfix gap loan) - == + ++ boog !: + %+ knee [p=*whit q=*term r=*help s=*hoon] + |.(~+((scye ;~(pose bola boba)))) + ++ bola :: ++ arms + %+ knee [q=*term r=*help s=*hoon] |. ~+ + %+ cook + |= [q=term r=whiz s=hoon] + ?: =(r *whiz) + [q *help s] + [q [[%funk q]~ [r]~] s] + ;~ pfix (jest '++') + ;~ plug + ;~(pfix gap ;~(pose (cold %$ buc) sym)) + apse:docs + ;~(pfix jump loaf) == == + ::TODO consider special casing $% + ++ boba :: +$ arms + %+ knee [q=*term r=*help s=*hoon] |. ~+ + %+ cook + |= [q=term r=whiz s=spec] + ?: =(r *whiz) + [q *help [%ktcl %name q s]] + [q [[%plan q]~ [r]~] [%ktcl %name q s]] + ;~ pfix (jest '+$') + ;~ plug + ;~(pfix gap sym) + apse:docs + ;~(pfix jump loan) + == + == + :: :: parses a or [a b c] or a b c == ++ lynx =/ wid (ifix [sel ser] (most ace sym)) @@ -13292,24 +13249,81 @@ :: lestify |= a=(list term) ?~(a !! a) + :: ++ whap !: :: chapter %+ cook - |= a=(list (pair term hoon)) + |= a=(list (qual whit term help hoon)) + :: separate $helps into their own list to be passed to +glow + =/ [duds=(list help) nude=(list (pair term hoon))] + %+ roll a + |= $: $= bog + (qual whit term help hoon) + :: + $= gob + [duds=(list help) nude=(list (pair term hoon))] + == + =/ [unt=(list help) tag=(list help)] + %+ skid ~(tap by bat.p.bog) |=(=help =(~ cuff.help)) + :- ?: =(*help r.bog) + (weld tag duds.gob) + [r.bog (weld tag duds.gob)] + |- + ?~ unt [[q.bog s.bog] nude.gob] + =. s.bog [%note help/i.unt s.bog] + $(unt t.unt) + :: + %+ glow duds |- ^- (map term hoon) - ?~ a ~ - =+ $(a t.a) + ?~ nude ~ + =+ $(nude t.nude) %+ ~(put by -) - p.i.a - ?: (~(has by -) p.i.a) - [%eror (weld "duplicate arm: +" (trip p.i.a))] - q.i.a - (most muck boog) + p.i.nude + ?: (~(has by -) p.i.nude) + [%eror (weld "duplicate arm: +" (trip p.i.nude))] + q.i.nude + :: + (most mush boog) + :: + :: +glow: moves batch comments to the correct arm + ++ glow + |= [duds=(list help) nude=(map term hoon)] + ^- (map term hoon) + |- + ?~ duds nude + :: if there is no link, its not part of a batch comment + ?~ cuff.i.duds + :: this shouldn't happen yet until we look for cuffs of length >1 + :: but we need to prove that cuff is nonempty anyways + $(duds t.duds) + :: + ::TODO: look past the first link. this probably requires + ::a major rethink on how batch comments work + =/ nom=(unit term) + ?+ i.cuff.i.duds ~ + :: we only support ++ and +$ batch comments right now + :: + ?([%funk *] [%plan *]) + `p.i.cuff.i.duds + == + %= $ + duds t.duds + nude ?~ nom nude + ?. (~(has by nude) u.nom) + :: ~> %slog.[0 leaf+"glow: unmatched link"] + nude + (~(jab by nude) u.nom |=(a=hoon [%note help+i.duds a])) + == :: ++ whip :: chapter declare - ;~ plug - (ifix [cen gap] sym) - whap - == + %+ cook + |= [[a=whit b=term c=whiz] d=(map term hoon)] + ^- [whit (pair term (map term hoon))] + ?. =(*whit a) + [a b d] + ?: =(*whiz c) + [*whit b d] + [%*(. *whit bat (malt [[%chat b]~ [c]~]~)) b d] + ;~(plug (seam ;~(pfix (jest '+|') gap cen sym)) whap) :: ++ wasp :: $brcb aliases ;~ pose @@ -13323,75 +13337,82 @@ ++ wisp !: :: core tail ?. tol fail %+ cook - |= a=(list (pair term (map term hoon))) + |= a=(list [wit=whit wap=(pair term (map term hoon))]) ^- (map term tome) =< p |- ^- (pair (map term tome) (map term hoon)) ?~ a [~ ~] =/ mor $(a t.a) - =. q.i.a - %- ~(urn by q.i.a) + =. q.wap.i.a + %- ~(urn by q.wap.i.a) |= b=(pair term hoon) ^+ +.b + :: tests for duplicate arms between two chapters ?. (~(has by q.mor) p.b) +.b [%eror (weld "duplicate arm: +" (trip p.b))] - :_ (~(uni by q.mor) q.i.a) + :_ (~(uni by q.mor) q.wap.i.a) %+ ~(put by p.mor) - p.i.a - :- *what - ?. (~(has by p.mor) p.i.a) - q.i.a - [[%$ [%eror (weld "duplicate chapter: |" (trip p.i.a))]] ~ ~] + p.wap.i.a + :- %- ~(get by bat.wit.i.a) + ?: (~(has by bat.wit.i.a) [%chat p.wap.i.a]~) + [%chat p.wap.i.a]~ + ~ + ?. (~(has by p.mor) p.wap.i.a) + q.wap.i.a + [[%$ [%eror (weld "duplicate chapter: |" (trip p.wap.i.a))]] ~ ~] :: + ::TODO: allow cores with unnamed chapter as well as named chapters? ;~ pose dun ;~ sfix ;~ pose - (most muck ;~(pfix (jest '+|') ;~(pfix gap whip))) - ;~(plug (stag %$ whap) (easy ~)) + (most mush whip) + ;~(plug (stag *whit (stag %$ whap)) (easy ~)) == gap dun == == :: - ++ toad :: untrap parser exp - =+ har=expa - |@ ++ $ - =+ dur=(ifix [pal par] $:har(tol |)) - ?:(tol ;~(pose ;~(pfix gap $:har(tol &)) dur) dur) - -- + ::TODO: check parser performance + ++ toad :: untrap parser expr + |* har=_expa + =+ dur=(ifix [pal par] $:har(tol |)) + ?. tol + dur + ;~(pose ;~(pfix jump $:har(tol &)) ;~(pfix gap $:har(tol &)) dur) :: ++ rune :: build rune - =+ [dif=*rule tuq=** har=expa] - |@ ++ $ - ;~(pfix dif (stag tuq (toad har))) - -- + |* [dif=rule tuq=* har=_expa] + ;~(pfix dif (stag tuq (toad har))) :: ++ runo :: rune plus - =+ [dif=*rule hil=** tuq=** har=expa] - |@ ++ $ - ;~(pfix dif (stag hil (stag tuq (toad har)))) - -- + |* [dif=rule hil=* tuq=* har=_expa] + ;~(pfix dif (stag hil (stag tuq (toad har)))) + :: ++ runq :: wide or tall if tol |* [wid=rule tal=rule] :: else wide ?. tol wid ;~(pose wid tal) :: - ++ glop ~+((glue mash)) :: separated by space - ++ gunk ~+((glue muck)) :: separated list ++ butt |* zor=rule :: closing == if tall ?:(tol ;~(sfix zor ;~(plug gap duz)) zor) ++ ulva |* zor=rule :: closing -- and tall ?.(tol fail ;~(sfix zor ;~(plug gap dun))) - ++ hank (most muck loaf) :: gapped hoons - ++ hunk (most muck loan) :: gapped specs + ++ glop ~+((glue mash)) :: separated by space + ++ gunk ~+((glue muck)) :: separated list + ++ goop ~+((glue mush)) :: separator list & docs + ++ hank (most mush loaf) :: gapped hoons + ++ hunk (most mush loan) :: gapped specs + ++ jump ;~(pose leap:docs gap) :: gap before docs + ++ loaf ?:(tol tall wide) :: hoon + ++ loan ?:(tol till wyde) :: spec ++ lore (sear |=(=hoon ~(flay ap hoon)) loaf) :: skin - ++ loaf ?:(tol tall wide) :: tall/wide hoon - ++ loan ?:(tol till wyde) :: tall/wide spec ++ lomp ;~(plug sym (punt ;~(pfix tis wyde))) :: typeable name ++ mash ?:(tol gap ;~(plug com ace)) :: list separator + ++ muss ?:(tol jump ;~(plug com ace)) :: list w/ doccords ++ muck ?:(tol gap ace) :: general separator + ++ mush ?:(tol jump ace) :: separator w/ docs ++ teak %+ knee *tiki |. ~+ :: wing or hoon =+ ^= gub |= [a=term b=$%([%& p=wing] [%| p=hoon])] @@ -13423,57 +13444,55 @@ :: (stag %| (stag ~ tall)) == - ++ rack (most mash ;~(gunk loaf loaf)) :: list [hoon hoon] - ++ ruck (most mash ;~(gunk loan loaf)) :: list [spec hoon] - ++ rick (most mash ;~(gunk rope loaf)) :: list [wing hoon] - :: - :: hoon contents + ++ rack (most muss ;~(goop loaf loaf)) :: list [hoon hoon] + ++ ruck (most muss ;~(goop loan loaf)) :: list [spec hoon] + ++ rick (most mash ;~(goop rope loaf)) :: list [wing hoon] + :: hoon contents :: ++ expa |.(loaf) :: one hoon - ++ expb |.(;~(gunk loaf loaf)) :: two hoons - ++ expc |.(;~(gunk loaf loaf loaf)) :: three hoons - ++ expd |.(;~(gunk loaf loaf loaf loaf)) :: four hoons + ++ expb |.(;~(goop loaf loaf)) :: two hoons + ++ expc |.(;~(goop loaf loaf loaf)) :: three hoons + ++ expd |.(;~(goop loaf loaf loaf loaf)) :: four hoons ++ expe |.(wisp) :: core tail - ++ expf |.(;~(gunk ;~(pfix cen sym) loaf)) :: %term and hoon - ++ expg |.(;~(gunk lomp loaf loaf)) :: term/spec, two hoons - ++ exph |.((butt ;~(gunk rope rick))) :: wing, [spec hoon]s - ++ expi |.((butt ;~(gunk loaf hank))) :: one or more hoons - ++ expj |.(;~(gunk lore loaf)) :: skin and hoon - ++ expk |.(;~(gunk loaf ;~(plug loaf (easy ~)))) :: list of two hoons - ++ expl |.(;~(gunk sym loaf loaf)) :: term, two hoons + ++ expf |.(;~(goop ;~(pfix cen sym) loaf)) :: %term and hoon + ++ expg |.(;~(goop lomp loaf loaf)) :: term/spec, two hoons + ++ exph |.((butt ;~(gunk rope rick))) :: wing, [wing hoon]s + ++ expi |.((butt ;~(goop loaf hank))) :: one or more hoons + ++ expj |.(;~(goop lore loaf)) :: skin and hoon + :: ++ expk |.(;~(gunk loaf ;~(plug loaf (easy ~)))):: list of two hoons + :: ++ expl |.(;~(gunk sym loaf loaf)) :: term, two hoons ++ expm |.((butt ;~(gunk rope loaf rick))) :: several [spec hoon]s ++ expn |. ;~ gunk rope loaf :: wing, hoon, ;~(plug loaf (easy ~)) :: list of one hoon == :: - ++ expo |.(;~(gunk wise loaf loaf)) :: =; - ++ expp |.(;~(gunk (butt rick) loaf)) :: [wing hoon]s, hoon - ++ expq |.(;~(gunk rope loaf loaf)) :: wing and two hoons - ++ expr |.(;~(gunk loaf wisp)) :: hoon and core tail + ++ expo |.(;~(goop wise loaf loaf)) :: =; + ++ expp |.(;~(goop (butt rick) loaf)) :: [wing hoon]s, hoon + ++ expq |.(;~(goop rope loaf loaf)) :: wing and two hoons + ++ expr |.(;~(goop loaf wisp)) :: hoon and core tail ++ exps |.((butt hank)) :: closed gapped hoons ++ expt |.(;~(gunk wise rope loaf loaf)) :: =^ ++ expu |.(;~(gunk rope loaf (butt hank))) :: wing, hoon, hoons - ++ expv |.((butt rick)) :: just changes - ++ expw |.(;~(gunk rope loaf loaf loaf)) :: wing and three hoons - ++ expx |.(;~(gunk loaf wisp)) :: hoon and core tail - ++ expy |.(;~(gunk ropa loaf loaf)) :: wings and two hoons - ++ expz |.(loaf(bug &)) :: hoon with tracing - ++ exp1 |.(;~(gunk loan loaf loaf loaf)) :: spec and three hoons - :: spec contents + :: ++ expv |.((butt rick)) :: just changes + ++ expw |.(;~(goop rope loaf loaf loaf)) :: wing and three hoons + ++ expx |.(;~(goop ropa loaf loaf)) :: wings and two hoons + ++ expy |.(loaf(bug &)) :: hoon with tracing + ++ expz |.(;~(goop loan loaf loaf loaf)) :: spec and three hoons + :: spec contents :: - ++ exqa |.(loan) :: one hoon - ++ exqb |.(;~(gunk loan loan)) :: two specs - ++ exqc |.(;~(gunk loan loaf)) :: spec then hoon - ++ exqd |.(;~(gunk loaf loan)) :: hoon then spec - ++ exqe |.(;~(gunk lynx loan)) :: list of names then spec + ++ exqa |.(loan) :: one spec + ++ exqb |.(;~(goop loan loan)) :: two specs + ++ exqc |.(;~(goop loan loaf)) :: spec then hoon + ++ exqd |.(;~(goop loaf loan)) :: hoon then spec + ++ exqe |.(;~(goop lynx loan)) :: list of names then spec ++ exqs |.((butt hunk)) :: closed gapped specs - ++ exqg |.(;~(gunk sym loan)) :: term and spec - ++ exqk |.(;~(gunk loaf ;~(plug loan (easy ~)))) :: hoon with one spec - ++ exqr |.(;~(gunk loan ;~(plug wasp wisp))) :: spec/aliases?/tail + ++ exqg |.(;~(goop sym loan)) :: term and spec + ::++ exqk |.(;~(goop loaf ;~(plug loan (easy ~)))):: hoon with one spec ++ exqn |.(;~(gunk loan (stag %cltr (butt hank)))):: autoconsed hoons - ++ exqw |.(;~(gunk loaf loan)) :: hoon and spec - ++ exqx |.(;~(gunk loaf loan loan)) :: hoon, two specs - ++ exqy |.(;~(gunk loaf loan loan loan)) :: hoon, three specs - ++ exqz |.(;~(gunk loaf (butt hunk))) :: hoon, n specs + ++ exqr |.(;~(gunk loan ;~(plug wasp wisp))) :: spec/aliases?/tail + ::++ exqw |.(;~(goop loaf loan)) :: hoon and spec + ++ exqx |.(;~(goop loaf loan loan)) :: hoon, two specs + ++ exqy |.(;~(goop loaf loan loan loan)) :: hoon, three specs + ++ exqz |.(;~(goop loaf (butt hunk))) :: hoon, n specs :: :: tiki expansion for %wt runes :: @@ -13499,22 +13518,22 @@ (~(wthx ah b) a) ;~(gunk lore teak) :: - :: hint syntax + :: hint syntax :: - ++ hinb |.(;~(gunk bont loaf)) :: hint and hoon + ++ hinb |.(;~(goop bont loaf)) :: hint and hoon ++ hinc |. :: optional =en, hoon - ;~(pose ;~(gunk bony loaf) (stag ~ loaf)) :: - ++ hind |.(;~(gunk bonk loaf bonz loaf)) :: jet hoon "bon"s hoon - ++ hine |.(;~(gunk bonk loaf)) :: jet-hint and hoon + ;~(pose ;~(goop bony loaf) (stag ~ loaf)) :: + ++ hind |.(;~(gunk bonk loaf ;~(goop bonz loaf))) :: jet hoon "bon"s hoon + ++ hine |.(;~(goop bonk loaf)) :: jet-hint and hoon ++ hinf |. :: 0-3 >s, two hoons ;~ pose - ;~(gunk (cook lent (stun [1 3] gar)) loaf loaf) - (stag 0 ;~(gunk loaf loaf)) + ;~(goop (cook lent (stun [1 3] gar)) loaf loaf) + (stag 0 ;~(goop loaf loaf)) == ++ hing |. :: 0-3 >s, three hoons ;~ pose - ;~(gunk (cook lent (stun [1 3] gar)) loaf loaf loaf) - (stag 0 ;~(gunk loaf loaf loaf)) + ;~(goop (cook lent (stun [1 3] gar)) loaf loaf loaf) + (stag 0 ;~(goop loaf loaf loaf)) == ++ bonk :: jet signature ;~ pfix cen @@ -13526,7 +13545,7 @@ == == ++ hinh |. :: 1/2 numbers, hoon - ;~ gunk + ;~ goop ;~ pose dem (ifix [sel ser] ;~(plug dem ;~(pfix ace dem))) @@ -13646,12 +13665,13 @@ [%spec spec %base %noun] wyde == + :: ++ tall :: full tall form %+ knee *hoon - |.(~+((wart ;~(pose expression:(norm &) long lute apex:(sail &))))) + |.(~+((wart (clad ;~(pose expression:(norm &) long lute apex:(sail &)))))) ++ till :: mold tall form %+ knee *spec - |.(~+((wert ;~(pose structure:(norm &) scad)))) + |.(~+((wert (coat ;~(pose structure:(norm &) scad))))) ++ wede :: wide bulb :: XX: lus deprecated :: @@ -13718,8 +13738,9 @@ ~< %slog.[0 leaf/"ride: compiled"] (~(mint ut typ) %noun gen) :: -:::: 5e: molds and mold builders - :: +:: 5e: molds and mold builders ++| %molds-and-mold-builders +:: +$ mane $@(@tas [@tas @tas]) :: XML name+space +$ manx $~([[%$ ~] ~] [g=marx c=marl]) :: dynamic XML node +$ marl (list manx) :: XML node list @@ -13734,8 +13755,8 @@ +$ spur path :: ship desk case spur +$ time @da :: galactic time :: -:::: 5f: profiling support (XX move) - :: +:: 5f: profiling support (XX move) ++| %profiling-support :: ++ pi-heck |= [nam=@tas day=doss] diff --git a/pkg/arvo/sys/lull.hoon b/pkg/arvo/sys/lull.hoon index 0936cdd58..9bca8c59b 100644 --- a/pkg/arvo/sys/lull.hoon +++ b/pkg/arvo/sys/lull.hoon @@ -3,7 +3,7 @@ !: => ..part |% -++ lull %328 +++ lull %326 :: :: :: :::: :: :: (1) models :: :: :: @@ -360,6 +360,7 @@ :: %init: vane boot :: %prod: re-send a packet per flow, to all peers if .ships is ~ :: %sift: limit verbosity to .ships + :: %snub: set packet blacklist to .ships :: %spew: set verbosity toggles :: %trim: release memory :: %vega: kernel reload notification @@ -375,6 +376,7 @@ $>(%init vane-task) [%prod ships=(list ship)] [%sift ships=(list ship)] + [%snub ships=(list ship)] [%spew veb=(list verb)] [%stir arg=@t] $>(%trim vane-task) @@ -752,7 +754,6 @@ [%hill p=(list @tas)] :: mount points [%done error=(unit error:ames)] :: ames message (n)ack [%mere p=(each (set path) (pair term tang))] :: merge result - [%note p=@tD q=tank] :: debug message [%ogre p=@tas] :: delete mount point [%rule red=dict wit=dict] :: node r+w permissions [%tire p=(each rock:tire wave:tire)] :: app state @@ -1160,9 +1161,7 @@ ++ dill ^? |% +$ gift :: out result <-$ - $% [%bbye ~] :: reset prompt - [%blit p=(list blit)] :: terminal output - [%burl p=@t] :: activate url + $% [%blit p=(list blit)] :: terminal output [%logo ~] :: logout [%meld ~] :: unify memory [%pack ~] :: compact memory @@ -1170,29 +1169,32 @@ == :: +$ task :: in request ->$ $~ [%vega ~] :: - $% [%belt p=belt] :: terminal input - [%blew p=blew] :: terminal config - [%boot lit=? p=*] :: weird %dill boot + $% [%boot lit=? p=*] :: weird %dill boot [%crop p=@ud] :: trim kernel state [%crud p=@tas q=(list tank)] :: print error - [%flee session=~] :: unwatch session [%flog p=flog] :: wrapped error - [%flow p=@tas q=(list gill:gall)] :: terminal config - [%hail ~] :: terminal refresh [%heft ~] :: memory report - [%hook ~] :: this term hung up - [%harm ~] :: all terms hung up $>(%init vane-task) :: after gall ready [%meld ~] :: unify memory - [%noop ~] :: no operation [%pack ~] :: compact memory - [%talk p=tank] :: - [%text p=tape] :: - [%view session=~] :: watch session blits + [%shot ses=@tas task=session-task] :: task for session + [%talk p=(list tank)] :: print tanks + [%text p=tape] :: print tape $>(%trim vane-task) :: trim state $>(%vega vane-task) :: report upgrade [%verb ~] :: verbose mode [%knob tag=term level=?(%hush %soft %loud)] :: error verbosity + session-task :: for default session + == :: + :: :: + +$ session-task :: session request + $% [%belt p=belt] :: terminal input + [%blew p=blew] :: terminal config + [%flee ~] :: unwatch session + [%hail ~] :: terminal refresh + [%open p=dude:gall q=(list gill:gall)] :: setup session + [%shut ~] :: close session + [%view ~] :: watch session blits == :: :: :::: :: (1d2) @@ -1200,59 +1202,41 @@ +$ blew [p=@ud q=@ud] :: columns rows +$ belt :: client input $? bolt :: simple input - $% [%mod mod=?(%ctl %met %hyp) key=bolt] :: w/ modifier + [%mod mod=?(%ctl %met %hyp) key=bolt] :: w/ modifier [%txt p=(list @c)] :: utf32 text ::TODO consider moving %hey, %rez, %yow here :: - ::TMP forward backwards-compatibility :: - :: :: - [%ctl p=@c] :: - [%met p=@c] :: - == == :: + == :: +$ bolt :: simple input $@ @c :: simple keystroke $% [%aro p=?(%d %l %r %u)] :: arrow key [%bac ~] :: true backspace [%del ~] :: true delete - [%hit r=@ud c=@ud] :: mouse click + [%hit x=@ud y=@ud] :: mouse click [%ret ~] :: return == :: - +$ blit :: old blit + +$ blit :: client output $% [%bel ~] :: make a noise [%clr ~] :: clear the screen - [%hop p=@ud] :: set cursor position - [%klr p=stub] :: set styled line - [%lin p=(list @c)] :: set current line - [%mor ~] :: newline + [%hop p=$@(@ud [x=@ud y=@ud])] :: set cursor col/pos + [%klr p=stub] :: put styled + [%mor p=(list blit)] :: multiple blits + [%nel ~] :: newline + [%put p=(list @c)] :: put text at cursor [%sag p=path q=*] :: save to jamfile [%sav p=path q=@] :: save to file [%url p=@t] :: activate url + [%wyp ~] :: wipe cursor line == :: - +$ dill-belt :: new belt - $% [%aro p=?(%d %l %r %u)] :: arrow key - [%bac ~] :: true backspace + +$ dill-belt :: arvo input + $% belt :: client input [%cru p=@tas q=(list tank)] :: echo error - [%ctl p=@] :: control-key - [%del ~] :: true delete [%hey ~] :: refresh - [%met p=@] :: meta-key - [%ret ~] :: return [%rez p=@ud q=@ud] :: resize, cols, rows - [%txt p=(list @c)] :: utf32 text [%yow p=gill:gall] :: connect to app == :: - +$ dill-blit :: new blit - $% [%bel ~] :: make a noise - [%clr ~] :: clear the screen - [%hop p=@ud] :: set cursor position - [%klr p=stub] :: styled text - [%mor p=(list dill-blit)] :: multiple blits - [%pom p=stub] :: styled prompt - [%pro p=(list @c)] :: show as cursor+line + +$ dill-blit :: arvo output + $% blit :: client output [%qit ~] :: close console - [%out p=(list @c)] :: send output line - [%sag p=path q=*] :: save to jamfile - [%sav p=path q=@] :: save to file - [%url p=@t] :: activate url == :: +$ flog :: sent to %dill $% [%crop p=@ud] :: trim kernel state @@ -1263,6 +1247,11 @@ [%text p=tape] :: [%verb ~] :: verbose mode == :: + :: :: + +$ poke :: dill to userspace + $: ses=@tas :: target session + dill-belt :: input + == :: -- ::dill :: :::: :::: ++eyre :: (1e) http-server @@ -1763,7 +1752,6 @@ +$ gift :: outgoing result $% [%boon payload=*] :: ames response [%done error=(unit error:ames)] :: ames message (n)ack - [%onto p=(each suss tang)] :: about agent [%unto p=unto] :: == :: +$ task :: incoming request @@ -2531,9 +2519,6 @@ :: %ames: hear packet :: $>(%hear task:ames) - :: %dill: hangup - :: - $>(%hook task:dill) :: %clay: external edit :: $>(%into task:clay) @@ -2554,6 +2539,9 @@ :: %eyre: starts handling an backdoor http request :: $>(%request-local task:eyre) + :: %dill: close session + :: + $>(%shut task:dill) :: %behn: wakeup :: $>(%wake task:behn) diff --git a/pkg/arvo/sys/vane/ames.hoon b/pkg/arvo/sys/vane/ames.hoon index f6f1f9a58..41b64dd71 100644 --- a/pkg/arvo/sys/vane/ames.hoon +++ b/pkg/arvo/sys/vane/ames.hoon @@ -607,19 +607,20 @@ :: life: our $life; how many times we've rekeyed :: crypto-core: interface for encryption and signing :: bug: debug printing configuration -:: corks(STALE):wires for cork flows pending publisher update +:: snub: blocklist for incoming packets :: :: Note: .corks is only still present for unreleased migration reasons :: +:: +$ ames-state $: peers=(map ship ship-state) =unix=duct =life crypto-core=acru:ames =bug - corks=(set wire) ::TODO unused, remove in next version of state + corks=(set wire) + snub=(set ship) == -:: +$ ames-state-4 ames-state-5 +$ ames-state-5 $: peers=(map ship ship-state-5) @@ -686,6 +687,17 @@ crypto-core=acru:ames =bug == +:: ++$ ames-state-8 + $: peers=(map ship ship-state) + =unix=duct + =life + crypto-core=acru:ames + =bug + corks=(set wire) + == +:: + :: $bug: debug printing configuration :: :: veb: verbosity toggles @@ -733,6 +745,7 @@ $% [%private-keys ~] [%public-keys ships=(set ship)] [%turf ~] + [%ruin ships=(set ship)] == == $: @tas $% [%plea =ship =plea] @@ -841,7 +854,14 @@ :: =< =* adult-gate . =| queued-events=(qeu queued-event) - =| cached-state=(unit $%([%5 ames-state-5] [%6 ames-state-6] [%7 ames-state-7] [%8 ^ames-state])) + =| $= cached-state + %- unit + $% [%5 ames-state-5] + [%6 ames-state-6] + [%7 ames-state-7] + [%8 ames-state-8] + [%9 ^ames-state] + == :: |= [now=@da eny=@ rof=roof] =* larval-gate . @@ -963,7 +983,7 @@ :: lifecycle arms; mostly pass-throughs to the contained adult ames :: ++ scry scry:adult-core - ++ stay [%8 %larva queued-events ames-state.adult-gate] + ++ stay [%9 %larva queued-events ames-state.adult-gate] ++ load |= $= old $% $: %4 @@ -995,6 +1015,13 @@ [%adult state=ames-state-7] == == $: %8 + $% $: %larva + events=(qeu queued-event) + state=ames-state-8 + == + [%adult state=ames-state-8] + == == + $: %9 $% $: %larva events=(qeu queued-event) state=_ames-state.adult-gate @@ -1039,12 +1066,22 @@ =. queued-events events.old larval-gate :: - [%8 %adult *] (load:adult-core %8 state.old) + [%8 %adult *] + =. cached-state `[%8 state.old] + ~> %slog.0^leaf/"ames: larva reload" + larval-gate :: [%8 %larva *] + ~> %slog.0^leaf/"ames: larva: load" + =. queued-events events.old + larval-gate + :: + [%9 %adult *] (load:adult-core %9 state.old) + :: + [%9 %larva *] ~> %slog.1^leaf/"ames: larva: load" =. queued-events events.old - =. adult-gate (load:adult-core %8 state.old) + =. adult-gate (load:adult-core %9 state.old) larval-gate :: == @@ -1063,7 +1100,9 @@ ~> %slog.0^leaf/"ames: init daily recork timer" :- [[/ames]~ %pass /recork %b %wait `@da`(add now ~d1)]~ 8+(state-7-to-8:load:adult-core +.u.cached-state) - ?> ?=(%8 -.u.cached-state) + =? u.cached-state ?=(%8 -.u.cached-state) + 9+(state-8-to-9:load:adult-core +.u.cached-state) + ?> ?=(%9 -.u.cached-state) =. ames-state.adult-gate +.u.cached-state [moz larval-core(cached-state ~)] -- @@ -1102,6 +1141,7 @@ %jilt (on-jilt:event-core ship.task) %prod (on-prod:event-core ships.task) %sift (on-sift:event-core ships.task) + %snub (on-snub:event-core ships.task) %spew (on-spew:event-core veb.task) %stir (on-stir:event-core arg.task) %trim on-trim:event-core @@ -1138,15 +1178,15 @@ [moves ames-gate] :: +stay: extract state before reload :: -++ stay [%8 %adult ames-state] +++ stay [%9 %adult ames-state] :: +load: load in old state after reload :: ++ load =< |= $= old-state - $% [%8 ^ames-state] + $% [%9 ^ames-state] == ^+ ames-gate - ?> ?=(%8 -.old-state) + ?> ?=(%9 -.old-state) ames-gate(ames-state +.old-state) :: |% @@ -1210,7 +1250,7 @@ :: ++ state-7-to-8 |= ames-state=ames-state-7 - ^- ^^ames-state + ^- ames-state-8 :* peers.ames-state unix-duct.ames-state life.ames-state @@ -1218,6 +1258,17 @@ bug.ames-state *(set wire) == + ++ state-8-to-9 + |= ames-state=ames-state-8 + ^- ^^ames-state + :* peers.ames-state + unix-duct.ames-state + life.ames-state + crypto-core.ames-state + bug.ames-state + corks.ames-state + *(set ship) + == -- :: +scry: dereference namespace :: @@ -1247,7 +1298,7 @@ =(%$ syd) == ?. for.veb.bug.ames-state ~ - ~> %slog.0^leaf/"ames: scry-fail {<[why=why lot=lot now=now syd=syd]>}" + ~> %slog.0^leaf/"ames: scry-fail {}" ~ :: /ax/protocol/version @ :: /ax/peers (map ship ?(%alien %known)) @@ -1430,6 +1481,13 @@ ^+ event-core =. ships.bug.ames-state (sy ships) event-core + :: +on-snub: handle request to change ship blacklist + :: + ++ on-snub + |= ships=(list ship) + ^+ event-core + =. snub.ames-state (sy ships) + event-core :: +on-spew: handle request to set verbosity toggles on debug output :: ++ on-spew @@ -1561,11 +1619,13 @@ ~/ %on-hear-packet |= [=lane =packet dud=(unit goof)] ^+ event-core - %- %^ trace odd.veb sndr.packet - |.("received packet") + %- (trace odd.veb sndr.packet |.("received packet")) :: ?: =(our sndr.packet) event-core + ?: (~(has in snub.ames-state) sndr.packet) + %- (trace rcv.veb sndr.packet |.("snubbed")) + event-core :: %. +< :: @@ -1774,28 +1834,30 @@ |. ^- tape =/ sndr [our our-life.channel] =/ rcvr [ship her-life.channel] - "plea {}" + "plea {}" abet:(on-memo:(make-peer-core peer-state channel) bone plea %plea) :: +on-cork: handle request to kill a flow :: ++ on-cork |= =ship ^+ event-core + =/ =plea [%$ /flow [%cork ~]] =/ ship-state (~(get by peers.ames-state) ship) - :: - ?> ?=([~ %known *] ship-state) + ?. ?=([~ %known *] ship-state) + %+ enqueue-alien-todo ship + |= todos=alien-agenda + todos(messages [[duct plea] messages.todos]) =/ =peer-state +.u.ship-state =/ =channel [[our ship] now channel-state -.peer-state] :: =^ =bone ossuary.peer-state (bind-duct ossuary.peer-state duct) - =/ =plea [%$ /flow [%cork ~]] :: =. closing.peer-state (~(put in closing.peer-state) bone) %- %^ trace msg.veb ship |. ^- tape =/ sndr [our our-life.channel] =/ rcvr [ship her-life.channel] - "cork plea {}" + "cork plea {}" abet:(on-memo:(make-peer-core peer-state channel) bone plea %plea) :: +on-take-wake: receive wakeup or error notification from behn :: @@ -1923,14 +1985,14 @@ :: we shouldn't be hearing about ships we don't care about :: ?~ ship-state - ~> %slog.0^leaf/"ames: breach unknown {}" + ~> %slog.0^leaf/"ames: breach unknown {}" event-core :: if an alien breached, this doesn't affect us :: ?: ?=([~ %alien *] ship-state) - ~> %slog.0^leaf/"ames: breach alien {}" + ~> %slog.0^leaf/"ames: breach alien {}" event-core - ~> %slog.0^leaf/"ames: breach peer {}" + ~> %slog.0^leaf/"ames: breach peer {}" :: a peer breached; drop messaging state :: =/ =peer-state +.u.ship-state @@ -2063,6 +2125,8 @@ =. event-core %+ reel messages.todos |= [[=^duct =plea] core=_event-core] + ?: ?=(%$ -.plea) + (on-cork:core(duct duct) ship) (on-plea:core(duct duct) ship plea) :: apply outgoing packet blobs :: @@ -2141,10 +2205,27 @@ :: (emit unix-duct.ames-state %give %turf turfs) :: +on-vega: handle kernel reload - :: +on-trim: handle request to free memory :: ++ on-vega event-core - ++ on-trim event-core + :: +on-trim: handle request to free memory + :: + :: %ruin comets not seen for six months + :: + ++ on-trim + ^+ event-core + =; rui=(set @p) + (emit duct %pass /ruin %j %ruin rui) + =- (silt (turn - head)) + %+ skim + ~(tap by peers.ames-state) + |= [=ship s=ship-state] + ?. &(?=(%known -.s) =(%pawn (clan:title ship))) %.n + ?& (gth (sub now ~d180) last-contact.qos.s) + :: + %- ~(any by snd.s) + |= m=message-pump-state + !=(~ unsent-fragments.m) + == :: +enqueue-alien-todo: helper to enqueue a pending request :: :: Also requests key and life from Jael on first request. @@ -2590,12 +2671,12 @@ =(~ unsent-fragments.pum) =(~ live.packet-pump-state.pum) == - ~> %slog.0^leaf/"ames: bad pump state {<[her.channel i.boz]>}" + ~> %slog.0^leaf/"ames: bad pump state {}" $(boz t.boz) :: no outstanding messages, so send a new %cork :: :: TODO use +trace - ~> %slog.0^leaf/"ames: recork {<[her.channel i.boz]>}" + ~> %slog.0^leaf/"ames: recork {}" =/ =plea [%$ /flow [%cork ~]] (on-memo i.boz plea %plea) :: +got-duct: look up $duct by .bone, asserting already bound @@ -2768,11 +2849,18 @@ :: (emit [/ames]~ %pass wire %b %rest next-wake) =/ nax-bone=^bone (mix 0b10 bone) + =? peer-core (~(has by snd.peer-state) nax-bone) + %. peer-core + %+ trace odd.veb + =/ dat [her.channel bone=nax-bone message-num=message-num -.task] + |.("remove naxplanation flow {}") =. peer-state =, peer-state %_ peer-state + :: preemptively delete nax flows (e.g. nacks for initial %watches) + :: + snd (~(del by (~(del by snd) bone)) nax-bone) rcv (~(del by rcv) bone) - snd (~(del by snd) bone) corked (~(put in corked) bone) closing (~(del in closing) bone) krocs (~(del in krocs) bone) @@ -3196,9 +3284,14 @@ ++ packet-queue %- (ordered-map live-packet-key live-packet-val) lte-packets + :: +live-packets: number of sent packets awaiting ack + :: + ++ live-packets + ^- @ud + ~(wyt by live.state) :: +gauge: inflate a |pump-gauge to track congestion control :: - ++ gauge (make-pump-gauge now.channel metrics.state [her bug]:channel) + ++ gauge (make-pump-gauge metrics.state live-packets [now her bug]:channel) :: +work: handle $packet-pump-task request :: ++ work @@ -3253,7 +3346,7 @@ =? packet-pump ?=(^ static-fragment) %- %+ trace snd.veb =/ nums [message-num fragment-num]:u.static-fragment.res - |.("dead {}") + |.("dead {}") (give %send u.static-fragment.res) packet-pump :: @@ -3312,7 +3405,6 @@ :: update .live and .metrics :: =. live.state (gas:packet-queue live.state send-list) - =. metrics.state (on-sent:gauge (lent send-list)) :: TMI :: => .(sent `(list static-fragment)`sent) @@ -3374,7 +3466,7 @@ =(0 (mod counter.metrics.state 20)) == same - (trace snd.veb |.("send: {<[fragment=fragment-num show:gauge]>}")) + (trace snd.veb |.("send: {}")) :: .resends is backward, so fold backward and emit :: =. packet-pump @@ -3398,7 +3490,7 @@ == ^- [new-val=(unit live-packet-val) stop=? _acc] :: - =/ gauge (make-pump-gauge now.channel metrics.acc [her bug]:channel) + =/ gauge (make-pump-gauge metrics.acc live-packets [now her bug]:channel) :: is this the acked packet? :: ?: =(key [message-num fragment-num]) @@ -3433,7 +3525,7 @@ =- =. metrics.state metrics.- =. live.state live.- :: - %- (trace snd.veb |.("done {}")) + %- (trace snd.veb |.("done {}")) (fast-resend-after-ack message-num `fragment-num`0) :: ^+ [metrics=metrics.state live=live.state] @@ -3445,7 +3537,7 @@ == ^- [new-val=(unit live-packet-val) stop=? pump-metrics] :: - =/ gauge (make-pump-gauge now.channel metrics [her bug]:channel) + =/ gauge (make-pump-gauge metrics live-packets [now her bug]:channel) :: if we get an out-of-order ack for a message, skip until it :: ?: (lth message-num.key message-num) @@ -3493,9 +3585,10 @@ :: +make-pump-gauge: construct |pump-gauge congestion control core :: ++ make-pump-gauge - |= [now=@da pump-metrics =ship =bug] + |= [pump-metrics live-packets=@ud now=@da =ship =bug] + :: TODO rename live-packets num-live =* veb veb.bug - =* metrics +<+< + =* metrics +<- |% ++ trace |= [verb=? print=(trap tape)] @@ -3515,15 +3608,7 @@ :: ++ num-slots ^- @ud - (sub-safe cwnd num-live) - :: +on-sent: adjust metrics based on sending .num-sent fresh packets - :: - ++ on-sent - |= num-sent=@ud - ^- pump-metrics - :: - =. num-live (add num-live num-sent) - metrics + (sub-safe cwnd live-packets) :: +on-ack: adjust metrics based on a packet getting acknowledged :: ++ on-ack @@ -3531,7 +3616,6 @@ ^- pump-metrics :: =. counter +(counter) - =. num-live (dec num-live) :: if below congestion threshold, add 1; else, add avg. 1 / cwnd :: =. cwnd @@ -3571,7 +3655,7 @@ :: =? cwnd !in-recovery (max 2 (div cwnd 2)) %- %+ trace snd.veb - |.("skip {<[resend=resend in-recovery=in-recovery show]>}") + |.("skip {}") metrics :: +on-timeout: (re)enter slow-start mode on packet loss :: @@ -3597,12 +3681,12 @@ (lth cwnd ssthresh) :: +in-recovery: %.y iff we're recovering from a skipped packet :: - :: We finish recovering when .num-live finally dips back down to + :: We finish recovering when .live-packets finally dips back down to :: .cwnd. :: ++ in-recovery ^- ? - (gth num-live cwnd) + (gth live-packets cwnd) :: +sub-safe: subtract with underflow protection :: ++ sub-safe @@ -3619,7 +3703,7 @@ rttvar=(div rttvar ms) ssthresh=ssthresh cwnd=cwnd - num-live=num-live + num-live=live-packets counter=counter == -- @@ -3665,7 +3749,7 @@ :: ?: (gte seq (add 10 last-acked.state)) %- %+ trace odd.veb - |.("future %hear {}") + |.("future %hear {}") message-sink :: =/ is-last-fragment=? =(+(fragment-num) num-fragments) @@ -3676,7 +3760,7 @@ :: single packet ack :: %- %+ trace rcv.veb - |.("send dupe ack {}") + |.("send dupe ack {}") (give %send seq %& fragment-num) :: whole message (n)ack :: @@ -3696,8 +3780,8 @@ %- %+ trace rcv.veb |. ^- tape =/ data - :* her.channel seq=seq bone=bone - fragment-num=fragment-num num-fragments=num-fragments + :* her.channel seq=seq bone=bone.shut-packet + fragment-num num-fragments la=last-acked.state lh=last-heard.state == "hear last in-progress {}" @@ -3706,8 +3790,8 @@ :: %- %+ trace rcv.veb |. =/ data - :* seq=seq fragment-num=fragment-num - num-fragments=num-fragments closing=closing + :* seq=seq fragment-num + num-fragments closing=closing == "send ack-1 {}" (give %send seq %& fragment-num) @@ -3737,7 +3821,7 @@ "hear last dupe {}" message-sink %- %+ trace rcv.veb - |.("send dupe ack {}") + |.("send dupe ack {}") (give %send seq %& fragment-num) :: new fragment; store in state and check if message is done :: @@ -3754,7 +3838,7 @@ =? message-sink !is-last-fragment %- %+ trace rcv.veb |. =/ data - [seq=seq fragment-num=fragment-num num-fragments=num-fragments] + [seq=seq fragment-num num-fragments] "send ack-2 {}" (give %send seq %& fragment-num) :: enqueue all completed messages starting at +(last-heard.state) diff --git a/pkg/arvo/sys/vane/clay.hoon b/pkg/arvo/sys/vane/clay.hoon index ff2ccaf89..f9a6f5954 100644 --- a/pkg/arvo/sys/vane/clay.hoon +++ b/pkg/arvo/sys/vane/clay.hoon @@ -432,7 +432,10 @@ task :: == :: $: %d :: to %dill - $>(%flog task:dill) :: + $> $? %flog :: + %text :: + == :: + task:dill :: == :: $: %g :: to %gall $> $? %deal @@ -460,14 +463,13 @@ == == :: $: %clay :: $> $? %mere :: - %note :: %writ :: + %wris :: == :: gift :: == :: $: %gall - $> $? %onto - %unto + $> $? %unto == gift:gall == @@ -2209,7 +2211,8 @@ |= [prefix=@tD paths=(set path)] %+ turn ~(tap in paths) |= =path - [u.hun %give %note prefix (path-to-tank path)] + ^- move + [u.hun %pass /note %d %text prefix ' ' ~(ram re (path-to-tank path))] :: ++ path-to-tank |= =path @@ -5774,8 +5777,6 @@ ?^ dud ~|(%clay-take-dud (mean tang.u.dud)) ?: ?=([%lu %load *] tea) - ?: ?=(%onto +<.hin) - [~ ..^$] ?> ?=(%unto +<.hin) ?> ?=(%poke-ack -.p.hin) ?~ p.p.hin @@ -5822,6 +5823,7 @@ [mos ..^$] :: ?: ?=([%foreign-warp *] tea) + ?: ?=(%wris +<.hin) ~& %dropping-wris `..^$ ?> ?=(%writ +<.hin) :_ ..^$ [hen %give %boon `(unit rand)`(bind `riot`p.hin rant-to-rand)]~ @@ -5950,7 +5952,6 @@ q.p.p.+.hin [~ ..^$] :: - %note [[hen %give +.hin]~ ..^$] %wake :: TODO: handle behn errors :: @@ -5973,8 +5974,8 @@ :: %boon !! %lost !! - %onto !! %unto !! + %wris ~& %strange-wris !! %writ %- (slog leaf+"clay: strange writ (expected on upgrade to Fusion)" ~) [~ ..^$] diff --git a/pkg/arvo/sys/vane/dill.hoon b/pkg/arvo/sys/vane/dill.hoon index ab9f77af6..f58a73bd0 100644 --- a/pkg/arvo/sys/vane/dill.hoon +++ b/pkg/arvo/sys/vane/dill.hoon @@ -8,27 +8,26 @@ -- :: => |% :: console protocol +$ axle :: - $: %4 ::TODO replace ducts with session ids :: + $: %6 :: hey=(unit duct) :: default duct - dug=(map duct axon) :: conversations - eye=(jug duct duct) :: outside listeners + dug=(map @tas axon) :: conversations + eye=(jug @tas duct) :: outside listeners lit=? :: boot in lite mode $= veb :: vane verbosities $~ (~(put by *(map @tas log-level)) %hole %soft) :: quiet packet crashes (map @tas log-level) :: + egg=_| :: see +take, removeme == :: -+$ axon :: dill per duct ++$ axon :: dill session $: ram=term :: console program tem=(unit (list dill-belt)) :: pending, reverse wid=_80 :: terminal width - pos=@ud :: cursor position - see=$%([%lin (list @c)] [%klr stub]) :: current line == :: +$ log-level ?(%hush %soft %loud) :: none, line, full -- => :: |% :: protocol outward +$ mess :: - $% [%dill-belt p=(hypo dill-belt)] :: + $% [%dill-poke p=(hypo poke)] :: == :: +$ move [p=duct q=(wind note gift)] :: local move +$ note :: out request $-> @@ -69,7 +68,6 @@ == == :: $: %clay :: $> $? %mere :: - %note :: %writ :: == :: gift:clay :: @@ -78,10 +76,7 @@ $>(%blit gift:dill) :: == :: $: %gall :: - $> $? %onto :: - %unto :: - == :: - gift:gall :: + $>(%unto gift:gall) :: == == :: :::::::: :: dill tiles -- @@ -91,39 +86,27 @@ |% ++ as :: per cause =| moz=(list move) - |_ [hen=duct axon] + |_ [hen=duct ses=@tas axon] ++ abet :: resolve ^- [(list move) axle] - [(flop moz) all(dug (~(put by dug.all) hen +<+))] + [(flop moz) all(dug (~(put by dug.all) ses +<+>))] :: ++ call :: receive input |= kyz=task ^+ +> ?+ -.kyz ~& [%strange-kiss -.kyz] +> - %flow +> - %harm +> - %hail (send %hey ~) - %text (from %out (tuba p.kyz)) - %crud :: (send `dill-belt`[%cru p.kyz q.kyz]) - (crud p.kyz q.kyz) - %blew (send %rez p.p.kyz q.p.kyz) - %heft (pass /whey %$ whey/~) - %meld (dump kyz) - %pack (dump kyz) - %crop (dump trim+p.kyz) - %verb (pass /verb %$ kyz) - %noop +> - %belt - %- send - ::TMP forwards compatibility with next-dill - :: - ?@ p.kyz [%txt p.kyz ~] - ?: ?=(%hit -.p.kyz) [%txt ~] - ?. ?=(%mod -.p.kyz) p.kyz - =/ =@c - ?@ key.p.kyz key.p.kyz - ?:(?=(?(%bac %del %ret) -.key.p.kyz) `@`-.key.p.kyz ~-) - ?:(?=(%met mod.p.kyz) [%met c] [%ctl c]) + %hail (send %hey ~) + %belt (send `dill-belt`p.kyz) + %talk (talk p.kyz) + %text (fore (tuba p.kyz) ~) + %crud :: (send `dill-belt`[%cru p.kyz q.kyz]) + (crud p.kyz q.kyz) + %blew (send(wid p.p.kyz) %rez p.p.kyz q.p.kyz) + %heft (pass /whey %$ whey/~) + %meld (dump kyz) + %pack (dump kyz) + %crop (dump trim+p.kyz) + %verb (pass /verb %$ kyz) == :: ++ crud @@ -133,30 +116,30 @@ =/ lev=log-level (~(gut by veb.all) err %loud) :: apply log level for this error tag :: - =/ =wall - ?- lev - %hush ~ - %soft ~["crud: %{(trip err)} event failed"] - %loud :- "crud: %{(trip err)} event failed" - %- zing - %+ turn (flop tac) - |=(a=tank (~(win re a) [0 wid])) - == - |- ^+ +>.^$ - ?~ wall +>.^$ - $(wall t.wall, +>.^$ (from %out (tuba i.wall))) + ?- lev + %hush +>.$ + %soft (fore (tuba "crud: %{(trip err)} event failed") ~) + %loud (talk leaf+"crud: %{(trip err)} event failed" (flop tac)) + == + :: + ++ talk + |= tac=(list tank) + %- fore + %- zing + %+ turn tac + |= a=tank + (turn (~(win re a) [0 wid]) tuba) :: ++ dump :: pass down to hey |= git=gift ?> ?=(^ hey.all) +>(moz [[u.hey.all %give git] moz]) :: - ++ done :: return gift + ++ done :: gift to viewers |= git=gift =- +>.$(moz (weld - moz)) %+ turn - :- hen - ~(tap in (~(get ju eye.all) hen)) + ~(tap in (~(get ju eye.all) ses)) |=(=duct [duct %give git]) :: ++ deal :: pass to %gall @@ -167,44 +150,37 @@ |= [=wire =note] +>(moz :_(moz [hen %pass wire note])) :: + ++ fore :: send dill output + ::NOTE there are still implicit assumptions + :: about the underlying console app's + :: semantics here. specifically, trailing + :: newlines are important to not getting + :: overwritten by the drum prompt, and a + :: bottom-of-screen cursor position gives + :: nicest results. a more agnostic solution + :: will need to replace this arm, someday. + :: perhaps +send this to .ram instead? + :: + |= liz=(list (list @c)) + ~? !=(%$ ses) [%d %foreing-in-session ses] + ^+ +> + =. +> + =| biz=(list blit) + |- ^+ +>.^$ + ?~ liz (done %blit [%hop 0] [%wyp ~] biz) + $(liz t.liz, biz (welp biz [%put i.liz] [%nel ~] ~)) + :: since dill is acting on its own accord, + :: we %hey the term app so it may clean up. + :: + (send %hey ~) + :: ++ from :: receive blit |= bit=dill-blit ^+ +> - ?: ?=(%mor -.bit) - |- ^+ +>.^$ - ?~ p.bit +>.^$ - $(p.bit t.p.bit, +>.^$ ^$(bit i.p.bit)) - ?: ?=(%out -.bit) - %+ done %blit - :~ [%lin p.bit] - [%mor ~] - see - [%hop pos] - == - ?: ?=(%klr -.bit) - %+ done %blit - :~ [%klr p.bit] - [%mor ~] - see - [%hop pos] - == - ?: ?=(%pro -.bit) - =. see [%lin p.bit] - (done %blit [see [%hop pos] ~]) - ?: ?=(%pom -.bit) - ::NOTE treat "styled prompt" without style as plain prompt, - :: to allow rendering by older runtimes - ::TODO remove me once v0.10.9+ has high/guaranteed adoption - :: - ?: (levy p.bit (cork head |*(s=stye =(*stye s)))) - $(bit [%pro (zing (turn p.bit tail))]) - =. see [%klr p.bit] - (done %blit [see [%hop pos] ~]) - ?: ?=(%hop -.bit) - (done(pos p.bit) %blit [bit ~]) ?: ?=(%qit -.bit) (dump %logo ~) - (done %blit [bit ~]) + ::TODO so why is this a (list blit) again? + (done %blit bit ~) :: ++ sponsor ^- ship @@ -221,7 +197,7 @@ =. tem ~ =. ..mere (pass /zest %c %zest %base %live) =. ..mere (show-desk %kids) - =. ..mere drum-watch + =. ..mere (open ~) |- ^+ ..mere ?~ myt ..mere $(myt t.myt, ..mere (send i.myt)) @@ -231,15 +207,27 @@ =. tem `(turn gyl |=(a=gill [%yow a])) (pass / [%c %warp our %base `[%sing %y [%ud 1] /]]) :: + ++ open + |= gyl=(list gill) + ::TODO should allow handlers from non-base desks + ::TODO maybe ensure :ram is running? + =. +> peer + %+ roll gyl + |= [g=gill _..open] + (send [%yow g]) + :: ++ send :: send action |= bet=dill-belt ^+ +> ?^ tem +>(tem `[bet u.tem]) - (deal / [%poke [%dill-belt -:!>(bet) bet]]) + (deal /send/[ses] [%poke [%dill-poke !>([ses bet])]]) :: - ++ drum-watch - (deal / [%watch /drum]) + ++ peer + (deal /peer/[ses] %watch /dill/[ses]) + :: + ++ pull + (deal /peer/[ses] %leave ~) :: ++ show-desk :: permit reads on desk |= des=desk @@ -249,21 +237,11 @@ |= [tea=wire sih=sign] ^+ +> ?- sih - [%gall %onto *] - :: NOTE effects during initial boot sequence are ignored, - :: so :hood compilation errors will not print; slog if desired - :: - :: ~& [%take-gall-onto +>.sih] - ?- -.+>.sih - %| (crud %onto p.p.+>.sih) - %& (done %blit [%lin (tuba "{}")]~) - == - :: [%gall %unto *] :: ~& [%take-gall-unto +>.sih] ?- -.+>.sih %raw-fact !! - %kick drum-watch + %kick peer %poke-ack ?~(p.p.+>.sih +>.$ (crud %coup u.p.p.+>.sih)) %watch-ack ?~ p.p.+>.sih @@ -275,9 +253,6 @@ +>.$ (from ;;(dill-blit q.q.cage.p.+>.sih)) == - :: - [%clay %note *] - (from %out (tuba p.sih ' ' ~(ram re q.sih))) :: [?(%behn %clay) %writ *] init @@ -292,12 +267,20 @@ == -- :: - ++ ax :: make ++as - |= hen=duct + ++ ax :: make ++as from name + |= [hen=duct ses=@tas] ^- (unit _as) - =/ nux (~(get by dug.all) hen) + =/ nux (~(get by dug.all) ses) ?~ nux ~ - (some ~(. as hen u.nux)) + (some ~(. as hen ses u.nux)) + :: + ++ aw :: make ++as from wire + |= [hen=duct wir=wire] + ^- (unit _as) + %+ ax hen + ?+ wir %$ + [?(%peer %send) @ *] i.t.wir + == -- |% :: poke+peek pattern ++ call :: handle request @@ -308,7 +291,10 @@ ^+ [*(list move) ..^$] ~| wrapped-task =/ task=task ((harden task) wrapped-task) + :: unwrap session tasks, default to session %$ :: + =^ ses=@tas task + ?:(?=(%shot -.task) +.task [%$ task]) :: error notifications "downcast" to %crud :: =? task ?=(^ dud) @@ -338,10 +324,11 @@ :: =* duc (need hey.all) =/ app %hood - =/ see (tuba "") - =/ zon=axon [app input=[~ ~] width=80 cursor=(lent see) lin+see] + =/ say (tuba "") + =/ zon=axon [app input=[~ ~] width=80] :: - =^ moz all abet:(~(into as duc zon) ~) + =^ moz all abet:(~(into as duc %$ zon) ~) + =. eye.all (~(put ju eye.all) %$ duc) [moz ..^$] :: %flog tasks are unwrapped and sent back to us on our default duct :: @@ -362,35 +349,60 @@ ?: ?=(%knob -.task) =. veb.all (~(put by veb.all) tag.task level.task) [~ ..^$] + :: %open opens a new dill session + :: + ?: ?=(%open -.task) + ?: (~(has by dug.all) ses) + ::TODO should we allow, and just send the %yow blits? + ~| [%cannot-open-existing ses] + !! + =/ zon=axon [p.task ~ width=80] + =^ moz all abet:(~(open as hen ses zon) q.task) + =. eye.all (~(put ju eye.all) ses hen) + [moz ..^$] + :: %shut closes an existing dill session + :: + ?: ?=(%shut -.task) + ?: =(%$ ses) + ~| %cannot-shut-default-session + !! + =/ nus + ~| [%no-session ses] + (need (ax hen ses)) + ::NOTE we do deletion from state outside of the core, + :: because +abet would re-insert. + ::TODO send a %bye blit? xx + =^ moz all abet:pull:nus + =. dug.all (~(del by dug.all) ses) + =. eye.all (~(del by eye.all) ses) + [moz ..^$] + :: %view opens a subscription to the target session, on the current duct :: ?: ?=(%view -.task) - :: crash on viewing non-existent session + =/ nus + :: crash on viewing non-existent session + :: + ~| [%no-session ses] + (need (ax hen ses)) + :: register the viewer and send a %hey so they get the full screen :: - ~| [%no-session session.task] - ?> =(~ session.task) - =/ session (need hey.all) - =/ =axon (~(got by dug.all) session) - :: register the viewer and send them the prompt line - :: - :- [hen %give %blit [see.axon]~]~ - ..^$(eye.all (~(put ju eye.all) session hen)) + =^ moz all + abet:(send:nus %hey ~) + :- moz + ..^$(eye.all (~(put ju eye.all) ses hen)) + :: %flee closes a subscription to the target session, from the current duct :: ?: ?=(%flee -.task) :- ~ - ~| [%no-session session.task] - ?> =(~ session.task) - =/ session (need hey.all) - ..^$(eye.all (~(del ju eye.all) session hen)) + ..^$(eye.all (~(del ju eye.all) ses hen)) :: - =/ nus (ax hen) - =? nus &(?=(~ nus) ?=(^ hey.all)) - ::TODO allow specifying target session in task - (ax u.hey.all) + =/ nus + (ax hen ses) ?~ nus - :: :hen is an unrecognized duct + :: session :ses does not exist :: could be before %boot (or %boot failed) :: - ~& [%dill-call-no-flow hen -.task] + ~& [%dill-call-no-session ses hen -.task] =/ tan ?:(?=(%crud -.task) q.task ~) [((slog (flop tan)) ~) ..^$] :: @@ -398,8 +410,79 @@ [moz ..^$] :: ++ load :: import old state - |= old=axle - ..^$(all old) + =< |= old=any-axle + ?- -.old + %6 ..^$(all old) + %5 $(old (axle-5-to-6 old)) + %4 $(old (axle-4-to-5 old)) + == + |% + +$ any-axle $%(axle axle-5 axle-4) + :: + +$ axle-5 + $: %5 + hey=(unit duct) :: default duct + dug=(map @tas axon) :: conversations + eye=(jug @tas duct) :: outside listeners + lit=? :: boot in lite mode + veb=(map @tas log-level) + == + :: + ++ axle-5-to-6 + |= a=axle-5 + ^- axle + :: [%6 hey `(map @tas axon)`dug eye lit veb |] + a(- %6, veb [veb.a &]) + :: + +$ axle-4 + $: %4 + hey=(unit duct) + dug=(map duct axon-4) + eye=(jug duct duct) + lit=? + veb=(map @tas log-level) + == + :: + +$ axon-4 + $: ram=term + tem=(unit (list dill-belt-4)) + wid=_80 + pos=$@(@ud [@ud @ud]) + see=$%([%lin (list @c)] [%klr stub]) + == + :: + +$ dill-belt-4 + $% [%ctl p=@c] + [%met p=@c] + dill-belt + == + :: + ++ axle-4-to-5 + |= axle-4 + ^- axle-5 + :- %5 + =- [hey nug nay lit veb] + %+ roll ~(tap by dug) + |= [[=duct =axon-4] nug=(map @tas axon) nay=(jug @tas duct)] + =/ ses=@tas + ~| [%unexpected-duct duct] + ?>(=([//term/1]~ duct) %$) + :- (~(put by nug) ses (axon-4-to-5 axon-4)) + %+ ~(put by nay) ses + (~(put in (~(get ju eye) duct)) duct) + :: + ++ axon-4-to-5 + |= axon-4 + ^- axon + =; tem [ram tem wid] + ?~ tem ~ + %- some + %+ turn u.tem + |= b=dill-belt-4 + ^- dill-belt + ?. ?=(?(%ctl %met) -.b) b + [%mod -.b p.b] + -- :: ++ scry ^- roon @@ -428,19 +511,12 @@ =(%$ syd) == ~ - :: /dx/sessions//line blit current line (prompt) of default session - :: /dx/sessions//cursor @ud current cursor position of default session - ::TODO support asking for specific sessions once session ids are real + :: /dy/sessions (set @tas) all existing sessions + :: /du/sessions/[ses] ? does session ses exist? :: - ?. ?=(%x ren) ~ - ?+ tyl ~ - [%sessions %$ *] - ?~ hey.all [~ ~] - ?~ session=(~(get by dug.all) u.hey.all) [~ ~] - ?+ t.t.tyl ~ - [%line ~] ``blit+!>(`blit`see.u.session) - [%cursor ~] ``atom+!>(pos.u.session) - == + ?+ [ren tyl] ~ + [%y %sessions ~] ``noun+!>(~(key by dug.all)) + [%u %sessions @ ~] ``noun+!>((~(has by dug.all) (snag 1 tyl))) == :: ++ stay all @@ -451,12 +527,27 @@ ?^ dud ~|(%dill-take-dud (mean tang.u.dud)) :: - =/ nus (ax hen) + =; [moz=(list move) lax=_..^$] + =? moz egg.all.lax + :: dill pre-release (version %5) in some cases ended up in a state + :: where it had both an old-style and new-style subscription open + :: for the default session. here, we obliterate both and establish + :: only the new-style subscription. + :: + =/ hey (need hey.all.lax) + :* [hey %pass / %g %deal [our our] %hood %leave ~] + [hey %pass [%peer %$ ~] %g %deal [our our] %hood %leave ~] + [hey %pass [%peer %$ ~] %g %deal [our our] %hood %watch [%dill %$ ~]] + moz + == + =. egg.all.lax | + [moz lax] + :: + =/ nus (aw hen tea) ?~ nus - :: :hen is an unrecognized duct - :: could be before %boot (or %boot failed) + :: :tea points to an unrecognized session :: - ~& [%dill-take-no-flow hen -.hin +<.hin] + ~& [%dill-take-no-session tea -.hin +<.hin] [~ ..^$] =^ moz all abet:(take:u.nus tea hin) [moz ..^$] diff --git a/pkg/arvo/sys/vane/gall.hoon b/pkg/arvo/sys/vane/gall.hoon index 842d9d356..8ce10c655 100644 --- a/pkg/arvo/sys/vane/gall.hoon +++ b/pkg/arvo/sys/vane/gall.hoon @@ -198,11 +198,21 @@ :: +mo-abet: finalize, reversing moves :: +mo-pass: prepend a standard %pass to the current list of moves :: +mo-give: prepend a standard %give to the current list of moves + :: +mo-talk: build task to print config report or failure trace :: ++ mo-core . ++ mo-abed |=(hun=duct mo-core(hen hun)) ++ mo-abet [(flop moves) gall-payload] ++ mo-give |=(g=gift mo-core(moves [[hen give+g] moves])) + ++ mo-talk + |= rup=(each suss tang) + ^- [wire note-arvo] + :+ /sys/say %d + ^- task:dill + ?- -.rup + %& [%text "gall: {(t q)}ed %{(t p)}":[t=trip p.rup]] + %| [%talk leaf+"gall: failed" (flop p.rup)] + == ++ mo-pass |=(p=[wire note-arvo] mo-core(moves [[hen pass+p] moves])) ++ mo-slip |=(p=note-arvo mo-core(moves [[hen slip+p] moves])) ++ mo-past @@ -303,12 +313,12 @@ =/ ap-core +.wag ?^ maybe-tang =. mo-core old - (mo-give %onto %.n u.maybe-tang) + (mo-pass (mo-talk %.n u.maybe-tang)) :: =. mo-core ap-abet:ap-core =. mo-core (mo-clear-queue dap) =/ =suss [dap %boot now] - (mo-give %onto [%.y suss]) + (mo-pass (mo-talk %.y suss)) :: +mo-send-foreign-request: handle local request to .ship :: ++ mo-send-foreign-request @@ -523,6 +533,11 @@ ?~ error=error.sign-arvo ~ `[[%leaf (trip tag.u.error)] tang.u.error] + :: send a %cork if we get a nack upon initial subscription + :: + =? mo-core + &(?=(^ err) |(?=(%watch-as remote-request) ?=(%watch remote-request))) + (mo-pass [%sys wire] %a %cork ship) :: ?- remote-request %watch-as (mo-give %unto %watch-ack err) @@ -899,8 +914,8 @@ :: =/ running (~(put by yokes.state) agent-name yoke) =/ moves - =/ giver |=(report=(each suss tang) [hen %give %onto report]) - =/ from-suss (turn agent-config giver) + =/ talker |=(report=(each suss tang) [hen %pass (mo-talk report)]) + =/ from-suss (turn agent-config talker) :(weld agent-moves from-suss moves) :: %_ mo-core diff --git a/pkg/arvo/sys/vane/jael.hoon b/pkg/arvo/sys/vane/jael.hoon index 69596a5c3..2f1335564 100644 --- a/pkg/arvo/sys/vane/jael.hoon +++ b/pkg/arvo/sys/vane/jael.hoon @@ -105,11 +105,8 @@ $>(%wake gift:behn) :: == :: $: %gall :: - $> $? %onto :: - %unto :: - == :: - gift:gall :: - == + $>(%unto gift:gall) :: + == :: == :: -- :: :: :::: @@ -462,12 +459,12 @@ :: [%vega ~] :: %vega - +>.$:: + +>.$ + :: :: in response to memory pressure :: [%trim p=@ud] :: %trim - ::TODO consider %ruin-ing long-offline comets +>.$ :: :: watch private keys @@ -507,7 +504,7 @@ %ruin ::NOTE we blast this out to _all_ known ducts, because the common :: use case for this is comets, about who nobody cares. - =/ dus ~(key by yen.zim.pki) + =/ dus (~(uni in nel.zim.pki) ~(key by yen.zim.pki)) =/ sus ~(. su hen now pki etn) =/ sis ~(tap in ships.tac) |- @@ -550,10 +547,6 @@ =/ ships (~(get ju ship-sources-reverse.etn) source-id) %- curd =< abet (sources:~(feel su hen now pki etn) ships source) - :: - [%gall %onto *] - ~& [%jael-onto tea hin] - +>.$ :: [%gall %unto *] ?- +>-.hin @@ -736,12 +729,10 @@ ++ subscribers-on-ship |= =ship ^- (set duct) - =/ specific-subs (~(get ju ney.zim) ship) - =/ general-subs=(set duct) - ?: ?=(?(%czar %king %duke) (clan:title ship)) - nel.zim - ~ - (~(uni in specific-subs) general-subs) + :: union of general and ship-specific subs + :: + %- ~(uni in nel.zim) + (~(get ju ney.zim) ship) :: ++ feed |_ :: hen: subscription source @@ -997,7 +988,7 @@ =| lex=state-2 |= $: :: now: current time :: eny: unique entropy - :: ski: namespace resolver + :: rof: namespace resolver :: now=@da eny=@uvJ diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 7591a4087..3759ec5b5 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -4,7 +4,7 @@ => ..lull ~% %zuse ..part ~ |% -++ zuse %417 +++ zuse %415 :: :: :: :::: :: :: (2) engines :: :: :: @@ -3843,6 +3843,102 @@ ~ (some (~(run by lum) need)) -- ::dejs-soft + :: + ++ klr :: styx/stub engine + =, dill + |% + ++ make :: stub from styx + |= a=styx ^- stub + =| b=stye + %+ reel + |- ^- stub + %- zing %+ turn a + |= a=$@(@t (pair styl styx)) + ?@ a [b (tuba (trip a))]~ + ^$(a q.a, b (styd p.a b)) + :: + |= [a=(pair stye (list @c)) b=stub] + ?~ b [a ~] + ?. =(p.a p.i.b) [a b] + [[p.a (weld q.a q.i.b)] t.b] + :: + ++ styd :: stye from styl + |= [a=styl b=stye] ^+ b :: with inheritance + :+ ?~ p.a p.b + ?~ u.p.a ~ + (~(put in p.b) u.p.a) + (fall p.q.a p.q.b) + (fall q.q.a q.q.b) + :: + ++ lent-char + |= a=stub ^- @ + (roll (lnts-char a) add) + :: + ++ lnts-char :: stub text lengths + |= a=stub ^- (list @) + %+ turn a + |= a=(pair stye (list @c)) + (lent q.a) + :: + ++ brek :: index + incl-len of + |= [a=@ b=(list @)] :: stub pair w/ idx a + =| [c=@ i=@] + |- ^- (unit (pair @ @)) + ?~ b ~ + =. c (add c i.b) + ?: (gte c a) + `[i c] + $(i +(i), b t.b) + :: + ++ pact :: condense stub + |= a=stub + ^- stub + ?~ a ~ + ?~ t.a a + ?. =(p.i.a p.i.t.a) [i.a $(a t.a)] + =. q.i.t.a (weld q.i.a q.i.t.a) + $(a t.a) + :: + ++ slag :: slag stub + |= [a=@ b=stub] + ^- stub + ?: =(0 a) b + ?~ b ~ + =+ c=(lent q.i.b) + ?: =(c a) t.b + ?: (gth c a) + [[p.i.b (^slag a q.i.b)] t.b] + $(a (sub a c), b t.b) + :: + ++ scag :: scag stub + |= [a=@ b=stub] + ^- stub + ?: =(0 a) ~ + ?~ b ~ + =+ c=(lent q.i.b) + ?: (gth c a) + [p.i.b (^scag a q.i.b)]~ + :- i.b + $(a (sub a c), b t.b) + :: + ++ swag :: swag stub + |= [[a=@ b=@] c=stub] + (scag b (slag a c)) + :: + ++ wail :: overlay stub + |= [a=stub b=@ c=stub d=@c] + ^- stub + ;: weld + (scag b a) + :: + =+ e=(lent-char a) + ?: (lte b e) ~ + [*stye (reap (sub b e) d)]~ + :: + c + (slag (add b (lent-char c)) a) + == + -- :: klr -- :: |cloy: clay helpers :: @@ -4928,7 +5024,7 @@ =< q.q %- need %- need (rof ~ %j `beam`[[our %sein %da now] /(scot %p who)]) -- - :: middle core: for userspace use, with .^ + :: middle core: stateless queries for default numeric sponsorship :: => |% :: :: ++clan:title @@ -4968,7 +5064,7 @@ %pawn (end 4 who) == -- - :: surface core: stateless queries for default numeric sponsorship + :: surface core: for userspace use, with .^ :: |% :: :: ++cite:title @@ -5003,13 +5099,25 @@ %j /(scot %p our)/sein/(scot %da now)/(scot %p who) == + :: +team was created with two meanings: + :: A. her / her moon + :: B. whoever should be able to control her ship + :: + :: these two things aren't obviously equal anymore, + :: and it's more important for +team to satisfy B than A, + :: so now +team just means "her". + :: + :: (ships can definitely be trusted to control themselves) :: :: ++team:title - ++ team :: our / our moon - |= [our=ship who=ship] + ++ team :: her + |= [her=ship who=ship] ^- ? - ?| =(our who) - &(?=(%earl (clan who)) =(our (^sein who))) - == + =(her who) + :: :: ++moon:title + ++ moon :: her moon + |= [her=ship who=ship] + ^- ? + &(=(%earl (clan who)) =(her (^sein who))) -- ::title :: :: :::: ++milly :: (2k) milliseconds diff --git a/pkg/arvo/ted/aqua/dill.hoon b/pkg/arvo/ted/aqua/dill.hoon index e001a65dc..e7cb19017 100644 --- a/pkg/arvo/ted/aqua/dill.hoon +++ b/pkg/arvo/ted/aqua/dill.hoon @@ -17,15 +17,16 @@ %+ roll blits |= [b=blit:dill line=tape] ?- -.b - %lin (tape p.b) + %put (tape p.b) %klr (tape (zing (turn p.b tail))) - %mor ~& "{}: {line}" "" + %nel ~& "{}: {line}" "" %hop line %bel line %clr "" %sag ~& [%save-jamfile-to p.b] line %sav ~& [%save-file-to p.b] line %url ~& [%activate-url p.b] line + %wyp "" == ~? !=(~ last-line) last-line ~ diff --git a/pkg/base-dev/lib/agentio.hoon b/pkg/base-dev/lib/agentio.hoon index 5ab007361..aa1a9d6c8 100644 --- a/pkg/base-dev/lib/agentio.hoon +++ b/pkg/base-dev/lib/agentio.hoon @@ -93,11 +93,6 @@ (arvo %e %connect binding app) -- :: -++ fact-curry - |* [=mark =mold] - |= [paths=(list path) fac=mold] - (fact mark^!>(fac) paths) -:: ++ fact-kick |= [=path =cage] ^- (list card) diff --git a/pkg/base-dev/lib/bitcoin-utils.hoon b/pkg/base-dev/lib/bitcoin-utils.hoon index 648fb781b..a23354c58 100644 --- a/pkg/base-dev/lib/bitcoin-utils.hoon +++ b/pkg/base-dev/lib/bitcoin-utils.hoon @@ -143,6 +143,7 @@ |= a=@ ^- hexb =/ l=@ (met 3 a) + ?: =(l 0) 1^a ?: =(l 1) 1^a ?: =(l 2) (cat:byt ~[1^0xfd (flip:byt 2^a)]) ?: (lte l 4) (cat:byt ~[1^0xfe (flip:byt 4^a)]) @@ -162,7 +163,7 @@ %0xfe 2 %0xff 3 == - :_ (drop:byt (add 1 len) h) + :_ (drop:byt (add 1 (bex len)) h) %- flip:byt (take:byt (bex len) (drop:byt 1 h)) :: +dea: atom instead of hexb for parsed CompactSize diff --git a/pkg/base-dev/lib/dill.hoon b/pkg/base-dev/lib/dill.hoon new file mode 100644 index 000000000..41608b263 --- /dev/null +++ b/pkg/base-dev/lib/dill.hoon @@ -0,0 +1,94 @@ +:: dill: utilities for dill's data structures +:: +=, dill +|% +++ enjs + |% + ++ blit + |= =blit:dill + ^- json + =, enjs:format + %+ frond -.blit + ?- -.blit + %bel b+& + %clr b+& + %hop ?@ p.blit (numb p.blit) + (pairs 'x'^(numb x.p.blit) 'y'^(numb y.p.blit) ~) + %put a+(turn p.blit |=(c=@c s+(tuft c))) + %nel b+& + %url s+p.blit + %wyp b+& + %mor a+(turn p.blit ^blit) + :: + %sag + %- pairs + :~ 'path'^(path p.blit) + 'file'^s+(en:base64:mimes:html (as-octs:mimes:html (jam q.blit))) + == + :: + %sav + %- pairs + :~ 'path'^(path p.blit) + 'file'^s+(en:base64:mimes:html (as-octs:mimes:html q.blit)) + == + :: + %klr + :- %a + %+ turn p.blit + |= [=stye text=(list @c)] + %- pairs + :~ 'text'^a+(turn text |=(c=@c s+(tuft c))) + :: + :- 'stye' + %- pairs + |^ :~ 'back'^(color p.q.stye) + 'fore'^(color q.q.stye) + 'deco'^a+(turn ~(tap in p.stye) |=(d=deco ?~(d ~ s+d))) + == + ++ color + |= =tint + ?@ tint ?~(tint ~ s+tint) + =, tint + (pairs r+(numb r) g+(numb g) b+(numb b) ~) + -- + == + == + -- +:: +++ dejs + |% + ++ belt + |= jon=json + ^- belt:dill + ?: ?=([%s *] jon) + (taft p.jon) + =, dejs:format + %. jon + %- of + |^ :* mod+(ot 'mod'^mod 'key'^bot ~) + txt+(ar (cu taft so)) + bol + == + :: + ++ bol + :~ aro+(su (perk %d %l %r %u ~)) + bac+ul + del+ul + hit+(ot 'x'^ni 'y'^ni ~) + ret+ul + == + :: + ++ bot + |= j=json + ^- bolt:dill + ?+ j !! + [%s *] (taft p.j) + [%o *] ((of bol) j) + == + :: + ++ mod + |= j=json + ((su (perk %ctl %met %hyp ~)) j) + -- + -- +-- \ No newline at end of file diff --git a/pkg/base-dev/lib/language-server/complete.hoon b/pkg/base-dev/lib/language-server/complete.hoon index 56b3ca498..95ec07af7 100644 --- a/pkg/base-dev/lib/language-server/complete.hoon +++ b/pkg/base-dev/lib/language-server/complete.hoon @@ -3,7 +3,8 @@ :: =/ debug | |% -+* option [item] +++ option + |$ [item] [term=cord detail=item] :: :: Like +rose except also produces line number diff --git a/pkg/base-dev/lib/ph/util.hoon b/pkg/base-dev/lib/ph/util.hoon index eee08a2ac..f4b53ceb6 100644 --- a/pkg/base-dev/lib/ph/util.hoon +++ b/pkg/base-dev/lib/ph/util.hoon @@ -28,8 +28,8 @@ %+ send-events-to who ^- (list unix-event) :~ - [/d/term/1 %belt %ctl `@c`%e] - [/d/term/1 %belt %ctl `@c`%u] + [/d/term/1 %belt %mod %ctl `@c`%e] + [/d/term/1 %belt %mod %ctl `@c`%u] [/d/term/1 %belt %txt ((list @c) what)] [/d/term/1 %belt %ret ~] == @@ -40,7 +40,7 @@ |= [who=ship what=term] ^- (list ph-event) %+ send-events-to who - :~ [/d/term/1 %belt %ctl (,@c what)] + :~ [/d/term/1 %belt %mod %ctl (,@c what)] == :: :: Inject a file into a ship @@ -67,7 +67,7 @@ :: %+ lien p.q.uf |= =blit:dill - ?. ?=(%lin -.blit) + ?. ?=(%put -.blit) | !=(~ (find what p.blit)) == diff --git a/pkg/base-dev/lib/shoe.hoon b/pkg/base-dev/lib/shoe.hoon index cd4ab18db..856a4d782 100644 --- a/pkg/base-dev/lib/shoe.hoon +++ b/pkg/base-dev/lib/shoe.hoon @@ -13,15 +13,15 @@ /- *sole /+ sole, auto=language-server-complete |% -+$ state-0 - $: %0 - soles=(map @ta sole-share) ++$ state-1 + $: %1 + soles=(map sole-id sole-share) == :: $card: standard gall cards plus shoe effects :: +$ card $% card:agent:gall - [%shoe sole-ids=(list @ta) effect=shoe-effect] :: ~ sends to all soles + [%shoe sole-ids=(list sole-id) effect=shoe-effect] :: ~ sends to all == :: $shoe-effect: easier sole-effects :: @@ -47,30 +47,30 @@ :: if the head of the result is true, instantly run the command :: ++ command-parser - |~ sole-id=@ta + |~ =sole-id |~(nail *(like [? command-type])) :: +tab-list: autocomplete options for the session (to match +command-parser) :: ++ tab-list - |~ sole-id=@ta + |~ =sole-id :: (list [@t tank]) *(list (option:auto tank)) :: +on-command: called when a valid command is run :: ++ on-command - |~ [sole-id=@ta command=command-type] + |~ [=sole-id command=command-type] *(quip card _^|(..on-init)) :: ++ can-connect - |~ sole-id=@ta + |~ =sole-id *? :: ++ on-connect - |~ sole-id=@ta + |~ =sole-id *(quip card _^|(..on-init)) :: ++ on-disconnect - |~ sole-id=@ta + |~ =sole-id *(quip card _^|(..on-init)) :: ::NOTE standard gall agent arms below, though they may produce %shoe cards @@ -119,27 +119,27 @@ |* [shoe=* command-type=mold] |_ =bowl:gall ++ command-parser - |= sole-id=@ta + |= =sole-id (easy *[? command-type]) :: ++ tab-list - |= sole-id=@ta + |= =sole-id ~ :: ++ on-command - |= [sole-id=@ta command=command-type] + |= [=sole-id command=command-type] [~ shoe] :: ++ can-connect - |= sole-id=@ta + |= =sole-id (team:title [our src]:bowl) :: ++ on-connect - |= sole-id=@ta + |= =sole-id [~ shoe] :: ++ on-disconnect - |= sole-id=@ta + |= =sole-id [~ shoe] -- :: +agent: creates wrapper core that handles sole events and calls shoe arms @@ -147,7 +147,7 @@ ++ agent |* command-type=mold |= =(shoe command-type) - =| state-0 + =| state-1 =* state - ^- agent:gall => @@ -164,8 +164,7 @@ %+ turn ?^ sole-ids.card sole-ids.card ~(tap in ~(key by soles)) - |= sole-id=@ta - /sole/[sole-id] + id-to-path:sole :: %table =; fez=(list sole-effect) @@ -202,9 +201,36 @@ ?. ?=([%shoe-app ^] q.old-state) =^ cards shoe (on-load:og old-state) [(deal cards) this] - =^ old-inner state +:!<([%shoe-app vase state-0] old-state) - =^ cards shoe (on-load:og old-inner) - [(deal cards) this] + |^ =| old-outer=state-any + =^ old-inner old-outer + +:!<([%shoe-app vase state-any] old-state) + :: ~! q.old-state + :: ?+ +>.q.old-state !! + :: [%0 *] +:!<([%shoe-app vase state-0] old-state) + :: [%1 *] +:!<([%shoe-app vase state-1] old-state) + :: == + =^ caz shoe (on-load:og old-inner) + =^ cuz old-outer + ?. ?=(%0 -.old-outer) [~ old-outer] + (state-0-to-1 old-outer) + ?> ?=(%1 -.old-outer) + [(weld cuz (deal caz)) this(state old-outer)] + :: + +$ state-any $%(state-1 state-0) + +$ state-0 [%0 soles=(map @ta sole-share)] + ++ state-0-to-1 + |= old=state-0 + ^- (quip card:agent:gall state-1) + :- %+ turn ~(tap in ~(key by soles.old)) + |= id=@ta + ^- card:agent:gall + [%give %kick ~[/sole/[id]] ~] + :- %1 + %- ~(gas by *(map sole-id sole-share)) + %+ murn ~(tap by soles.old) + |= [id=@ta s=sole-share] + (bind (upgrade-id:sole id) (late s)) + -- :: ++ on-poke |= [=mark =vase] @@ -326,19 +352,18 @@ ++ on-watch |= =path ^- (quip card:agent:gall agent:gall) - ?. ?=([%sole @ ~] path) + ?~ sole-id=(path-to-id:sole path) =^ cards shoe (on-watch:og path) [(deal cards) this] - =* sole-id i.t.path - ?> (can-connect:og sole-id) - =. soles (~(put by soles) sole-id *sole-share) + ?> (can-connect:og u.sole-id) + =. soles (~(put by soles) u.sole-id *sole-share) =^ cards shoe - (on-connect:og sole-id) + (on-connect:og u.sole-id) :_ this %- deal :_ cards - [%shoe [sole-id]~ %sole %pro & dap.bowl "> "] + [%shoe [u.sole-id]~ %sole %pro & dap.bowl "> "] :: ++ on-leave |= =path diff --git a/pkg/base-dev/lib/sole.hoon b/pkg/base-dev/lib/sole.hoon index 66684668a..ad6b74962 100644 --- a/pkg/base-dev/lib/sole.hoon +++ b/pkg/base-dev/lib/sole.hoon @@ -136,4 +136,28 @@ =+ dat=(transmute [%mor leg] [%ins pos `@c`0]) ?> ?=(%ins -.dat) p.dat +:: +:: +++ path-to-id + |= =path + ^- (unit sole-id) + ?. ?=([%sole @ ?(~ [@ ~])] path) ~ + ?~ who=(slaw %p i.t.path) ~ + `[u.who ?~(t.t.path %$ i.t.t.path)] +:: +++ id-to-path + |= sole-id + ^- path + ::TODO this whole "no empty path ending" business feels icky. + :: do we want default session to be ~.~ ? + :: concern here is that outsiders cannot subscribe to the default + :: session, because /sole/~zod/ isn't a valid path... + [%sole (scot %p who) ?~(ses ~ /[ses])] +:: +++ upgrade-id + |= old=@ta + ^- (unit sole-id) + %+ rush old + %+ cook (late %$) + ;~(pfix (jest 'drum_~') fed:ag) -- diff --git a/pkg/base-dev/mar/belt.hoon b/pkg/base-dev/mar/belt.hoon index 1c5a6e1ea..acbf284c9 100644 --- a/pkg/base-dev/mar/belt.hoon +++ b/pkg/base-dev/mar/belt.hoon @@ -1,5 +1,7 @@ :: belt: runtime belt structure :: +/+ dill +:: |_ =belt:dill ++ grad %noun :: +grab: convert from @@ -7,18 +9,7 @@ ++ grab |% ++ noun belt:dill - ++ json - ^- $-(^json belt:dill) - =, dejs:format - %- of - :~ aro+(su (perk %d %l %r %u ~)) - bac+ul - ctl+(cu taft so) - del+ul - met+(cu taft so) - ret+ul - txt+(ar (cu taft so)) - == + ++ json belt:dejs:dill -- :: +grow: convert to :: diff --git a/pkg/base-dev/mar/blit.hoon b/pkg/base-dev/mar/blit.hoon index 4c23c5705..4b852aa60 100644 --- a/pkg/base-dev/mar/blit.hoon +++ b/pkg/base-dev/mar/blit.hoon @@ -1,5 +1,7 @@ :: blit: runtime blit structure :: +/+ dill +:: |_ =blit:dill ++ grad %noun :: +grab: convert from @@ -13,49 +15,6 @@ ++ grow |% ++ noun blit - ++ json - ^- ^json - =, enjs:format - %+ frond -.blit - ?- -.blit - %bel b+& - %clr b+& - %hop (numb p.blit) - %lin a+(turn p.blit |=(c=@c s+(tuft c))) - %mor b+& - %url s+p.blit - :: - %sag - %- pairs - :~ 'path'^(path p.blit) - 'file'^s+(en:base64:mimes:html (as-octs:mimes:html (jam q.blit))) - == - :: - %sav - %- pairs - :~ 'path'^(path p.blit) - 'file'^s+(en:base64:mimes:html (as-octs:mimes:html q.blit)) - == - :: - %klr - :- %a - %+ turn p.blit - |= [=stye text=(list @c)] - %- pairs - :~ 'text'^a+(turn text |=(c=@c s+(tuft c))) - :: - :- 'stye' - %- pairs - |^ :~ 'back'^(color p.q.stye) - 'fore'^(color q.q.stye) - 'deco'^a+(turn ~(tap in p.stye) |=(d=deco ?~(d ~ s+d))) - == - ++ color - |= =tint - ?@ tint ?~(tint ~ s+tint) - s+(crip ((x-co:co 6) (rep 3 ~[b g r]:tint))) - -- - == - == + ++ json (blit:enjs:dill blit) -- -- diff --git a/pkg/base-dev/mar/sole/action.hoon b/pkg/base-dev/mar/sole/action.hoon index 149ef5ef1..de2835d72 100644 --- a/pkg/base-dev/mar/sole/action.hoon +++ b/pkg/base-dev/mar/sole/action.hoon @@ -20,7 +20,9 @@ |= jon=^json ^- sole-action %- need %. jon => [dejs-soft:format ..sole-action] - |^ (ot id+so dat+(fo %ret (of det+change tab+ni ~)) ~) + |^ (ot id+id dat+(fo %ret (of det+change tab+ni ~)) ~) + ++ id + (ot who+(su ;~(pfix sig fed:ag)) ses+so ~) ++ fo |* [a=term b=fist] |=(c=json ?.(=([%s a] c) (b c) (some [a ~]))) diff --git a/pkg/base-dev/sur/sole.hoon b/pkg/base-dev/sur/sole.hoon index e942bccb8..f8141f701 100644 --- a/pkg/base-dev/sur/sole.hoon +++ b/pkg/base-dev/sur/sole.hoon @@ -3,8 +3,9 @@ :: ^? |% ++$ sole-id [who=@p ses=@ta] +$ sole-action :: sole to app - $: id=@ta :: duct id + $: id=sole-id :: session id $= dat $% :: [%abo ~] :: reset interaction [%det sole-change] :: command line edit diff --git a/pkg/bitcoin/sys.kelvin b/pkg/bitcoin/sys.kelvin index b7bcb9ecd..47c282b53 100644 --- a/pkg/bitcoin/sys.kelvin +++ b/pkg/bitcoin/sys.kelvin @@ -1 +1,2 @@ [%zuse 417] +[%zuse 416] diff --git a/pkg/garden/sys.kelvin b/pkg/garden/sys.kelvin index b7bcb9ecd..0cb1220e5 100644 --- a/pkg/garden/sys.kelvin +++ b/pkg/garden/sys.kelvin @@ -1 +1 @@ -[%zuse 417] +[%zuse 416] diff --git a/pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs b/pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs index 5a5782912..6037e0298 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs @@ -119,15 +119,25 @@ deriveNoun ''BehnEf data Blit = Bel () | Clr () - | Hop Word64 + | Hop HopTarget | Klr Stub - | Lin [Char] - | Mor () + | Put [Char] + | Nel () | Sag Path Noun | Sav Path Atom | Url Cord + | Wyp () + --TMP backwards compatibility + | Lin [Char] + | Mor () deriving (Eq, Ord) +--NOTE bottom-left-0-based coordinates +data HopTarget + = Col Word64 + | Roc Word64 Word64 -- row, col + deriving (Eq, Ord, Show) + data Deco = DecoBl | DecoBr @@ -205,18 +215,33 @@ instance FromNoun Tint where "w" -> pure TintW t -> fail ("invalid: " <> unpack t) +instance FromNoun HopTarget where + parseNoun = \case + A c -> pure $ Col (fromIntegral c) + C (A r) (A c) -> pure $ Roc (fromIntegral r) (fromIntegral c) + n -> fail ("invalid hop target: " <> show n) + +instance ToNoun HopTarget where + toNoun = \case + Col c -> A (fromIntegral c) + Roc r c -> C (A (fromIntegral r)) (A (fromIntegral c)) + -- Manual instance to not save the noun/atom in Sag/Sav, because these can be -- megabytes and makes king hang. instance Show Blit where show (Bel ()) = "Bel ()" show (Clr ()) = "Clr ()" - show (Hop x) = "Hop " ++ (show x) + show (Hop t) = "Hop " ++ (show t) show (Klr s) = "Klr " ++ (show s) - show (Lin c) = "Lin " ++ (show c) - show (Mor ()) = "Mor ()" + show (Put c) = "Put " ++ (show c) + show (Nel ()) = "Nel ()" show (Sag path _) = "Sag " ++ (show path) show (Sav path _) = "Sav " ++ (show path) show (Url c) = "Url " ++ (show c) + show (Wyp ()) = "Wyp ()" + -- + show (Lin c) = "Lin " ++ (show c) + show (Mor ()) = "Mor ()" {-| %blip -- TODO diff --git a/pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs b/pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs index d2f316a53..50ef1ac1f 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs @@ -20,6 +20,7 @@ import Urbit.Arvo.Common (ReOrg(..), reorgThroughNoun) import qualified Crypto.Sign.Ed25519 as Ed import qualified Data.ByteString as BS +import qualified Data.Char as C import qualified Data.ByteString.Char8 as C import qualified Network.HTTP.Types.Method as H @@ -318,19 +319,52 @@ data LegacyBootEvent | Dawn Dawn deriving (Eq, Show) -data ArrowKey = D | L | R | U +data Bolt + = Key Char + | Aro ArrowKey + | Bac () + | Del () + | Hit Word64 Word64 + | Ret () deriving (Eq, Ord, Show) data Belt - = Aro ArrowKey - | Bac () - | Ctl Cord - | Del () - | Met Cord - | Ret () + = Bol Bolt + | Mod Modifier Bolt | Txt Tour deriving (Eq, Ord, Show) +data ArrowKey = D | L | R | U + deriving (Eq, Ord, Show) + +data Modifier = Ctl | Met | Hyp + deriving (Eq, Ord, Show) + +--NOTE required to get the above declarations into reify's type environment +-- see also ghc/ghc#9813 +$(pure []) + +instance FromNoun Bolt where + parseNoun = \case + A c -> pure $ Key $ C.chr $ fromIntegral c + C (A 7955819) _ -> fail "%key not valid bolt tag" + n -> $(deriveFromNounFunc ''Bolt) n + +instance FromNoun Belt where + parseNoun = \case + C (A 7106402) _ -> fail "%bol not valid belt tag" + n -> Bol <$> parseNoun n <|> $(deriveFromNounFunc ''Belt) n + +instance ToNoun Bolt where + toNoun = \case + Key c -> A $ fromIntegral $ C.ord c + n -> $(deriveToNounFunc ''Bolt) n + +instance ToNoun Belt where + toNoun = \case + Bol b -> toNoun b + n -> $(deriveToNounFunc ''Belt) n + data TermEv = TermEvBelt (UD, ()) Belt | TermEvBlew (UD, ()) Word Word @@ -341,7 +375,7 @@ data TermEv deriveNoun ''LegacyBootEvent deriveNoun ''ArrowKey -deriveNoun ''Belt +deriveNoun ''Modifier deriveNoun ''TermEv @@ -392,27 +426,23 @@ instance FromNoun Ev where -- Short Event Names ----------------------------------------------------------- {- - In the case of the user hitting enter, the cause is technically a - terminal event, but we don't display any name because the cause is - really the user. + In the case of user input, the cause is technically a terminal event, + but we don't display any name because the cause is really the user. -} getSpinnerNameForEvent :: Ev -> Maybe Text getSpinnerNameForEvent = \case EvBlip b -> case b of - BlipEvAmes _ -> Just "ames" - BlipEvArvo _ -> Just "arvo" - BlipEvBehn _ -> Just "behn" - BlipEvBoat _ -> Just "boat" - BlipEvHttpClient _ -> Just "iris" - BlipEvHttpServer _ -> Just "eyre" - BlipEvJael _ -> Just "jael" - BlipEvNewt _ -> Just "newt" - BlipEvSync _ -> Just "clay" - BlipEvTerm t | isRet t -> Nothing - BlipEvTerm t -> Just "term" - where - isRet (TermEvBelt _ (Ret ())) = True - isRet _ = False + BlipEvAmes _ -> Just "ames" + BlipEvArvo _ -> Just "arvo" + BlipEvBehn _ -> Just "behn" + BlipEvBoat _ -> Just "boat" + BlipEvHttpClient _ -> Just "iris" + BlipEvHttpServer _ -> Just "eyre" + BlipEvJael _ -> Just "jael" + BlipEvNewt _ -> Just "newt" + BlipEvSync _ -> Just "clay" + BlipEvTerm (TermEvBelt _ _) -> Nothing + BlipEvTerm t -> Just "term" summarizeEvent :: Ev -> Text summarizeEvent ev = diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs index 590267570..886da15c8 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs @@ -333,7 +333,7 @@ pier (serf, log) vSlog startedSig injected = do io $ readTVarIO siteSlog >>= ($ s) logOther "serf" (display $ T.strip $ tankToText tank) - let err = atomically . Term.trace muxed . (<> "\r\n") + let err = atomically . Term.trace muxed (bootEvents, startDrivers) <- do env <- ask siz <- atomically $ Term.curDemuxSize demux diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs index 0f86dd253..ccd4c676d 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs @@ -45,8 +45,8 @@ import qualified Urbit.Vere.Term.Render as T -- | All stateful data in the printing to stdOutput. data LineState = LineState - { lsLine :: Text - , lsCurPos :: Int + { lsLine :: [(Stye, [Char])] + , lsCurPos :: CurPos , lsSpinTimer :: Maybe (Async ()) , lsSpinCause :: Maybe Text , lsSpinFirstRender :: Bool @@ -54,11 +54,19 @@ data LineState = LineState , lsPrevEndTime :: Wen } +data CurPos = CurPos + { row :: Int + , col :: Int + } + -- | A record used in reading data from stdInput. data ReadData = ReadData { rdBuf :: Ptr Word8 , rdEscape :: Bool , rdBracket :: Bool + , rdMouse :: Bool + , rdMouseBut :: Word8 + , rdMouseCol :: Word8 , rdUTF8 :: ByteString , rdUTF8width :: Int } @@ -165,7 +173,8 @@ leftBracket, rightBracket :: Text leftBracket = "«" rightBracket = "»" -_spin_cool_us, _spin_warm_us, _spin_rate_us, _spin_idle_us :: Integral i => i +_spin_fast_us, _spin_cool_us, _spin_warm_us, _spin_rate_us, _spin_idle_us :: Integral i => i +_spin_fast_us = 100000 _spin_cool_us = 500000 _spin_warm_us = 50000 _spin_rate_us = 250000 @@ -201,6 +210,9 @@ localClient doneSignal = fst <$> mkRAcquire start stop -- to the muxing client. putTMVar tsSizeChange ts) + -- start mouse reporting + putStr "\x1b[?9h" + pWriterThread <- asyncBound (writeTerminal tsWriteQueue spinnerMVar tsizeTVar) @@ -217,7 +229,7 @@ localClient doneSignal = fst <$> mkRAcquire start stop tsReadQueue <- newTQueueIO pReaderThread <- asyncBound - (readTerminal tsReadQueue tsWriteQueue (bell tsWriteQueue)) + (readTerminal tsReadQueue tsWriteQueue tsizeTVar (bell tsWriteQueue)) let client = Client { take = Just <$> asum [ readTQueue tsReadQueue <&> ClientTakeBelt, @@ -238,6 +250,9 @@ localClient doneSignal = fst <$> mkRAcquire start stop -- at shutdown, just leak the file descriptor. cancel pWriterThread + -- stop mouse reporting + putStr "\x1b[?9l" + -- inject one final newline, as we're usually on the prompt. putStr "\r\n" @@ -266,31 +281,50 @@ localClient doneSignal = fst <$> mkRAcquire start stop -- Writes data to the terminal. Both the terminal reading, normal logging, -- and effect handling can all emit bytes which go to the terminal. + --TODO blanks, traces and slogs should only be written into the default + -- terminal session. writeTerminal :: TQueue [Term.Ev] -> TMVar () -> TVar TermSize -> RIO e () writeTerminal q spinner termSizeVar = do currentTime <- io $ now - loop (LineState "" 0 Nothing Nothing True 0 currentTime) + loop + termSizeVar + (LineState [] (CurPos 0 0) Nothing Nothing True 0 currentTime) where writeBlank :: LineState -> RIO e LineState - writeBlank ls = putStr "\r\n" $> ls + writeBlank ls = do + TermSize _ height <- readTVarIO termSizeVar + --NOTE hijack creates a blank line + T.hijack (fromIntegral height) $ pure () + pure ls writeTrace :: LineState -> Text -> RIO e LineState writeTrace ls p = do - putStr "\r" - T.clearLine - putStr p - termRefreshLine ls + TermSize _ height <- readTVarIO termSizeVar + T.hijack (fromIntegral height) $ putStr p + pure ls writeSlog :: LineState -> (Atom, Tank) -> RIO e LineState writeSlog ls slog = do - putStr "\r" - T.clearLine - TermSize width _ <- atomically $ readTVar termSizeVar - -- TODO: Ignoring priority for now. Priority changes the color of, - -- and adds a prefix of '>' to, the output. - let lines = fmap unTape $ wash (WashCfg 0 width) $ tankTree $ snd slog - forM lines $ \line -> putStr (line <> "\r\n") - termRefreshLine ls + TermSize width height <- readTVarIO termSizeVar + T.hijack (fromIntegral height) do + let lines = fmap (pref . unTape) $ + wash (WashCfg 0 width) $ tankTree $ snd slog + T.putCsi 'm' styl + forM (intersperse "\n" lines) $ \line -> putStr line + T.putCsi 'm' [0] + pure ls + where + prio = fromIntegral $ fst slog + maxp = 3 + styl + | prio == 3 = [31] + | prio == 2 = [33] + | prio == 1 = [32] + | otherwise = [90] + pref + | prio > 0 && prio <= maxp = + ((replicate prio '>' ++ replicate (1 + maxp - prio) ' ') ++) + | otherwise = id {- Figure out how long to wait to show the spinner. When we @@ -305,7 +339,7 @@ localClient doneSignal = fst <$> mkRAcquire start stop current <- io $ now delay <- pure $ case mTxt of - Nothing -> 0 + Nothing -> _spin_fast_us Just _ -> if (gap current lsPrevEndTime ^. microSecs) < _spin_idle_us then _spin_warm_us @@ -326,34 +360,41 @@ localClient doneSignal = fst <$> mkRAcquire start stop maybe (pure ()) cancel lsSpinTimer -- We do a final flush of the spinner mvar to ensure we don't -- have a lingering signal which will redisplay the spinner after - -- we call termRefreshLine below. + -- we call termRestoreLine below. atomically $ tryTakeTMVar spinner -- If we ever actually ran the spinner display callback, we need -- to force a redisplay of the command prompt. - ls <- if not lsSpinFirstRender || True - then termRefreshLine ls - else pure ls + if not lsSpinFirstRender + then termRestoreLine ls termSizeVar + else pure () endTime <- io $ now pure $ ls { lsSpinTimer = Nothing, lsPrevEndTime = endTime } execEv :: LineState -> Term.Ev -> RIO e LineState execEv ls = \case - Term.Blits bs -> foldM writeBlit ls bs + Term.Blits bs -> foldM (writeBlit termSizeVar) ls bs Term.Trace p -> writeTrace ls (unCord p) Term.Slog s -> writeSlog ls s Term.Blank -> writeBlank ls Term.Spinr (Just txt) -> doSpin ls (unCord <$> txt) Term.Spinr Nothing -> unspin ls - -- TODO What does this do? - spin :: LineState -> RIO e LineState - spin ls@LineState{..} = do + spin :: TVar TermSize -> LineState -> RIO e LineState + spin ts ls@LineState{..} = do let spinner = (spinners !! lsSpinFrame) ++ case lsSpinCause of Nothing -> "" Just str -> leftBracket ++ str ++ rightBracket + --NOTE even after first render, because cursor might have moved... + if row lsCurPos > 0 + then do + TermSize _ h <- readTVarIO ts + T.cursorMove (fromIntegral h - 1) 0 + else + T.cursorRestore + putStr (spinner <> pack (ANSI.cursorBackwardCode (length spinner))) let newFrame = (lsSpinFrame + 1) `mod` length spinners @@ -362,28 +403,35 @@ localClient doneSignal = fst <$> mkRAcquire start stop , lsSpinFrame = newFrame } - loop :: LineState -> RIO e () - loop ls = do + loop :: TVar TermSize -> LineState -> RIO e () + loop ts ls = do join $ atomically $ asum - [ readTQueue q >>= pure . (foldM execEv ls >=> loop) - , takeTMVar spinner >> pure (spin ls >>= loop) + [ readTQueue q >>= pure . (foldM execEv ls >=> loop ts) + , takeTMVar spinner >> pure (spin ts ls >>= loop ts) ] -- Writes an individual blit to the screen - writeBlit :: LineState -> Blit -> RIO e LineState - writeBlit ls = \case + writeBlit :: TVar TermSize -> LineState -> Blit -> RIO e LineState + writeBlit ts ls = \case Bel () -> T.soundBell $> ls Clr () -> do T.clearScreen - termRefreshLine ls - Hop w -> termShowCursor ls (fromIntegral w) - Klr s -> do ls2 <- termShowClear ls - termShowStub ls2 s - Lin c -> do ls2 <- termShowClear ls - termShowLine ls2 (pack c) - Mor () -> termShowMore ls + T.cursorRestore + pure ls + Hop t -> case t of + Col c -> termShowCursor ls ts 0 (fromIntegral c) + Roc r c -> termShowCursor ls ts (fromIntegral r) (fromIntegral c) + Klr s -> termShowStub ls s + Put c -> termShowLine ls (pack c) + Nel () -> termShowNewline ls Sag path noun -> pure ls Sav path atom -> pure ls Url url -> pure ls + Wyp () -> termShowClear ls + -- + Lin c -> do termShowCursor ls ts 0 0 + termShowClear ls + termShowLine ls (pack c) + Mor () -> termShowNewline ls termRenderDeco :: Deco -> Char termRenderDeco = \case @@ -428,55 +476,88 @@ localClient doneSignal = fst <$> mkRAcquire start stop styled = mconcat [escape, styles, "m", tape, escape, "0m"] - -- Displays and sets styled text as the current line + bareStub :: [Char] -> [(Stye, [Char])] + bareStub c = [(Stye (setToHoonSet mempty) TintNull TintNull, c)] + + -- overwrite substring of base with put, starting at index + overwriteStub :: [(Stye, [Char])] -> Int -> [(Stye, [Char])] -> [(Stye, [Char])] + overwriteStub base index put = + scagStub index base + ++ ( let l = lentStub base in + if index <= l then [] + else bareStub $ take (index - l) [' ',' '..] + ) + ++ put + ++ slagStub (index + lentStub put) base + where + lentStub :: [(Stye, [Char])] -> Int + lentStub s = sum $ map (length . snd) s + + scagStub :: Int -> [(Stye, [Char])] -> [(Stye, [Char])] + scagStub 0 _ = [] + scagStub _ [] = [] + scagStub i ((y,c):s) = + (y, take i c) : scagStub (i - min i (length c)) s + + slagStub :: Int -> [(Stye, [Char])] -> [(Stye, [Char])] + slagStub 0 s = s + slagStub _ [] = [] + slagStub i ((y,c):s) + | i > l = slagStub (i - l) s + | otherwise = (y, drop i c) : s + where l = length c + + -- Displays styled text at the cursor termShowStub :: LineState -> Stub -> RIO e LineState - termShowStub ls (Stub s) = do - let visualLength = sum $ fmap (length . snd) s - let outText = pack $ mconcat $ fmap (uncurry termRenderStubSegment) s - putStr outText - pure ls { lsLine = outText, lsCurPos = visualLength } + termShowStub ls@LineState{lsCurPos, lsLine} (Stub s) = do + putStr $ pack $ mconcat $ fmap (uncurry termRenderStubSegment) s + T.cursorRestore + case row lsCurPos of + 0 -> pure ls { lsLine = overwriteStub lsLine (col lsCurPos) s } + _ -> pure ls -- Moves the cursor to the requested position - termShowCursor :: LineState -> Int -> RIO e LineState - termShowCursor ls@LineState{..} {-line pos)-} newPos = do - if newPos < lsCurPos then do - T.cursorLeft (lsCurPos - newPos) - pure ls { lsCurPos = newPos } - else if newPos > lsCurPos then do - T.cursorRight (newPos - lsCurPos) - pure ls { lsCurPos = newPos } - else - pure ls - - -- Moves the cursor left without any mutation of the LineState. Used only - -- in cursor spinning. - _termSpinnerMoveLeft :: Int -> RIO e () - _termSpinnerMoveLeft = T.cursorLeft + termShowCursor :: LineState -> TVar TermSize -> Int -> Int -> RIO e LineState + termShowCursor ls ts row col = do + TermSize _ h <- readTVarIO ts + T.cursorMove (max 0 (fromIntegral h - row - 1)) col + T.cursorSave + pure ls { lsCurPos = CurPos row col } -- Displays and sets the current line termShowLine :: LineState -> Text -> RIO e LineState - termShowLine ls newStr = do + termShowLine ls@LineState{lsCurPos, lsLine} newStr = do putStr newStr - pure ls { lsLine = newStr, lsCurPos = (length newStr) } + T.cursorRestore + case row lsCurPos of + 0 -> pure ls { lsLine = overwriteStub lsLine (col lsCurPos) (bareStub $ unpack newStr) } + _ -> pure ls termShowClear :: LineState -> RIO e LineState - termShowClear ls = do + termShowClear ls@LineState{lsCurPos} = do putStr "\r" T.clearLine - pure ls { lsLine = "", lsCurPos = 0 } + T.cursorRestore + case row lsCurPos of + 0 -> pure ls { lsLine = [] } + _ -> pure ls -- New Current Line - termShowMore :: LineState -> RIO e LineState - termShowMore ls = do + termShowNewline :: LineState -> RIO e LineState + termShowNewline ls@LineState{lsCurPos} = do putStr "\r\n" - pure ls { lsLine = "", lsCurPos = 0 } + case row lsCurPos of + 0 -> pure ls { lsLine = [], lsCurPos = lsCurPos { col = 0 } } + r -> pure ls { lsCurPos = CurPos (r-1) 0 } - -- Redraw the current LineState, maintaining the current curpos - termRefreshLine :: LineState -> RIO e LineState - termRefreshLine ls@LineState{lsCurPos,lsLine} = do - ls <- termShowClear ls - ls <- termShowLine ls lsLine - termShowCursor ls lsCurPos + -- Redraw the bottom LineState, maintaining the current curpos + termRestoreLine :: LineState -> TVar TermSize -> RIO e () + termRestoreLine ls@LineState{lsLine} ts = do + TermSize _ h <- readTVarIO ts + T.cursorMove (fromIntegral h - 1) 0 + T.clearLine + putStr $ pack $ mconcat $ fmap (uncurry termRenderStubSegment) lsLine + T.cursorRestore -- ring my bell bell :: TQueue [Term.Ev] -> RIO e () @@ -491,9 +572,14 @@ localClient doneSignal = fst <$> mkRAcquire start stop -- A better way to do this would be to get some sort of epoll on stdInput, -- since that's kinda closer to what libuv does? readTerminal :: forall e. HasLogFunc e - => TQueue Belt -> TQueue [Term.Ev] -> (RIO e ()) -> RIO e () - readTerminal rq wq bell = - rioAllocaBytes 1 $ \ buf -> loop (ReadData buf False False mempty 0) + => TQueue Belt + -> TQueue [Term.Ev] + -> TVar TermSize + -> RIO e () + -> RIO e () + readTerminal rq wq ts bell = + rioAllocaBytes 1 $ \ buf + -> loop (ReadData buf False False False 0 0 mempty 0) where loop :: ReadData -> RIO e () loop rd@ReadData{..} = do @@ -513,26 +599,41 @@ localClient doneSignal = fst <$> mkRAcquire start stop if rdEscape then if rdBracket then do case c of - 'A' -> sendBelt $ Aro U - 'B' -> sendBelt $ Aro D - 'C' -> sendBelt $ Aro R - 'D' -> sendBelt $ Aro L + 'A' -> sendBelt $ Bol $ Aro U + 'B' -> sendBelt $ Bol $ Aro D + 'C' -> sendBelt $ Bol $ Aro R + 'D' -> sendBelt $ Bol $ Aro L + 'M' -> pure () _ -> bell - loop rd { rdEscape = False, rdBracket = False} + rd <- case c of + 'M' -> pure rd { rdMouse = True } + _ -> pure rd + loop rd { rdEscape = False, rdBracket = False } else if isAsciiLower c then do - sendBelt $ Met $ Cord $ pack [c] - loop rd { rdEscape = False } - else if c == '.' then do - sendBelt $ Met $ Cord "dot" + sendBelt $ Mod Met $ Key c loop rd { rdEscape = False } else if w == 8 || w == 127 then do - sendBelt $ Met $ Cord "bac" + sendBelt $ Mod Met $ Bac () loop rd { rdEscape = False } else if c == '[' || c == '0' then do loop rd { rdBracket = True } else do bell loop rd { rdEscape = False } + else if rdMouse then + if rdMouseBut == 0 then do + loop rd { rdMouseBut = w - 31 } + else if rdMouseCol == 0 then do + loop rd { rdMouseCol = w - 32 } + else do + if rdMouseBut == 1 then do + let rdMouseRow = w - 32 + TermSize _ h <- readTVarIO ts + sendBelt $ Bol $ Hit + (fromIntegral h - fromIntegral rdMouseRow) + (fromIntegral rdMouseCol - 1) + else do pure () + loop rd { rdMouse = False, rdMouseBut = 0, rdMouseCol = 0 } else if rdUTF8width /= 0 then do -- continue reading into the utf8 accumulation buffer rd@ReadData{..} <- pure rd { rdUTF8 = snoc rdUTF8 w } @@ -543,30 +644,31 @@ localClient doneSignal = fst <$> mkRAcquire start stop error "empty utf8 accumulation buffer" Just (c, bytes) | bytes /= rdUTF8width -> error "utf8 character size mismatch?!" - Just (c, bytes) -> sendBelt $ Txt $ Tour $ [c] + Just (c, bytes) -> sendBelt $ Bol $ Key c loop rd { rdUTF8 = mempty, rdUTF8width = 0 } else if w >= 32 && w < 127 then do - sendBelt $ Txt $ Tour $ [c] + sendBelt $ Bol $ Key c loop rd else if w == 0 then do bell loop rd else if w == 8 || w == 127 then do - sendBelt $ Bac () + sendBelt $ Bol $ Bac () loop rd else if w == 13 then do - sendBelt $ Ret () + sendBelt $ Bol $ Ret () loop rd else if w == 3 then do -- ETX (^C) logInfo $ "Ctrl-c interrupt" atomically $ do - writeTQueue wq [Term.Trace "interrupt\r\n"] - writeTQueue rq $ Ctl $ Cord "c" + writeTQueue wq [Term.Trace "interrupt"] + writeTQueue rq $ Mod Ctl $ Key 'c' loop rd else if w <= 26 then do - case pack [BS.w2c (w + 97 - 1)] of - c -> do sendBelt $ Ctl $ Cord c + case BS.w2c (w + 97 - 1) of + 'd' -> atomically doneSignal + c -> do sendBelt $ Mod Ctl $ Key c loop rd else if w == 27 then do loop rd { rdEscape = True } @@ -643,7 +745,7 @@ term env (tsize, Client{..}) plan stat serfSIGINT = runTerm atomically take >>= \case Nothing -> pure () Just (ClientTakeBelt b) -> do - when (b == Ctl (Cord "c")) $ do + when (b == Mod Ctl (Key 'c')) $ do io serfSIGINT let beltEv = EvBlip $ BlipEvTerm $ TermEvBelt (UD 1, ()) $ b let beltFailed _ = pure () diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs index 7e65d49e5..d6b6fde60 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs @@ -22,7 +22,7 @@ import Urbit.TermSize Input Event for terminal driver: %blits -- list of blits from arvo. - %trace -- stderr line from runtime. + %trace -- stderr line from runtime (without trailing newline). %slog -- nock worker logging with priority %blank -- print a blank line %spinr -- Start or stop the spinner diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Logic.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Logic.hs index 770742a68..748b3fa5a 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Logic.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Logic.hs @@ -39,11 +39,11 @@ data Ev = EvLine Text | EvSlog (Atom, Tank) | EvSpin SpinnerState - | EvMove Word + | EvMove (Word, Word) | EvBell | EvDraw | EvEdit Text - | EvMore + | EvNewl deriving (Show) data Ef @@ -62,7 +62,7 @@ data History data St = St { sHistory :: !(Seq History) , sLine :: !Text - , sCurPos :: !Word + , sCurPos :: !(Word, Word) , sSpinner :: !SpinnerState } deriving (Show) @@ -70,10 +70,10 @@ data St = St -------------------------------------------------------------------------------- init :: St -init = St mempty "" 0 Nothing +init = St mempty "" (0, 0) Nothing {-| - When we process `EvMore`, we need to append a newline to the end of + When we process `EvNewl`, we need to append a newline to the end of the current line. During normal play, the ENTER key inserts the newline for us, so we need to recreate that newline when we rebuild the state for a new terminal connection. @@ -83,15 +83,17 @@ step st@St{..} = \case EvLine t -> st & recordText t EvSlog s -> st & recordSlog s EvSpin s -> st { sSpinner = s } - EvMove w -> st { sCurPos = min w (word $ length sLine) } - EvEdit t -> st { sLine = t, sCurPos = word (length t) } - EvMore -> st { sLine = "", sCurPos = 0 } & recordText (sLine <> "\n") + EvMove p -> st { sCurPos = p } EvBell -> st EvDraw -> st + EvEdit t | (0, _) <- sCurPos -> st { sLine = t } + | otherwise -> st + EvNewl | (0, _) <- sCurPos -> + st { sLine = "", sCurPos = (0, 0) } + & recordText (sLine <> "\n") + | otherwise -> + st { sCurPos = (fst sCurPos - 1, 0) } where - word :: Integral i => i -> Word - word = fromIntegral - recordText :: Text -> St -> St recordText !t st@St{..} = st { sHistory = trim (sHistory |> (HistoryText t)) @@ -111,8 +113,10 @@ drawState :: St -> [Ev] drawState St{..} = hist <> out <> cur <> spin where hist = drawHistory <$> toList sHistory - out = if null sLine then [] else [EvEdit sLine] - cur = if 0 == sCurPos then [] else [EvMove $ fromIntegral $ sCurPos] + out | null sLine = [] + | otherwise = [EvEdit sLine] + cur | (0, _) <- sCurPos = [] + | otherwise = [EvMove sCurPos] spin = maybe [] (singleton . EvSpin . Just) sSpinner drawHistory (HistoryText t) = EvLine t @@ -123,12 +127,13 @@ drawState St{..} = hist <> out <> cur <> spin fromBlit :: Arvo.Blit -> Maybe Ev fromBlit = \case - Arvo.Hop w -> Just $ EvMove $ fromIntegral w - Arvo.Bel () -> Just EvBell - Arvo.Clr () -> Just EvDraw - Arvo.Lin s -> Just $ EvEdit (pack s) - Arvo.Mor () -> Just EvMore - _ -> Nothing + Arvo.Hop (Arvo.Col c) -> Just $ EvMove (0, fromIntegral c) + Arvo.Hop (Arvo.Roc r c) -> Just $ EvMove (fromIntegral r, fromIntegral c) + Arvo.Bel () -> Just EvBell + Arvo.Clr () -> Just EvDraw + Arvo.Put s -> Just $ EvEdit (pack s) + Arvo.Nel () -> Just EvNewl + _ -> Nothing toCause :: Maybe Cord -> SpinnerCause toCause Nothing = User @@ -148,12 +153,12 @@ fromTermEv = \case toTermEv :: Ev -> Term.Ev toTermEv = \case - EvLine "" -> Term.Blank - EvLine t -> Term.Trace (Cord t) - EvSlog s -> Term.Slog s - EvSpin s -> Term.Spinr (fromCause <$> s) - EvMove w -> Term.Blits [Arvo.Hop $ fromIntegral w] - EvBell -> Term.Blits [Arvo.Bel ()] - EvDraw -> Term.Blits [Arvo.Clr ()] - EvEdit t -> Term.Blits [Arvo.Lin $ unpack t] - EvMore -> Term.Blits [Arvo.Mor ()] + EvLine "" -> Term.Blank + EvLine t -> Term.Trace (Cord t) + EvSlog s -> Term.Slog s + EvSpin s -> Term.Spinr (fromCause <$> s) + EvMove (r, c) -> Term.Blits [Arvo.Hop $ Arvo.Roc (fromIntegral r) (fromIntegral c)] + EvBell -> Term.Blits [Arvo.Bel ()] + EvDraw -> Term.Blits [Arvo.Clr ()] + EvEdit t -> Term.Blits [Arvo.Put $ unpack t] + EvNewl -> Term.Blits [Arvo.Nel ()] diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs index f0982dfbe..829003259 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs @@ -4,9 +4,12 @@ module Urbit.Vere.Term.Render ( clearScreen , clearLine - , cursorRight - , cursorLeft , soundBell + , cursorMove + , cursorSave + , cursorRestore + , putCsi + , hijack ) where import Urbit.Prelude @@ -25,8 +28,27 @@ clearLine = liftIO $ ANSI.clearLine soundBell :: MonadIO m => m () soundBell = liftIO $ putStr "\a" -cursorLeft :: MonadIO m => Int -> m () -cursorLeft = liftIO . ANSI.cursorBackward +--NOTE top-left-0-based coordinates +cursorMove :: MonadIO m => Int -> Int -> m () +cursorMove r c = liftIO $ ANSI.setCursorPosition r c -cursorRight :: MonadIO m => Int -> m () -cursorRight = liftIO . ANSI.cursorForward +cursorSave :: MonadIO m => m () +cursorSave = liftIO ANSI.saveCursor + +cursorRestore :: MonadIO m => m () +cursorRestore = liftIO ANSI.restoreCursor + +putCsi :: MonadIO m => Char -> [Int] -> m () +putCsi c a = liftIO do + putStr "\x1b[" + putStr $ pack $ mconcat $ intersperse ";" (fmap show a) + putStr $ pack [c] + +hijack :: MonadIO m => Int -> IO () -> m () +hijack h d = liftIO do + putCsi 'r' [1, h-1] -- set scroll region to exclude bottom line + putCsi 'S' [1] -- scroll up one line + cursorMove (h-2) 0 -- move cursor to empty space + d + putCsi 'r' [] -- reset scroll region + cursorRestore -- restory cursor position diff --git a/pkg/interface/dbug/src/css/custom.css b/pkg/interface/dbug/src/css/custom.css index 112ad47eb..00bcd4f4d 100644 --- a/pkg/interface/dbug/src/css/custom.css +++ b/pkg/interface/dbug/src/css/custom.css @@ -158,6 +158,7 @@ a { @media all and (prefers-color-scheme: dark) { body { background-color: #333; + color: white; } .bg-black-d { background-color: black; diff --git a/pkg/interface/webterm/.eslintrc.js b/pkg/interface/webterm/.eslintrc.js new file mode 100644 index 000000000..8f36013ed --- /dev/null +++ b/pkg/interface/webterm/.eslintrc.js @@ -0,0 +1,23 @@ +module.exports = exports = { + "rules": { + "spaced-comment": 0, + }, + "extends": [ + "eslint:recommended", + "plugin:import/errors", + "plugin:react/recommended", + ], + "settings": { + "react": { + "version": "detect" + }, + "import/resolver": { + typescript: {} // this loads /tsconfig.json to eslint + }, + }, + "env": { + "browser": true, + "es6": true + }, + "plugins": ["import", "react-hooks"] +} diff --git a/pkg/interface/webterm/.nvmrc b/pkg/interface/webterm/.nvmrc new file mode 100644 index 000000000..0b77208ae --- /dev/null +++ b/pkg/interface/webterm/.nvmrc @@ -0,0 +1 @@ +16.14.0 \ No newline at end of file diff --git a/pkg/interface/webterm/App.tsx b/pkg/interface/webterm/App.tsx new file mode 100644 index 000000000..211066b74 --- /dev/null +++ b/pkg/interface/webterm/App.tsx @@ -0,0 +1,94 @@ +import React, { + useCallback, useEffect +} from 'react'; + +import useTermState from './state'; +import { useDark } from './lib/useDark'; +import api from './api'; + +import { _dark, _light } from '@tlon/indigo-react'; + +import 'xterm/css/xterm.css'; + +import { + scrySessions +} from '@urbit/api/term'; + +import { ThemeProvider } from 'styled-components'; +import { Tabs } from './Tabs'; +import Buffer from './Buffer'; +import { DEFAULT_SESSION } from './constants'; +import { showSlog } from './lib/blit'; +import { InfoButton } from './InfoButton'; + +const initSessions = async () => { + const response = await api.scry(scrySessions()); + + useTermState.getState().set((state) => { + state.names = response.sort(); + }); +}; + +export default function TermApp() { + const { names, selected } = useTermState(); + const dark = useDark(); + + const setupSlog = useCallback(() => { + console.log('slog: setting up...'); + let available = false; + const slog = new EventSource('/~_~/slog', { withCredentials: true }); + + slog.onopen = () => { + console.log('slog: opened stream'); + available = true; + }; + + slog.onmessage = (e) => { + const session = useTermState.getState().sessions[DEFAULT_SESSION]; + if (!session) { + console.log('slog: default session mia!', 'msg:', e.data); + console.log(Object.keys(useTermState.getState().sessions), session); + return; + } + showSlog(session.term, e.data); + }; + + slog.onerror = (e) => { + console.error('slog: eventsource error:', e); + if (available) { + window.setTimeout(() => { + if (slog.readyState !== EventSource.CLOSED) { + return; + } + console.log('slog: reconnecting...'); + setupSlog(); + }, 10000); + } + }; + + useTermState.getState().set((state) => { + state.slogstream = slog; + }); + }, []); + + useEffect(() => { + initSessions(); + setupSlog(); + }, []); + + return ( + <> + +
+ + +
+
+ {names.map((name) => { + return ; + })} +
+
+ + ); +} diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx new file mode 100644 index 000000000..1ee512f1a --- /dev/null +++ b/pkg/interface/webterm/Buffer.tsx @@ -0,0 +1,350 @@ +import { Terminal, ITerminalOptions } from 'xterm'; +import { FitAddon } from 'xterm-addon-fit'; +import { debounce } from 'lodash'; +import bel from './lib/bel'; +import api from './api'; + +import { + Belt, pokeTask, pokeBelt +} from '@urbit/api/term'; +import { Session } from './state'; +import { useCallback, useEffect, useRef } from 'react'; +import useTermState from './state'; +import React from 'react'; +import { Box, Col } from '@tlon/indigo-react'; +import { makeTheme } from './lib/theme'; +import { showBlit, csi, hasBell } from './lib/blit'; +import { DEFAULT_SESSION, RESIZE_DEBOUNCE_MS, RESIZE_THRESHOLD_PX } from './constants'; +import { retry } from './lib/retry'; + +const termConfig: ITerminalOptions = { + logLevel: 'warn', + // + convertEol: true, + // + rows: 24, + cols: 80, + scrollback: 10000, + // + fontFamily: '"Source Code Pro", "Roboto mono", "Courier New", monospace', + fontWeight: 400, + // NOTE theme colors configured dynamically + // + bellStyle: 'sound', + bellSound: bel, + // + // allows text selection by holding modifier (option, or shift) + macOptionClickForcesSelection: true, + // prevent insertion of simulated arrow keys on-altclick + altClickMovesCursor: false +}; + +const readInput = (term: Terminal, e: string): Belt[] => { + const belts: Belt[] = []; + let strap = ''; + + while (e.length > 0) { + let c = e.charCodeAt(0); + + // text input + // + if (c >= 32 && c !== 127) { + strap += e[0]; + e = e.slice(1); //TODO revisit wrt (list @c) & unicode characters + continue; + } else if ('' !== strap) { + belts.push({ txt: strap.split('') }); + strap = ''; + } + + // special keys/characters + // + if (0 === c) { + term.write('\x07'); // bel + } else if (8 === c || 127 === c) { + belts.push({ bac: null }); + } else if (13 === c) { + belts.push({ ret: null }); + } else if (c <= 26) { + const k = String.fromCharCode(96 + c); + //NOTE prevent remote shut-downs + if ('d' !== k) { + belts.push({ mod: { mod: 'ctl', key: k } }); + } + } + + // escape sequences + // + if (27 === c) { // ESC + e = e.slice(1); + c = e.charCodeAt(0); + if (91 === c || 79 === c) { // [ or O + e = e.slice(1); + c = e.charCodeAt(0); + /* eslint-disable max-statements-per-line */ + switch (c) { + case 65: belts.push({ aro: 'u' }); break; + case 66: belts.push({ aro: 'd' }); break; + case 67: belts.push({ aro: 'r' }); break; + case 68: belts.push({ aro: 'l' }); break; + // + case 77: { + const m = e.charCodeAt(1) - 31; + if (1 === m) { + const c = e.charCodeAt(2) - 32; + const r = e.charCodeAt(3) - 32; + belts.push({ hit: { y: r - 1, x: c - 1 } }); + } + e = e.slice(3); + break; + } + // + default: term.write('\x07'); break; // bel + } + } else if (c >= 97 && c <= 122) { // a <= c <= z + belts.push({ mod: { mod: 'met', key: e[0] } }); + } else if (c === 46) { // . + belts.push({ mod: { mod: 'met', key: '.' } }); + } else if (c === 8 || c === 127) { + belts.push({ mod: { mod: 'met', key: { bac: null } } }); + } else { + term.write('\x07'); break; // bel + } + } + + e = e.slice(1); + } + if ('' !== strap) { + if (1 === strap.length) { + belts.push(strap); + } else { + belts.push({ txt: strap.split('') }); + } + strap = ''; + } + return belts; +}; + +const onResize = async (name: string, session: Session) => { + if (session) { + session.fit.fit(); + useTermState.getState().set((state) => { + state.sessions[name].pending++; + }); + api.poke(pokeTask(name, { blew: { w: session.term.cols, h: session.term.rows } })).then(() => { + useTermState.getState().set((state) => { + state.sessions[name].pending--; + }); + }); + } +}; + +const onInput = (name: string, session: Session, e: string) => { + if (!session) { + return; + } + const term = session.term; + const belts = readInput(term, e); + belts.forEach((b) => { + useTermState.getState().set((state) => { + state.sessions[name].pending++; + }); + api.poke(pokeBelt(name, b)).then(() => { + useTermState.getState().set((state) => { + state.sessions[name].pending--; + }); + }); + }); +}; + +interface BufferProps { + name: string, + selected: boolean, + dark: boolean, +} + +export default function Buffer({ name, selected, dark }: BufferProps) { + const containerRef = useRef(null); + + const session: Session = useTermState(s => s.sessions[name]); + + const initSession = useCallback(async (name: string, dark: boolean) => { + console.log('setting up', name === DEFAULT_SESSION ? 'default' : name); + + // set up xterm terminal + // + const term = new Terminal(termConfig); + term.options.theme = makeTheme(dark); + const fit = new FitAddon(); + term.loadAddon(fit); + fit.fit(); + term.focus(); + + // start mouse reporting + // + term.write(csi('?9h')); + + const ses: Session = { + term, + fit, + hasBell: false, + pending: 0, + subscriptionId: null + }; + + // set up event handlers + // + term.attachCustomKeyEventHandler((e: KeyboardEvent) => { + //NOTE ctrl+shift keypresses never make it into term.onData somehow, + // so we handle them specially ourselves. + // we may be able to remove this once xterm.js fixes #3382 & co. + if (e.shiftKey + && e.ctrlKey + && e.type === 'keydown' + && e.key.length === 1 + ) { + api.poke(pokeBelt(name, { mod: { mod: 'ctl', key: e.key } })); + return false; + } + return true; + }); + term.onData(e => onInput(name, ses, e)); + term.onBinary(e => onInput(name, ses, e)); + + // open subscription + // + const initSubscription = async () => { + const subscriptionId = await api.subscribe({ + app: 'herm', path: '/session/' + name + '/view', + event: (e) => { + showBlit(ses.term, e); + //NOTE getting selected from state because selected prop is stale + if (hasBell(e) && (useTermState.getState().selected !== name)) { + useTermState.getState().set((state) => { + state.sessions[name].hasBell = true; + }); + } + //TODO should handle %bye on this higher level though, for deletion + }, + err: (e, id) => { + console.log(`subscription error, id ${id}:`, e); + }, + quit: async () => { // quit + console.error('quit, reconnecting...'); + try { + const newSubscriptionId = await retry(initSubscription, () => { + console.log('attempting to reconnect ...'); + }, 5); + useTermState.getState().set((state) => { + state.sessions[name].subscriptionId = newSubscriptionId; + }); + } catch (error) { + console.log('unable to reconnect', error); + } + } + }); + + return subscriptionId; + }; + + ses.subscriptionId = await initSubscription(); + + useTermState.getState().set((state) => { + state.sessions[name] = ses; + }); + }, []); + + const shouldResize = useCallback(() => { + if(!session) { + return false; + } + + const containerHeight = document.querySelector('.buffer-container')?.clientHeight || Infinity; + const terminalHeight = session.term.element?.clientHeight || 0; + + return (containerHeight - terminalHeight) >= RESIZE_THRESHOLD_PX; + }, [session]); + + const onSelect = useCallback(async () => { + if (session && selected && shouldResize()) { + session.fit.fit(); + await api.poke(pokeTask(name, { blew: { w: session.term.cols, h: session.term.rows } })); + session.term.focus(); + } + }, [session?.term, selected]); + + // Effects + // init session + useEffect(() => { + if(session) { + return; + } + + initSession(name, dark); + }, [name]); + + // attach to DOM when ref is available + useEffect(() => { + if(session && containerRef.current && !session.term.element) { + session.term.open(containerRef.current); + } + }, [session, containerRef]); + + // initialize resize listeners + // + useEffect(() => { + if(!session) { + return; + } + + // TODO: use ResizeObserver for improved performance? + const debouncedResize = debounce(() => onResize(name, session), RESIZE_DEBOUNCE_MS); + window.addEventListener('resize', debouncedResize); + + return () => { + window.removeEventListener('resize', debouncedResize); + }; + }, [session]); + + // on dark mode change, change terminals' theme + // + useEffect(() => { + const theme = makeTheme(dark); + if (session) { + session.term.options.theme = theme; + } + if (containerRef.current) { + containerRef.current.style.backgroundColor = theme.background || ''; + } + }, [session, dark]); + + // On select, resize, focus, and poke herm with updated cols and rows + useEffect(() => { + onSelect(); + }, [onSelect]); + + return ( + !session && !selected ? +

Loading...

+ : + + + + + ); +} diff --git a/pkg/interface/webterm/InfoButton.tsx b/pkg/interface/webterm/InfoButton.tsx new file mode 100644 index 000000000..b0ba22953 --- /dev/null +++ b/pkg/interface/webterm/InfoButton.tsx @@ -0,0 +1,24 @@ +import React, { useCallback } from 'react'; +import { Icon } from '@tlon/indigo-react'; +import { useDetectOS } from './lib/useDetectOS'; + +export const InfoButton = () => { + const { isMacOS } = useDetectOS(); + + const onInfoClick = useCallback(() => { + const key = isMacOS ? 'alt' : 'shift'; + + alert(`To select text in the terminal, hold down the ${key} key.`); + }, [isMacOS]); + + return ( + <> + + + ); +}; diff --git a/pkg/interface/webterm/Spinner.tsx b/pkg/interface/webterm/Spinner.tsx new file mode 100644 index 000000000..3dc9392a1 --- /dev/null +++ b/pkg/interface/webterm/Spinner.tsx @@ -0,0 +1,55 @@ +import useIsMounted from './lib/useIsMounted'; +import React from 'react'; +import { useEffect, useState } from 'react'; + +const DELAY_MS = 1000; +const FRAME_MS = 250; +const CHARS = '|/-\\'; + +const Spinner = () => { + const [index, setIndex] = useState(0); + const [intervalTimer, setIntervalTimer] = useState | undefined>(); + const isMounted = useIsMounted(); + + useEffect(() => { + setIntervalTimer( + setInterval(() => { + if (isMounted()) { + setIndex(idx => idx === CHARS.length - 1 ? 0 : idx + 1); + } + }, FRAME_MS) + ); + + return () => { + if (intervalTimer) { + clearInterval(intervalTimer); + } + }; + }, []); + + return  {CHARS[index]}; +}; + +export const DelayedSpinner = () => { + const [showSpinner, setShowSpinner] = useState(false); + const [delayTimer, setDelayTimer] = useState | undefined>(); + const isMounted = useIsMounted(); + + useEffect(() => { + setDelayTimer( + setTimeout(() => { + if (isMounted()) { + setShowSpinner(true); + } + }, DELAY_MS) + ); + + return () => { + if (delayTimer) { + clearTimeout(delayTimer); + } + }; + }, []); + + return showSpinner ? : null; +}; diff --git a/pkg/interface/webterm/Tab.tsx b/pkg/interface/webterm/Tab.tsx new file mode 100644 index 000000000..85a08ef5e --- /dev/null +++ b/pkg/interface/webterm/Tab.tsx @@ -0,0 +1,55 @@ +import { DEFAULT_SESSION } from './constants'; +import React, { useCallback, useEffect } from 'react'; +import useTermState, { Session } from './state'; +import api from './api'; +import { pokeTask } from '@urbit/api/term'; +import { DelayedSpinner as Spinner } from './Spinner'; + +interface TabProps { + session: Session; + name: string; +} + +export const Tab = ( { session, name }: TabProps ) => { + const isSelected = useTermState().selected === name; + + const onClick = () => { + useTermState.getState().set((state) => { + state.selected = name; + state.sessions[name].hasBell = false; + }); + }; + + const onDelete = useCallback(async (e) => { + e.stopPropagation(); + + // clean up subscription + if(session && session.subscriptionId) { + await api.unsubscribe(session.subscriptionId); + } + + // DELETE + await api.poke(pokeTask(name, { shut: null })); + + // remove from zustand + useTermState.getState().set((state) => { + if (state.selected === name) { + state.selected = DEFAULT_SESSION; + } + state.names = state.names.filter(n => n !== name); + delete state.sessions[name]; + }); + }, [session]); + + return ( +
+ + {session?.hasBell ? '🔔 ' : ''} + {name === DEFAULT_SESSION ? 'default' : name} + {session && session.pending > 0 ? : null} + {' '} + + {name === DEFAULT_SESSION ? null : x} +
+ ); +}; diff --git a/pkg/interface/webterm/Tabs.tsx b/pkg/interface/webterm/Tabs.tsx new file mode 100644 index 000000000..ed583635a --- /dev/null +++ b/pkg/interface/webterm/Tabs.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import useTermState from './state'; +import { Tab } from './Tab'; +import { useAddSession } from './lib/useAddSession'; +import { Icon } from '@tlon/indigo-react'; + +export const Tabs = () => { + const { sessions, names } = useTermState(); + const addSession = useAddSession(); + + return ( +
+ {names.map((n, i) => { + return ( + + ); + })} + +
+ ); +}; diff --git a/pkg/interface/webterm/app.tsx b/pkg/interface/webterm/app.tsx deleted file mode 100644 index c8de116fb..000000000 --- a/pkg/interface/webterm/app.tsx +++ /dev/null @@ -1,475 +0,0 @@ -/* eslint-disable max-lines */ -import React, { - useEffect, - useRef, - useCallback -} from 'react'; - -import useTermState from './state'; -import { useDark } from './join'; -import api from './api'; - -import { Terminal, ITerminalOptions, ITheme } from 'xterm'; -import { FitAddon } from 'xterm-addon-fit'; -import { saveAs } from 'file-saver'; - -import { Box, Col, Reset, _dark, _light } from '@tlon/indigo-react'; - -import 'xterm/css/xterm.css'; - -import { - Belt, Blit, Stye, Stub, Tint, Deco, - pokeTask, pokeBelt -} from '@urbit/api/term'; - -import bel from './lib/bel'; -import { ThemeProvider } from 'styled-components'; - -type TermAppProps = { - ship: string; -} - -const makeTheme = (dark: boolean): ITheme => { - let fg, bg: string; - if (dark) { - fg = 'white'; - bg = 'rgb(26,26,26)'; - } else { - fg = 'black'; - bg = 'white'; - } - // TODO indigo colors. - // we can't pluck these from ThemeContext because they have transparency. - // technically xterm supports transparency, but it degrades performance. - return { - foreground: fg, - background: bg, - brightBlack: '#7f7f7f', // NOTE slogs - cursor: fg, - cursorAccent: bg, - selection: fg - }; -}; - -const termConfig: ITerminalOptions = { - logLevel: 'warn', - // - convertEol: true, - // - rows: 24, - cols: 80, - scrollback: 10000, - // - fontFamily: '"Source Code Pro", "Roboto mono", "Courier New", monospace', - fontWeight: 400, - // NOTE theme colors configured dynamically - // - bellStyle: 'sound', - bellSound: bel, - // - // allows text selection by holding modifier (option, or shift) - macOptionClickForcesSelection: true, - // prevent insertion of simulated arrow keys on-altclick - altClickMovesCursor: false -}; - -const csi = (cmd: string, ...args: number[]) => { - return '\x1b[' + args.join(';') + cmd; -}; - -const tint = (t: Tint) => { - switch (t) { - case null: return '9'; - case 'k': return '0'; - case 'r': return '1'; - case 'g': return '2'; - case 'y': return '3'; - case 'b': return '4'; - case 'm': return '5'; - case 'c': return '6'; - case 'w': return '7'; - default: return `8;2;${t.r%256};${t.g%256};${t.b%256}`; - } -}; - -const stye = (s: Stye) => { - let out = ''; - - // text decorations - // - if (s.deco.length > 0) { - out += s.deco.reduce((decs: number[], deco: Deco) => { - /* eslint-disable max-statements-per-line */ - switch (deco) { - case null: decs.push(0); return decs; - case 'br': decs.push(1); return decs; - case 'un': decs.push(4); return decs; - case 'bl': decs.push(5); return decs; - default: console.log('weird deco', deco); return decs; - } - }, []).join(';'); - } - - // background color - // - if (s.back !== null) { - if (out !== '') { - out += ';'; - } - out += '4'; - out += tint(s.back); - } - - // foreground color - // - if (s.fore !== null) { - if (out !== '') { - out += ';'; - } - out += '3'; - out += tint(s.fore); - } - - if (out === '') { - return out; - } - return '\x1b[' + out + 'm'; -}; - -const showBlit = (term: Terminal, blit: Blit) => { - let out = ''; - - if ('bel' in blit) { - out += '\x07'; - } else if ('clr' in blit) { - term.clear(); - out += csi('u'); - } else if ('hop' in blit) { - if (typeof blit.hop === 'number') { - out += csi('H', term.rows, blit.hop + 1); - } else { - out += csi('H', term.rows - blit.hop.r, blit.hop.c + 1); - } - out += csi('s'); // save cursor position - } else if ('put' in blit) { - out += blit.put.join(''); - out += csi('u'); - } else if ('klr' in blit) { - //TODO remove for new backend - { - out += csi('H', term.rows, 1); - out += csi('K'); - } - out += blit.klr.reduce((lin: string, p: Stub) => { - lin += stye(p.stye); - lin += p.text.join(''); - lin += csi('m', 0); - return lin; - }, ''); - out += csi('u'); - } else if ('nel' in blit) { - out += '\n'; - } else if ('sag' in blit || 'sav' in blit) { - const sav = ('sag' in blit) ? blit.sag : blit.sav; - const name = sav.path.split('/').slice(-2).join('.'); - const buff = Buffer.from(sav.file, 'base64'); - const blob = new Blob([buff], { type: 'application/octet-stream' }); - saveAs(blob, name); - } else if ('url' in blit) { - window.open(blit.url); - } else if ('wyp' in blit) { - out += '\r' + csi('K'); - out += csi('u'); - // - //TODO remove for new backend - } else if ('lin' in blit) { - out += csi('H', term.rows, 1); - out += csi('K'); - out += blit.lin.join(''); - } else if ('mor' in blit) { - out += '\n'; - } else { - console.log('weird blit', blit); - } - - term.write(out); -}; - -// NOTE should generally only be passed the default terminal session -const showSlog = (term: Terminal, slog: string) => { - // set scroll region to exclude the bottom line, - // scroll up one line, - // move cursor to start of the newly created whitespace, - // set text to grey, - // print the slog, - // restore color, scroll region, and cursor. - // - term.write(csi('r', 1, term.rows - 1) - + csi('S', 1) - + csi('H', term.rows - 1, 1) - + csi('m', 90) - + slog - + csi('m', 0) - + csi('r') - + csi('u')); -}; - -const readInput = (term: Terminal, e: string): Belt[] => { - const belts: Belt[] = []; - let strap = ''; - - while (e.length > 0) { - let c = e.charCodeAt(0); - - // text input - // - if (c >= 32 && c !== 127) { - strap += e[0]; - e = e.slice(1); - continue; - } else if ('' !== strap) { - belts.push({ txt: strap.split('') }); - strap = ''; - } - - // special keys/characters - // - if (0 === c) { - term.write('\x07'); // bel - } else if (8 === c || 127 === c) { - belts.push({ bac: null }); - } else if (13 === c) { - belts.push({ ret: null }); - } else if (c <= 26) { - let k = String.fromCharCode(96 + c); - //NOTE prevent remote shut-downs - if ('d' !== k) { - belts.push({ ctl: k }); - //TODO for new backend - // belts.push({ mod: { mod: 'ctl', key: k } }); - } - } - - // escape sequences - // - if (27 === c) { // ESC - e = e.slice(1); - c = e.charCodeAt(0); - if (91 === c || 79 === c) { // [ or O - e = e.slice(1); - c = e.charCodeAt(0); - /* eslint-disable max-statements-per-line */ - switch (c) { - case 65: belts.push({ aro: 'u' }); break; - case 66: belts.push({ aro: 'd' }); break; - case 67: belts.push({ aro: 'r' }); break; - case 68: belts.push({ aro: 'l' }); break; - // - case 77: { - const m = e.charCodeAt(1) - 31; - if (1 === m) { - const c = e.charCodeAt(2) - 32; - const r = e.charCodeAt(3) - 32; - //TODO re-enable for new backend - // belts.push({ hit: { r: term.rows - r, c: c - 1 } }); - } - e = e.slice(3); - break; - } - // - default: term.write('\x07'); break; // bel - } - } else if (c >= 97 && c <= 122) { // a <= c <= z - belts.push({ mod: { mod: 'met', key: e[0] } }); - } else if (c === 46) { // . - belts.push({ mod: { mod: 'met', key: '.' } }); - } else if (c === 8 || c === 127) { - belts.push({ mod: { mod: 'met', key: { bac: null } } }); - } else { - term.write('\x07'); break; // bel - } - } - - e = e.slice(1); - } - if ('' !== strap) { - belts.push({ txt: strap.split('') }); - strap = ''; - } - return belts; -}; - -export default function TermApp(props: TermAppProps) { - const container = useRef(null); - // TODO allow switching of selected - const { sessions, selected, slogstream, set } = useTermState(); - const session = sessions[selected]; - const dark = useDark(); - - const setupSlog = useCallback(() => { - console.log('slog: setting up...'); - let available = false; - const slog = new EventSource('/~_~/slog', { withCredentials: true }); - - slog.onopen = (e) => { - console.log('slog: opened stream'); - available = true; - }; - - slog.onmessage = (e) => { - const session = useTermState.getState().sessions['']; - if (!session) { - console.log('default session mia!', 'slog:', slog); - return; - } - showSlog(session.term, e.data); - }; - - slog.onerror = (e) => { - console.error('slog: eventsource error:', e); - if (available) { - window.setTimeout(() => { - if (slog.readyState !== EventSource.CLOSED) { - return; - } - console.log('slog: reconnecting...'); - setupSlog(); - }, 10000); - } - }; - - set((state) => { - state.slogstream = slog; - }); - }, [sessions]); - - const onInput = useCallback((ses: string, e: string) => { - const term = useTermState.getState().sessions[ses].term; - const belts = readInput(term, e); - belts.map((b) => { // NOTE passing api.poke(pokeBelt makes `this` undefined! - //TODO pokeBelt(ses, b); - api.poke({ - app: 'herm', - mark: 'belt', - json: b - }); - }); - }, [sessions]); - - const onResize = useCallback(() => { - // TODO debounce, if it ever becomes a problem - session?.fit.fit(); - }, [session]); - - // on-init, open slogstream - // - useEffect(() => { - if (!slogstream) { - setupSlog(); - } - window.addEventListener('resize', onResize); - return () => { - // TODO clean up subs? - window.removeEventListener('resize', onResize); - }; - }, [onResize, setupSlog]); - - // on dark mode change, change terminals' theme - // - useEffect(() => { - const theme = makeTheme(dark); - for (const ses in sessions) { - sessions[ses].term.setOption('theme', theme); - } - if (container.current) { - container.current.style.backgroundColor = theme.background || ''; - } - }, [dark, sessions]); - - // on selected change, maybe setup the term, or put it into the container - // - useEffect(() => { - let ses = session; - // initialize terminal - // - if (!ses) { - // set up terminal - // - const term = new Terminal(termConfig); - term.setOption('theme', makeTheme(dark)); - const fit = new FitAddon(); - term.loadAddon(fit); - - // start mouse reporting - // - term.write(csi('?9h')); - - // set up event handlers - // - term.onData(e => onInput(selected, e)); - term.onBinary(e => onInput(selected, e)); - term.onResize((e) => { - //TODO re-enable once new backend lands - // api.poke(pokeTask(selected, { blew: { w: e.cols, h: e.rows } })); - }); - - ses = { term, fit }; - - // open subscription - // - api.subscribe({ app: 'herm', path: '/session/'+selected+'/view', - event: (e) => { - const ses = useTermState.getState().sessions[selected]; - if (!ses) { - console.log('on blit: no such session', selected, sessions, useTermState.getState().sessions); - return; - } - showBlit(ses.term, e); - }, - quit: () => { // quit - // TODO show user a message - } - }); - } - - if (container.current && !container.current.contains(ses.term.element || null)) { - ses.term.open(container.current); - ses.fit.fit(); - ses.term.focus(); - } - - set((state) => { - state.sessions[selected] = ses; - }); - - return () => { - // TODO unload term from container - // but term.dispose is too powerful? maybe just empty the container? - }; - }, [set, session, container]); - - return ( - <> - - - - - - - - - ); -} diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts new file mode 100644 index 000000000..d945b1b46 --- /dev/null +++ b/pkg/interface/webterm/constants.ts @@ -0,0 +1,28 @@ +export const DEFAULT_SESSION = ''; +export const DEFAULT_HANDLER = 'hood'; +export const RESIZE_DEBOUNCE_MS = 100; +export const RESIZE_THRESHOLD_PX = 15; + +/** + * Session ID validity: + * + * - must start with an alphabetical + * - can be composed of alphanumerics with hyphens + * - can be length 1 or longer + */ +export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d-]*$)/; + +/** + * Open a session with a given agent using `[agent]![session_name]` + * + * For example: + * ``` + * book!my-session + * ``` + * + * This will create a new session in webterm for the `%book` agent. + * + * Note that the second capture group after the ! is composed of the session ID + * regex above. + */ +export const AGENT_SESSION_REGEX = /^([a-z]{1}[a-z\d-]*)!([a-z]{1}[a-z\d-]*$)/; diff --git a/pkg/interface/webterm/index.html b/pkg/interface/webterm/index.html index 5eaf05c35..610ba697a 100644 --- a/pkg/interface/webterm/index.html +++ b/pkg/interface/webterm/index.html @@ -23,10 +23,113 @@ diff --git a/pkg/interface/webterm/lib/blit.ts b/pkg/interface/webterm/lib/blit.ts new file mode 100644 index 000000000..720941ff6 --- /dev/null +++ b/pkg/interface/webterm/lib/blit.ts @@ -0,0 +1,129 @@ +import { Terminal } from 'xterm'; +import { saveAs } from 'file-saver'; +import { Blit, Stub, Stye } from '@urbit/api/term'; +import { stye } from '../lib/stye'; + +export const csi = (cmd: string, ...args: number[]) => { + return '\x1b[' + args.join(';') + cmd; +}; + +export const showBlit = (term: Terminal, blit: Blit) => { + let out = ''; + + if ('mor' in blit) { + return blit.mor.map(b => showBlit(term, b)); + } else if ('bel' in blit) { + out += '\x07'; + } else if ('clr' in blit) { + term.clear(); + out += csi('u'); + } else if ('hop' in blit) { + if (typeof blit.hop === 'number') { + out += csi('H', term.rows, blit.hop + 1); + } else { + out += csi('H', blit.hop.y + 1, blit.hop.x + 1); + } + out += csi('s'); // save cursor position + } else if ('put' in blit) { + out += blit.put.join(''); + out += csi('u'); + } else if ('klr' in blit) { + out += blit.klr.reduce((lin: string, p: Stub) => { + lin += stye(p.stye); + lin += p.text.join(''); + lin += csi('m', 0); + return lin; + }, ''); + out += csi('u'); + } else if ('nel' in blit) { + out += '\n'; + } else if ('sag' in blit || 'sav' in blit) { + const sav = ('sag' in blit) ? blit.sag : blit.sav; + const name = sav.path.split('/').slice(-2).join('.'); + const buff = Buffer.from(sav.file, 'base64'); + const blob = new Blob([buff], { type: 'application/octet-stream' }); + saveAs(blob, name); + } else if ('url' in blit) { + window.open(blit.url); + } else if ('wyp' in blit) { + out += '\r' + csi('K'); + out += csi('u'); + // + } else { + console.log('weird blit', blit); + } + + term.write(out); +}; + +export const showSlog = (term: Terminal, slog: string) => { + // set scroll region to exclude the bottom line, + // scroll up one line, + // move cursor to start of the newly created whitespace, + // set text to grey, + // print the slog, + // restore color, scroll region, and cursor. + // + term.write(csi('r', 1, term.rows - 1) + + csi('S', 1) + + csi('H', term.rows - 1, 1) + + csi('m', 90) + + slog + + csi('m', 0) + + csi('r') + + csi('u')); +}; + +export const hasBell = (blit: Blit) => { + if ('bel' in blit) { + return true; + } else if ('mor' in blit) { + return blit.mor.some(hasBell); + } else { + return false; + } +}; + +// debug rendering +//NOTE doesn't behave nicely in the presence of eob %nel blits, +// because those aren't idempotent + +const blotStye: Stye = { deco: [], back: { r: 255, g: 0, b: 255 }, fore: 'k' }; +const blitToBlot = (blit: Blit): Blit => { + if ('mor' in blit) { + return { mor: blit.mor.map(blitToBlot) }; + } else if ('put' in blit) { + return { klr: [{ text: blit.put, stye: blotStye }] }; + } else if ('klr' in blit) { + return { klr: blit.klr.map((s: Stub) => { + return { text: s.text, stye: blotStye }; + }) }; + } else { + return blit; + } +}; + +const queue: {term: Terminal, blit: Blit}[] = []; +const renderFromQueue = () => { + const next = queue.shift(); + if (!next) { + return; + } + showBlit(next.term, next.blit); + if (0 === queue.length) { + return; + } + setTimeout(renderFromQueue, 200); +}; + +export const showBlitDebug = (term: Terminal, blit: Blit) => { + const blot = blitToBlot(blit); + if (0 === queue.length) { + showBlit(term, blot); + queue.push({ term, blit }); + setTimeout(renderFromQueue, 200); + } else { + queue.push({ term, blit: blot }); + queue.push({ term, blit }); + } +}; diff --git a/pkg/interface/webterm/lib/retry.ts b/pkg/interface/webterm/lib/retry.ts new file mode 100644 index 000000000..dea78b0b2 --- /dev/null +++ b/pkg/interface/webterm/lib/retry.ts @@ -0,0 +1,39 @@ +/** + * Wait for the given milliseconds + * @param {number} milliseconds The given time to wait + * @returns {Promise} A fulfiled promise after the given time has passed + */ + function waitFor(milliseconds) { + return new Promise(resolve => setTimeout(resolve, milliseconds)); +} + +/** + * Execute a promise and retry with exponential backoff + * based on the maximum retry attempts it can perform + * @param {Promise} promise promise to be executed + * @param {function} onRetry callback executed on every retry + * @param {number} maxRetries The maximum number of retries to be attempted + * @returns {Promise} The result of the given promise passed in + */ +export function retry(promise, onRetry, maxRetries) { + async function retryWithBackoff(retries) { + try { + if (retries > 0) { + const timeToWait = 2 ** retries * 100; + console.log(`waiting for ${timeToWait}ms...`); + await waitFor(timeToWait); + } + return await promise(); + } catch (e) { + if (retries < maxRetries) { + onRetry(); + return retryWithBackoff(retries + 1); + } else { + console.warn('Max retries reached. Bubbling the error up'); + throw e; + } + } + } + + return retryWithBackoff(0); +} diff --git a/pkg/interface/webterm/lib/stye.ts b/pkg/interface/webterm/lib/stye.ts new file mode 100644 index 000000000..bc2d99b5e --- /dev/null +++ b/pkg/interface/webterm/lib/stye.ts @@ -0,0 +1,60 @@ +import { Deco, Stye, Tint } from '@urbit/api/term'; + +const tint = (t: Tint) => { + switch (t) { + case null: return '9'; + case 'k': return '0'; + case 'r': return '1'; + case 'g': return '2'; + case 'y': return '3'; + case 'b': return '4'; + case 'm': return '5'; + case 'c': return '6'; + case 'w': return '7'; + default: return `8;2;${t.r%256};${t.g%256};${t.b%256}`; + } +}; + +export const stye = (s: Stye) => { + let out = ''; + + // text decorations + // + if (s.deco.length > 0) { + out += s.deco.reduce((decs: number[], deco: Deco) => { + /* eslint-disable max-statements-per-line */ + switch (deco) { + case null: decs.push(0); return decs; + case 'br': decs.push(1); return decs; + case 'un': decs.push(4); return decs; + case 'bl': decs.push(5); return decs; + default: console.log('weird deco', deco); return decs; + } + }, []).join(';'); + } + + // background color + // + if (s.back !== null) { + if (out !== '') { + out += ';'; + } + out += '4'; + out += tint(s.back); + } + + // foreground color + // + if (s.fore !== null) { + if (out !== '') { + out += ';'; + } + out += '3'; + out += tint(s.fore); + } + + if (out === '') { + return out; + } + return '\x1b[' + out + 'm'; +}; diff --git a/pkg/interface/webterm/lib/theme.ts b/pkg/interface/webterm/lib/theme.ts new file mode 100644 index 000000000..cf2beb152 --- /dev/null +++ b/pkg/interface/webterm/lib/theme.ts @@ -0,0 +1,23 @@ +import { ITheme } from 'xterm'; + +export const makeTheme = (dark: boolean): ITheme => { + let fg, bg: string; + if (dark) { + fg = 'white'; + bg = 'rgb(26,26,26)'; + } else { + fg = 'black'; + bg = 'white'; + } + // TODO indigo colors. + // we can't pluck these from ThemeContext because they have transparency. + // technically xterm supports transparency, but it degrades performance. + return { + foreground: fg, + background: bg, + brightBlack: '#7f7f7f', // NOTE slogs + cursor: fg, + cursorAccent: bg, + selection: fg + }; +}; diff --git a/pkg/interface/webterm/lib/useAddSession.ts b/pkg/interface/webterm/lib/useAddSession.ts new file mode 100644 index 000000000..c5556c14b --- /dev/null +++ b/pkg/interface/webterm/lib/useAddSession.ts @@ -0,0 +1,66 @@ +import { + DEFAULT_HANDLER, + AGENT_SESSION_REGEX, + SESSION_ID_REGEX +} from '../constants'; +import useTermState from '../state'; +import api from '../api'; +import { pokeTask } from '@urbit/api/term'; +import { useCallback } from 'react'; + +export const useAddSession = () => { + const { names } = useTermState(); + + const addSession = useCallback(async () => { + let agent = DEFAULT_HANDLER; + let sessionName: string; + + const userInput = prompt('Please enter an alpha-numeric session name.'); + // user canceled or did not enter a value + if (null === userInput) { + return; + } + + // check for custom agent session syntax + if (AGENT_SESSION_REGEX.test(userInput)) { + const match = AGENT_SESSION_REGEX.exec(userInput); + if (!match) { + alert('Invalid format. Valid syntax: agent!session-name'); + return; + } + agent = match[1]; + sessionName = match[2]; + // else, use the default session creation regex + } else if (SESSION_ID_REGEX.test(userInput)) { + const match = SESSION_ID_REGEX.exec(userInput); + if (!match) { + alert('Invalid format. Valid syntax: session-name'); + return; + } + sessionName = match[1]; + } else { + alert('Invalid format. Valid syntax: session-name'); + return; + } + + // prevent duplicate sessions + if(names.includes(sessionName)) { + alert(`Session name must be unique ("${sessionName}" already in use)`); + return; + } + + try { + //TODO eventually, customizable app pre-linking? + await api.poke(pokeTask(sessionName, { open: { term: agent, apps: [{ who: '~' + (window as any).ship, app: 'dojo' }] } })); + useTermState.getState().set((state) => { + state.names = [sessionName, ...state.names].sort(); + state.selected = sessionName; + state.sessions[sessionName] = null; + }); + } catch (error) { + console.log('unable to create session:', error); + } + }, [names]); + + return addSession; +}; diff --git a/pkg/interface/webterm/join.ts b/pkg/interface/webterm/lib/useDark.ts similarity index 74% rename from pkg/interface/webterm/join.ts rename to pkg/interface/webterm/lib/useDark.ts index 957abbd3d..ddd9c10ae 100644 --- a/pkg/interface/webterm/join.ts +++ b/pkg/interface/webterm/lib/useDark.ts @@ -1,6 +1,5 @@ import { useEffect, useState } from 'react'; -import { useTheme } from './settings'; -import useTermState from './state'; +import useTermState from '../state'; export function useDark() { const [osDark, setOsDark] = useState(false); @@ -11,12 +10,11 @@ export function useDark() { setOsDark(e.matches); }; setOsDark(themeWatcher.matches); - themeWatcher.addListener(update); + themeWatcher.addEventListener('change', update); return () => { - themeWatcher.removeListener(update); - } - + themeWatcher.removeEventListener('change', update); + }; }, []); const theme = useTermState(s => s.theme); diff --git a/pkg/interface/webterm/lib/useDetectOS.ts b/pkg/interface/webterm/lib/useDetectOS.ts new file mode 100644 index 000000000..7b8f915f9 --- /dev/null +++ b/pkg/interface/webterm/lib/useDetectOS.ts @@ -0,0 +1,44 @@ +/* eslint-disable no-useless-escape */ +// Regex patterns inspired by: +// https://github.com/faisalman/ua-parser-js/blob/master/src/ua-parser.js +const LINUX = [ + /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i, + /(mint)[\/\(\) ]?(\w*)/i, + /(mageia|vectorlinux)[; ]/i, + /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i, + /(hurd|linux) ?([\w\.]*)/i, + /(gnu) ?([\w\.]*)/i, + /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, + /(haiku) (\w+)/i, + /(sunos) ?([\w\.\d]*)/i, + /((?:open)?solaris)[-\/ ]?([\w\.]*)/i, + /(aix) ((\d)(?=\.|\)| )[\w\.])*/i, + /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux)/i, + /(unix) ?([\w\.]*)/i +]; + +const MAC_OS = [ + /(mac os x) ?([\w\. ]*)/i, + /(macintosh|mac_powerpc\b)(?!.+haiku)/i +]; + +const WINDOWS = [ + /microsoft (windows) (vista|xp)/i, + /(windows) nt 6\.2; (arm)/i, + /(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i, + /(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i +]; + +export const useDetectOS = () => { + const userAgent = navigator.userAgent; + + const isLinux = LINUX.some(regex => regex.test(userAgent)); + const isMacOS = MAC_OS.some(regex => regex.test(userAgent)); + const isWindows = WINDOWS.some(regex => regex.test(userAgent)); + + return { + isLinux, + isMacOS, + isWindows + }; +}; diff --git a/pkg/interface/webterm/lib/useIsMounted.ts b/pkg/interface/webterm/lib/useIsMounted.ts new file mode 100644 index 000000000..fdfaca3e0 --- /dev/null +++ b/pkg/interface/webterm/lib/useIsMounted.ts @@ -0,0 +1,17 @@ +import { useCallback, useEffect, useRef } from 'react'; + +function useIsMounted() { + const isMounted = useRef(false); + + useEffect(() => { + isMounted.current = true; + + return () => { + isMounted.current = false; + }; + }, []); + + return useCallback(() => isMounted.current, []); +} + +export default useIsMounted; diff --git a/pkg/interface/webterm/package-lock.json b/pkg/interface/webterm/package-lock.json index 2e42a0ff0..4e617d5f3 100644 Binary files a/pkg/interface/webterm/package-lock.json and b/pkg/interface/webterm/package-lock.json differ diff --git a/pkg/interface/webterm/package.json b/pkg/interface/webterm/package.json index e859b4825..0e58cc608 100644 --- a/pkg/interface/webterm/package.json +++ b/pkg/interface/webterm/package.json @@ -11,6 +11,7 @@ "@urbit/api": "^1.1.1", "@urbit/http-api": "^1.2.1", "file-saver": "^2.0.5", + "lodash": "^4.17.21", "react": "^16.14.0", "react-dom": "^16.14.0", "react-router-dom": "^5.2.0", @@ -36,7 +37,7 @@ "@types/styled-system": "^5.1.10", "@typescript-eslint/eslint-plugin": "^4.15.0", "@typescript-eslint/parser": "^4.24.0", - "@urbit/eslint-config": "^1.0.0", + "@urbit/eslint-config": "^1.0.3", "@welldone-software/why-did-you-render": "^6.1.0", "babel-eslint": "^10.1.0", "babel-jest": "^26.6.3", @@ -45,7 +46,9 @@ "clean-webpack-plugin": "^3.0.0", "cross-env": "^7.0.3", "eslint": "^7.26.0", - "eslint-plugin-react": "^7.22.0", + "eslint-import-resolver-typescript": "^2.5.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-react-hooks": "^4.3.0", "file-loader": "^6.2.0", "html-webpack-plugin": "^4.5.1", "husky": "^6.0.0", @@ -58,7 +61,8 @@ "webpack-dev-server": "^3.11.2" }, "scripts": { - "lint": "eslint ./src/**/*.{ts,tsx}", + "lint": "eslint ./**/*.{ts,tsx}", + "lint-fix": "eslint --fix ./**/*.{ts,tsx}", "lint-file": "eslint", "tsc": "tsc", "tsc:watch": "tsc --watch", diff --git a/pkg/interface/webterm/state.ts b/pkg/interface/webterm/state.ts index 253e7854f..d61d798cb 100644 --- a/pkg/interface/webterm/state.ts +++ b/pkg/interface/webterm/state.ts @@ -3,21 +3,33 @@ import { FitAddon } from 'xterm-addon-fit'; import create from 'zustand'; import produce from 'immer'; -type Session = { term: Terminal, fit: FitAddon }; -type Sessions = { [id: string]: Session; } +export type Session = { + term: Terminal, + fit: FitAddon, + hasBell: boolean, + pending: number, + subscriptionId: number | null, +} | null; +export type Sessions = { [id: string]: Session; } export interface TermState { sessions: Sessions, + names: string[], selected: string, slogstream: null | EventSource, - theme: 'auto' | 'light' | 'dark' -}; + theme: 'auto' | 'light' | 'dark', + //TODO: figure out the type + set: any, +} +// eslint-disable-next-line no-unused-vars const useTermState = create((set, get) => ({ sessions: {} as Sessions, + names: [''], selected: '', // empty string is default session slogstream: null, theme: 'auto', + // eslint-disable-next-line no-unused-vars set: (f: (draft: TermState) => void) => { set(produce(f)); } diff --git a/pkg/interface/webterm/tsconfig.json b/pkg/interface/webterm/tsconfig.json new file mode 100644 index 000000000..9a8642966 --- /dev/null +++ b/pkg/interface/webterm/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "noFallthroughCasesInSwitch": true, + "noUnusedParameters": false, + "noImplicitReturns": false, + "moduleResolution": "node", + "esModuleInterop": true, + "noUnusedLocals": false, + "noImplicitAny": false, + "noEmit": true, + "target": "ESNext", + "module": "ESNext", + "strict": false, + "strictNullChecks": true, + "jsx": "react", + "baseUrl": "." + }, + "include": [ + "**/*" + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/pkg/landscape/app/chat-cli.hoon b/pkg/landscape/app/chat-cli.hoon index 4398cc7e8..a5aa5dee2 100644 --- a/pkg/landscape/app/chat-cli.hoon +++ b/pkg/landscape/app/chat-cli.hoon @@ -16,15 +16,15 @@ +$ card card:shoe :: +$ versioned-state - $% state-3 + $% state-4 + state-3 state-2 state-1 state-0 == :: -+$ state-3 - $: %3 - ::TODO support multiple sessions ++$ state-4 + $: %4 sessions=(map sole-id session) :: sole sessions bound=(map resource glyph) :: bound resource glyphs binds=(jug glyph resource) :: resource glyph lookup @@ -33,7 +33,17 @@ timez=(pair ? @ud) :: timezone adjustment == :: -+$ sole-id @ta ++$ state-3 + $: %3 + sessions=(map @ta session) + bound=(map resource glyph) + binds=(jug glyph resource) + settings=(set term) + width=@ud + timez=(pair ? @ud) + == +:: ++$ sole-id sole-id:shoe +$ session $: viewing=(set resource) :: connected graphs history=(list uid:post) :: scrollback pointers @@ -115,7 +125,7 @@ == :: :: -- -=| state-3 +=| state-4 =* state - :: %- agent:dbug @@ -258,14 +268,14 @@ settings width timez == :: - =^ cards u.old + =^ cards-1 u.old ?. ?=(%2 -.u.old) [~ u.old] :- :~ [%pass /chat-store %agent [our-self %chat-store] %leave ~] [%pass /invites %agent [our.bowl %invite-store] %leave ~] == ^- state-3 :- %3 - :* %+ ~(put in *(map sole-id session)) + :* %+ ~(put in *(map @ta session)) (cat 3 'drum_' (scot %p our.bowl)) :* ~ ~ 0 :: @@ -290,14 +300,29 @@ timez.u.old == :: - ?> ?=(%3 -.u.old) + =^ cards-2 u.old + ?. ?=(%3 -.u.old) [~ u.old] + :- %+ turn ~(tap in ~(key by sessions.u.old)) + |= id=@ta + ^- card:agent:gall + [%give %kick ~[/sole/[id]] ~] + =- u.old(- %4, sessions -) + %- ~(gas by *(map sole-id session)) + %+ murn ~(tap by sessions.u.old) + |= [id=@ta s=session] + (bind (upgrade-id:sole:shoe id) (late s)) + :: + ?> ?=(%4 -.u.old) :_ u.old - %+ welp - cards - ?: %- ~(has by wex.bowl) - [/graph-store our-self %graph-store] - ~ - ~[connect] + ;: welp + cards-1 + cards-2 + :: + ?: %- ~(has by wex.bowl) + [/graph-store our-self %graph-store] + ~ + ~[connect] + == :: +connect: connect to the graph-store :: ++ connect diff --git a/pkg/landscape/lib/dill.hoon b/pkg/landscape/lib/dill.hoon new file mode 120000 index 000000000..f9c2362f0 --- /dev/null +++ b/pkg/landscape/lib/dill.hoon @@ -0,0 +1 @@ +../../base-dev/lib/dill.hoon \ No newline at end of file diff --git a/pkg/landscape/sys.kelvin b/pkg/landscape/sys.kelvin index b7bcb9ecd..0cb1220e5 100644 --- a/pkg/landscape/sys.kelvin +++ b/pkg/landscape/sys.kelvin @@ -1 +1 @@ -[%zuse 417] +[%zuse 416] diff --git a/pkg/npm/api/README.md b/pkg/npm/api/README.md index c8381a52d..6de8a5f66 100644 --- a/pkg/npm/api/README.md +++ b/pkg/npm/api/README.md @@ -24,7 +24,7 @@ With: import UrbitInterface from '@urbit/http-api'; import { settings } from '@urbit/api'; const api: UrbitInterface = useApi(); -api.poke(setings.putEntry(bucket, key, value)); +api.poke(settings.putEntry(bucket, key, value)); ``` You may import single functions @@ -38,4 +38,4 @@ import { settings } from '@urbit/api'; This package also provides types and utilities for working with Urbit's internal data structures, such as Nouns, Das, Tas, and so forth. -This package was originally developed as part of Tlon's Landscape client and therefore the best reference material exists [there](https://github.com/urbit/urbit/tree/master/pkg/interface/src). \ No newline at end of file +This package was originally developed as part of Tlon's Landscape client and therefore the best reference material exists [there](https://github.com/urbit/urbit/tree/master/pkg/interface/src). diff --git a/pkg/npm/api/term/lib.ts b/pkg/npm/api/term/lib.ts index d67f91477..67e14175f 100644 --- a/pkg/npm/api/term/lib.ts +++ b/pkg/npm/api/term/lib.ts @@ -1,4 +1,5 @@ -import { Poke } from '../lib' +import { Scry } from '../../http-api/src' +import { Poke } from '../../http-api/src/types'; import { Belt, Task, SessionTask } from './types'; export const pokeTask = (session: string, task: Task): Poke => ({ @@ -13,9 +14,7 @@ export const pokeBelt = ( ): Poke => pokeTask(session, { belt }); //NOTE scry will return string[] -// export const scrySessions = (): Scry => ({ -// app: 'herm', -// path: `/sessions` -// }); -//TODO remove stub once new backend lands -export const scrySessions = (): string[] => ['']; +export const scrySessions = (): Scry => ({ + app: 'herm', + path: `/sessions` +}); diff --git a/pkg/npm/api/term/types.ts b/pkg/npm/api/term/types.ts index 2920200aa..2f352a728 100644 --- a/pkg/npm/api/term/types.ts +++ b/pkg/npm/api/term/types.ts @@ -25,17 +25,15 @@ export type Stub = { export type Blit = | { bel: null } // make a noise | { clr: null } // clear the screen - | { hop: number | { r: number, c: number } } // set cursor col/pos + | { hop: number | { x: number, y: number } } // set cursor col/pos | { klr: Stub[] } // put styled - | { put: string[] } // put text at cursor + | { mor: Blit[] } // multiple blits | { nel: null } // newline + | { put: string[] } // put text at cursor | { sag: { path: string, file: string } } // save to jamfile | { sav: { path: string, file: string } } // save to file | { url: string } // activate url | { wyp: null } // wipe cursor line - // - | { lin: string[] } // legacy put - | { mor: true } // legacy nel // inputs // @@ -45,21 +43,19 @@ export type Bolt = | { aro: 'd' | 'l' | 'r' | 'u' } | { bac: null } | { del: null } - | { hit: { r: number, c: number } } + | { hit: { x: number, y: number } } | { ret: null } export type Belt = | Bolt | { mod: { mod: 'ctl' | 'met' | 'hyp', key: Bolt } } | { txt: Array } - // - | { ctl: string }; // legacy mod export type Task = | { belt: Belt } | { blew: { w: number, h: number } } - | { flow: { term: string, apps: Array<{ who: string, app: string }> } } | { hail: null } - | { hook: null } + | { open: { term: string, apps: Array<{ who: string, app: string }> } } + | { shut: null } export type SessionTask = { session: string } & Task diff --git a/pkg/urbit/compat/posix/ptty.c b/pkg/urbit/compat/posix/ptty.c index ff42abff9..7c1a17f00 100644 --- a/pkg/urbit/compat/posix/ptty.c +++ b/pkg/urbit/compat/posix/ptty.c @@ -167,6 +167,9 @@ u3_ptty_init(uv_loop_t* lup_u, const c3_c** err_c) // Construct raw termios configuration. // + // makes input available per-character, does not echo input, + // disables special input pre-processing, output post-processing. + // { pty_u->raw_u = pty_u->bak_u; diff --git a/pkg/urbit/configure b/pkg/urbit/configure index db2b1ec5c..acea03a86 100755 --- a/pkg/urbit/configure +++ b/pkg/urbit/configure @@ -211,7 +211,7 @@ for citem in $compat; do done cat >config.mk <cax.har_p); @@ -31,7 +31,7 @@ u3qe_jam(u3_atom a) u3a_print_memory(stderr, "total", tot_w); u3a_print_memory(stderr, "memoization cache", mem_w); u3h_root* har_u = u3to(u3h_root, u3R->cax.har_p); - u3l_log("memoization entries: %d\r\n", har_u->use_w); + u3l_log("memoization entries: %d", har_u->use_w); u3a_print_memory(stderr, "unused free", u3a_open(u3R)); return tot_w; } diff --git a/pkg/urbit/jets/e/rub.c b/pkg/urbit/jets/e/rub.c index 641e53035..48a1116b3 100644 --- a/pkg/urbit/jets/e/rub.c +++ b/pkg/urbit/jets/e/rub.c @@ -31,7 +31,7 @@ // Sanity check: crash if decoding more bits than available if ( c3y == u3qa_gth(x, m)) { - // u3l_log("[%%rub-hard %d %d %d]\r\n", a, x, m); + // u3l_log("[%%rub-hard %d %d %d]", a, x, m); return u3m_bail(c3__exit); } diff --git a/pkg/urbit/jets/e/secp.c b/pkg/urbit/jets/e/secp.c index 21569603c..21c6f7daa 100644 --- a/pkg/urbit/jets/e/secp.c +++ b/pkg/urbit/jets/e/secp.c @@ -16,7 +16,7 @@ u3je_secp_init() sec_u = malloc(urcrypt_secp_prealloc_size()); if ( 0 != urcrypt_secp_init(sec_u, ent_y) ) { - u3l_log("u3e_secp_init failed\r\n"); + u3l_log("u3e_secp_init failed"); abort(); } } diff --git a/pkg/urbit/jets/f/core.c b/pkg/urbit/jets/f/core.c index 753ea74de..5d7ef8015 100644 --- a/pkg/urbit/jets/f/core.c +++ b/pkg/urbit/jets/f/core.c @@ -22,7 +22,7 @@ (u3_nul == u3h(hr_con)) && (u3_nul == u3t(hr_con)) ) { - u3l_log("old core\r\n"); + u3l_log("old core"); abort(); } } diff --git a/pkg/urbit/jets/f/look.c b/pkg/urbit/jets/f/look.c index e54091b0b..038f7a522 100644 --- a/pkg/urbit/jets/f/look.c +++ b/pkg/urbit/jets/f/look.c @@ -20,7 +20,7 @@ u3r_trel(dab, &n_dab, &l_dab, &r_dab); if ( c3n == u3du(n_dab) ) { // return u3m_bail(c3__fail); - u3l_log("bad look\r\n"); + u3l_log("bad look"); return u3m_bail(c3__exit) ; } else { diff --git a/pkg/urbit/noun/allocate.c b/pkg/urbit/noun/allocate.c index f7ce67958..3eb32dac8 100644 --- a/pkg/urbit/noun/allocate.c +++ b/pkg/urbit/noun/allocate.c @@ -431,7 +431,7 @@ _ca_willoc(c3_w len_w, c3_w ald_w, c3_w alp_w) sel_w += 1; } - // u3l_log("walloc %d: *pfr_p %x\n", len_w, u3R->all.fre_p[sel_w]); + // u3l_log("walloc %d: *pfr_p %x", len_w, u3R->all.fre_p[sel_w]); while ( 1 ) { u3p(u3a_fbox) *pfr_p = &u3R->all.fre_p[sel_w]; @@ -566,7 +566,7 @@ u3a_walloc(c3_w len_w) u3a_botox(ptr_v) == (u3a_box*)(void *)0x200dfe3e4 ) { static int xuc_i; - u3l_log("xuc_i %d\r\n", xuc_i); + u3l_log("xuc_i %d", xuc_i); if ( 1 == xuc_i ) { u3a_box* box_u = u3a_botox(ptr_v); @@ -682,7 +682,7 @@ u3a_malloc(size_t len_i) if ( u3a_botox(out_w) == (u3a_box*)(void *)0x3bdd1c80) { static int xuc_i = 0; - u3l_log("xuc_i %d\r\n", xuc_i); + u3l_log("xuc_i %d", xuc_i); // if ( 1 == xuc_i ) { abort(); } xuc_i++; } @@ -885,7 +885,7 @@ u3a_free(void* tox_v) c3_w pad_w = tox_w[-1]; c3_w* org_w = tox_w - (pad_w + 1); - // u3l_log("free %p %p\r\n", org_w, tox_w); + // u3l_log("free %p %p", org_w, tox_w); u3a_wfree(org_w); } @@ -1013,7 +1013,7 @@ _ca_take_atom(u3a_atom* old_u) u3_noun new = u3a_to_pug(u3a_outa(new_u)); #ifdef VERBOSE_TAKE - u3l_log("%s: atom %p to %p\r\n", ( c3y == u3a_is_north(u3R) ) + u3l_log("%s: atom %p to %p", ( c3y == u3a_is_north(u3R) ) ? "north" : "south", old_u, @@ -1051,7 +1051,7 @@ _ca_take_cell(u3a_cell* old_u, u3_noun hed, u3_noun tel) u3_cell new = u3a_to_pom(u3a_outa(new_u)); #ifdef VERBOSE_TAKE - u3l_log("%s: cell %p to %p\r\n", ( c3y == u3a_is_north(u3R) ) + u3l_log("%s: cell %p to %p", ( c3y == u3a_is_north(u3R) ) ? "north" : "south", old_u, @@ -1110,7 +1110,7 @@ _ca_take_next_north(u3a_pile* pil_u, u3_noun veb) c3_assert( c3y == u3a_north_is_normal(u3R, nov) ); #ifdef VERBOSE_TAKE - u3l_log("north: %p is already %p\r\n", veb_u, u3a_to_ptr(nov)); + u3l_log("north: %p is already %p", veb_u, u3a_to_ptr(nov)); #endif _me_gain_use(nov); // bypass branches in u3k() @@ -1165,7 +1165,7 @@ _ca_take_next_south(u3a_pile* pil_u, u3_noun veb) c3_assert( c3y == u3a_south_is_normal(u3R, nov) ); #ifdef VERBOSE_TAKE - u3l_log("south: %p is already %p\r\n", veb_u, u3a_to_ptr(nov)); + u3l_log("south: %p is already %p", veb_u, u3a_to_ptr(nov)); #endif _me_gain_use(nov); // bypass branches in u3k() diff --git a/pkg/urbit/noun/events.c b/pkg/urbit/noun/events.c index ceec1bd41..d277213c0 100644 --- a/pkg/urbit/noun/events.c +++ b/pkg/urbit/noun/events.c @@ -142,7 +142,7 @@ u3e_check(c3_c* cap_c) } sum_w += mug_w; } - u3l_log("%s: sum %x (%x, %x)\r\n", cap_c, sum_w, nor_w, sou_w); + u3l_log("%s: sum %x (%x, %x)", cap_c, sum_w, nor_w, sou_w); } } @@ -488,7 +488,7 @@ _ce_patch_verify(u3_ce_patch* pat_u) } #if 0 else { - u3l_log("verify: patch %d/%d, %x\r\n", pag_w, i_w, mug_w); + u3l_log("verify: patch %d/%d, %x", pag_w, i_w, mug_w); } #endif } @@ -815,7 +815,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) } } #if 0 - u3l_log("apply: %d, %x\n", pag_w, u3r_mug_words(mem_w, pag_wiz_i)); + u3l_log("apply: %d, %x", pag_w, u3r_mug_words(mem_w, pag_wiz_i)); #endif } } @@ -1169,13 +1169,13 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) (u3_Loom + u3C.wor_i) - pag_wiz_i, -(ssize_t)pag_wiz_i); - u3l_log("boot: protected loom\r\n"); + u3l_log("boot: protected loom"); } /* If the images were empty, we are logically booting. */ if ( (0 == u3P.nor_u.pgs_w) && (0 == u3P.sou_u.pgs_w) ) { - u3l_log("live: logical boot\r\n"); + u3l_log("live: logical boot"); nuu_o = c3y; } else { diff --git a/pkg/urbit/noun/jets.c b/pkg/urbit/noun/jets.c index 357e94bd8..c60badf5d 100644 --- a/pkg/urbit/noun/jets.c +++ b/pkg/urbit/noun/jets.c @@ -75,7 +75,7 @@ _cj_hash(c3_c* has_c) { c3_w i_w, len_w = strlen(has_c); if ( 64 != len_w ) { - u3l_log("bash not 64 characters: %s\r\n", has_c); + u3l_log("bash not 64 characters: %s", has_c); c3_assert(0); } c3_assert( 64 == len_w ); @@ -236,18 +236,18 @@ _cj_axis(u3_noun fol) (0 != p_fol) || (!_(u3a_is_cat(q_fol))) ) { - u3l_log("axis: bad a\r\n"); + u3l_log("axis: bad a"); return 0; } return q_fol; } else { if ( 9 != p_fol ) - { u3l_log("axis: bad b\r\n"); return 0; } + { u3l_log("axis: bad b"); return 0; } if ( !_(u3a_is_cat(q_fol)) ) - { u3l_log("axis: bad c\r\n"); return 0; } + { u3l_log("axis: bad c"); return 0; } if ( !_(u3du(r_fol)) || (0 != u3h(r_fol)) || (1 != u3t(r_fol)) ) - { u3l_log("axis: bad d\r\n"); return 0; } + { u3l_log("axis: bad d"); return 0; } return q_fol; } @@ -278,7 +278,7 @@ _cj_warm_hump(c3_l jax_l, u3_noun huc) ((1 << 31) & (axe_l = (c3_w)axe_d)) || (axe_l < 2) ) { - u3l_log("jets: activate: bad fcs %s\r\n", jet_u->fcs_c); + u3l_log("jets: activate: bad fcs %s", jet_u->fcs_c); } } else { @@ -286,7 +286,7 @@ _cj_warm_hump(c3_l jax_l, u3_noun huc) u3_noun fol = u3kdb_get(u3k(huc), nam); if ( u3_none == fol ) { - u3l_log("jets: activate: bad fcs %s\r\n", jet_u->fcs_c); + u3l_log("jets: activate: bad fcs %s", jet_u->fcs_c); } else { axe_l = _cj_axis(fol); @@ -781,7 +781,7 @@ _cj_hot_mean(c3_l par_l, u3_noun nam) while ( (cop_u = &dev_u[i_l])->cos_c ) { if ( _(u3r_sing_c(cop_u->cos_c, nam)) ) { #if 0 - u3l_log("hot: bound jet %d/%s/%s/\r\n", + u3l_log("hot: bound jet %d/%s/%s/", cop_u->jax_l, cop_u->cos_c, par_u ? par_u->cos_c : "~"); @@ -893,7 +893,7 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) ham_u->liv = c3y; if ( c3n == u3r_sing(ame, pro) ) { - u3l_log("test: %s %s: mismatch: good %x, bad %x\r\n", + u3l_log("test: %s %s: mismatch: good %x, bad %x", cop_u->cos_c, (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c, u3r_mug(ame), @@ -905,7 +905,7 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) else { #if 0 - u3l_log("test: %s %s\r\n", + u3l_log("test: %s %s", cop_u->cos_c, (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c); #endif @@ -928,13 +928,13 @@ _cj_hook_in(u3_noun cor, u3_noun roc, tem, got, pat, nam, huc; if ( c3n == u3du(cor) ) { - u3l_log("_cj_hook_in failure: c3n == u3du(cor)\r\n"); + u3l_log("_cj_hook_in failure: c3n == u3du(cor)"); return u3m_bail(c3__fail); } loc = _cj_spot(cor, NULL); if ( u3_none == loc ) { - u3l_log("_cj_hook_in failure: u3_none == loc\r\n"); + u3l_log("_cj_hook_in failure: u3_none == loc"); return u3m_bail(c3__fail); } @@ -999,7 +999,7 @@ _cj_hook_in(u3_noun cor, else { u3_noun sat = u3t(pat); if ( c3y == u3h(sat) ) { - u3l_log("_cj_hook_in failure: c3y == u3h(sat)\r\n"); + u3l_log("_cj_hook_in failure: c3y == u3h(sat)"); return u3m_bail(c3__fail); } else { @@ -1687,7 +1687,7 @@ u3j_gate_prep(u3j_site* sit_u, u3_noun cor) pay = u3qc_cap(pax), pam = u3qc_mas(pax); if ( 3 != pay || 2 == pam || (3 != pam && 3 != u3qc_cap(pam)) ) { - u3l_log("u3j_gate_prep(): parent axis includes sample\r\n"); + u3l_log("u3j_gate_prep(): parent axis includes sample"); u3m_p("axis", pax); u3_weak act = _cj_find_warm(loc); c3_assert( u3_none != act ); @@ -1758,12 +1758,12 @@ _cj_minx(u3_noun cey, u3_noun cor) par = u3r_at(axe, cor); if ( u3_none == par || c3n == u3du(par) ) { - u3l_log("fund: %s is bogus\r\n", u3r_string(nam)); + u3l_log("fund: %s is bogus", u3r_string(nam)); return u3_none; } pel = _cj_spot(par, NULL); if ( u3_none == pel ) { - u3l_log("fund: in %s, parent %x not found at %d\r\n", + u3l_log("fund: in %s, parent %x not found at %d", u3r_string(nam), u3r_mug(u3h(par)), axe); @@ -1822,7 +1822,7 @@ _cj_mine(u3_noun cey, u3_noun cor, u3_noun bas) jax_l = _cj_hot_mean(par_l, nam); #if 0 u3m_p("new jet", bal); - u3l_log(" bat %x, jax %d\r\n", u3r_mug(bat), jax_l); + u3l_log(" bat %x, jax %d", u3r_mug(bat), jax_l); #endif if ( !(u3C.wag_w & u3o_hashless) ) { @@ -1840,7 +1840,7 @@ _cj_mine(u3_noun cey, u3_noun cor, u3_noun bas) for ( i_w = 32; i_w > 0; ) { u3l_log("%02x", dig_y[--i_w]); } - u3l_log("\r\n"); + u3l_log(""); } } @@ -1870,7 +1870,7 @@ _cj_mine(u3_noun cey, u3_noun cor, u3_noun bas) if ( c3n == hav_o ) { u3m_p("unregistered battery", bal); - u3l_log("hash: %x\r\n", bas); + u3l_log("hash: %x", bas); } u3z(bas); } @@ -2093,7 +2093,7 @@ _cj_ream(u3_noun all) act = u3nq(jax_l, hap, bal, _cj_jit(jax_l, bat)); #if 0 u3m_p("old jet", bal); - u3l_log(" bat %x, jax %d\r\n", u3r_mug(bat), jax_l); + u3l_log(" bat %x, jax %d", u3r_mug(bat), jax_l); #endif u3h_put(u3R->jed.war_p, loc, act); } @@ -2132,7 +2132,7 @@ _cj_ream(u3_noun all) act = u3nq(jax_l, hap, bal, _cj_jit(jax_l, bat)); #if 0 u3m_p("old jet", bal); - u3l_log(" bat %x, jax %d\r\n", u3r_mug(bat), jax_l); + u3l_log(" bat %x, jax %d", u3r_mug(bat), jax_l); #endif u3h_put(u3R->jed.war_p, loc, act); } diff --git a/pkg/urbit/noun/log.c b/pkg/urbit/noun/log.c index 866a7430e..ddab9d52b 100644 --- a/pkg/urbit/noun/log.c +++ b/pkg/urbit/noun/log.c @@ -22,6 +22,8 @@ u3l_log(const char* format, ...) // this process did not set a logging function, fallback to stderr // vfprintf(stderr, format, myargs); + fprintf(stderr, "\r\n"); + fflush(stderr); } va_end(myargs); @@ -31,7 +33,7 @@ u3_weak u3l_punt(const char* name, u3_weak pro) { if ( u3_none == pro ) { - u3l_log("%s-punt\r\n", name); + u3l_log("%s-punt", name); } return pro; } diff --git a/pkg/urbit/noun/manage.c b/pkg/urbit/noun/manage.c index aa33b0328..7052c4d40 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -318,7 +318,7 @@ _cm_signal_recover(c3_l sig_l, u3_noun arg) while ( rod_u->kid_p ) { #if 0 - u3l_log("collecting %d frames\r\n", + u3l_log("collecting %d frames", u3kb_lent((u3to(u3_road, rod_u->kid_p)->bug.tax)); #endif tax = u3kb_weld(_cm_stack_recover(u3to(u3_road, rod_u->kid_p)), tax); @@ -374,7 +374,7 @@ _cm_signal_deep(c3_w mil_w) itm_u.it_value.tv_usec = 1000 * (mil_w % 1000); if ( rsignal_setitimer(ITIMER_VIRTUAL, &itm_u, 0) ) { - u3l_log("loom: set timer failed %s\r\n", strerror(errno)); + u3l_log("loom: set timer failed %s", strerror(errno)); } else { rsignal_install_handler(SIGVTALRM, _cm_signal_handle_alrm); @@ -407,7 +407,7 @@ _cm_signal_done() timerclear(&itm_u.it_value); if ( rsignal_setitimer(ITIMER_VIRTUAL, &itm_u, 0) ) { - u3l_log("loom: clear timer failed %s\r\n", strerror(errno)); + u3l_log("loom: clear timer failed %s", strerror(errno)); } } @@ -439,7 +439,7 @@ u3m_file(c3_c* pas_c) c3_y* pad_y; if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) { - u3l_log("%s: %s\r\n", pas_c, strerror(errno)); + u3l_log("%s: %s", pas_c, strerror(errno)); return u3m_bail(c3__fail); } fln_w = buf_b.st_size; @@ -639,7 +639,7 @@ u3m_dump(void) fre_u = fre_u->nex_u; } } - u3l_log("dump: hat_w %x, fre_w %x, allocated %x\n", + u3l_log("dump: hat_w %x, fre_w %x, allocated %x", hat_w, fre_w, (hat_w - fre_w)); if ( 0 != (hat_w - fre_w) ) { @@ -651,14 +651,14 @@ u3m_dump(void) if ( 0 != box_u->use_w ) { #ifdef U3_MEMORY_DEBUG - // u3l_log("live %d words, code %x\n", box_u->siz_w, box_u->cod_w); + // u3l_log("live %d words, code %x", box_u->siz_w, box_u->cod_w); #endif mem_w += box_u->siz_w; } box_w += box_u->siz_w; } - u3l_log("second count: %x\n", mem_w); + u3l_log("second count: %x", mem_w); } } #endif @@ -1585,7 +1585,7 @@ u3m_p(const c3_c* cap_c, u3_noun som) { c3_c* pre_c = u3m_pretty(som); - u3l_log("%s: %s\r\n", cap_c, pre_c); + u3l_log("%s: %s", cap_c, pre_c); c3_free(pre_c); } @@ -1646,7 +1646,7 @@ _cm_limits(void) rlm.rlim_cur = c3_min(rlm.rlim_max, (65536 << 10)); if ( 0 != setrlimit(RLIMIT_STACK, &rlm) ) { - u3l_log("boot: stack size: %s\r\n", strerror(errno)); + u3l_log("boot: stack size: %s", strerror(errno)); exit(1); } } @@ -1665,7 +1665,7 @@ _cm_limits(void) // no exit, not a critical limit // if ( 0 != setrlimit(RLIMIT_NOFILE, &rlm) ) { - u3l_log("boot: open file limit: %s\r\n", strerror(errno)); + u3l_log("boot: open file limit: %s", strerror(errno)); } } @@ -1679,7 +1679,7 @@ _cm_limits(void) // no exit, not a critical limit // if ( 0 != setrlimit(RLIMIT_CORE, &rlm) ) { - u3l_log("boot: core limit: %s\r\n", strerror(errno)); + u3l_log("boot: core limit: %s", strerror(errno)); } } # endif @@ -1702,7 +1702,7 @@ _cm_signals(void) // access and stack overflow exceptions. It calls u3e_fault directly. # else if ( 0 != sigsegv_install_handler(u3e_fault) ) { - u3l_log("boot: sigsegv install failed\n"); + u3l_log("boot: sigsegv install failed"); exit(1); } # endif @@ -1718,7 +1718,7 @@ _cm_signals(void) sigaddset(&set, SIGPROF); if ( 0 != pthread_sigmask(SIG_BLOCK, &set, NULL) ) { - u3l_log("boot: thread mask SIGPROF: %s\r\n", strerror(errno)); + u3l_log("boot: thread mask SIGPROF: %s", strerror(errno)); exit(1); } } @@ -1772,7 +1772,7 @@ _cm_crypto() if ( 0 == CRYPTO_set_mem_functions(&_cm_malloc_ssl, &_cm_realloc_ssl, &_cm_free_ssl) ) { - u3l_log("%s\r\n", "openssl initialization failed"); + u3l_log("%s", "openssl initialization failed"); abort(); } @@ -1815,7 +1815,7 @@ u3m_init(size_t len_i) || (len_i < (1 << (u3a_page + 2))) || (len_i > u3a_bytes) ) { - u3l_log("loom: bad size: %zu\r\n", len_i); + u3l_log("loom: bad size: %zu", len_i); exit(1); } @@ -1835,18 +1835,18 @@ u3m_init(size_t len_i) (MAP_ANON | MAP_PRIVATE), -1, 0); - u3l_log("boot: mapping %zuMB failed\r\n", len_i >> 20); + u3l_log("boot: mapping %zuMB failed", len_i >> 20); u3l_log("see urbit.org/using/install/#about-swap-space" - " for adding swap space\r\n"); + " for adding swap space"); if ( -1 != (c3_ps)map_v ) { - u3l_log("if porting to a new platform, try U3_OS_LoomBase %p\r\n", + u3l_log("if porting to a new platform, try U3_OS_LoomBase %p", map_v); } exit(1); } u3C.wor_i = len_i >> 2; - u3l_log("loom: mapped %zuMB\r\n", len_i >> 20); + u3l_log("loom: mapped %zuMB", len_i >> 20); } } @@ -1894,7 +1894,7 @@ u3m_boot(c3_c* dir_c, size_t len_i) */ { c3_w len_w = u3j_boot(nuu_o); - u3l_log("boot: installed %d jets\r\n", len_w); + u3l_log("boot: installed %d jets", len_w); } /* Reactivate jets on old kernel. diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index dda8a4921..518ff5161 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -44,7 +44,7 @@ _n_hint(u3_noun zep, low_i = 1; if ( 0 == (u3R->pro.nox_d % 65536ULL) ) { if ( c3__spot == zep ) { - u3l_log("spot %d/%d : %d/%d\r\n", + u3l_log("spot %d/%d : %d/%d", u3h(u3h(u3t(hod))), u3t(u3h(u3t(hod))), u3h(u3t(u3t(hod))), diff --git a/pkg/urbit/noun/trace.c b/pkg/urbit/noun/trace.c index 79d290930..841d51ca7 100644 --- a/pkg/urbit/noun/trace.c +++ b/pkg/urbit/noun/trace.c @@ -167,7 +167,7 @@ _t_samp_process(u3_road* rod_u) pef = t_pef; } - // u3l_log("sample: stack length %d\r\n", u3kb_lent(u3k(pal))); + // u3l_log("sample: stack length %d", u3kb_lent(u3k(pal))); return pal; } } @@ -540,7 +540,7 @@ u3t_boot(void) sigemptyset(&set); sigaddset(&set, SIGPROF); if ( 0 != pthread_sigmask(SIG_UNBLOCK, &set, NULL) ) { - u3l_log("trace: thread mask SIGPROF: %s\r\n", strerror(errno)); + u3l_log("trace: thread mask SIGPROF: %s", strerror(errno)); } } @@ -569,7 +569,7 @@ u3t_boff(void) sigemptyset(&set); sigaddset(&set, SIGPROF); if ( 0 != pthread_sigmask(SIG_BLOCK, &set, NULL) ) { - u3l_log("trace: thread mask SIGPROF: %s\r\n", strerror(errno)); + u3l_log("trace: thread mask SIGPROF: %s", strerror(errno)); } } diff --git a/pkg/urbit/noun/vortex.c b/pkg/urbit/noun/vortex.c index 016588ea8..7b6eb0da4 100644 --- a/pkg/urbit/noun/vortex.c +++ b/pkg/urbit/noun/vortex.c @@ -60,9 +60,9 @@ _cv_lite(u3_noun pil) eve = tal; } - u3l_log("lite: arvo formula %x\r\n", u3r_mug(pil)); + u3l_log("lite: arvo formula %x", u3r_mug(pil)); pro = u3v_life(u3k(eve)); - u3l_log("lite: core %x\r\n", u3r_mug(pro)); + u3l_log("lite: core %x", u3r_mug(pro)); u3z(pil); return pro; @@ -89,7 +89,7 @@ u3v_boot_lite(u3_noun pil) u3z(pro); } - u3l_log("lite: final state %x\r\n", u3r_mug(u3A->roc)); + u3l_log("lite: final state %x", u3r_mug(u3A->roc)); return c3y; } @@ -198,7 +198,7 @@ u3v_lily(u3_noun fot, u3_noun txt, c3_l* tid_l) (c3n == u3r_safe_word(q_uco, &wad_w)) || (wad_w & 0x80000000) ) { - u3l_log("strange lily %s\n", u3r_string(txt)); + u3l_log("strange lily %s", u3r_string(txt)); u3z(txt); u3z(uco); return c3n; } else { diff --git a/pkg/urbit/vere/auto.c b/pkg/urbit/vere/auto.c index c03cd93e2..e1d4de0c0 100644 --- a/pkg/urbit/vere/auto.c +++ b/pkg/urbit/vere/auto.c @@ -91,7 +91,7 @@ u3_auto_bail_slog(u3_ovum* egg_u, u3_noun lud) c3_w len_w = 1; while ( u3_nul != dul ) { - u3l_log("%s: bail %u\r\n", car_c, len_w++); + u3l_log("%s: bail %u", car_c, len_w++); u3_pier_punt_goof(car_c, u3k(u3h(dul))); dul = u3t(dul); @@ -240,7 +240,7 @@ _auto_kick_lost(u3_noun pax, u3_noun fav) c3_c* tag_c = u3r_string(u3h(fav)); c3_c* pax_c = u3r_string(tox); - u3l_log("kick: lost %%%s on %s\n", tag_c, pax_c); + u3l_log("kick: lost %%%s on %s", tag_c, pax_c); c3_free(pax_c); c3_free(tag_c); @@ -376,12 +376,12 @@ u3_auto_slog(u3_auto* car_u) { u3_auto* nex_u; - u3l_log(" drivers:\n"); + u3l_log(" drivers:"); while ( car_u ) { nex_u = car_u->nex_u; - u3l_log(" %.*s: live=%s, queue=%u\n", + u3l_log(" %.*s: live=%s, queue=%u", u3r_met(3, car_u->nam_m), (c3_c*)&car_u->nam_m, ( c3y == car_u->liv_o ) ? "&" : "|", diff --git a/pkg/urbit/vere/dawn.c b/pkg/urbit/vere/dawn.c index ca6eb31a7..195d5ccac 100644 --- a/pkg/urbit/vere/dawn.c +++ b/pkg/urbit/vere/dawn.c @@ -71,7 +71,7 @@ _dawn_post_json(c3_c* url_c, uv_buf_t lod_u) uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0); if ( !(curl = curl_easy_init()) ) { - u3l_log("failed to initialize libcurl\n"); + u3l_log("failed to initialize libcurl"); exit(1); } @@ -95,12 +95,12 @@ _dawn_post_json(c3_c* url_c, uv_buf_t lod_u) // XX retry? if ( CURLE_OK != result ) { - u3l_log("failed to fetch %s: %s\n", + u3l_log("failed to fetch %s: %s", url_c, curl_easy_strerror(result)); exit(1); } if ( 300 <= cod_l ) { - u3l_log("error fetching %s: HTTP %ld\n", url_c, cod_l); + u3l_log("error fetching %s: HTTP %ld", url_c, cod_l); exit(1); } @@ -122,7 +122,7 @@ _dawn_get_jam(c3_c* url_c) uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0); if ( !(curl = curl_easy_init()) ) { - u3l_log("failed to initialize libcurl\n"); + u3l_log("failed to initialize libcurl"); exit(1); } @@ -138,12 +138,12 @@ _dawn_get_jam(c3_c* url_c) // XX retry? if ( CURLE_OK != result ) { - u3l_log("failed to fetch %s: %s\n", + u3l_log("failed to fetch %s: %s", url_c, curl_easy_strerror(result)); exit(1); } if ( 300 <= cod_l ) { - u3l_log("error fetching %s: HTTP %ld\n", url_c, cod_l); + u3l_log("error fetching %s: HTTP %ld", url_c, cod_l); exit(1); } @@ -207,7 +207,7 @@ _dawn_fail(u3_noun who, u3_noun rac, u3_noun sas) } } - u3l_log("boot: invalid keys for %s '%s'\r\n", rac_c, how_c); + u3l_log("boot: invalid keys for %s '%s'", rac_c, how_c); // XX deconstruct sas, print helpful error messages while ( u3_nul != sas ) { @@ -226,7 +226,7 @@ static u3_noun _dawn_need_unit(u3_noun nit, c3_c* msg_c) { if ( u3_nul == nit ) { - u3l_log("%s\r\n", msg_c); + u3l_log("%s", msg_c); exit(1); } else { @@ -248,11 +248,11 @@ _dawn_turf(c3_c* dns_c) u3_noun rul = u3dc("rush", u3k(dns), u3k(par)); if ( (u3_nul == rul) || (c3n == u3h(u3t(rul))) ) { - u3l_log("boot: invalid domain specified with -H %s\r\n", dns_c); + u3l_log("boot: invalid domain specified with -H %s", dns_c); exit(1); } else { - u3l_log("boot: overriding network domains with %s\r\n", dns_c); + u3l_log("boot: overriding network domains with %s", dns_c); u3_noun dom = u3t(u3t(rul)); tuf = u3nc(u3k(dom), u3_nul); } @@ -308,7 +308,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) pot = u3v_wish("*point:azimuth"); } else { - u3l_log("boot: retrieving %s's public keys\r\n", + u3l_log("boot: retrieving %s's public keys", u3_Host.ops_u.who_c); { @@ -327,7 +327,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) u3_noun liv = u3_nul; // u3_noun liv = _dawn_get_json(parent, /some/url) - u3l_log("boot: verifying keys\r\n"); + u3l_log("boot: verifying keys"); // (each seed (lest error=@tas)) // @@ -339,7 +339,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) return u3_none; } - u3l_log("boot: getting sponsor\r\n"); + u3l_log("boot: getting sponsor"); pos = _dawn_sponsor(u3k(ship), u3k(rank), u3k(pot)); u3z(pot); u3z(liv); } @@ -348,7 +348,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) // (map ship [=life =pass]): galaxy table // { - u3l_log("boot: retrieving galaxy table\r\n"); + u3l_log("boot: retrieving galaxy table"); u3_noun oct = u3v_wish("czar:give:dawn"); u3_noun raz = _dawn_eth_rpc(url_c, u3k(oct)); @@ -364,7 +364,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) tuf = _dawn_turf(u3_Host.ops_u.dns_c); } else { - u3l_log("boot: retrieving network domains\r\n"); + u3l_log("boot: retrieving network domains"); u3_noun oct = u3v_wish("turf:give:dawn"); u3_noun fut = _dawn_eth_rpc(url_c, u3k(oct)); @@ -382,7 +382,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) { u3_noun who = u3dc("scot", 'p', u3k(pos)); c3_c* who_c = u3r_string(who); - u3l_log("boot: retrieving keys for sponsor %s\r\n", who_c); + u3l_log("boot: retrieving keys for sponsor %s", who_c); u3z(who); c3_free(who_c); } @@ -436,8 +436,8 @@ _dawn_come(u3_noun stars) c3_rand(eny_w); eny = u3i_words(16, eny_w); - u3l_log("boot: mining a comet. May take up to an hour.\r\n"); - u3l_log("If you want to boot faster, get an Urbit identity.\r\n"); + u3l_log("boot: mining a comet. May take up to an hour."); + u3l_log("If you want to boot faster, get an Urbit identity."); seed = u3dc("come:dawn", u3k(stars), u3k(eny)); u3z(eny); @@ -447,7 +447,7 @@ _dawn_come(u3_noun stars) u3_noun who = u3dc("scot", 'p', u3k(u3h(seed))); c3_c* who_c = u3r_string(who); - u3l_log("boot: found comet %s\r\n", who_c); + u3l_log("boot: found comet %s", who_c); // enable to print and save comet private key for future reuse // @@ -456,7 +456,7 @@ _dawn_come(u3_noun stars) u3_noun key = u3dc("scot", c3__uw, u3qe_jam(seed)); c3_c* key_c = u3r_string(key); - u3l_log("boot: comet private key\n %s\n", key_c); + u3l_log("boot: comet private key\n %s", key_c); { c3_c pat_c[64]; diff --git a/pkg/urbit/vere/disk.c b/pkg/urbit/vere/disk.c index eb4a27533..817a424c1 100644 --- a/pkg/urbit/vere/disk.c +++ b/pkg/urbit/vere/disk.c @@ -242,7 +242,7 @@ u3_disk_plan(u3_disk* log_u, u3_fact* tac_u) { c3_assert( (1ULL + log_u->sen_d) == tac_u->eve_d ); log_u->sen_d++; - + if ( !log_u->put_u.ent_u ) { c3_assert( !log_u->put_u.ext_u ); log_u->put_u.ent_u = log_u->put_u.ext_u = tac_u; @@ -610,7 +610,7 @@ u3_disk_acquire(c3_c* pax_c) if ( NULL != (loq_u = c3_fopen(paf_c, "r")) ) { if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) { - u3l_log("lockfile %s is corrupt!\n", paf_c); + u3l_log("lockfile %s is corrupt!", paf_c); kill(getpid(), SIGTERM); sleep(1); c3_assert(0); } @@ -620,13 +620,13 @@ u3_disk_acquire(c3_c* pax_c) int ret = kill(pid_w, SIGTERM); if ( -1 == ret && errno == EPERM ) { - u3l_log("disk: permission denied when trying to kill process %d!\n", pid_w); + u3l_log("disk: permission denied when trying to kill process %d!", pid_w); kill(getpid(), SIGTERM); sleep(1); c3_assert(0); } if ( -1 != ret ) { - u3l_log("disk: stopping process %d, live in %s...\n", + u3l_log("disk: stopping process %d, live in %s...", pid_w, pax_c); for ( i_w = 0; i_w < 16; i_w++ ) { @@ -644,10 +644,10 @@ u3_disk_acquire(c3_c* pax_c) } } if ( 16 == i_w ) { - u3l_log("disk: process %d seems unkillable!\n", pid_w); + u3l_log("disk: process %d seems unkillable!", pid_w); c3_assert(0); } - u3l_log("disk: stopped old process %u\n", pid_w); + u3l_log("disk: stopped old process %u", pid_w); } } fclose(loq_u); @@ -655,7 +655,7 @@ u3_disk_acquire(c3_c* pax_c) } if ( NULL == (loq_u = c3_fopen(paf_c, "w")) ) { - u3l_log("disk: unable to open %s\n", paf_c); + u3l_log("disk: unable to open %s", paf_c); c3_assert(0); } @@ -703,7 +703,7 @@ u3_disk_exit(u3_disk* log_u) if ( (c3y == log_u->ted_o) && (0 > uv_cancel(&log_u->req_u)) ) { - // u3l_log("disk: unable to cleanup\r\n"); + // u3l_log("disk: unable to cleanup"); return; } @@ -781,7 +781,7 @@ u3_disk_info(u3_disk* log_u) void u3_disk_slog(u3_disk* log_u) { - u3l_log(" disk: live=%s, event=%" PRIu64 "\n", + u3l_log(" disk: live=%s, event=%" PRIu64, ( c3y == log_u->liv_o ) ? "&" : "|", log_u->dun_d); @@ -789,7 +789,7 @@ u3_disk_slog(u3_disk* log_u) u3_read* red_u = log_u->red_u; while ( red_u ) { - u3l_log(" read: %" PRIu64 "-%" PRIu64 "\n", + u3l_log(" read: %" PRIu64 "-%" PRIu64, red_u->eve_d, (red_u->eve_d + red_u->len_d) - 1); red_u = red_u->nex_u; @@ -798,12 +798,12 @@ u3_disk_slog(u3_disk* log_u) if ( log_u->put_u.ext_u ) { if ( log_u->put_u.ext_u != log_u->put_u.ent_u ) { - u3l_log(" save: %" PRIu64 "-%" PRIu64 "\n", + u3l_log(" save: %" PRIu64 "-%" PRIu64, log_u->put_u.ext_u->eve_d, log_u->put_u.ent_u->eve_d); } else { - u3l_log(" save: %" PRIu64 "\n", log_u->put_u.ext_u->eve_d); + u3l_log(" save: %" PRIu64, log_u->put_u.ext_u->eve_d); } } } diff --git a/pkg/urbit/vere/foil.c b/pkg/urbit/vere/foil.c index 1d844f5d4..186c8fdec 100644 --- a/pkg/urbit/vere/foil.c +++ b/pkg/urbit/vere/foil.c @@ -36,10 +36,10 @@ static void _foil_fail(const c3_c* why_c, c3_i err_i) { if ( err_i ) { - u3l_log("%s: error: %s\r\n", why_c, uv_strerror(err_i)); + u3l_log("%s: error: %s", why_c, uv_strerror(err_i)); c3_assert(0); } else { - u3l_log("%s: file error\r\n", why_c); + u3l_log("%s: file error", why_c); } exit(1); } diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index bdc3201af..913045b3e 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -341,7 +341,7 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) u3_ames* sam_u = pac_u->sam_u; if ( sas_i && (c3y == sam_u->fig_u.net_o) ) { - u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); + u3l_log("ames: send fail: %s", uv_strerror(sas_i)); sam_u->fig_u.net_o = c3n; } else { @@ -380,7 +380,7 @@ _ames_send(u3_pact* pac_u) if ( sas_i ) { if ( c3y == sam_u->fig_u.net_o ) { - u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); + u3l_log("ames: send fail: %s", uv_strerror(sas_i)); sam_u->fig_u.net_o = c3n; } @@ -517,7 +517,7 @@ _ames_czar_gone(u3_pact* pac_u, time_t now) u3_ames* sam_u = pac_u->sam_u; if ( c3y == sam_u->imp_o[pac_u->imp_y] ) { - u3l_log("ames: czar at %s: not found (b)\n", pac_u->dns_c); + u3l_log("ames: czar at %s: not found (b)", pac_u->dns_c); sam_u->imp_o[pac_u->imp_y] = c3n; } @@ -547,7 +547,7 @@ _ames_czar_here(u3_pact* pac_u, time_t now, struct sockaddr_in* add_u) u3_noun nam = u3dc("scot", c3__if, u3i_word(pip_w)); c3_c* nam_c = u3r_string(nam); - u3l_log("ames: czar %s: ip %s\n", pac_u->dns_c, nam_c); + u3l_log("ames: czar %s: ip %s", pac_u->dns_c, nam_c); c3_free(nam_c); u3z(nam); @@ -612,7 +612,7 @@ _ames_czar(u3_pact* pac_u) if ( !sam_u->dns_c ) { u3_noun nam = u3dc("scot", 'p', pac_u->imp_y); c3_c* nam_c = u3r_string(nam); - u3l_log("ames: no galaxy domain for %s, no-op\r\n", nam_c); + u3l_log("ames: no galaxy domain for %s, no-op", nam_c); c3_free(nam_c); u3z(nam); @@ -657,7 +657,7 @@ _ames_czar(u3_pact* pac_u) } if ( 255 <= sas_i ) { - u3l_log("ames: czar: galaxy domain %s truncated\n", sam_u->dns_c); + u3l_log("ames: czar: galaxy domain %s truncated", sam_u->dns_c); _ames_pact_free(pac_u); return; } @@ -670,7 +670,7 @@ _ames_czar(u3_pact* pac_u) _ames_czar_cb, pac_u->dns_c, 0, 0)) ) { - u3l_log("ames: %s\n", uv_strerror(sas_i)); + u3l_log("ames: %s", uv_strerror(sas_i)); _ames_czar_gone(pac_u, now); return; } @@ -685,7 +685,7 @@ static void _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) { if ( c3n == sam_u->car_u.liv_o ) { - u3l_log("ames: not yet live, dropping outbound\r\n"); + u3l_log("ames: not yet live, dropping outbound"); u3z(lan); u3z(pac); return; } @@ -726,7 +726,7 @@ _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) // else if ( 0 == lan_u.por_s ) { if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: inscrutable lane\n"); + u3l_log("ames: inscrutable lane"); } _ames_pact_free(pac_u); } @@ -755,7 +755,7 @@ _ames_cap_queue(u3_ames* sam_u) sam_u->sat_u.dop_d++; if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: packet dropped (%" PRIu64 " total)\n", sam_u->sat_u.dop_d); + u3l_log("ames: packet dropped (%" PRIu64 " total)", sam_u->sat_u.dop_d); } } @@ -765,7 +765,7 @@ _ames_cap_queue(u3_ames* sam_u) if ( (sam_u->sat_u.dop_d && (0 == (sam_u->sat_u.dop_d % 1000))) && !(u3C.wag_w & u3o_verbose) ) { - u3l_log("ames: packet dropped (%" PRIu64 " total)\n", sam_u->sat_u.dop_d); + u3l_log("ames: packet dropped (%" PRIu64 " total)", sam_u->sat_u.dop_d); } } @@ -784,7 +784,7 @@ _ames_hear_bail(u3_ovum* egg_u, u3_noun lud) || (0 == (sam_u->sat_u.bad_d % 100)) ) { u3l_log("ames: heard bad crypto (%" PRIu64 " total), " - "check azimuth state\r\n", + "check azimuth state", sam_u->sat_u.bad_d); } } @@ -804,7 +804,7 @@ _ames_hear_bail(u3_ovum* egg_u, u3_noun lud) u3_pier_punt_goof("hear", u3k(u3h(lud))); } - u3l_log("ames: packet failed (%" PRIu64 " total)\r\n", + u3l_log("ames: packet failed (%" PRIu64 " total)", sam_u->sat_u.fal_d); } } @@ -840,7 +840,7 @@ _ames_forward(u3_panc* pac_u, u3_noun las) sam_u->sat_u.fow_d++; if ( 0 == (sam_u->sat_u.fow_d % 1000000) ) { - u3l_log("ames: forwarded %" PRIu64 " total\n", sam_u->sat_u.fow_d); + u3l_log("ames: forwarded %" PRIu64 " total", sam_u->sat_u.fow_d); } if ( u3C.wag_w & u3o_verbose ) { @@ -851,7 +851,7 @@ _ames_forward(u3_panc* pac_u, u3_noun las) c3_y* pip_y = (c3_y*)&pac_u->ore_u.pip_w; //NOTE ip byte order assumes little-endian - u3l_log("ames: forwarding for %s to %s from %d.%d.%d.%d:%d\n", + u3l_log("ames: forwarding for %s to %s from %d.%d.%d.%d:%d", sen_c, rec_c, pip_y[3], pip_y[2], pip_y[1], pip_y[0], pac_u->ore_u.por_s); @@ -870,7 +870,7 @@ _ames_forward(u3_panc* pac_u, u3_noun las) // validate lane and skip self if galaxy // if ( c3n == u3r_cell(lan, &tag, &dat) ) { - u3l_log("ames: bogus lane\n"); + u3l_log("ames: bogus lane"); u3m_p("lan", lan); } else { @@ -885,7 +885,7 @@ _ames_forward(u3_panc* pac_u, u3_noun las) { sen_o = c3n; if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: forward skipping self\n"); + u3l_log("ames: forward skipping self"); } } } @@ -918,7 +918,7 @@ _ames_lane_scry_cb(void* vod_p, u3_noun nun) // if ( u3_none == las ) { if ( 5 < ++sam_u->sat_u.saw_d ) { - u3l_log("ames: giving up scry\n"); + u3l_log("ames: giving up scry"); sam_u->fig_u.see_o = c3n; } _ames_put_packet(sam_u, _ames_serialize_packet(pac_u, c3n), pac_u->ore_u); @@ -982,7 +982,7 @@ _ames_try_forward(u3_ames* sam_u, if ( (u3_none == lac) && (1000 < sam_u->sat_u.foq_d) ) { sam_u->sat_u.fod_d++; if ( 0 == (sam_u->sat_u.fod_d % 10000) ) { - u3l_log("ames: dropped %" PRIu64 " forwards total\n", + u3l_log("ames: dropped %" PRIu64 " forwards total", sam_u->sat_u.fod_d); } @@ -1086,7 +1086,7 @@ _ames_hear(u3_ames* sam_u, { sam_u->sat_u.hed_d++; if ( 0 == (sam_u->sat_u.hed_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped, failed to read header\n", + u3l_log("ames: %" PRIu64 " dropped, failed to read header", sam_u->sat_u.hed_d); } @@ -1103,7 +1103,7 @@ _ames_hear(u3_ames* sam_u, { sam_u->sat_u.vet_d++; if ( 0 == (sam_u->sat_u.vet_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped for version mismatch\n", + u3l_log("ames: %" PRIu64 " dropped for version mismatch", sam_u->sat_u.vet_d); } @@ -1120,7 +1120,7 @@ _ames_hear(u3_ames* sam_u, if ( (c3n == _ames_sift_body(&hed_u, &bod_u, bod_w, bod_y)) ) { sam_u->sat_u.bod_d++; if ( 0 == (sam_u->sat_u.bod_d % 100) ) { - u3l_log("ames: %" PRIu64 " dropped, failed to read body\n", + u3l_log("ames: %" PRIu64 " dropped, failed to read body", sam_u->sat_u.bod_d); } @@ -1133,7 +1133,7 @@ _ames_hear(u3_ames* sam_u, if ( bod_u.mug_l != hed_u.mug_l ) { sam_u->sat_u.mut_d++; if ( 0 == (sam_u->sat_u.mut_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped for invalid mug\n", + u3l_log("ames: %" PRIu64 " dropped for invalid mug", sam_u->sat_u.mut_d); } @@ -1181,7 +1181,7 @@ _ames_recv_cb(uv_udp_t* wax_u, { if ( 0 > nrd_i ) { if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: recv: fail: %s\n", uv_strerror(nrd_i)); + u3l_log("ames: recv: fail: %s", uv_strerror(nrd_i)); } c3_free(buf_u->base); } @@ -1190,7 +1190,7 @@ _ames_recv_cb(uv_udp_t* wax_u, } else if ( flg_i & UV_UDP_PARTIAL ) { if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: recv: fail: message truncated\n"); + u3l_log("ames: recv: fail: message truncated"); } c3_free(buf_u->base); } @@ -1226,8 +1226,8 @@ _ames_io_start(u3_ames* sam_u) por_s = zar_s; } else if ( por_s != zar_s ) { - u3l_log("ames: czar: overriding port %d with -p %d\n", zar_s, por_s); - u3l_log("ames: czar: WARNING: %d required for discoverability\n", zar_s); + u3l_log("ames: czar: overriding port %d with -p %d", zar_s, por_s); + u3l_log("ames: czar: WARNING: %d required for discoverability", zar_s); } } @@ -1246,12 +1246,12 @@ _ames_io_start(u3_ames* sam_u) if ( (ret_i = uv_udp_bind(&sam_u->wax_u, (const struct sockaddr*)&add_u, 0)) != 0 ) { - u3l_log("ames: bind: %s\n", uv_strerror(ret_i)); + u3l_log("ames: bind: %s", uv_strerror(ret_i)); if ( (c3__czar == rac) && (UV_EADDRINUSE == ret_i) ) { - u3l_log(" ...perhaps you've got two copies of vere running?\n"); + u3l_log(" ...perhaps you've got two copies of vere running?"); } // XX revise @@ -1266,10 +1266,10 @@ _ames_io_start(u3_ames* sam_u) } if ( c3y == u3_Host.ops_u.net ) { - u3l_log("ames: live on %d\n", sam_u->pir_u->por_s); + u3l_log("ames: live on %d", sam_u->pir_u->por_s); } else { - u3l_log("ames: live on %d (localhost only)\n", sam_u->pir_u->por_s); + u3l_log("ames: live on %d (localhost only)", sam_u->pir_u->por_s); } uv_udp_recv_start(&sam_u->wax_u, _ames_alloc, _ames_recv_cb); @@ -1300,7 +1300,7 @@ _ames_ef_turf(u3_ames* sam_u, u3_noun tuf) u3z(tuf); } else if ( (c3n == sam_u->pir_u->fak_o) && (0 == sam_u->dns_c) ) { - u3l_log("ames: turf: no domains\n"); + u3l_log("ames: turf: no domains"); } // XX is this ever necessary? @@ -1444,7 +1444,7 @@ _ames_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) ret_o = c3n; } else { - u3l_log("kick: strange send\r\n"); + u3l_log("kick: strange send"); ret_o = _ames_kick_newt(sam_u, u3k(tag), u3k(dat)); } } break; @@ -1521,21 +1521,21 @@ _ames_io_slog(u3_auto* car_u) // TODO rewrite in terms of info_f // - u3l_log(" config:\n"); - u3l_log(" filtering: %s\n", FLAG(sam_u->fig_u.fit_o)); - u3l_log(" can send: %s\n", FLAG(sam_u->fig_u.net_o)); - u3l_log(" can scry: %s\n", FLAG(sam_u->fig_u.see_o)); - u3l_log(" counters:\n"); - u3l_log(" dropped: %" PRIu64 "\n", sam_u->sat_u.dop_d); - u3l_log(" forwards dropped: %" PRIu64 "\n", sam_u->sat_u.fod_d); - u3l_log(" forwards pending: %" PRIu64 "\n", sam_u->sat_u.foq_d); - u3l_log(" forwarded: %" PRIu64 "\n", sam_u->sat_u.fow_d); - u3l_log(" filtered (hed): %" PRIu64 "\n", sam_u->sat_u.hed_d); - u3l_log(" filtered (ver): %" PRIu64 "\n", sam_u->sat_u.vet_d); - u3l_log(" filtered (mug): %" PRIu64 "\n", sam_u->sat_u.mut_d); - u3l_log(" filtered (bod): %" PRIu64 "\n", sam_u->sat_u.bod_d); - u3l_log(" crashed: %" PRIu64 "\n", sam_u->sat_u.fal_d); - u3l_log(" cached lanes: %u\n", u3h_wyt(sam_u->lax_p)); + u3l_log(" config:"); + u3l_log(" filtering: %s", FLAG(sam_u->fig_u.fit_o)); + u3l_log(" can send: %s", FLAG(sam_u->fig_u.net_o)); + u3l_log(" can scry: %s", FLAG(sam_u->fig_u.see_o)); + u3l_log(" counters:"); + u3l_log(" dropped: %" PRIu64, sam_u->sat_u.dop_d); + u3l_log(" forwards dropped: %" PRIu64, sam_u->sat_u.fod_d); + u3l_log(" forwards pending: %" PRIu64, sam_u->sat_u.foq_d); + u3l_log(" forwarded: %" PRIu64, sam_u->sat_u.fow_d); + u3l_log(" filtered (hed): %" PRIu64, sam_u->sat_u.hed_d); + u3l_log(" filtered (ver): %" PRIu64, sam_u->sat_u.vet_d); + u3l_log(" filtered (mug): %" PRIu64, sam_u->sat_u.mut_d); + u3l_log(" filtered (bod): %" PRIu64, sam_u->sat_u.bod_d); + u3l_log(" crashed: %" PRIu64, sam_u->sat_u.fal_d); + u3l_log(" cached lanes: %u", u3h_wyt(sam_u->lax_p)); } /* u3_ames_io_init(): initialize ames I/O. diff --git a/pkg/urbit/vere/io/behn.c b/pkg/urbit/vere/io/behn.c index 45a434773..7f42805a3 100644 --- a/pkg/urbit/vere/io/behn.c +++ b/pkg/urbit/vere/io/behn.c @@ -48,7 +48,7 @@ _behn_wake_bail(u3_ovum* egg_u, u3_noun lud) u3_auto_bail_slog(egg_u, lud); u3_ovum_free(egg_u); - u3l_log("behn: timer failed; queue blocked\n"); + u3l_log("behn: timer failed; queue blocked"); // XX review, add flag to continue? // @@ -149,7 +149,7 @@ _behn_born_bail(u3_ovum* egg_u, u3_noun lud) u3_auto_bail_slog(egg_u, lud); u3_ovum_free(egg_u); - u3l_log("behn: initialization failed\n"); + u3l_log("behn: initialization failed"); // XX review, add flag to continue? // diff --git a/pkg/urbit/vere/io/conn.c b/pkg/urbit/vere/io/conn.c index ab717dd1e..86d9087ff 100644 --- a/pkg/urbit/vere/io/conn.c +++ b/pkg/urbit/vere/io/conn.c @@ -333,7 +333,7 @@ _conn_moor_bail(void* ptr_v, ssize_t err_i, const c3_c* err_c) u3_shan* san_u = can_u->san_u; if ( err_i != UV_EOF ) { - u3l_log("conn: moor bail %zd %s\n", err_i, err_c); + u3l_log("conn: moor bail %zd %s", err_i, err_c); if ( _(can_u->liv_o) ) { _conn_send_noun(can_u, u3nq(0, c3__bail, u3i_word(err_i), u3i_string(err_c))); @@ -573,7 +573,7 @@ _conn_moor_poke(void* ptr_v, c3_d len_d, c3_y* byt_y) rud = u3dc("scot", c3__uv, u3k(rid)); tag_c = u3r_string(tag); rid_c = u3r_string(rud); - u3l_log("conn: %s %s\n", tag_c, rid_c); + u3l_log("conn: %s %s", tag_c, rid_c); c3_free(tag_c); c3_free(rid_c); switch (tag) { @@ -690,7 +690,7 @@ _conn_init_sock(u3_shan* san_u) c3_assert(!ret_i); ret_i = uv_listen((uv_stream_t*)&san_u->pyp_u, 0, _conn_sock_cb); c3_assert(!ret_i); - u3l_log("conn: listening on %s\n", pip_c); + u3l_log("conn: listening on %s", pip_c); #else // _WIN32 // the full socket path is limited to about 108 characters, @@ -702,46 +702,46 @@ _conn_init_sock(u3_shan* san_u) c3_i err_i; if ( NULL == getcwd(pax_c, sizeof(pax_c)) ) { - u3l_log("conn: getcwd: %s\n", uv_strerror(errno)); + u3l_log("conn: getcwd: %s", uv_strerror(errno)); u3_king_bail(); } if ( 0 != chdir(u3_Host.dir_c) ) { - u3l_log("conn: chdir: %s\n", uv_strerror(errno)); + u3l_log("conn: chdir: %s", uv_strerror(errno)); u3_king_bail(); } if ( 0 != unlink(URB_SOCK_PATH) && errno != ENOENT ) { - u3l_log("conn: unlink: %s\n", uv_strerror(errno)); + u3l_log("conn: unlink: %s", uv_strerror(errno)); goto _conn_sock_err_chdir; } if ( 0 != (err_i = uv_pipe_init(u3L, &san_u->pyp_u, 0)) ) { - u3l_log("conn: uv_pipe_init: %s\n", uv_strerror(err_i)); + u3l_log("conn: uv_pipe_init: %s", uv_strerror(err_i)); goto _conn_sock_err_chdir; } if ( 0 != (err_i = uv_pipe_bind(&san_u->pyp_u, URB_SOCK_PATH)) ) { - u3l_log("conn: uv_pipe_bind: %s\n", uv_strerror(err_i)); + u3l_log("conn: uv_pipe_bind: %s", uv_strerror(err_i)); goto _conn_sock_err_chdir; } if ( 0 != (err_i = uv_listen((uv_stream_t*)&san_u->pyp_u, 0, _conn_sock_cb)) ) { - u3l_log("conn: uv_listen: %s\n", uv_strerror(err_i)); + u3l_log("conn: uv_listen: %s", uv_strerror(err_i)); goto _conn_sock_err_unlink; } if ( 0 != chdir(pax_c) ) { - u3l_log("conn: chdir: %s\n", uv_strerror(errno)); + u3l_log("conn: chdir: %s", uv_strerror(errno)); goto _conn_sock_err_close; } - u3l_log("conn: listening on %s/%s\n", u3_Host.dir_c, URB_SOCK_PATH); + u3l_log("conn: listening on %s/%s", u3_Host.dir_c, URB_SOCK_PATH); return; _conn_sock_err_close: uv_close((uv_handle_t*)&san_u->pyp_u, _conn_close_cb); _conn_sock_err_unlink: if ( 0 != unlink(URB_SOCK_PATH) ) { - u3l_log("conn: unlink: %s\n", uv_strerror(errno)); + u3l_log("conn: unlink: %s", uv_strerror(errno)); } _conn_sock_err_chdir: if ( 0 != chdir(pax_c) ) { - u3l_log("conn: chdir: %s\n", uv_strerror(errno)); + u3l_log("conn: chdir: %s", uv_strerror(errno)); } u3_king_bail(); #endif // _WIN32 @@ -764,7 +764,7 @@ _conn_born_news(u3_ovum* egg_u, u3_ovum_news new_e) static void _conn_born_bail(u3_ovum* egg_u, u3_noun lud) { - u3l_log("conn: %%born failure; %%fyrd not supported\n"); + u3l_log("conn: %%born failure; %%fyrd not supported"); u3z(lud); u3_ovum_free(egg_u); } @@ -820,7 +820,7 @@ _conn_ef_handle(u3_conn* con_u, } } else { - u3l_log("conn: handle-no-coq %" PRIx32 " %" PRIu32 "\n", + u3l_log("conn: handle-no-coq %" PRIx32 " %" PRIu32, sev_l, coq_l); } u3z(rid); u3z(tag); u3z(dat); @@ -866,11 +866,11 @@ _conn_io_exit(u3_auto* car_u) if ( 0 != unlink(paf_c) ) { if ( ENOENT != errno ) { - u3l_log("conn: failed to unlink socket: %s\n", uv_strerror(errno)); + u3l_log("conn: failed to unlink socket: %s", uv_strerror(errno)); } } else { - // u3l_log("conn: unlinked %s\n", paf_c); + // u3l_log("conn: unlinked %s", paf_c); } c3_free(paf_c); diff --git a/pkg/urbit/vere/io/cttp.c b/pkg/urbit/vere/io/cttp.c index 1f19c3e41..76c1dd396 100644 --- a/pkg/urbit/vere/io/cttp.c +++ b/pkg/urbit/vere/io/cttp.c @@ -558,7 +558,7 @@ _cttp_creq_new(u3_cttp* ctp_u, c3_l num_l, u3_noun hes) if ( c3n == u3r_du(unit_pul) ) { c3_c* url_c = u3r_string(url); - u3l_log("cttp: unable to parse url:\n %s\n", url_c); + u3l_log("cttp: unable to parse url:\n %s", url_c); c3_free(url_c); u3z(hes); return 0; @@ -735,7 +735,7 @@ _cttp_creq_fail(u3_creq* ceq_u, const c3_c* err_c) // XX anything other than a 504? c3_w cod_w = 504; - u3l_log("http: fail (%d, %d): %s\r\n", ceq_u->num_l, cod_w, err_c); + u3l_log("http: fail (%d, %d): %s", ceq_u->num_l, cod_w, err_c); // XX include err_c as response body? _cttp_http_client_receive(ceq_u, cod_w, u3_nul, u3_nul); @@ -1003,7 +1003,7 @@ _cttp_ef_http_client(u3_cttp* ctp_u, u3_noun tag, u3_noun dat) if ( (c3n == u3r_cell(dat, &num, &req)) || (c3n == u3r_safe_word(num, &num_l)) ) { - u3l_log("cttp: strange request\n"); + u3l_log("cttp: strange request"); ret_o = c3n; } else if ( (ceq_u = _cttp_creq_new(ctp_u, num_l, u3k(req))) ) { @@ -1018,7 +1018,7 @@ _cttp_ef_http_client(u3_cttp* ctp_u, u3_noun tag, u3_noun dat) c3_l num_l; if ( c3n == u3r_safe_word(dat, &num_l) ) { - u3l_log("cttp: strange cancel-request\n"); + u3l_log("cttp: strange cancel-request"); ret_o = c3n; } else if ( (ceq_u =_cttp_creq_find(ctp_u, num_l)) ) { @@ -1032,7 +1032,7 @@ _cttp_ef_http_client(u3_cttp* ctp_u, u3_noun tag, u3_noun dat) } } else { - u3l_log("cttp: strange effect (unknown type)\n"); + u3l_log("cttp: strange effect (unknown type)"); ret_o = c3n; } diff --git a/pkg/urbit/vere/io/fore.c b/pkg/urbit/vere/io/fore.c index 7354a8225..2fdd02237 100644 --- a/pkg/urbit/vere/io/fore.c +++ b/pkg/urbit/vere/io/fore.c @@ -10,7 +10,7 @@ static void _fore_inject_bail(u3_ovum* egg_u, u3_noun lud) { u3_auto_bail_slog(egg_u, lud); - u3l_log("pier: injected event failed\n"); + u3l_log("pier: injected event failed"); u3_ovum_free(egg_u); } @@ -21,7 +21,7 @@ static void _fore_import_bail(u3_ovum* egg_u, u3_noun lud) { u3_auto_bail_slog(egg_u, lud); - u3l_log("pier: import failed\n"); + u3l_log("pier: import failed"); u3_ovum_free(egg_u); } @@ -37,20 +37,20 @@ _fore_inject(u3_auto* car_u, c3_c* pax_c) u3_noun riw, cad, tar, wir; if ( c3n == u3r_cell(ovo, &riw, &cad) ) { - u3l_log("pier: invalid ovum in -I\n"); + u3l_log("pier: invalid ovum in -I"); } else if ( (c3n == u3a_is_cell(cad)) || (c3n == u3a_is_atom(u3h(cad))) ) { - u3l_log("pier: invalid card in -I ovum\n"); + u3l_log("pier: invalid card in -I ovum"); } else if ( c3n == u3r_cell(riw, &tar, &wir) ) { - u3l_log("pier: invalid wire in -I ovum\n"); + u3l_log("pier: invalid wire in -I ovum"); } else if ( (c3n == u3a_is_atom(tar)) || (4 < u3r_met(3, tar)) ) { - u3l_log("pier: invalid target in -I wire\n"); + u3l_log("pier: invalid target in -I wire"); } else { { @@ -58,7 +58,7 @@ _fore_inject(u3_auto* car_u, c3_c* pax_c) u3_noun ser = u3do("spat", u3k(riw)); c3_c* wir_c = u3r_string(ser); - u3l_log("pier: injecting %%%s event on %s\n", tag_c, wir_c); + u3l_log("pier: injecting %%%s event on %s", tag_c, wir_c); c3_free(tag_c); c3_free(wir_c); diff --git a/pkg/urbit/vere/io/hind.c b/pkg/urbit/vere/io/hind.c index b0d207e83..d15534806 100644 --- a/pkg/urbit/vere/io/hind.c +++ b/pkg/urbit/vere/io/hind.c @@ -30,7 +30,7 @@ _hind_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) case c3__exit: { ret_o = c3y; - u3l_log("<<>>\n"); + u3l_log("<<>>"); u3_pier_exit(car_u->pir_u); } break; @@ -44,7 +44,7 @@ _hind_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) case c3__vega: { ret_o = c3y; - u3l_log("<<>>\n"); + u3l_log("<<>>"); } break; // NB: startup explicitly handled in pier.c diff --git a/pkg/urbit/vere/io/http.c b/pkg/urbit/vere/io/http.c index fa7d778f2..3f90df80d 100644 --- a/pkg/urbit/vere/io/http.c +++ b/pkg/urbit/vere/io/http.c @@ -33,7 +33,7 @@ typedef struct _u3_h2o_serv { void* gen_u; // response generator struct _u3_hcon* hon_u; // connection backlink struct _u3_hreq* nex_u; // next in connection's list - struct _u3_hreq* pre_u; // next in connection's list + struct _u3_hreq* pre_u; // prev in connection's list } u3_hreq; /* u3_hcon: incoming http connection. @@ -48,7 +48,7 @@ typedef struct _u3_h2o_serv { struct _u3_http* htp_u; // server backlink struct _u3_hreq* req_u; // request list struct _u3_hcon* nex_u; // next in server's list - struct _u3_hcon* pre_u; // next in server's list + struct _u3_hcon* pre_u; // prev in server's list } u3_hcon; /* u3_http: http server. @@ -640,10 +640,10 @@ _http_start_respond(u3_hreq* req_u, u3_noun data, u3_noun complete) { - // u3l_log("start\n"); + // u3l_log("start"); if ( u3_rsat_plan != req_u->sat_e ) { - //u3l_log("duplicate response\n"); + //u3l_log("duplicate response"); return; } @@ -724,14 +724,14 @@ _http_continue_respond(u3_hreq* req_u, u3_noun data, u3_noun complete) { - // u3l_log("continue\n"); + // u3l_log("continue"); // XX add sequence numbers for %continue effects? // Arvo does not (currently) guarantee effect idempotence!! // response has not yet been started if ( u3_rsat_ripe != req_u->sat_e ) { - // u3l_log("duplicate response\n"); + // u3l_log("duplicate response"); return; } @@ -874,7 +874,7 @@ _http_seq_continue(void* vod_p, u3_noun nun) _http_start_respond(req_u, 403, u3_nul, u3_nul, c3y); } else if ( u3_none == aut ) { - u3l_log("http: authentication scry failed\n"); + u3l_log("http: authentication scry failed"); _http_start_respond(req_u, 500, u3_nul, u3_nul, c3y); } else { @@ -962,7 +962,7 @@ _http_rec_accept(h2o_handler_t* han_u, h2o_req_t* rec_u) if ( u3_none == req ) { if ( (u3C.wag_w & u3o_verbose) ) { - u3l_log("strange %.*s request\n", (c3_i)rec_u->method.len, + u3l_log("strange %.*s request", (c3_i)rec_u->method.len, rec_u->method.base); } c3_c* msg_c = "bad request"; @@ -1052,7 +1052,7 @@ _http_conn_free(uv_handle_t* han_t) noh_u = noh_u->nex_u; } - u3l_log("http conn free %d of %u server %d\n", hon_u->coq_l, len_w, htp_u->sev_l); + u3l_log("http conn free %d of %u server %d", hon_u->coq_l, len_w, htp_u->sev_l); } #endif @@ -1069,13 +1069,13 @@ _http_conn_free(uv_handle_t* han_t) noh_u = noh_u->nex_u; } - u3l_log("http conn free %u remaining\n", len_w); + u3l_log("http conn free %u remaining", len_w); } #endif if ( (0 == htp_u->hon_u) && (0 != h2o_u->ctx_u.shutdown_requested) ) { #if 0 - u3l_log("http conn free %d free server %d\n", hon_u->coq_l, htp_u->sev_l); + u3l_log("http conn free %d free server %d", hon_u->coq_l, htp_u->sev_l); #endif _http_serv_free(htp_u); } @@ -1099,7 +1099,7 @@ _http_conn_new(u3_http* htp_u) _http_conn_link(htp_u, hon_u); #if 0 - u3l_log("http conn neww %d server %d\n", hon_u->coq_l, htp_u->sev_l); + u3l_log("http conn neww %d server %d", hon_u->coq_l, htp_u->sev_l); #endif return hon_u; @@ -1149,7 +1149,7 @@ _http_serv_unlink(u3_http* htp_u) { // XX link elsewhere initially, relink on start? #if 0 - u3l_log("http serv unlink %d\n", htp_u->sev_l); + u3l_log("http serv unlink %d", htp_u->sev_l); #endif u3_http* pre_u = htp_u->htd_u->htp_u; @@ -1258,7 +1258,7 @@ http_serv_free_cb(uv_timer_t* tim_u) u3_http* htp_u = tim_u->data; #if 0 - u3l_log("http serv free cb %d\n", htp_u->sev_l); + u3l_log("http serv free cb %d", htp_u->sev_l); #endif _http_serv_really_free(htp_u); @@ -1272,7 +1272,7 @@ static void _http_serv_free(u3_http* htp_u) { #if 0 - u3l_log("http serv free %d\n", htp_u->sev_l); + u3l_log("http serv free %d", htp_u->sev_l); #endif c3_assert( 0 == htp_u->hon_u ); @@ -1342,7 +1342,7 @@ _http_serv_close(u3_http* htp_u) h2o_context_request_shutdown(&h2o_u->ctx_u); #if 0 - u3l_log("http serv close %d %p\n", htp_u->sev_l, &htp_u->wax_u); + u3l_log("http serv close %d %p", htp_u->sev_l, &htp_u->wax_u); #endif uv_close((uv_handle_t*)&htp_u->wax_u, _http_serv_close_cb); @@ -1384,7 +1384,7 @@ _http_serv_accept(u3_http* htp_u) if ( 0 != (sas_i = uv_accept((uv_stream_t*)&htp_u->wax_u, (uv_stream_t*)&hon_u->wax_u)) ) { if ( (u3C.wag_w & u3o_verbose) ) { - u3l_log("http: accept: %s\n", uv_strerror(sas_i)); + u3l_log("http: accept: %s", uv_strerror(sas_i)); } uv_close((uv_handle_t*)&hon_u->wax_u, _http_conn_free); @@ -1413,7 +1413,7 @@ _http_serv_listen_cb(uv_stream_t* str_u, c3_i sas_i) u3_http* htp_u = (u3_http*)str_u; if ( 0 != sas_i ) { - u3l_log("http: listen_cb: %s\n", uv_strerror(sas_i)); + u3l_log("http: listen_cb: %s", uv_strerror(sas_i)); } else { _http_serv_accept(htp_u); @@ -1574,7 +1574,7 @@ _http_serv_start(u3_http* htp_u) return; } - u3l_log("http: %s live on %s://localhost:%d\n", + u3l_log("http: %s live on %s://localhost:%d", (c3y == htp_u->lop) ? "loopback" : "web interface", (c3y == htp_u->sec) ? "https" : "http", htp_u->por_s); @@ -1632,9 +1632,10 @@ _http_init_tls(uv_buf_t key_u, uv_buf_t cer_u) BIO_free(bio_u); if( 0 == sas_i ) { - u3l_log("http: load private key failed:\n"); - ERR_print_errors_fp(u3_term_io_hija()); - u3_term_io_loja(1); + u3l_log("http: load private key failed:"); + FILE* fil_u = u3_term_io_hija(); + ERR_print_errors_fp(fil_u); + u3_term_io_loja(1, fil_u); SSL_CTX_free(tls_u); @@ -1650,9 +1651,10 @@ _http_init_tls(uv_buf_t key_u, uv_buf_t cer_u) X509_free(xer_u); if( 0 == sas_i ) { - u3l_log("http: load certificate failed:\n"); - ERR_print_errors_fp(u3_term_io_hija()); - u3_term_io_loja(1); + u3l_log("http: load certificate failed:"); + FILE* fil_u = u3_term_io_hija(); + ERR_print_errors_fp(fil_u); + u3_term_io_loja(1,fil_u); BIO_free(bio_u); SSL_CTX_free(tls_u); @@ -1735,19 +1737,19 @@ _http_search_req(u3_httd* htd_u, if ( !(htp_u = _http_serv_find(htd_u, sev_l)) ) { if ( bug_w ) { - u3l_log("http: server not found: %x\r\n", sev_l); + u3l_log("http: server not found: %x", sev_l); } return 0; } else if ( !(hon_u = _http_conn_find(htp_u, coq_l)) ) { if ( bug_w ) { - u3l_log("http: connection not found: %x/%d\r\n", sev_l, coq_l); + u3l_log("http: connection not found: %x/%d", sev_l, coq_l); } return 0; } else if ( !(req_u = _http_req_find(hon_u, seq_l)) ) { if ( bug_w ) { - u3l_log("http: request not found: %x/%d/%d\r\n", + u3l_log("http: request not found: %x/%d/%d", sev_l, coq_l, seq_l); } return 0; @@ -1853,7 +1855,7 @@ _http_serv_restart(u3_httd* htd_u) _http_serv_start_all(htd_u); } else { - u3l_log("http: restarting servers to apply configuration\n"); + u3l_log("http: restarting servers to apply configuration"); while ( 0 != htp_u ) { if ( c3y == htp_u->liv ) { @@ -1905,7 +1907,7 @@ u3_http_ef_form(u3_httd* htd_u, u3_noun fig) !( c3y == pro || c3n == pro ) || !( c3y == log || c3n == log ) || !( c3y == red || c3n == red ) ) { - u3l_log("http: form: invalid card\n"); + u3l_log("http: form: invalid card"); u3z(fig); return; } @@ -2000,14 +2002,14 @@ _http_ef_http_server(u3_httd* htd_u, _http_continue_respond(req_u, u3k(data), u3k(complete)); } else if (c3y == u3r_sing_c("cancel", u3h(response))) { - u3l_log("http: %%cancel not handled yet\n"); + u3l_log("http: %%cancel not handled yet"); } else { - u3l_log("http: strange response\n"); + u3l_log("http: strange response"); } } else { - u3l_log("http: strange response\n"); + u3l_log("http: strange response"); } } @@ -2254,7 +2256,7 @@ _http_io_slog(u3_auto* car_u) sec_y++; seq_u = seq_u->nex_u; } - u3l_log(" open slogstreams: %d\n", sec_y); + u3l_log(" open slogstreams: %d", sec_y); } /* u3_http_io_init(): initialize http I/O. diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index 9994fcfcb..5970a56e1 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -16,6 +16,7 @@ static u3_utty* _term_main(); static void _term_read_cb(uv_stream_t* tcp_u, ssize_t siz_i, const uv_buf_t* buf_u); +static void _term_it_send_stub(u3_utty* uty_u, u3_noun tub); /* u3_write_fd(): retry interrupts, continue partial writes, assert errors. */ @@ -85,39 +86,6 @@ _term_alloc(uv_handle_t* had_u, *buf = uv_buf_init(ptr_v, 123); } -// XX unused, but %hook is in %zuse. -// implement or remove -// -#if 0 -/* _term_close_cb(): free terminal. -*/ -static void -_term_close_cb(uv_handle_t* han_t) -{ - u3_utty* tty_u = (void*) han_t; - if ( u3_Host.uty_u == tty_u ) { - u3_Host.uty_u = tty_u->nex_u; - } - else { - u3_utty* uty_u; - for (uty_u = u3_Host.uty_u; uty_u; uty_u = uty_u->nex_u ) { - if ( uty_u->nex_u == tty_u ) { - uty_u->nex_u = tty_u->nex_u; - break; - } - } - } - - { - u3_noun tid = u3dc("scot", c3__ud, tty_u->tid_l); - u3_noun pax = u3nq(u3_blip, c3__term, tid, u3_nul); - u3_pier_plan(u3k(pax), u3nc(c3__hook, u3_nul)); - u3z(pax); - } - c3_free(tty_u); -} -#endif - /* u3_term_log_init(): initialize terminal for logging */ void @@ -149,51 +117,44 @@ u3_term_log_init(void) // and simply use constant sequences. // { - uty_u->ufo_u.out.clear_u = TERM_LIT_BUF("\033[H\033[2J"); - uty_u->ufo_u.out.el_u = TERM_LIT_BUF("\033[K"); - // uty_u->ufo_u.out.el1_u = TERM_LIT_BUF("\033[1K"); - uty_u->ufo_u.out.ed_u = TERM_LIT_BUF("\033[J"); - uty_u->ufo_u.out.bel_u = TERM_LIT_BUF("\x7"); - uty_u->ufo_u.out.cub1_u = TERM_LIT_BUF("\x8"); - uty_u->ufo_u.out.cuf1_u = TERM_LIT_BUF("\033[C"); - uty_u->ufo_u.out.cuu1_u = TERM_LIT_BUF("\033[A"); - uty_u->ufo_u.out.cud1_u = TERM_LIT_BUF("\xa"); - // uty_u->ufo_u.out.cub_u = TERM_LIT_BUF("\033[%p1%dD"); - // uty_u->ufo_u.out.cuf_u = TERM_LIT_BUF("\033[%p1%dC"); - } + uty_u->ufo_u.mon_u = TERM_LIT_BUF("\033[?9h"); + uty_u->ufo_u.mof_u = TERM_LIT_BUF("\033[?9l"); - // configure input escape sequences - // - // NB: terminfo reports the wrong sequence for arrow keys on xterms. - // disabled, currently unused - // { - // uty_u->ufo_u.inn.kcuu1_u = TERM_LIT_BUF("\033[A"); // terminfo reports "\033OA" - // uty_u->ufo_u.inn.kcud1_u = TERM_LIT_BUF("\033[B"); // terminfo reports "\033OB" - // uty_u->ufo_u.inn.kcuf1_u = TERM_LIT_BUF("\033[C"); // terminfo reports "\033OC" - // uty_u->ufo_u.inn.kcub1_u = TERM_LIT_BUF("\033[D"); // terminfo reports "\033OD" - // } + uty_u->ufo_u.reg_u = TERM_LIT_BUF("\033[r"); + + uty_u->ufo_u.suc_u = TERM_LIT_BUF("\033[s"); + uty_u->ufo_u.ruc_u = TERM_LIT_BUF("\033[u"); + uty_u->ufo_u.cub_u = TERM_LIT_BUF("\x8"); + + uty_u->ufo_u.clr_u = TERM_LIT_BUF("\033[H\033[2J"); + uty_u->ufo_u.cel_u = TERM_LIT_BUF("\033[K"); + + uty_u->ufo_u.bel_u = TERM_LIT_BUF("\x7"); + } // Initialize mirror and accumulator state. // { - uty_u->tat_u.mir.lin_y = 0; - uty_u->tat_u.mir.byt_w = 0; - uty_u->tat_u.mir.wor_w = 0; - uty_u->tat_u.mir.sap_w = 0; + uty_u->tat_u.mir.lin = u3_nul; + uty_u->tat_u.mir.rus_w = 0; uty_u->tat_u.mir.cus_w = 0; uty_u->tat_u.esc.ape = c3n; uty_u->tat_u.esc.bra = c3n; + uty_u->tat_u.esc.mou = c3n; + uty_u->tat_u.esc.ton_y = 0; + uty_u->tat_u.esc.col_y = 0; uty_u->tat_u.fut.len_w = 0; uty_u->tat_u.fut.wid_w = 0; + uty_u->tat_u.fut.imp = u3_nul; } // default size // { uty_u->tat_u.siz.col_l = 80; - uty_u->tat_u.siz.row_l = 24; + uty_u->tat_u.siz.row_l = 0; } // initialize spinner state @@ -273,7 +234,7 @@ _term_it_write_cb(uv_write_t* wri_u, c3_i sas_i) // write failure is logged, but otherwise ignored. // if ( 0 != sas_i ) { - u3l_log("term: write: %s\n", uv_strerror(sas_i)); + u3l_log("term: write: %s", uv_strerror(sas_i)); } c3_free(wri_u->data); @@ -325,7 +286,7 @@ _term_it_write(u3_utty* uty_u, // synchronous write failure is logged, but otherwise ignored // if ( ret_i < 0 ) { - u3l_log("term: write: %s\n", uv_strerror(ret_i)); + u3l_log("term: write: %s", uv_strerror(ret_i)); } c3_free(ptr_v); @@ -370,32 +331,62 @@ _term_it_send(u3_utty* uty_u, } } -/* _term_it_send_cord(): write a cord. +/* _term_it_send_csi(): send csi escape sequence */ static void -_term_it_send_cord(u3_utty* uty_u, - u3_atom txt) +_term_it_send_csi(u3_utty *uty_u, c3_c cmd_c, c3_w num_w, ...) { - c3_w len_w = u3r_met(3, txt); - c3_y* hun_y = c3_malloc(len_w); - u3r_bytes(0, len_w, hun_y, txt); + va_list ap; + va_start(ap, num_w); - _term_it_send(uty_u, len_w, hun_y); + // allocate for escape sequence (2), command char (1), + // argument digits (5 per arg) and separators (1 per arg, minus 1). + // freed via _term_it_write. + // + c3_c* pas_c = c3_malloc( 2 + num_w * 6 ); + c3_y len_y = 0; - u3z(txt); + pas_c[len_y++] = '\033'; + pas_c[len_y++] = '['; + + while ( num_w-- ) { + c3_w par_w = va_arg(ap, c3_w); + len_y += sprintf(pas_c+len_y, "%d", par_w); + + if ( num_w ) { + pas_c[len_y++] = ';'; + } + } + + pas_c[len_y++] = cmd_c; + + _term_it_send(uty_u, len_y, (c3_y*)pas_c); + + va_end(ap); } -/* _term_it_show_clear(): clear to the beginning of the current line. +/* _term_it_free_line(): wipe line stored by _term_it_save_stub */ static void -_term_it_show_clear(u3_utty* uty_u) +_term_it_free_line(u3_utty* uty_u) { - if ( uty_u->tat_u.siz.col_l ) { - _term_it_dump(uty_u, TERM_LIT("\r")); - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.el_u); + u3z(uty_u->tat_u.mir.lin); + uty_u->tat_u.mir.lin = u3_nul; +} - uty_u->tat_u.mir.wor_w = 0; - uty_u->tat_u.mir.cus_w = 0; +/* _term_it_clear_line(): clear line of cursor +*/ +static void +_term_it_clear_line(u3_utty* uty_u) +{ + _term_it_dump(uty_u, TERM_LIT("\r")); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.cel_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.ruc_u); + + // if we're clearing the bottom line, clear our mirror of it too + // + if ( uty_u->tat_u.siz.row_l - 1 == uty_u->tat_u.mir.rus_w ) { + _term_it_free_line(uty_u); } } @@ -404,87 +395,35 @@ _term_it_show_clear(u3_utty* uty_u) static void _term_it_show_blank(u3_utty* uty_u) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.clear_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.clr_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.ruc_u); } -/* _term_it_show_cursor(): set current line, transferring pointer. -*/ +/* _term_it_move_cursor(): move cursor to row & column + * + * row 0 is at the top, col 0 is to the left. + * if the given position exceeds the known window size, + * it is clipped to stay within the window. + */ static void -_term_it_show_cursor(u3_utty* uty_u, c3_w cur_w) +_term_it_move_cursor(u3_utty* uty_u, c3_w col_w, c3_w row_w) { - c3_w cus_w = uty_u->tat_u.mir.cus_w; - c3_w dif_w; + c3_l row_l = uty_u->tat_u.siz.row_l; + c3_l col_l = uty_u->tat_u.siz.col_l; + if ( row_w >= row_l ) { row_w = row_l - 1; } + if ( col_w >= col_l ) { col_w = col_l - 1; } - //NOTE assumes all styled text precedes the cursor. drum enforces this. - // - cur_w += uty_u->tat_u.mir.sap_w; + _term_it_send_csi(uty_u, 'H', 2, row_w + 1, col_w + 1); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.suc_u); - if ( cur_w < cus_w ) { - dif_w = cus_w - cur_w; - - while ( dif_w-- ) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.cub1_u); - } - } - else if ( cur_w > cus_w ) { - dif_w = cur_w - cus_w; - - while ( dif_w-- ) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.cuf1_u); - } - } - - uty_u->tat_u.mir.cus_w = cur_w; + uty_u->tat_u.mir.rus_w = row_w; + uty_u->tat_u.mir.cus_w = col_w; } -/* _term_it_show_line(): render current line. +/* _term_it_show_line(): print at cursor */ static void -_term_it_show_line(u3_utty* uty_u, c3_w wor_w, c3_w sap_w) -{ - u3_utat* tat_u = &uty_u->tat_u; - - // we have to reallocate the current line on write, - // or we have a data race if a) the write is async, - // and b) a new output line arrives before the write completes. - // - { - c3_w len_w = tat_u->mir.byt_w; - c3_y* hun_y = c3_malloc(len_w); - memcpy(hun_y, tat_u->mir.lin_y, len_w); - - _term_it_send(uty_u, len_w, hun_y); - } - - // XX refactor to avoid updating state - // - tat_u->mir.cus_w += wor_w; - tat_u->mir.wor_w = wor_w; - tat_u->mir.sap_w = sap_w; -} - -/* _term_it_refresh_line(): refresh current line. -*/ -static void -_term_it_refresh_line(u3_utty* uty_u) -{ - u3_utat* tat_u = &uty_u->tat_u; - c3_w wor_w = tat_u->mir.wor_w; - c3_w sap_w = tat_u->mir.sap_w; - c3_w cus_w = tat_u->mir.cus_w; - - _term_it_show_clear(uty_u); - _term_it_show_line(uty_u, wor_w, sap_w); - _term_it_show_cursor(uty_u, cus_w); -} - -/* _term_it_set_line(): set current line. -*/ -static void -_term_it_set_line(u3_utty* uty_u, - c3_w* lin_w, - c3_w wor_w, - c3_w sap_w) +_term_it_show_line(u3_utty* uty_u, c3_w* lin_w, c3_w wor_w) { u3_utat* tat_u = &uty_u->tat_u; c3_y* hun_y = (c3_y*)lin_w; @@ -522,28 +461,67 @@ _term_it_set_line(u3_utty* uty_u, } } - c3_free(tat_u->mir.lin_y); - tat_u->mir.lin_y = hun_y; - tat_u->mir.byt_w = byt_w; - tat_u->mir.wor_w = wor_w; - tat_u->mir.sap_w = sap_w; - - _term_it_show_line(uty_u, wor_w, sap_w); + //NOTE lin_w freed through hun_y by _send + _term_it_send(uty_u, byt_w, hun_y); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.ruc_u); } -/* _term_it_show_more(): new current line. +/* _term_it_restore_line(): re-render original line at bottom of screen */ static void -_term_it_show_more(u3_utty* uty_u) +_term_it_restore_line(u3_utty* uty_u) +{ + u3_utat* tat_u = &uty_u->tat_u; + + _term_it_send_csi(uty_u, 'H', 2, tat_u->siz.row_l, 1); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.cel_u); + _term_it_send_stub(uty_u, u3k(tat_u->mir.lin)); + //NOTE send_stub restores cursor position +} + +/* _term_it_save_stub(): store line if relevant to internal logic + */ +static void +_term_it_save_stub(u3_utty* uty_u, u3_noun tub) +{ + u3_utat* tat_u = &uty_u->tat_u; + u3_noun lin = tat_u->mir.lin; + + // keep track of changes to bottom-most line, to aid spinner drawing logic. + // -t mode doesn't need this logic, because it doesn't render the spinner. + // + if ( ( tat_u->siz.row_l - 1 == tat_u->mir.rus_w ) && + ( c3n == u3_Host.ops_u.tem ) ) { + lin = u3dq("wail:klr:format", lin, tat_u->mir.cus_w, u3k(tub), ' '); + lin = u3do("pact:klr:format", lin); + } + + tat_u->mir.lin = lin; + u3z(tub); +} + +/* _term_it_show_nel(): render newline, moving cursor down +*/ +static void +_term_it_show_nel(u3_utty* uty_u) { if ( c3y == u3_Host.ops_u.tem ) { _term_it_dump(uty_u, TERM_LIT("\n")); } else { _term_it_dump(uty_u, TERM_LIT("\r\n")); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.suc_u); } uty_u->tat_u.mir.cus_w = 0; + if ( uty_u->tat_u.mir.rus_w < uty_u->tat_u.siz.row_l - 1 ) { + uty_u->tat_u.mir.rus_w++; + } + else { + // newline at bottom of screen, so bottom line is now empty + // + _term_it_free_line(uty_u); + } } /* _term_it_path(): path for console file. @@ -641,39 +619,83 @@ _term_io_belt(u3_utty* uty_u, u3_noun blb) } } -/* _term_io_suck_char(): process a single character. +/* _term_io_spit(): input the buffer (if any), then input the belt (if any) */ static void +_term_io_spit(u3_utty* uty_u, u3_noun bet) { + u3_utat* tat_u = &uty_u->tat_u; + if (u3_nul != tat_u->fut.imp) { + _term_io_belt(uty_u, u3nc(c3__txt, u3kb_flop(tat_u->fut.imp))); + tat_u->fut.imp = u3_nul; + } + if (u3_none != bet) { + _term_io_belt(uty_u, bet); + } +} + +/* _term_io_suck_char(): process a single character. + * + * Note that this accumulates simple inputs in a buffer, and is not + * guaranteed to flush it fully. After a call (or sequence of calls) + * to this function, please call _term_io_spit(uty_u, u3_none) to + * flush any remainder. + */ +static void _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) { u3_utat* tat_u = &uty_u->tat_u; + // escape sequences + // if ( c3y == tat_u->esc.ape ) { if ( c3y == tat_u->esc.bra ) { - switch ( cay_y ) { - default: { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.bel_u); - break; + // vt sequence + // + if ( cay_y == '~' ) { + switch ( tat_u->esc.seq_y ) { + default: { + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); + break; + } + case '3': _term_io_spit(uty_u, u3nc(c3__del, u3_nul)); break; } - case 'A': _term_io_belt(uty_u, u3nc(c3__aro, 'u')); break; - case 'B': _term_io_belt(uty_u, u3nc(c3__aro, 'd')); break; - case 'C': _term_io_belt(uty_u, u3nc(c3__aro, 'r')); break; - case 'D': _term_io_belt(uty_u, u3nc(c3__aro, 'l')); break; + tat_u->esc.ape = tat_u->esc.bra = c3n; + tat_u->esc.seq_y = 0; + } + else if ( cay_y <= '9' ) { + tat_u->esc.seq_y = cay_y; + } + // xterm sequence + // + else { + switch ( cay_y ) { + default: { + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); + break; + } + case 'A': _term_io_spit(uty_u, u3nc(c3__aro, 'u')); break; + case 'B': _term_io_spit(uty_u, u3nc(c3__aro, 'd')); break; + case 'C': _term_io_spit(uty_u, u3nc(c3__aro, 'r')); break; + case 'D': _term_io_spit(uty_u, u3nc(c3__aro, 'l')); break; + // + case 'M': tat_u->esc.mou = c3y; break; + } + tat_u->esc.ape = tat_u->esc.bra = c3n; } - tat_u->esc.ape = tat_u->esc.bra = c3n; } else { if ( (cay_y >= 'a') && (cay_y <= 'z') ) { tat_u->esc.ape = c3n; - _term_io_belt(uty_u, u3nc(c3__met, cay_y)); - } - else if ( '.' == cay_y ) { - tat_u->esc.ape = c3n; - _term_io_belt(uty_u, u3nc(c3__met, c3__dot)); + // XX for backwards compatibility, check kelvin version + // and fallback to [%met @c] + // + _term_io_spit(uty_u, u3nt(c3__mod, c3__met, cay_y)); } else if ( 8 == cay_y || 127 == cay_y ) { tat_u->esc.ape = c3n; - _term_io_belt(uty_u, u3nc(c3__met, c3__bac)); + // XX backwards compatibility [%met @c] + // + _term_io_spit(uty_u, u3nq(c3__mod, c3__met, c3__bac, u3_nul)); } else if ( ('[' == cay_y) || ('O' == cay_y) ) { tat_u->esc.bra = c3y; @@ -681,10 +703,31 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) else { tat_u->esc.ape = c3n; - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.bel_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); } } } + // mouse input + // + else if ( c3y == tat_u->esc.mou ) { + if ( 0 == tat_u->esc.ton_y ) { + tat_u->esc.ton_y = cay_y - 31; + } + else if ( 0 == tat_u->esc.col_y ) { + tat_u->esc.col_y = cay_y - 32; + } + else { + c3_y row_y = cay_y - 32; + // only acknowledge button 1 presses within our known window + if ( 1 != tat_u->esc.ton_y && row_y <= tat_u->siz.row_l ) { + _term_io_spit(uty_u, u3nt(c3__hit, tat_u->esc.col_y - 1, row_y - 1)); + } + tat_u->esc.mou = c3n; + tat_u->esc.ton_y = tat_u->esc.col_y = 0; + } + } + // unicode inputs + // else if ( 0 != tat_u->fut.wid_w ) { tat_u->fut.syb_y[tat_u->fut.len_w++] = cay_y; @@ -697,29 +740,28 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) wug = u3do("taft", huv); tat_u->fut.len_w = tat_u->fut.wid_w = 0; - _term_io_belt(uty_u, u3nt(c3__txt, wug, u3_nul)); + tat_u->fut.imp = u3nc(wug, tat_u->fut.imp); } } + // individual characters + // else { - if ( (cay_y >= 32) && (cay_y < 127) ) { - _term_io_belt(uty_u, u3nt(c3__txt, cay_y, u3_nul)); + if ( (cay_y >= 32) && (cay_y < 127) ) { // visual ascii + tat_u->fut.imp = u3nc(cay_y, tat_u->fut.imp); } - else if ( 0 == cay_y ) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.bel_u); + else if ( 0 == cay_y ) { // null + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); } - else if ( 8 == cay_y || 127 == cay_y ) { - _term_io_belt(uty_u, u3nc(c3__bac, u3_nul)); + else if ( 8 == cay_y || 127 == cay_y ) { // backspace & delete + _term_io_spit(uty_u, u3nc(c3__bac, u3_nul)); } - else if ( 13 == cay_y || 10 == cay_y ) { - _term_io_belt(uty_u, u3nc(c3__ret, u3_nul)); + else if ( 10 == cay_y || 13 == cay_y ) { // newline & carriage return + _term_io_spit(uty_u, u3nc(c3__ret, u3_nul)); } -#if 0 - else if ( 6 == cay_y ) { - _term_io_flow(uty_u); // XX hack - } -#endif else if ( cay_y <= 26 ) { - _term_io_belt(uty_u, u3nc(c3__ctl, ('a' + (cay_y - 1)))); + // XX backwards compatibility [%ctl @c] + // + _term_io_spit(uty_u, u3nt(c3__mod, c3__ctl, ('a' + (cay_y - 1)))); } else if ( 27 == cay_y ) { tat_u->esc.ape = c3y; @@ -762,14 +804,14 @@ _term_suck(u3_utty* uty_u, const c3_y* buf, ssize_t siz_i) // The process hangs if we do nothing (and ctrl-z // then corrupts the event log), so we force shutdown. // - u3l_log("term: hangup (EOF)\r\n"); + u3l_log("term: hangup (EOF)"); // XX revise // u3_pier_bail(u3_king_stub()); } else if ( siz_i < 0 ) { - u3l_log("term %d: read: %s\n", uty_u->tid_l, uv_strerror(siz_i)); + u3l_log("term %d: read: %s", uty_u->tid_l, uv_strerror(siz_i)); } else { c3_i i; @@ -777,6 +819,7 @@ _term_suck(u3_utty* uty_u, const c3_y* buf, ssize_t siz_i) for ( i=0; i < siz_i; i++ ) { _term_io_suck_char(uty_u, buf[i]); } + _term_io_spit(uty_u, u3_none); } } } @@ -855,14 +898,20 @@ _term_spin_step(u3_utty* uty_u) // NB: we simply bail out if anything goes wrong // { - uv_buf_t lef_u = uty_u->ufo_u.out.cub1_u; + uv_buf_t lef_u = uty_u->ufo_u.cub_u; c3_i fid_i = uty_u->fid_i; // One-time cursor backoff. // if ( c3n == tat_u->sun_u.diz_o ) { - c3_w i_w; + // if we know where the bottom line is, and the cursor is not on it, + // move it to the bottom left + // + if ( tat_u->siz.row_l && tat_u->mir.rus_w < tat_u->siz.row_l - 1 ) { + _term_it_send_csi(uty_u, 'H', 2, tat_u->siz.row_l, 1); + } + c3_w i_w; for ( i_w = bac_w; i_w < sol_w; i_w++ ) { if ( lef_u.len != write(fid_i, lef_u.base, lef_u.len) ) { return; @@ -898,6 +947,7 @@ _term_spin_timer_cb(uv_timer_t* tim_u) _term_spin_step(uty_u); } +#define _SPIN_FAST_US 100UL // spinner activation delay when expected #define _SPIN_COOL_US 500UL // spinner activation delay when cool #define _SPIN_WARM_US 50UL // spinner activation delay when warm #define _SPIN_RATE_US 250UL // spinner rate (ms/frame) @@ -922,7 +972,7 @@ u3_term_start_spinner(u3_atom say, c3_o del_o) { c3_d now_d = _term_msc_out_host(); c3_d end_d = tat_u->sun_u.end_d; - c3_d wen_d = (c3n == del_o) ? 0UL : + c3_d wen_d = (c3n == del_o) ? _SPIN_FAST_US : (now_d - end_d < _SPIN_IDLE_US) ? _SPIN_WARM_US : _SPIN_COOL_US; @@ -947,7 +997,7 @@ u3_term_stop_spinner(void) uv_timer_stop(&tat_u->sun_u.tim_u); if ( c3y == tat_u->sun_u.diz_o ) { - _term_it_refresh_line(uty_u); + _term_it_restore_line(uty_u); tat_u->sun_u.end_d = _term_msc_out_host(); tat_u->sun_u.diz_o = c3n; } @@ -1038,13 +1088,11 @@ u3_term_ef_ctlc(void) if ( uty_u->car_u ) { u3_noun wir = u3nt(c3__term, '1', u3_nul); - u3_noun cad = u3nt(c3__belt, c3__ctl, 'c'); + u3_noun cad = u3nq(c3__belt, c3__mod, c3__ctl, 'c'); c3_assert( 1 == uty_u->tid_l ); _term_ovum_plan(uty_u->car_u, wir, cad); } - - _term_it_refresh_line(uty_u); } /* _term_it_put_value(): put numeric color value on lin_w. @@ -1131,10 +1179,10 @@ _term_it_put_deco(c3_w* lin_w, } } -/* _term_it_show_stub(): send styled text to terminal as ansi escape sequences +/* _term_it_send_stub(): send styled text, without saving */ static void -_term_it_show_stub(u3_utty* uty_u, +_term_it_send_stub(u3_utty* uty_u, u3_noun tub) { c3_w tuc_w = u3qb_lent(tub); @@ -1153,17 +1201,16 @@ _term_it_show_stub(u3_utty* uty_u, // allocate enough memory for every display character, plus styles // - //NOTE we use max 31 characters per styl for escape codes: - // 3 for opening, 4 for decorations, 15 for colors, 4 for closing, - // and 5 as separators between decorations and colors. + //NOTE we use max 48 characters per styl for escape codes: + // 2 for opening, 7 for decorations, 2x16 for colors, 4 for closing, + // and 3 as separators between decorations and colors. // - c3_w* lin_w = c3_malloc( sizeof(c3_w) * (lec_w + (31 * tuc_w)) ); + c3_w* lin_w = c3_malloc( sizeof(c3_w) * (lec_w + (48 * tuc_w)) ); // write the contents to the buffer, // tracking total and escape characters written // c3_w i_w = 0; - c3_w sap_w = 0; { u3_noun nub = tub; while ( u3_nul != nub ) { @@ -1183,7 +1230,6 @@ _term_it_show_stub(u3_utty* uty_u, c3_o mor_o = c3n; lin_w[i_w++] = 27; lin_w[i_w++] = '['; - sap_w += 2; // text decorations // @@ -1193,10 +1239,8 @@ _term_it_show_stub(u3_utty* uty_u, while ( u3_nul != des ) { if ( c3y == mor_o ) { lin_w[i_w++] = ';'; - sap_w++; } _term_it_put_deco(&lin_w[i_w++], u3h(des)); - sap_w++; mor_o = c3y; des = u3t(des); } @@ -1208,12 +1252,10 @@ _term_it_show_stub(u3_utty* uty_u, if ( u3_nul != bag ) { if ( c3y == mor_o ) { lin_w[i_w++] = ';'; - sap_w++; } lin_w[i_w++] = '4'; c3_w put_w = _term_it_put_tint(&lin_w[i_w], bag); i_w += put_w; - sap_w += ++put_w; mor_o = c3y; } @@ -1222,17 +1264,14 @@ _term_it_show_stub(u3_utty* uty_u, if ( u3_nul != fog ) { if ( c3y == mor_o ) { lin_w[i_w++] = ';'; - sap_w++; } lin_w[i_w++] = '3'; c3_w put_w = _term_it_put_tint(&lin_w[i_w], fog); i_w += put_w; - sap_w += ++put_w; mor_o = c3y; } lin_w[i_w++] = 'm'; - sap_w++; } // write the text itself @@ -1248,18 +1287,27 @@ _term_it_show_stub(u3_utty* uty_u, lin_w[i_w++] = '['; lin_w[i_w++] = '0'; lin_w[i_w++] = 'm'; - sap_w += 4; } nub = u3t(nub); } } - _term_it_set_line(uty_u, lin_w, i_w, sap_w); + _term_it_show_line(uty_u, lin_w, i_w); u3z(tub); } +/* _term_it_send_stub(): send styled text to terminal as ansi escape sequences +*/ +static void +_term_it_show_stub(u3_utty* uty_u, + u3_noun tub) +{ + _term_it_send_stub(uty_u, u3k(tub)); + _term_it_save_stub(uty_u, tub); +} + /* _term_it_show_tour(): send utf32 to terminal. */ static void @@ -1277,9 +1325,14 @@ _term_it_show_tour(u3_utty* uty_u, } } - _term_it_set_line(uty_u, lin_w, len_w, 0); + _term_it_show_line(uty_u, lin_w, len_w); - u3z(lin); + { + u3_noun tub = u3i_list(u3nc(u3nt(u3_nul, u3_nul, u3_nul), lin), u3_none); + _term_it_save_stub(uty_u, tub); + } + + //NOTE lin transferred to tub above } /* _term_ef_blit(): send blit to terminal. @@ -1292,40 +1345,48 @@ _term_ef_blit(u3_utty* uty_u, default: break; case c3__bel: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.bel_u); - } + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); } break; case c3__clr: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_show_blank(uty_u); - _term_it_refresh_line(uty_u); - } + _term_it_show_blank(uty_u); } break; case c3__hop: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_show_cursor(uty_u, u3t(blt)); + u3_noun pos = u3t(blt); + if ( c3y == u3r_ud(pos) ) { + _term_it_move_cursor(uty_u, pos, uty_u->tat_u.siz.row_l - 1); + } + else { + _term_it_move_cursor(uty_u, u3h(pos), u3t(pos)); } } break; case c3__klr: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_show_clear(uty_u); - } _term_it_show_stub(uty_u, u3k(u3t(blt))); } break; - case c3__lin: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_show_clear(uty_u); - } + case c3__lin: { //TMP backwards compatibility + _term_it_move_cursor(uty_u, 0, uty_u->tat_u.siz.row_l - 1); + _term_it_clear_line(uty_u); + } // + case c3__put: { _term_it_show_tour(uty_u, u3k(u3t(blt))); } break; case c3__mor: { - _term_it_show_more(uty_u); + if (u3_nul != u3t(blt)) { + u3_noun bis = u3t(blt); + while (u3_nul != bis) { + _term_ef_blit(uty_u, u3k(u3h(bis))); + bis = u3t(bis); + } + break; + } + //TMP fall through to nel for backwards compatibility + } + case c3__nel: { + _term_it_show_nel(uty_u); } break; case c3__sav: { @@ -1343,20 +1404,50 @@ _term_ef_blit(u3_utty* uty_u, } break; case c3__url: { - u3_noun txt = u3t(blt); + // platform-agnostically opening the default web browser from within a + // c program is an unsolved problem. + } break; - // XX check u3_Host.ops_u.tem ? - // XX this looks to be broken, - // multiple calls to _show_clear will discard the mirror state - // - if ( c3y == u3a_is_atom(txt) ) { - _term_it_show_clear(uty_u); + case c3__wyp: { + _term_it_clear_line(uty_u); + } break; + } - _term_it_send_cord(uty_u, u3k(txt)); + u3z(blt); +} - _term_it_show_more(uty_u); - _term_it_refresh_line(uty_u); - } +/* _term_ef_blit_lame(): simplified output handling for -t +*/ +static void +_term_ef_blit_lame(u3_utty* uty_u, + u3_noun blt) +{ + switch ( u3h(blt) ) { + default: break; + + case c3__klr: { + _term_it_show_stub(uty_u, u3k(u3t(blt))); + _term_it_show_nel(uty_u); + } break; + + case c3__lin: //TMP backwards compatibility + case c3__put: { + _term_it_show_tour(uty_u, u3k(u3t(blt))); + _term_it_show_nel(uty_u); + } break; + + case c3__sav: { + u3_noun pax, dat; + u3x_cell(u3t(blt), &pax, &dat); + + _term_it_save(u3k(pax), u3k(dat)); + } break; + + case c3__sag: { + u3_noun pax, dat; + u3x_cell(u3t(blt), &pax, &dat); + + _term_it_save(u3k(pax), u3qe_jam(dat)); } break; } @@ -1370,7 +1461,7 @@ u3_term_io_hija(void) { u3_utty* uty_u = _term_main(); - if ( uty_u ) { + if ( uty_u && uty_u->tat_u.siz.row_l ) { if ( uty_u->fid_i > 2 ) { // We *should* in fact, produce some kind of fake FILE* for // non-console terminals. If we use this interface enough... @@ -1382,11 +1473,14 @@ u3_term_io_hija(void) if ( c3y != uty_u->hij_f(uty_u) ) { c3_assert(!"hija-tcsetattr"); } - u3_write_fd(uty_u->fid_i, "\r", 1); - { - uv_buf_t* buf_u = &uty_u->ufo_u.out.el_u; - u3_write_fd(uty_u->fid_i, buf_u->base, buf_u->len); - } + + // set scroll region to exclude the prompt, + // scroll up one line to make space, + // and move the cursor onto that space. + // + _term_it_send_csi(uty_u, 'r', 2, 1, uty_u->tat_u.siz.row_l - 1); + _term_it_send_csi(uty_u, 'S', 1, 1); + _term_it_send_csi(uty_u, 'H', 2, uty_u->tat_u.siz.row_l - 1, 1); } } } @@ -1396,11 +1490,11 @@ u3_term_io_hija(void) /* u3_term_io_loja(): release console from fprintf. */ void -u3_term_io_loja(int x) +u3_term_io_loja(int x, FILE* f) { u3_utty* uty_u = _term_main(); - if ( uty_u ) { + if ( uty_u && uty_u->tat_u.siz.row_l ) { if ( uty_u->fid_i > 2 ) { // We *should* in fact, produce some kind of fake FILE* for // non-console terminals. If we use this interface enough... @@ -1409,15 +1503,25 @@ u3_term_io_loja(int x) } else { if ( c3y == u3_Host.ops_u.tem ) { - fflush(stdout); - } else { + fprintf(f, "\n"); + fflush(f); + } + else { if ( c3y != uty_u->loj_f(uty_u) ) { c3_assert(!"loja-tcsetattr"); } - _term_it_refresh_line(uty_u); + + // clear the scrolling region we set previously, + // and restore cursor to its original position. + // + _term_it_dump_buf(uty_u, &uty_u->ufo_u.reg_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.ruc_u); } } } + else { + fprintf(f, "\r\n"); + } } /* u3_term_it_log(): writes a log message @@ -1426,7 +1530,9 @@ void u3_term_io_log(c3_c* line) { FILE* stream = u3_term_io_hija(); - u3_term_io_loja(fprintf(stream, "%s", line)); + int x = fprintf(stream, "%s", line); + fflush(stream); + u3_term_io_loja(x, stream); //TODO remove arg? unused... } /* u3_term_tape_to(): dump a tape to a file. @@ -1458,7 +1564,7 @@ u3_term_tape(u3_noun tep) u3_term_tape_to(fil_f, tep); - u3_term_io_loja(0); + u3_term_io_loja(0, fil_f); } /* u3_term_wall(): dump a wall to stdout. @@ -1477,7 +1583,7 @@ u3_term_wall(u3_noun wol) wal = u3t(wal); } - u3_term_io_loja(0); + u3_term_io_loja(0, fil_f); u3z(wol); } @@ -1490,12 +1596,16 @@ _term_io_talk(u3_auto* car_u) if ( c3n == u3_Host.ops_u.tem ) { u3_utty* uty_u = _term_main(); + // start mouse handling + // + _term_it_dump_buf(uty_u, &uty_u->ufo_u.mon_u); + uv_read_start((uv_stream_t*)&(uty_u->pin_u), _term_alloc, _term_read_cb); } - // XX groace hardcoded terminal number + //TODO reevaluate wrt dill sessions // u3_noun wir = u3nt(c3__term, '1', u3_nul); u3_noun cad; @@ -1507,10 +1617,6 @@ _term_io_talk(u3_auto* car_u) _term_ovum_plan(car_u, u3k(wir), cad); } - // NB, term.c used to also start :dojo - // - // u3nq(c3__flow, c3__seat, c3__dojo, u3_nul) - // refresh terminal state // { @@ -1563,7 +1669,7 @@ _term_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) || (u3_nul != q_pud) || (c3n == _reck_orchid(c3__ud, u3k(p_pud), &tid_l)) ) { - u3l_log("term: bad tire\n"); + u3l_log("term: bad tire"); ret_o = c3n; } else { @@ -1572,26 +1678,25 @@ _term_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) ret_o = c3n; } break; - // XX review, accepted and ignored - // - case c3__bbye: { - ret_o = c3y; - } break; - case c3__blit: { ret_o = c3y; { u3_utty* uty_u = _term_ef_get(tid_l); if ( 0 == uty_u ) { - // u3l_log("no terminal %d\n", tid_l); - // u3l_log("uty_u %p\n", u3_Host.uty_u); + // u3l_log("no terminal %d", tid_l); + // u3l_log("uty_u %p", u3_Host.uty_u); } else { u3_noun bis = dat; while ( c3y == u3du(bis) ) { - _term_ef_blit(uty_u, u3k(u3h(bis))); + if (c3n == u3_Host.ops_u.tem) { + _term_ef_blit(uty_u, u3k(u3h(bis))); + } + else { + _term_ef_blit_lame(uty_u, u3k(u3h(bis))); + } bis = u3t(bis); } } @@ -1652,6 +1757,14 @@ _term_io_exit(u3_auto* car_u) u3_utty* uty_u = _term_main(); if ( c3n == u3_Host.ops_u.tem ) { + // stop mouse handling + // + _term_it_dump_buf(uty_u, &uty_u->ufo_u.mof_u); + + // move cursor to the end + // + _term_it_move_cursor(uty_u, 0, uty_u->tat_u.siz.row_l - 1); + // NB, closed in u3_term_log_exit() // uv_read_stop((uv_stream_t*)&(uty_u->pin_u)); diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index f9e175b5d..57df1f999 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -293,7 +293,7 @@ _unix_mkdirp(c3_c* pax_c) while ( fas_c ) { *fas_c = 0; if ( 0 != mkdir(pax_c, 0777) && EEXIST != errno ) { - u3l_log("unix: mkdir %s: %s\n", pax_c, strerror(errno)); + u3l_log("unix: mkdir %s: %s", pax_c, strerror(errno)); u3m_bail(c3__fail); } *fas_c++ = '/'; @@ -318,7 +318,7 @@ u3_unix_save(c3_c* pax_c, u3_atom pad) c3_c* ful_c; if ( !u3_unix_cane(pax_c) ) { - u3l_log("%s: non-canonical path\n", pax_c); + u3l_log("%s: non-canonical path", pax_c); u3z(pad); u3m_bail(c3__fail); } if ( '/' == *pax_c) { @@ -333,7 +333,7 @@ u3_unix_save(c3_c* pax_c, u3_atom pad) _unix_mkdirp(ful_c); fid_i = c3_open(ful_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); if ( fid_i < 0 ) { - u3l_log("%s: %s\n", ful_c, strerror(errno)); + u3l_log("%s: %s", ful_c, strerror(errno)); c3_free(ful_c); u3z(pad); u3m_bail(c3__fail); } @@ -347,7 +347,7 @@ u3_unix_save(c3_c* pax_c, u3_atom pad) c3_free(pad_y); if ( rit_w != fln_w ) { - u3l_log("%s: %s\n", ful_c, strerror(errno)); + u3l_log("%s: %s", ful_c, strerror(errno)); c3_free(ful_c); u3m_bail(c3__fail); } @@ -364,35 +364,35 @@ _unix_rm_r_cb(const c3_c* pax_c, { switch ( typeflag ) { default: - u3l_log("bad file type in rm_r: %s\r\n", pax_c); + u3l_log("bad file type in rm_r: %s", pax_c); break; case FTW_F: if ( 0 != c3_unlink(pax_c) && ENOENT != errno ) { - u3l_log("error unlinking (in rm_r) %s: %s\n", + u3l_log("error unlinking (in rm_r) %s: %s", pax_c, strerror(errno)); c3_assert(0); } break; case FTW_D: - u3l_log("shouldn't have gotten pure directory: %s\r\n", pax_c); + u3l_log("shouldn't have gotten pure directory: %s", pax_c); break; case FTW_DNR: - u3l_log("couldn't read directory: %s\r\n", pax_c); + u3l_log("couldn't read directory: %s", pax_c); break; case FTW_NS: - u3l_log("couldn't stat path: %s\r\n", pax_c); + u3l_log("couldn't stat path: %s", pax_c); break; case FTW_DP: if ( 0 != c3_rmdir(pax_c) && ENOENT != errno ) { - u3l_log("error rmdiring %s: %s\n", pax_c, strerror(errno)); + u3l_log("error rmdiring %s: %s", pax_c, strerror(errno)); c3_assert(0); } break; case FTW_SL: - u3l_log("got symbolic link: %s\r\n", pax_c); + u3l_log("got symbolic link: %s", pax_c); break; case FTW_SLN: - u3l_log("got nonexistent symbolic link: %s\r\n", pax_c); + u3l_log("got nonexistent symbolic link: %s", pax_c); break; } @@ -406,7 +406,7 @@ _unix_rm_r(c3_c* pax_c) { if ( 0 > nftw(pax_c, _unix_rm_r_cb, 100, FTW_DEPTH | FTW_PHYS ) && ENOENT != errno) { - u3l_log("rm_r error on %s: %s\r\n", pax_c, strerror(errno)); + u3l_log("rm_r error on %s: %s", pax_c, strerror(errno)); } } @@ -416,7 +416,7 @@ static void _unix_mkdir(c3_c* pax_c) { if ( 0 != c3_mkdir(pax_c, 0755) && EEXIST != errno) { - u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno)); + u3l_log("error mkdiring %s: %s", pax_c, strerror(errno)); c3_assert(0); } } @@ -433,7 +433,7 @@ _unix_write_file_hard(c3_c* pax_c, u3_noun mim) u3_noun dat = u3t(u3t(mim)); if ( fid_i < 0 ) { - u3l_log("error opening %s for writing: %s\r\n", + u3l_log("error opening %s for writing: %s", pax_c, strerror(errno)); u3z(mim); return 0; @@ -449,7 +449,7 @@ _unix_write_file_hard(c3_c* pax_c, u3_noun mim) rit_w = write(fid_i, dat_y, siz_w); if ( rit_w != siz_w ) { - u3l_log("error writing %s: %s\r\n", + u3l_log("error writing %s: %s", pax_c, strerror(errno)); mug_w = 0; } @@ -479,7 +479,7 @@ _unix_write_file_soft(u3_ufil* fil_u, u3_noun mim) goto _unix_write_file_soft_go; } else { - u3l_log("error opening file (soft) %s: %s\r\n", + u3l_log("error opening file (soft) %s: %s", fil_u->pax_c, strerror(errno)); u3z(mim); return; @@ -492,17 +492,17 @@ _unix_write_file_soft(u3_ufil* fil_u, u3_noun mim) red_ws = read(fid_i, old_y, len_ws); if ( close(fid_i) < 0 ) { - u3l_log("error closing file (soft) %s: %s\r\n", + u3l_log("error closing file (soft) %s: %s", fil_u->pax_c, strerror(errno)); } if ( len_ws != red_ws ) { if ( red_ws < 0 ) { - u3l_log("error reading file (soft) %s: %s\r\n", + u3l_log("error reading file (soft) %s: %s", fil_u->pax_c, strerror(errno)); } else { - u3l_log("wrong # of bytes read in file %s: %d %d\r\n", + u3l_log("wrong # of bytes read in file %s: %d %d", fil_u->pax_c, len_ws, red_ws); } c3_free(old_y); @@ -578,7 +578,7 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) { DIR* rid_u = c3_opendir(mon_u->dir_u.pax_c); if ( !rid_u ) { - u3l_log("error opening pier directory: %s: %s\r\n", + u3l_log("error opening pier directory: %s: %s", mon_u->dir_u.pax_c, strerror(errno)); return; } @@ -591,7 +591,7 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) c3_w err_w; if ( 0 != (err_w = u3_readdir_r(rid_u, &ent_u, &out_u)) ) { - u3l_log("erroring loading pier directory %s: %s\r\n", + u3l_log("erroring loading pier directory %s: %s", mon_u->dir_u.pax_c, strerror(errno)); c3_assert(0); @@ -611,7 +611,7 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) struct stat buf_u; if ( 0 != stat(pax_c, &buf_u) ) { - u3l_log("can't stat pier directory %s: %s\r\n", + u3l_log("can't stat pier directory %s: %s", mon_u->dir_u.pax_c, strerror(errno)); c3_free(pax_c); continue; @@ -654,7 +654,7 @@ static void _unix_free_file(u3_ufil *fil_u) { if ( 0 != c3_unlink(fil_u->pax_c) && ENOENT != errno ) { - u3l_log("error unlinking %s: %s\n", fil_u->pax_c, strerror(errno)); + u3l_log("error unlinking %s: %s", fil_u->pax_c, strerror(errno)); c3_assert(0); } @@ -766,7 +766,7 @@ _unix_delete_mount_point(u3_unix* unx_u, u3_noun mon) mon_u = unx_u->mon_u; if ( !mon_u ) { - u3l_log("mount point already gone: %s\r\n", nam_c); + u3l_log("mount point already gone: %s", nam_c); goto _delete_mount_point_out; } if ( 0 == strcmp(nam_c, mon_u->nam_c) ) { @@ -782,7 +782,7 @@ _unix_delete_mount_point(u3_unix* unx_u, u3_noun mon) } if ( !mon_u->nex_u ) { - u3l_log("mount point already gone: %s\r\n", nam_c); + u3l_log("mount point already gone: %s", nam_c); goto _delete_mount_point_out; } @@ -901,7 +901,7 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) return u3nc(u3nc(_unix_string_to_path(unx_u, fil_u->pax_c), u3_nul), u3_nul); } else { - u3l_log("error opening file %s: %s\r\n", + u3l_log("error opening file %s: %s", fil_u->pax_c, strerror(errno)); return u3_nul; } @@ -913,17 +913,17 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) red_ws = read(fid_i, dat_y, len_ws); if ( close(fid_i) < 0 ) { - u3l_log("error closing file %s: %s\r\n", + u3l_log("error closing file %s: %s", fil_u->pax_c, strerror(errno)); } if ( len_ws != red_ws ) { if ( red_ws < 0 ) { - u3l_log("error reading file %s: %s\r\n", + u3l_log("error reading file %s: %s", fil_u->pax_c, strerror(errno)); } else { - u3l_log("wrong # of bytes read in file %s: %d %d\r\n", + u3l_log("wrong # of bytes read in file %s: %d %d", fil_u->pax_c, len_ws, red_ws); } c3_free(dat_y); @@ -992,7 +992,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) { if ( ENOENT != errno ) { - u3l_log("_unix_update_dir: error opening file %s: %s\r\n", + u3l_log("_unix_update_dir: error opening file %s: %s", nod_u->pax_c, strerror(errno)); } @@ -1002,7 +1002,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) } else { if ( close(fid_i) < 0 ) { - u3l_log("_unix_update_dir: error closing file %s: %s\r\n", + u3l_log("_unix_update_dir: error closing file %s: %s", nod_u->pax_c, strerror(errno)); } @@ -1017,7 +1017,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) DIR* rid_u = c3_opendir(dir_u->pax_c); if ( !rid_u ) { - u3l_log("error opening directory %s: %s\r\n", + u3l_log("error opening directory %s: %s", dir_u->pax_c, strerror(errno)); c3_assert(0); } @@ -1029,7 +1029,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( (err_w = u3_readdir_r(rid_u, &ent_u, &out_u)) != 0 ) { - u3l_log("error loading directory %s: %s\r\n", + u3l_log("error loading directory %s: %s", dir_u->pax_c, strerror(err_w)); c3_assert(0); } @@ -1045,7 +1045,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) struct stat buf_u; if ( 0 != stat(pax_c, &buf_u) ) { - u3l_log("can't stat %s: %s\r\n", pax_c, strerror(errno)); + u3l_log("can't stat %s: %s", pax_c, strerror(errno)); c3_free(pax_c); continue; } @@ -1055,13 +1055,13 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( 0 == strcmp(pax_c, nod_u->pax_c) ) { if ( S_ISDIR(buf_u.st_mode) ) { if ( c3n == nod_u->dir ) { - u3l_log("not a directory: %s\r\n", nod_u->pax_c); + u3l_log("not a directory: %s", nod_u->pax_c); c3_assert(0); } } else { if ( c3y == nod_u->dir ) { - u3l_log("not a file: %s\r\n", nod_u->pax_c); + u3l_log("not a file: %s", nod_u->pax_c); c3_assert(0); } } @@ -1095,7 +1095,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) } if ( closedir(rid_u) < 0 ) { - u3l_log("error closing directory %s: %s\r\n", + u3l_log("error closing directory %s: %s", dir_u->pax_c, strerror(errno)); } @@ -1167,7 +1167,7 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) return u3_nul; } else { - u3l_log("error opening initial file %s: %s\r\n", + u3l_log("error opening initial file %s: %s", pax_c, strerror(errno)); return u3_nul; } @@ -1179,17 +1179,17 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) red_ws = read(fid_i, dat_y, len_ws); if ( close(fid_i) < 0 ) { - u3l_log("error closing initial file %s: %s\r\n", + u3l_log("error closing initial file %s: %s", pax_c, strerror(errno)); } if ( len_ws != red_ws ) { if ( red_ws < 0 ) { - u3l_log("error reading initial file %s: %s\r\n", + u3l_log("error reading initial file %s: %s", pax_c, strerror(errno)); } else { - u3l_log("wrong # of bytes read in initial file %s: %d %d\r\n", + u3l_log("wrong # of bytes read in initial file %s: %d %d", pax_c, len_ws, red_ws); } c3_free(dat_y); @@ -1217,7 +1217,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) DIR* rid_u = c3_opendir(pax_c); if ( !rid_u ) { - u3l_log("error opening initial directory: %s: %s\r\n", + u3l_log("error opening initial directory: %s: %s", pax_c, strerror(errno)); return u3_nul; } @@ -1228,7 +1228,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) c3_w err_w; if ( 0 != (err_w = u3_readdir_r(rid_u, &ent_u, &out_u)) ) { - u3l_log("error loading initial directory %s: %s\r\n", + u3l_log("error loading initial directory %s: %s", pax_c, strerror(errno)); c3_assert(0); @@ -1245,7 +1245,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) struct stat buf_u; if ( 0 != stat(pox_c, &buf_u) ) { - u3l_log("initial can't stat %s: %s\r\n", + u3l_log("initial can't stat %s: %s", pox_c, strerror(errno)); c3_free(pox_c); continue; @@ -1263,7 +1263,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) } if ( closedir(rid_u) < 0 ) { - u3l_log("error closing initial directory %s: %s\r\n", + u3l_log("error closing initial directory %s: %s", pax_c, strerror(errno)); } @@ -1354,16 +1354,16 @@ _unix_sync_change(u3_unix* unx_u, u3_udir* dir_u, u3_noun pax, u3_noun mim) if ( c3n == u3du(pax) ) { if ( u3_nul == pax ) { - u3l_log("can't sync out file as top-level, strange\r\n"); + u3l_log("can't sync out file as top-level, strange"); } else { - u3l_log("sync out: bad path\r\n"); + u3l_log("sync out: bad path"); } u3z(pax); u3z(mim); return; } else if ( c3n == u3du(u3t(pax)) ) { - u3l_log("can't sync out file as top-level, strangely\r\n"); + u3l_log("can't sync out file as top-level, strangely"); u3z(pax); u3z(mim); } else { @@ -1393,7 +1393,7 @@ _unix_sync_change(u3_unix* unx_u, u3_udir* dir_u, u3_noun pax, u3_noun mim) } if ( c3n == nod_u->dir ) { - u3l_log("weird, we got a file when we weren't expecting to\r\n"); + u3l_log("weird, we got a file when we weren't expecting to"); c3_assert(0); } diff --git a/pkg/urbit/vere/king.c b/pkg/urbit/vere/king.c index 44a8cd502..64896a697 100644 --- a/pkg/urbit/vere/king.c +++ b/pkg/urbit/vere/king.c @@ -246,7 +246,7 @@ _king_curl_bytes(c3_c* url_c, c3_w* len_w, c3_y** hun_y, c3_t veb_t) uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0); if ( !(cul_u = curl_easy_init()) ) { - u3l_log("failed to initialize libcurl\n"); + u3l_log("failed to initialize libcurl"); exit(1); } @@ -262,13 +262,13 @@ _king_curl_bytes(c3_c* url_c, c3_w* len_w, c3_y** hun_y, c3_t veb_t) // if ( CURLE_OK != res_i ) { if ( veb_t ) { - u3l_log("curl: failed %s: %s\n", url_c, curl_easy_strerror(res_i)); + u3l_log("curl: failed %s: %s", url_c, curl_easy_strerror(res_i)); } ret_i = -1; } if ( 300 <= cod_i ) { if ( veb_t ) { - u3l_log("curl: error %s: HTTP %ld\n", url_c, cod_i); + u3l_log("curl: error %s: HTTP %ld", url_c, cod_i); } ret_i = -2; } @@ -406,12 +406,12 @@ _get_cmd_output(c3_c *cmd_c, c3_c *out_c, c3_w len_c) { FILE *fp = popen(cmd_c, "r"); if ( NULL == fp ) { - u3l_log("'%s' failed\n", cmd_c); + u3l_log("'%s' failed", cmd_c); exit(1); } if ( NULL == fgets(out_c, len_c, fp) ) { - u3l_log("'%s' produced no output\n", cmd_c); + u3l_log("'%s' produced no output", cmd_c); exit(1); } @@ -444,7 +444,7 @@ _git_pill_url(c3_c *out_c, c3_c *arv_c) assert(NULL != arv_c); if ( 0 != system("which git >> /dev/null") ) { - u3l_log("boot: could not find git executable\r\n"); + u3l_log("boot: could not find git executable"); exit(1); } @@ -461,7 +461,7 @@ _boothack_pill(void) u3_noun pil; if ( 0 != u3_Host.ops_u.pil_c ) { - u3l_log("boot: loading pill %s\r\n", u3_Host.ops_u.pil_c); + u3l_log("boot: loading pill %s", u3_Host.ops_u.pil_c); pil = u3m_file(u3_Host.ops_u.pil_c); } else { @@ -477,12 +477,12 @@ _boothack_pill(void) strcpy(url_c, u3_Host.ops_u.url_c); } - u3l_log("boot: downloading pill %s\r\n", url_c); + u3l_log("boot: downloading pill %s", url_c); pil = _king_get_atom(url_c); } if ( 0 != u3_Host.ops_u.arv_c ) { - u3l_log("boot: preparing filesystem from %s\r\n", + u3l_log("boot: preparing filesystem from %s", u3_Host.ops_u.arv_c); arv = u3nc(u3_nul, u3_unix_initial_into_card(u3_Host.ops_u.arv_c)); } @@ -503,7 +503,7 @@ _boothack_key(u3_noun kef) if ( u3_nul == des ) { c3_c* kef_c = u3r_string(kef); - u3l_log("dawn: invalid private keys: %s\r\n", kef_c); + u3l_log("dawn: invalid private keys: %s", kef_c); c3_free(kef_c); exit(1); } @@ -512,7 +512,7 @@ _boothack_key(u3_noun kef) // u3_noun pro = u3m_soft(0, u3ke_cue, u3k(u3t(des))); if ( u3_blip != u3h(pro) ) { - u3l_log("dawn: unable to cue keyfile\r\n"); + u3l_log("dawn: unable to cue keyfile"); exit(1); } seed = u3k(u3t(pro)); @@ -535,7 +535,7 @@ _boothack_key(u3_noun kef) u3_noun whu = u3dc("slaw", 'p', u3k(woh)); if ( u3_nul == whu ) { - u3l_log("dawn: invalid ship specified with -w %s\r\n", + u3l_log("dawn: invalid ship specified with -w %s", u3_Host.ops_u.who_c); exit(1); } @@ -545,7 +545,7 @@ _boothack_key(u3_noun kef) { u3_noun how = u3dc("scot", 'p', u3k(ship)); c3_c* how_c = u3r_string(u3k(how)); - u3l_log("dawn: mismatch between -w %s and -K %s\r\n", + u3l_log("dawn: mismatch between -w %s and -K %s", u3_Host.ops_u.who_c, how_c); u3z(how); @@ -576,7 +576,7 @@ _boothack_doom(void) u3_noun whu = u3dc("slaw", 'p', u3k(fak)); if ( u3_nul == whu ) { - u3l_log("boot: malformed -F ship %s\r\n", u3_Host.ops_u.fak_c); + u3l_log("boot: malformed -F ship %s", u3_Host.ops_u.fak_c); u3_king_bail(); } @@ -610,7 +610,7 @@ _boothack_doom(void) kef = u3i_string(u3_Host.ops_u.gen_c); } else { - u3l_log("boot: must specify a key with -k or -G\r\n"); + u3l_log("boot: must specify a key with -k or -G"); exit(1); } @@ -705,7 +705,7 @@ _king_sign_cb(uv_signal_t* sil_u, c3_i num_i) { switch ( num_i ) { default: { - u3l_log("\r\nmysterious signal %d\r\n", num_i); + u3l_log("\r\nmysterious signal %d", num_i); break; } @@ -715,7 +715,7 @@ _king_sign_cb(uv_signal_t* sil_u, c3_i num_i) } case SIGINT: { - u3l_log("\r\ninterrupt\r\n"); + u3l_log("\r\ninterrupt"); u3_term_ef_ctlc(); #ifdef U3_OS_mingw @@ -818,7 +818,7 @@ _king_boot_ivory(void) if ( u3_Host.ops_u.lit_c ) { if ( c3n == u3u_mmap_read("lite", u3_Host.ops_u.lit_c, &len_d, &byt_y) ) { - u3l_log("lite: unable to load ivory pill at %s\n", + u3l_log("lite: unable to load ivory pill at %s", u3_Host.ops_u.lit_c); exit(1); } @@ -833,21 +833,21 @@ _king_boot_ivory(void) u3_weak pil; if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) { - u3l_log("lite: unable to cue ivory pill\r\n"); + u3l_log("lite: unable to cue ivory pill"); exit(1); } u3s_cue_xeno_done(sil_u); if ( c3n == u3v_boot_lite(pil)) { - u3l_log("lite: boot failed\r\n"); + u3l_log("lite: boot failed"); exit(1); } } if ( u3_Host.ops_u.lit_c ) { if ( c3n == u3u_munmap(len_d, byt_y) ) { - u3l_log("lite: unable to unmap ivory pill at %s\n", + u3l_log("lite: unable to unmap ivory pill at %s", u3_Host.ops_u.lit_c); exit(1); } @@ -901,7 +901,7 @@ u3_king_commence() rlm.rlim_cur = 0; if ( 0 != setrlimit(RLIMIT_CORE, &rlm) ) { - u3l_log("king: unable to disable core dumps: %s\r\n", strerror(errno)); + u3l_log("king: unable to disable core dumps: %s", strerror(errno)); exit(1); } } @@ -974,7 +974,7 @@ _king_save_file(c3_c* url_c, FILE* fil_u) long cod_i; if ( !(cul_u = curl_easy_init()) ) { - u3l_log("failed to initialize libcurl\n"); + u3l_log("failed to initialize libcurl"); exit(1); } @@ -988,11 +988,11 @@ _king_save_file(c3_c* url_c, FILE* fil_u) // XX retry? // if ( CURLE_OK != res_i ) { - u3l_log("curl: failed %s: %s\n", url_c, curl_easy_strerror(res_i)); + u3l_log("curl: failed %s: %s", url_c, curl_easy_strerror(res_i)); ret_i = -1; } if ( 300 <= cod_i ) { - u3l_log("curl: error %s: HTTP %ld\n", url_c, cod_i); + u3l_log("curl: error %s: HTTP %ld", url_c, cod_i); ret_i = -2; } @@ -1058,14 +1058,14 @@ _king_init_pace(c3_c* pac_c) return 0; } else { - u3l_log("dock: init pace (%s): open %s\n", pac_c, strerror(errno)); + u3l_log("dock: init pace (%s): open %s", pac_c, strerror(errno)); c3_free(bin_c); return -1; } } if ( _king_write_raw(fid_i, (c3_y*)pac_c, strlen(pac_c)) ) { - u3l_log("dock: init pace (%s): write %s\n", pac_c, strerror(errno)); + u3l_log("dock: init pace (%s): write %s", pac_c, strerror(errno)); close(fid_i); c3_free(bin_c); return -1; @@ -1073,12 +1073,12 @@ _king_init_pace(c3_c* pac_c) // XX sync first? // else if ( close(fid_i) ) { - u3l_log("dock: init pace (%s): close %s\n", pac_c, strerror(errno)); + u3l_log("dock: init pace (%s): close %s", pac_c, strerror(errno)); c3_free(bin_c); return 1; } - u3l_log("dock: pace (%s): configured at %s/.bin/pace\r\n", + u3l_log("dock: pace (%s): configured at %s/.bin/pace", pac_c, u3_Host.dir_c); return 0; @@ -1138,12 +1138,12 @@ u3_king_vere(c3_c* pac_c, // pace || !(fil_u = fdopen(fid_i, "wb")) ) { if ( EEXIST == errno ) { - u3l_log("already installed\n"); + u3l_log("already installed"); c3_free(bin_c); return 0; } else { - u3l_log("unable to open %s: %s\r\n", bin_c, strerror(errno)); + u3l_log("unable to open %s: %s", bin_c, strerror(errno)); c3_free(bin_c); return -1; } @@ -1154,7 +1154,7 @@ u3_king_vere(c3_c* pac_c, // pace c3_assert( ret_i > 0 ); if ( (ret_i = _king_save_file(url_c, fil_u)) ) { - u3l_log("unable to save %s to %s: %d\r\n", url_c, bin_c, ret_i); + u3l_log("unable to save %s to %s: %d", url_c, bin_c, ret_i); c3_free(url_c); fclose(fil_u); unlink(bin_c); @@ -1187,7 +1187,7 @@ u3_king_vere(c3_c* pac_c, // pace } } - u3l_log("vere: saved to %s\n", bin_c); + u3l_log("vere: saved to %s", bin_c); c3_free(url_c); c3_free(bin_c); @@ -1210,13 +1210,13 @@ _king_do_upgrade(c3_c* pac_c, c3_c* ver_c) arc_c = u3_Host.arc_c; } else { - u3l_log("vere: --arch required\r\n"); + u3l_log("vere: --arch required"); return; } #endif if ( _king_make_pace(pac_c) ) { - u3l_log("vere: unable to make pace (%s) directory in pier\n", pac_c); + u3l_log("vere: unable to make pace (%s) directory in pier", pac_c); u3_king_bail(); exit(1); } @@ -1229,13 +1229,13 @@ _king_do_upgrade(c3_c* pac_c, c3_c* ver_c) // XX get link option // if ( u3_king_vere(pac_c, ver_c, arc_c, dir_c, 1) ) { - u3l_log("vere: upgrade failed\r\n"); + u3l_log("vere: upgrade failed"); u3_king_bail(); exit(1); } c3_free(dir_c); - u3l_log("vere: upgrade succeeded\r\n"); + u3l_log("vere: upgrade succeeded"); // XX print restart instructions } @@ -1471,7 +1471,7 @@ u3_king_dock(c3_c* pac_c) // XX get link option // if ( _king_copy_vere(pac_c, URBIT_VERSION, arc_c, 1) ) { - u3l_log("vere: binary copy failed\r\n"); + u3l_log("vere: binary copy failed"); u3_king_bail(); exit(1); } @@ -1479,7 +1479,7 @@ u3_king_dock(c3_c* pac_c) // NB: failure ignored // _king_init_pace(pac_c); - u3l_log("vere: binary copy succeeded\r\n"); + u3l_log("vere: binary copy succeeded"); // XX print restart instructions } } @@ -1509,10 +1509,10 @@ u3_king_done(void) if ( u3_Host.xit_i ) { if ( c3y == u3_Host.nex_o ) { - u3l_log("vere: upgrade failed\r\n"); + u3l_log("vere: upgrade failed"); } else if ( c3y == u3_Host.pep_o ) { - u3l_log("vere: prep for upgrade failed\r\n"); + u3l_log("vere: prep for upgrade failed"); } } else { @@ -1530,15 +1530,15 @@ u3_king_done(void) switch ( u3_king_next(pac_c, &ver_c) ) { case -2: { - u3l_log("vere: unable to check for next version\n"); + u3l_log("vere: unable to check for next version"); } break; case -1: { - u3l_log("vere: up to date\n"); + u3l_log("vere: up to date"); } break; case 0: { - u3l_log("vere: next (%%%s): %s\n", pac_c, ver_c); + u3l_log("vere: next (%%%s): %s", pac_c, ver_c); _king_do_upgrade(pac_c, ver_c); c3_free(ver_c); } break; @@ -1549,7 +1549,7 @@ u3_king_done(void) c3_free(pac_c); } else if ( c3y == u3_Host.pep_o ) { - u3l_log("vere: ready for upgrade\n"); + u3l_log("vere: ready for upgrade"); } // copy binary into pier on boot @@ -1652,7 +1652,7 @@ u3_king_grab(void* vod_p) } #else { - u3_term_io_loja(0); + u3_term_io_loja(0, fil_u); } #endif } diff --git a/pkg/urbit/vere/lord.c b/pkg/urbit/vere/lord.c index 205190848..b7b356e57 100644 --- a/pkg/urbit/vere/lord.c +++ b/pkg/urbit/vere/lord.c @@ -267,13 +267,13 @@ _lord_plea_live(u3_lord* god_u, u3_noun dat) case u3_writ_meld: { // XX wire into cb // - u3l_log("pier: meld complete\n"); + u3l_log("pier: meld complete"); } break; case u3_writ_pack: { // XX wire into cb // - u3l_log("pier: pack complete\n"); + u3l_log("pier: pack complete"); } break; } @@ -1056,7 +1056,7 @@ _lord_on_serf_err_cb(uv_stream_t* pyp_u, uv_read_stop(pyp_u); if ( siz_i != UV_EOF ) { - u3l_log("lord: serf stderr: %s\r\n", uv_strerror(siz_i)); + u3l_log("lord: serf stderr: %s", uv_strerror(siz_i)); } } @@ -1098,10 +1098,10 @@ _lord_on_serf_bail(void* ptr_v, u3_lord* god_u = ptr_v; if ( UV_EOF == err_i ) { - u3l_log("pier: serf unexpectedly shut down\r\n"); + u3l_log("pier: serf unexpectedly shut down"); } else { - u3l_log("pier: serf error: %s\r\n", err_c); + u3l_log("pier: serf error: %s", err_c); } _lord_bail(god_u); @@ -1128,7 +1128,7 @@ u3_lord_info(u3_lord* god_u) void u3_lord_slog(u3_lord* god_u) { - u3l_log(" lord: live=%s, event=%" PRIu64 ", mug=%x, queue=%u\n", + u3l_log(" lord: live=%s, event=%" PRIu64 ", mug=%x, queue=%u", ( c3y == god_u->liv_o ) ? "&" : "|", god_u->eve_d, god_u->mug_l, @@ -1165,7 +1165,7 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) c3_c lom_c[11]; c3_i err_i; - sprintf(key_c, "%" PRIx64 ":%" PRIx64 ":%" PRIx64 ":%" PRIx64 "", + sprintf(key_c, "%" PRIx64 ":%" PRIx64 ":%" PRIx64 ":%" PRIx64, god_u->key_d[0], god_u->key_d[1], god_u->key_d[2], diff --git a/pkg/urbit/vere/newt.c b/pkg/urbit/vere/newt.c index 02dd23b10..583edf5e3 100644 --- a/pkg/urbit/vere/newt.c +++ b/pkg/urbit/vere/newt.c @@ -384,7 +384,7 @@ u3_newt_moat_slog(u3_moat* mot_u) } if ( len_w ) { - u3l_log(" newt: %u inbound ipc messages pending\n", len_w); + u3l_log(" newt: %u inbound ipc messages pending", len_w); } } diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index 9f1fd00e0..a0870ff60 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -251,7 +251,7 @@ _pier_work(u3_work* wok_u) // XX this is when "boot" is actually complete // XX even better would be after neighboring with our sponsor // - u3l_log("pier (%" PRIu64 "): live\r\n", pir_u->god_u->eve_d); + u3l_log("pier (%" PRIu64 "): live", pir_u->god_u->eve_d); // XX move callbacking to king // @@ -286,7 +286,7 @@ _pier_on_lord_work_spin(void* ptr_v, u3_atom pin, c3_o del_o) u3_term_start_spinner(pin, del_o); } -/* _pier_on_lord_work_spin(): stop spinner +/* _pier_on_lord_work_spun(): stop spinner */ static void _pier_on_lord_work_spun(void* ptr_v) @@ -472,13 +472,13 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) u3_weak res = u3r_at(7, nun); if (u3_none == res) { - u3l_log("pier: scry failed\n"); + u3l_log("pier: scry failed"); } else { u3_weak out; c3_c *ext_c, *pac_c; - u3l_log("pier: scry succeeded\n"); + u3l_log("pier: scry succeeded"); if ( u3_Host.ops_u.puk_c ) { pac_c = u3_Host.ops_u.puk_c; @@ -504,7 +504,7 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) ext_c = "txt"; } else { - u3l_log("pier: cannot export cell as %s\n", u3_Host.ops_u.puf_c); + u3l_log("pier: cannot export cell as %s", u3_Host.ops_u.puf_c); out = u3_none; } u3z(puf); @@ -517,11 +517,11 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) snprintf(fil_c, 256, "%s.%s", pac_c + 1, ext_c); u3_unix_save(fil_c, out); - u3l_log("pier: scry result in %s/.urb/put/%s\n", u3_Host.dir_c, fil_c); + u3l_log("pier: scry result in %s/.urb/put/%s", u3_Host.dir_c, fil_c); } } - u3l_log("pier: exit\n"); + u3l_log("pier: exit"); u3_pier_exit(pir_u); u3z(nun); @@ -600,7 +600,7 @@ _pier_work_init(u3_pier* pir_u) } else { // run the requested scry, jam to disk, then exit // - u3l_log("pier: scry\n"); + u3l_log("pier: scry"); u3_pier_peek_last(pir_u, u3_nul, u3k(car), u3k(dek), u3k(pax), pir_u, _pier_on_scry_done); } @@ -649,7 +649,7 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) { // XX version negotiation failed, print upgrade message // - u3l_log("pier: version negotation failed\n\n"); + u3l_log("pier: version negotation failed"); // XX only print trace with -v ? // @@ -673,8 +673,8 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) // XX organizing version constants // #define VERE_NAME "vere" -#define VERE_ZUSE 417 -#define VERE_LULL 328 +#define VERE_ZUSE 416 +#define VERE_LULL 327 /* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN */ @@ -736,7 +736,7 @@ _pier_on_lord_wyrd_done(void* ptr_v, // XX messaging, cli argument to bypass // - u3l_log("pier: version negotiation failed; downgrade\n"); + u3l_log("pier: version negotiation failed; downgrade"); _pier_wyrd_fail(pir_u, egg_u, u3_nul); } else { @@ -829,7 +829,7 @@ _pier_wyrd_init(u3_pier* pir_u) pir_u->sat_e = u3_psat_wyrd; - u3l_log("vere: checking version compatibility\n"); + u3l_log("vere: checking version compatibility"); { u3_lord* god_u = pir_u->god_u; @@ -1018,11 +1018,11 @@ _pier_play(u3_play* pay_u) if ( god_u->eve_d == pay_u->eve_d ) { // XX should be play_cb // - u3l_log("---------------- playback complete ----------------\r\n"); + u3l_log("---------------- playback complete ----------------"); u3_term_stop_spinner(); if ( pay_u->eve_d < log_u->dun_d ) { - // u3l_log("pier: replay barrier reached, shutting down\r\n"); + // u3l_log("pier: replay barrier reached, shutting down"); // // XX graceful shutdown // // // u3_lord_save(pir_u->god_u); @@ -1031,7 +1031,7 @@ _pier_play(u3_play* pay_u) // XX temporary hack // - u3l_log("pier: replay barrier reached, cramming\r\n"); + u3l_log("pier: replay barrier reached, cramming"); u3_pier_cram(pir_u); } else if ( pay_u->eve_d == log_u->dun_d ) { @@ -1067,12 +1067,12 @@ _pier_on_lord_play_done(void* ptr_v, u3_info fon_u, c3_l mug_l) c3_assert( u3_psat_play == pir_u->sat_e ); - u3l_log("pier: (%" PRIu64 "): play: done\r\n", tac_u->eve_d); + u3l_log("pier: (%" PRIu64 "): play: done", tac_u->eve_d); // XX optional // if ( tac_u->mug_l && (tac_u->mug_l != mug_l) ) { - u3l_log("pier: (%" PRIu64 "): play: mug mismatch %x %x\r\n", + u3l_log("pier: (%" PRIu64 "): play: mug mismatch %x %x", tac_u->eve_d, tac_u->mug_l, mug_l); @@ -1121,7 +1121,7 @@ _pier_on_lord_play_bail(void* ptr_v, u3_info fon_u, // XX optional // if ( las_l && (las_l != mug_l) ) { - u3l_log("pier: (%" PRIu64 "): play bail: mug mismatch %x %x\r\n", + u3l_log("pier: (%" PRIu64 "): play bail: mug mismatch %x %x", (c3_d)(eve_d - 1ULL), las_l, mug_l); @@ -1132,7 +1132,7 @@ _pier_on_lord_play_bail(void* ptr_v, u3_info fon_u, // #if 0 { - u3l_log("pier: (%" PRIu64 "): play: retry\r\n", eve_d); + u3l_log("pier: (%" PRIu64 "): play: retry", eve_d); fon_u.ext_u = tac_u; @@ -1153,7 +1153,7 @@ _pier_on_lord_play_bail(void* ptr_v, u3_info fon_u, } #else { - u3l_log("pier: (%" PRIu64 "): play: bail\r\n", eve_d); + u3l_log("pier: (%" PRIu64 "): play: bail", eve_d); u3_pier_punt_goof("play", dud); { u3_noun wir, tag; @@ -1189,12 +1189,12 @@ _pier_play_init(u3_pier* pir_u, c3_d eve_d) pay_u->eve_d = eve_d; pay_u->sen_d = god_u->eve_d; - u3l_log("---------------- playback starting ----------------\r\n"); + u3l_log("---------------- playback starting ----------------"); if ( (1ULL + god_u->eve_d) == eve_d ) { - u3l_log("pier: replaying event %" PRIu64 "\r\n", eve_d); + u3l_log("pier: replaying event %" PRIu64, eve_d); } else { - u3l_log("pier: replaying events %" PRIu64 "-%" PRIu64 "\r\n", + u3l_log("pier: replaying events %" PRIu64 "-%" PRIu64, (c3_d)(1ULL + god_u->eve_d), eve_d); } @@ -1323,7 +1323,7 @@ _pier_on_lord_cram(void* ptr_v) // XX temporary hack // if ( u3_psat_play == pir_u->sat_e ) { - u3l_log("pier: cram complete, shutting down\r\n"); + u3l_log("pier: cram complete, shutting down"); u3_pier_bail(pir_u); exit(0); } @@ -1352,7 +1352,7 @@ _pier_on_lord_exit(void* ptr_v) pir_u->god_u = 0; if ( u3_psat_done != pir_u->sat_e ) { - u3l_log("pier: serf shutdown unexpected\r\n"); + u3l_log("pier: serf shutdown unexpected"); u3_pier_bail(pir_u); } // if we made it all the way here, it's our jab to wrap up @@ -1413,10 +1413,10 @@ _pier_on_lord_live(void* ptr_v) // if ( u3_Host.ops_u.til_c ) { if ( 1 == sscanf(u3_Host.ops_u.til_c, "%" PRIu64 "", &eve_d) ) { - u3l_log("pier: replay till %" PRIu64 "\r\n", eve_d); + u3l_log("pier: replay till %" PRIu64, eve_d); } else { - u3l_log("pier: ignoring invalid replay barrier '%s'\r\n", + u3l_log("pier: ignoring invalid replay barrier '%s'", u3_Host.ops_u.til_c); eve_d = log_u->dun_d; } @@ -1534,51 +1534,51 @@ u3_pier_slog(u3_pier* pir_u) { switch ( pir_u->sat_e ) { default: { - u3l_log("pier: unknown state: %u\r\n", pir_u->sat_e); + u3l_log("pier: unknown state: %u", pir_u->sat_e); } break; case u3_psat_init: { - u3l_log("pier: init\n"); + u3l_log("pier: init"); } break; case u3_psat_boot: { - u3l_log("pier: boot\n"); + u3l_log("pier: boot"); } break; case u3_psat_play: { - u3l_log("pier: play\n"); + u3l_log("pier: play"); { u3_play* pay_u = pir_u->pay_u; - u3l_log(" target: %" PRIu64 "\n", pay_u->eve_d); - u3l_log(" sent: %" PRIu64 "\n", pay_u->sen_d); - u3l_log(" read: %" PRIu64 "\n", pay_u->req_d); + u3l_log(" target: %" PRIu64, pay_u->eve_d); + u3l_log(" sent: %" PRIu64, pay_u->sen_d); + u3l_log(" read: %" PRIu64, pay_u->req_d); } } break; case u3_psat_work: { - u3l_log("pier: work\n"); + u3l_log("pier: work"); { u3_work* wok_u = pir_u->wok_u; - u3l_log(" effects: released=%" PRIu64 "\n", wok_u->fec_u.rel_d); + u3l_log(" effects: released=%" PRIu64, wok_u->fec_u.rel_d); if ( wok_u->fec_u.ext_u ) { if ( wok_u->fec_u.ext_u != wok_u->fec_u.ent_u ) { - u3l_log(" pending %" PRIu64 "-%" PRIu64 "\n", + u3l_log(" pending %" PRIu64 "-%" PRIu64, wok_u->fec_u.ext_u->eve_d, wok_u->fec_u.ent_u->eve_d); } else { - u3l_log(" pending %" PRIu64 "\n", wok_u->fec_u.ext_u->eve_d); + u3l_log(" pending %" PRIu64, wok_u->fec_u.ext_u->eve_d); } } if ( wok_u->wal_u ) { - u3l_log(" wall: %" PRIu64 "\n", wok_u->wal_u->eve_d); + u3l_log(" wall: %" PRIu64, wok_u->wal_u->eve_d); } if ( wok_u->car_u ) { @@ -1588,7 +1588,7 @@ u3_pier_slog(u3_pier* pir_u) } break; case u3_psat_done: { - u3l_log("pier: done\n"); + u3l_log("pier: done"); } break; } @@ -1704,7 +1704,7 @@ u3_pier_stay(c3_w wag_w, u3_noun pax) if ( c3y == u3_Host.ops_u.veb ) { FILE* fil_u = u3_term_io_hija(); u3_lmdb_stat(pir_u->log_u->mdb_u, fil_u); - u3_term_io_loja(1); + u3_term_io_loja(1, fil_u); } u3z(pax); @@ -2317,10 +2317,12 @@ _pier_dump_wall(FILE* fil_u, u3_noun wol) while ( u3_nul != wal ) { _pier_dump_tape(fil_u, u3k(u3h(wal))); - putc(13, fil_u); - putc(10, fil_u); - wal = u3t(wal); + + if ( u3_nul != wal ) { + putc(13, fil_u); + putc(10, fil_u); + } } u3z(wol); @@ -2346,6 +2348,7 @@ u3_pier_tank(c3_l tab_l, c3_w pri_w, u3_noun tac) case 3: fprintf(fil_u, "\033[31m>>> "); break; case 2: fprintf(fil_u, "\033[33m>> "); break; case 1: fprintf(fil_u, "\033[32m> "); break; + case 0: fprintf(fil_u, "\033[90m" ); break; } } else { @@ -2362,8 +2365,6 @@ u3_pier_tank(c3_l tab_l, c3_w pri_w, u3_noun tac) if ( 0 == u3A->roc ) { if ( c3__leaf == u3h(tac) ) { _pier_dump_tape(fil_u, u3k(u3t(tac))); - putc(13, fil_u); - putc(10, fil_u); } } // We are calling nock here, but hopefully need no protection. @@ -2380,7 +2381,7 @@ u3_pier_tank(c3_l tab_l, c3_w pri_w, u3_noun tac) fflush(fil_u); - u3_term_io_loja(0); + u3_term_io_loja(0, fil_u); u3z(blu); u3z(tac); } @@ -2410,12 +2411,12 @@ u3_pier_punt_goof(const c3_c* cap_c, u3_noun dud) u3x_cell(dud, &mot, &tan); - u3l_log("\n"); + u3l_log(""); u3_pier_punt(0, u3qb_flop(tan)); { c3_c* mot_c = u3r_string(mot); - u3l_log("%s: bail: %%%s\r\n", cap_c, mot_c); + u3l_log("%s: bail: %%%s", cap_c, mot_c); c3_free(mot_c); } @@ -2431,7 +2432,7 @@ u3_pier_punt_ovum(const c3_c* cap_c, u3_noun wir, u3_noun tag) u3_noun riw = u3do("spat", wir); c3_c* wir_c = u3r_string(riw); - u3l_log("%s: %%%s event on %s failed\r\n\n", cap_c, tag_c, wir_c); + u3l_log("%s: %%%s event on %s failed", cap_c, tag_c, wir_c); c3_free(tag_c); c3_free(wir_c); diff --git a/pkg/urbit/vere/save.c b/pkg/urbit/vere/save.c index b2fc5b390..956d750cc 100644 --- a/pkg/urbit/vere/save.c +++ b/pkg/urbit/vere/save.c @@ -25,7 +25,7 @@ u3_save_ef_chld(u3_pier *pir_u) /* modified for cases with no pid_w */ - u3l_log("checkpoint: complete %d\n", sav_u->pid_w); + u3l_log("checkpoint: complete %d", sav_u->pid_w); pid_w = wait(&loc_i); if (0 != sav_u->pid_w) { c3_assert(pid_w == sav_u->pid_w); diff --git a/pkg/urbit/worker/serf.c b/pkg/urbit/worker/serf.c index 85420a122..ec20a32ec 100644 --- a/pkg/urbit/worker/serf.c +++ b/pkg/urbit/worker/serf.c @@ -243,7 +243,7 @@ _serf_grab(u3_noun sac) u3z(sac); - u3l_log("\n"); + u3l_log(""); } } @@ -318,7 +318,7 @@ u3_serf_post(u3_serf* sef_u) if ( c3y == sef_u->pac_o ) { u3a_print_memory(stderr, "serf: pack: gained", u3m_pack()); - u3l_log("\n"); + u3l_log(""); sef_u->pac_o = c3n; } } @@ -500,7 +500,7 @@ _serf_poke(u3_serf* sef_u, c3_c* cap_c, c3_w mil_w, u3_noun job) if ( (c3__belt != tag) && (c3__crud != tag) ) { - u3l_log("serf: %s (%" PRIu64 ") %s\r\n", cap_c, sef_u->sen_d, txt_c); + u3l_log("serf: %s (%" PRIu64 ") %s", cap_c, sef_u->sen_d, txt_c); } } #endif @@ -520,7 +520,7 @@ _serf_poke(u3_serf* sef_u, c3_c* cap_c, c3_w mil_w, u3_noun job) clr_w = ms_w > 1000 ? 1 : ms_w < 100 ? 2 : 3; // red, green, yellow if ( clr_w != 2 ) { - u3l_log("\x1b[3%dm%%%s (%" PRIu64 ") %4d.%02dms\x1b[0m\n", + u3l_log("\x1b[3%dm%%%s (%" PRIu64 ") %4d.%02dms\x1b[0m", clr_w, txt_c, sef_u->sen_d, ms_w, (int) (d0.tv_usec % 1000) / 10); } @@ -559,7 +559,7 @@ _serf_work(u3_serf* sef_u, c3_w mil_w, u3_noun job) // if ( u3_blip == u3h(gon) ) { u3_noun vir = _serf_sure(sef_u, pre_w, u3k(u3t(gon))); - + u3z(gon); u3z(job); return u3nc(c3__done, u3nt(u3i_chubs(1, &sef_u->dun_d), sef_u->mug_l, @@ -941,7 +941,7 @@ u3_serf_live(u3_serf* sef_u, u3_noun com, u3_noun* ret) return c3n; } - u3l_log("serf (%" PRIu64 "): saving rock\r\n", sef_u->dun_d); + u3l_log("serf (%" PRIu64 "): saving rock", sef_u->dun_d); if ( c3n == u3u_cram(sef_u->dir_c, eve_d) ) { fprintf(stderr, "serf (%" PRIu64 "): unable to jam state\r\n", eve_d); @@ -1085,7 +1085,7 @@ u3_serf_writ(u3_serf* sef_u, u3_noun wit, u3_noun* pel) static u3_noun _serf_ripe(u3_serf* sef_u) { - // u3l_log("serf: ripe %" PRIu64 "\r\n", sef_u->dun_d); + // u3l_log("serf: ripe %" PRIu64, sef_u->dun_d); sef_u->mug_l = ( 0 == sef_u->dun_d ) ? 0 diff --git a/pkg/webterm/desk.docket-0 b/pkg/webterm/desk.docket-0 index 549932de6..531bd1d58 100644 --- a/pkg/webterm/desk.docket-0 +++ b/pkg/webterm/desk.docket-0 @@ -1,9 +1,9 @@ :~ title+'Terminal' info+'A web interface to your Urbit\'s command line.' color+0x2e.4347 - glob-http+['https://bootstrap.urbit.org/glob-0v7.1hgb7.euged.6oj3e.cdhdg.rah02.glob' 0v7.1hgb7.euged.6oj3e.cdhdg.rah02] + glob-http+['https://bootstrap.urbit.org/glob-0v5.hvjci.n7c4h.1onl6.34g14.fut7c.glob' 0v5.hvjci.n7c4h.1onl6.34g14.fut7c] base+'webterm' - version+[1 0 1] + version+[1 1 0] website+'https://tlon.io' license+'MIT' == diff --git a/pkg/webterm/sys.kelvin b/pkg/webterm/sys.kelvin index b7bcb9ecd..0cb1220e5 100644 --- a/pkg/webterm/sys.kelvin +++ b/pkg/webterm/sys.kelvin @@ -1 +1 @@ -[%zuse 417] +[%zuse 416] diff --git a/tests/lib/dprint.hoon b/tests/lib/dprint.hoon new file mode 100644 index 000000000..756a7c8a2 --- /dev/null +++ b/tests/lib/dprint.hoon @@ -0,0 +1,318 @@ +:: This library contains unit tests for doccords. +:: +/+ *test, *dprint +:: +=> => + :: core-summary + :: + :: core-description + |% + :: chapter-summary + :: + :: chapter-description + +| %chapter-test + ++ empty ~ + -- + :: + :: arms used for testing doccords + |% + +| %types + +$ arm-dox [tape what what what] + +$ core-dox what + +$ chapter-dox [tape what] + :: + +| %helper-functions + ++ get-item + |= a=(list term) + ^- item + +:(find-item-in-type a -:!>(.)) + :: + ++ get-arm-dox + |= a=(list term) + ^- arm-dox + =/ itm=item (get-item a) + ?> ?=([%arm *] itm) + [name adoc pdoc cdoc]:itm + :: + ++ get-core-dox + |= a=(list term) + ^- core-dox + =/ itm=item (get-item a) + ?> ?=([%core *] itm) + docs:itm + :: + ++ get-chapter-dox + |= a=(list term) + ^- chapter-dox + =/ itm=item (get-item a) + ?> ?=([%chapter *] itm) + [name docs]:itm + :: + ++ arm-check + |= [arms=(list term) wat=(trel ? ? ?) docs=(trel what what what)] + ^- tang + =| res=tang + |- + ?~ arms res + %= $ + arms t.arms + res %+ weld + res + %+ expect-eq + !> ^- arm-dox + :* (trip i.arms) + ?:(p.wat p.docs *what) + ?:(q.wat q.docs *what) + ?:(r.wat r.docs *what) + == + :: + !> (get-arm-dox ~[i.arms]) + == + :: + ++ run-arm-tests + |= [wat=(trel ? ? ?)] + ^- tang + =/ num (sub 3 :(add p.wat q.wat r.wat)) + =/ prefix=term + ;: (cury cat 3) + %arm- + ?:(p.wat %adoc- ~) + ?:(q.wat %pdoc- ~) + ?:(r.wat %cdoc- ~) + == + =/ arms=(list term) + %- turn + :_ |= [postfix=term] + `term`(cat 3 prefix postfix) + ^- (list term) + ?+ num ~ + %1 ~[%pre %post] + %2 ~[%pre-pre %post-pre %post-post] + %3 :~ %pre-pre-pre + %pre-pre-post + %pre-post-pre + %post-pre-pre + %pre-post-post + %post-pre-post + %post-post-pre + == + == + %^ arm-check + arms + wat + [`['arm-doc' ~] `['product-doc' ~] `['core-doc' ~]] + :: + +| %batch-comments + :: +b-foo: a foo + :: $b-baz: a baz + :: +b-bar: a bar + :: + :: a very bar foo + :: + :: $b-boz: a boz + :: + :: a very boz baz + :: + ++ b-foo ~ + ++ b-bar ~ + +$ b-baz * + +$ b-boz * + :: + +| %docs-for-arms + ++ no-doc ~ + :: + :: +arm-adoc-pre: arm-doc + ++ arm-adoc-pre ~ + :: + ++ arm-adoc-post :: arm-doc + ~ + :: + ++ arm-pdoc-pre + :: product-doc + 'foo' + ++ arm-pdoc-post + 'foo' :: product-doc + :: + ++ arm-cdoc-pre + |% + :: core-doc + ++ $ ~ + -- + :: + ++ arm-cdoc-post + |% + ++ $ :: core-doc + ~ + -- + :: + :: +arm-adoc-pdoc-pre-pre: arm-doc + ++ arm-adoc-pdoc-pre-pre + :: product-doc + 'foo' + :: + ++ arm-adoc-pdoc-post-pre :: arm-doc + :: product-doc + 'foo' + :: + ++ arm-adoc-pdoc-post-post :: arm-doc + 'foo' :: product-doc + :: + :: +arm-adoc-cdoc-pre-pre: arm-doc + ++ arm-adoc-cdoc-pre-pre + |% + :: core-doc + ++ $ ~ + -- + :: + ++ arm-adoc-cdoc-post-pre :: arm-doc + |% + :: core-doc + ++ $ ~ + -- + :: + ++ arm-adoc-cdoc-post-post :: arm-doc + |% + ++ $ :: core-doc + ~ + -- + :: + ++ arm-pdoc-cdoc-pre-pre + :: product-doc + |% + :: core-doc + ++ $ ~ + -- + ++ arm-pdoc-cdoc-post-pre + |% + :: core-doc + ++ $ ~ + -- :: product-doc + :: + ++ arm-pdoc-cdoc-post-post + |% + ++ $ :: core-doc + ~ + -- :: product-doc + :: + :: +arm-adoc-pdoc-cdoc-pre-pre-pre: arm-doc + ++ arm-adoc-pdoc-cdoc-pre-pre-pre + :: product-doc + |% + :: core-doc + ++ $ ~ + -- + :: + ++ arm-adoc-pdoc-cdoc-post-pre-pre :: arm-doc + :: product-doc + |% + :: core-doc + ++ $ ~ + -- + :: + :: +arm-adoc-pdoc-cdoc-pre-post-pre: arm-doc + ++ arm-adoc-pdoc-cdoc-pre-post-pre + |% + :: core-doc + ++ $ ~ + -- :: product-doc + :: + :: +arm-adoc-pdoc-cdoc-pre-pre-post: arm-doc + ++ arm-adoc-pdoc-cdoc-pre-pre-post + :: product-doc + |% + ++ $ :: core-doc + ~ + -- + :: + ++ arm-adoc-pdoc-cdoc-post-post-pre :: arm-doc + |% + :: core-doc + ++ $ ~ + -- :: product-doc + :: + ++ arm-adoc-pdoc-cdoc-post-pre-post :: arm-doc + :: product-doc + |% + ++ $ :: core-doc + ~ + -- + :: + :: +arm-adoc-pdoc-cdoc-pre-post-post: arm-doc + ++ arm-adoc-pdoc-cdoc-pre-post-post + |% + ++ $ :: core-doc + ~ + -- :: product-doc + :: + ++ arm-adoc-pdoc-cdoc-post-post-post :: arm-doc + |% + ++ $ :: core-doc + ~ + -- :: product-doc + :: + -- +:: +:: contains the actual tests to be run by -test +|% ++| %batch-tests + ++ test-b-foo + %+ expect-eq + !> ^- arm-dox + ["b-foo" `['a foo' ~] *what *what] + :: + !> (get-arm-dox ~[%b-foo]) + :: + ++ test-b-bar + %+ expect-eq + !> ^- arm-dox + ["b-bar" `['a bar' ~[~[[& 'a very bar foo']]]] *what *what] + :: + !> (get-arm-dox ~[%b-bar]) + :: + ++ test-b-baz + %+ expect-eq + !> ^- arm-dox + ["b-baz" `['a baz' ~] *what *what] + :: + !> (get-arm-dox ~[%b-baz]) + :: + ++ test-b-boz + %+ expect-eq + !> ^- arm-dox + ["b-boz" `['a boz' ~[~[[& 'a very boz baz']]]] *what *what] + :: + !> (get-arm-dox ~[%b-boz]) + :: ++| %arm-tests + :: +++ test-no-doc + %+ expect-eq + !> ^- arm-dox + ["no-doc" *what *what *what] + :: + !> (get-arm-dox ~[%no-doc]) +:: +++ test-adoc (run-arm-tests & | |) +++ test-pdoc (run-arm-tests | & |) +++ test-cdoc (run-arm-tests | | &) +++ test-adoc-pdoc (run-arm-tests & & |) +++ test-adoc-cdoc (run-arm-tests & | &) +++ test-pdoc-cdoc (run-arm-tests | & &) +++ test-adoc-pdoc-cdoc (run-arm-tests & & &) +:: +:: +| %core-tests +:: ++ test-core +:: %+ expect-eq +:: !> ^- core-dox +:: `['core-summary' ~[~[[%.y 'core-description']]]] +:: :: +:: !> (get-core-dox ~[%core-summary]) +:: :: +:: ++ test-chapter +:: %+ expect-eq +:: !> ^- chapter-dox +:: ["chapter-test" `['chapter-summary' ~[~[[%.y 'chapter-description']]]]] +:: :: +:: !> (get-chapter-dox ~[%core-summary %chapter-test]) +:: +-- diff --git a/tests/sys/hoon/set.hoon b/tests/sys/hoon/set.hoon index 77ce543d2..c39656998 100644 --- a/tests/sys/hoon/set.hoon +++ b/tests/sys/hoon/set.hoon @@ -106,6 +106,10 @@ :: Doesn't follow horizontal & vertical ordering :: =/ unbalanced-e=(set @) [1 [3 ~ ~] [2 ~ ~]] + :: Duplicate elements + :: + =/ has-dupes=(set @) [1 [1 ~ ~] ~] + :: ;: weld %+ expect-eq !> [%b-a %.y] @@ -125,6 +129,9 @@ %+ expect-eq !> [%u-e %.n] !> [%u-e ~(apt in unbalanced-e)] + %+ expect-eq + !> [%h-d %.n] + !> [%h-d ~(apt in has-dupes)] == :: :: Test splits a in b