diff --git a/.all-contributorsrc b/.all-contributorsrc new file mode 100644 index 00000000..43bf7e57 --- /dev/null +++ b/.all-contributorsrc @@ -0,0 +1,217 @@ +{ + "projectName": "wtf", + "projectOwner": "senorprogrammer", + "repoType": "github", + "repoHost": "https://github.com", + "files": [ + "README.md" + ], + "imageSize": 48, + "commit": true, + "contributors": [ + { + "login": "senorprogrammer", + "name": "Chris Cummer", + "avatar_url": "https://avatars0.githubusercontent.com/u/6413?v=4", + "profile": "https://twitter.com/senorprogrammer", + "contributions": [] + }, + { + "login": "jeangovil", + "name": "Hossein Mehrabi", + "avatar_url": "https://avatars1.githubusercontent.com/u/34973359?v=4", + "profile": "https://github.com/jeangovil", + "contributions": [] + }, + { + "login": "Fengyalv", + "name": "FengYa", + "avatar_url": "https://avatars0.githubusercontent.com/u/11779018?v=4", + "profile": "https://github.com/Fengyalv", + "contributions": [] + }, + { + "login": "deltaxflux", + "name": "deltax", + "avatar_url": "https://avatars2.githubusercontent.com/u/17337753?v=4", + "profile": "https://fluxionnetwork.github.io/fluxion/", + "contributions": [] + }, + { + "login": "BillKeenan", + "name": "Bill Keenan", + "avatar_url": "https://avatars0.githubusercontent.com/u/1319630?v=4", + "profile": "https://github.com/BillKeenan", + "contributions": [] + }, + { + "login": "interlock", + "name": "June S", + "avatar_url": "https://avatars2.githubusercontent.com/u/118081?v=4", + "profile": "http://blog.sapara.com", + "contributions": [] + }, + { + "login": "XanthusL", + "name": "liyiheng", + "avatar_url": "https://avatars3.githubusercontent.com/u/16461061?v=4", + "profile": "https://github.com/XanthusL", + "contributions": [] + }, + { + "login": "baustinanki", + "name": "baustinanki", + "avatar_url": "https://avatars2.githubusercontent.com/u/9014288?v=4", + "profile": "https://github.com/baustinanki", + "contributions": [] + }, + { + "login": "lixin9311", + "name": "lucus lee", + "avatar_url": "https://avatars0.githubusercontent.com/u/371475?v=4", + "profile": "https://github.com/lixin9311", + "contributions": [] + }, + { + "login": "mxplusb", + "name": "Mike Lloyd", + "avatar_url": "https://avatars1.githubusercontent.com/u/7537841?v=4", + "profile": "https://github.com/mxplusb", + "contributions": [] + }, + { + "login": "rubiojr", + "name": "Sergio Rubio", + "avatar_url": "https://avatars3.githubusercontent.com/u/10998?v=4", + "profile": "http://rubiojr.rbel.co", + "contributions": [] + }, + { + "login": "FarhadF", + "name": "Farhad Farahi", + "avatar_url": "https://avatars3.githubusercontent.com/u/17374492?v=4", + "profile": "https://github.com/FarhadF", + "contributions": [] + }, + { + "login": "lasanthak", + "name": "Lasantha Kularatne", + "avatar_url": "https://avatars1.githubusercontent.com/u/634604?v=4", + "profile": "http://lasantha.blogspot.com/", + "contributions": [] + }, + { + "login": "dlom", + "name": "Mark Old", + "avatar_url": "https://avatars1.githubusercontent.com/u/823331?v=4", + "profile": "https://github.com/dlom", + "contributions": [] + }, + { + "login": "flw-cn", + "name": "flw", + "avatar_url": "https://avatars0.githubusercontent.com/u/5546718?v=4", + "profile": "http://flw.tools/", + "contributions": [] + }, + { + "login": "davebarda", + "name": "David Barda", + "avatar_url": "https://avatars0.githubusercontent.com/u/6024927?v=4", + "profile": "https://github.com/davebarda", + "contributions": [] + }, + { + "login": "matrinox", + "name": "Geoff Lee", + "avatar_url": "https://avatars2.githubusercontent.com/u/4261980?v=4", + "profile": "https://github.com/matrinox", + "contributions": [] + }, + { + "login": "International", + "name": "George Opritescu", + "avatar_url": "https://avatars3.githubusercontent.com/u/1022918?v=4", + "profile": "http://international.github.io", + "contributions": [] + }, + { + "login": "Grazfather", + "name": "Grazfather", + "avatar_url": "https://avatars3.githubusercontent.com/u/497310?v=4", + "profile": "https://twitter.com/Grazfather", + "contributions": [] + }, + { + "login": "mcordell", + "name": "Michael Cordell", + "avatar_url": "https://avatars2.githubusercontent.com/u/1691120?v=4", + "profile": "http://www.mikecordell.com/", + "contributions": [] + }, + { + "login": "patrickelectric", + "name": "Patrick José Pereira", + "avatar_url": "https://avatars2.githubusercontent.com/u/1215497?v=4", + "profile": "http://patrick.ibexcps.com", + "contributions": [] + }, + { + "login": "sherodtaylor", + "name": "sherod taylor", + "avatar_url": "https://avatars2.githubusercontent.com/u/1483092?v=4", + "profile": "https://github.com/sherodtaylor", + "contributions": [] + }, + { + "login": "askl56", + "name": "Andrew Scott", + "avatar_url": "https://avatars2.githubusercontent.com/u/3062663?v=4", + "profile": "http://cogentia.io", + "contributions": [] + }, + { + "login": "anandsudhir", + "name": "Anand Sudhir Prayaga", + "avatar_url": "https://avatars2.githubusercontent.com/u/3252403?v=4", + "profile": "https://github.com/anandsudhir", + "contributions": [] + }, + { + "login": "lsipii", + "name": "Lassi Piironen", + "avatar_url": "https://avatars1.githubusercontent.com/u/12018440?v=4", + "profile": "https://github.com/lsipii", + "contributions": [] + }, + { + "login": "BlackWebWolf", + "name": "BlackWebWolf", + "avatar_url": "https://avatars0.githubusercontent.com/u/14799210?v=4", + "profile": "https://github.com/BlackWebWolf", + "contributions": [] + }, + { + "login": "andrewzolotukhin", + "name": "andrewzolotukhin", + "avatar_url": "https://avatars0.githubusercontent.com/u/1894885?v=4", + "profile": "https://github.com/andrewzolotukhin", + "contributions": [] + }, + { + "login": "retgits", + "name": "Leon Stigter", + "avatar_url": "https://avatars1.githubusercontent.com/u/8568280?v=4", + "profile": "https://retgits.github.io", + "contributions": [] + }, + { + "login": "amrnt", + "name": "Amr Tamimi", + "avatar_url": "https://avatars3.githubusercontent.com/u/21756?v=4", + "profile": "https://tamimi.se", + "contributions": [ + ] + } + ] +} diff --git a/.github/ISSUE_TEMPLATE/Bug.md b/.github/ISSUE_TEMPLATE/Bug.md index 25eef495..adda2996 100644 --- a/.github/ISSUE_TEMPLATE/Bug.md +++ b/.github/ISSUE_TEMPLATE/Bug.md @@ -3,18 +3,8 @@ name: Bug Report about: Something is broken? --- -### Bug Report +#### What's the problem? -#### Summary - -##### What is the current behaviour? - +#### How did you expect it to behave? -### How to reproduce - -##### If the current behaviour is a bug, please provide the steps to reproduce it. - - -##### What do you think the expected behaviour should be? - diff --git a/.github/ISSUE_TEMPLATE/Feature.md b/.github/ISSUE_TEMPLATE/Feature.md index 9adde8b4..3d6ed228 100644 --- a/.github/ISSUE_TEMPLATE/Feature.md +++ b/.github/ISSUE_TEMPLATE/Feature.md @@ -3,14 +3,9 @@ name: Feature Request about: You have a neat idea that should be implemented? --- -### Feature Request - +#### What problem does this solve? + + +#### How do envision it working? -| Q | A -|------------ | ------ -| New Feature | yes -| RFC | yes/no -| BC Break | yes/no -#### Summary - diff --git a/.github/ISSUE_TEMPLATE/Support.md b/.github/ISSUE_TEMPLATE/Support.md index 8e127f00..35d66b97 100644 --- a/.github/ISSUE_TEMPLATE/Support.md +++ b/.github/ISSUE_TEMPLATE/Support.md @@ -3,9 +3,6 @@ name: ❓ Support Question about: Have a problem that you can't figure out? --- -| Q | A -|------------ | ----- -| Version | 0.0.4 -#### Support Question - +#### What problem are you having and how can we help? + diff --git a/.github/PULL_REQUEST_TEMPLATE/Improvement.md b/.github/PULL_REQUEST_TEMPLATE/Improvement.md index 8b616076..ef71c51d 100644 --- a/.github/PULL_REQUEST_TEMPLATE/Improvement.md +++ b/.github/PULL_REQUEST_TEMPLATE/Improvement.md @@ -3,14 +3,9 @@ name: Improvement about: You have some improvement to make wtf better? --- -### Improvement - +#### What problem does this solve? + + +#### Is this related to an existing Issue? If so, which one? -| Q | A -|------------ | ------ -| New Feature | yes -| RFC | yes/no -| BC Break | yes/no -#### Summary - diff --git a/.github/PULL_REQUEST_TEMPLATE/Other.md b/.github/PULL_REQUEST_TEMPLATE/Other.md index 65da67ee..d6e0c64b 100644 --- a/.github/PULL_REQUEST_TEMPLATE/Other.md +++ b/.github/PULL_REQUEST_TEMPLATE/Other.md @@ -1,18 +1,11 @@ --- name: Other -about: You have some other ideas you want to introduce? +about: You have some other ideas you want to introduce? --- -**What kind of change does this PR introduce?** - +#### What problem does this solve? -**Summary** - - -**Does this PR introduce a breaking change?** - -**Other information** diff --git a/.gitignore b/.gitignore index 7ff72253..2d038a3c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,9 @@ # Misc .DS_Store gcal/client_secret.json +gspreadsheets/client_secret.json #intellij idea .idea/ dist/* +bin/ diff --git a/.goreleaser.yml b/.goreleaser.yml index fa4af340..4d59e654 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -8,4 +8,8 @@ builds: - darwin - linux goarch: + - 386 - amd64 + +archive: + wrap_in_directory: true diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..b20b9c4a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: go +go: + - "1.10" +sudo: false +before_install: + # Make sure travis builds work for forks + - mkdir -p $TRAVIS_BUILD_DIR $GOPATH/src/github.com/senorprogrammer + - test ! -d $GOPATH/src/github.com/senorprogrammer/wtf && mv $TRAVIS_BUILD_DIR $GOPATH/src/github.com/senorprogrammer/wtf || true + - export TRAVIS_BUILD_DIR=$HOME/gopath/src/github.com/senorprogrammer/wtf + - cd $HOME/gopath/src/github.com/senorprogrammer/wtf + +script: go get ./... && go get github.com/go-test/deep && go test -v github.com/senorprogrammer/wtf/wtf_tests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dc502913..c0664b4d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,10 +9,9 @@ Note that we have a code of conduct. Please follow it in all your interactions w 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. -2. Update the [README.md](README.md) with details of changes to the interface, this includes new environment +2. Update the static documentation with details of changes to the interface, this includes new environment variables, useful file locations and configuration parameters. -3. Increase the version numbers in any examples files and the [README.md](README.md) to the new version that this - Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). +Documentation lives in the `_site` directory and is a [Hugo](https://gohugo.io) app. See Hugo's documentation for usage. ## Code of Conduct diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 00000000..805be2fb --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,188 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "cloud.google.com/go" + packages = ["compute/metadata"] + revision = "0fd7230b2a7505833d5f69b75cbd6c9582401479" + version = "v0.23.0" + +[[projects]] + branch = "master" + name = "github.com/adlio/trello" + packages = ["."] + revision = "05dcd358e32866f2353c4f49077346a0eb585436" + +[[projects]] + branch = "master" + name = "github.com/briandowns/openweathermap" + packages = ["."] + revision = "6a9abf92e34f4de62ac671caee3143f10b98892d" + +[[projects]] + branch = "master" + name = "github.com/gdamore/encoding" + packages = ["."] + revision = "b23993cbb6353f0e6aa98d0ee318a34728f628b9" + +[[projects]] + name = "github.com/gdamore/tcell" + packages = [ + ".", + "terminfo" + ] + revision = "061d51a604c546b48e92253cb65190d76cecf4c6" + version = "v1.0.0" + +[[projects]] + name = "github.com/go-test/deep" + packages = ["."] + revision = "6592d9cc0a499ad2d5f574fde80a2b5c5cc3b4f5" + version = "v1.0.1" + +[[projects]] + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/google/go-github" + packages = ["github"] + revision = "a83ae98ad5d09188c49d6056edb60ec9bdf202bd" + +[[projects]] + branch = "master" + name = "github.com/google/go-querystring" + packages = ["query"] + revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a" + +[[projects]] + name = "github.com/jessevdk/go-flags" + packages = ["."] + revision = "c6ca198ec95c841fdb89fc0de7496fed11ab854e" + version = "v1.4.0" + +[[projects]] + name = "github.com/lucasb-eyer/go-colorful" + packages = ["."] + revision = "345fbb3dbcdb252d9985ee899a84963c0fa24c82" + version = "v1.0" + +[[projects]] + name = "github.com/mattn/go-runewidth" + packages = ["."] + revision = "9e777a8366cce605130a531d2cd6363d07ad7317" + version = "v0.0.2" + +[[projects]] + branch = "master" + name = "github.com/olebedev/config" + packages = ["."] + revision = "9a10d05a33a8b9e828f20491e21e8927dec35f72" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/radovskyb/watcher" + packages = ["."] + revision = "6145e1439b9de93806925353403f91d2abbad8a5" + version = "v1.0.2" + +[[projects]] + branch = "master" + name = "github.com/rivo/tview" + packages = ["."] + revision = "e643d10b365df4caec5ed32e4c1103e185af9079" + +[[projects]] + branch = "master" + name = "github.com/xanzy/go-gitlab" + packages = ["."] + revision = "1c1cfedc5a8ffe122b1981e8b0822fe22f461643" + +[[projects]] + branch = "master" + name = "github.com/yfronto/newrelic" + packages = ["."] + revision = "f7fa0c6f30ac3d86360c73726cfe9dd526a63d21" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "context/ctxhttp" + ] + revision = "db08ff08e8622530d9ed3a0e8ac279f6d4c02196" + +[[projects]] + branch = "master" + name = "golang.org/x/oauth2" + packages = [ + ".", + "google", + "internal", + "jws", + "jwt" + ] + revision = "113ce6928c4638e14fd5eba69b9e6ec899d5dd83" + +[[projects]] + name = "golang.org/x/text" + packages = [ + "encoding", + "encoding/internal/identifier", + "internal/gen", + "transform", + "unicode/cldr" + ] + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + branch = "master" + name = "google.golang.org/api" + packages = [ + "calendar/v3", + "gensupport", + "googleapi", + "googleapi/internal/uritemplates", + "sheets/v4" + ] + revision = "2eea9ba0a3d94f6ab46508083e299a00bbbc65f6" + +[[projects]] + name = "google.golang.org/appengine" + packages = [ + ".", + "internal", + "internal/app_identity", + "internal/base", + "internal/datastore", + "internal/log", + "internal/modules", + "internal/remote_api", + "internal/urlfetch", + "urlfetch" + ] + revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" + version = "v1.1.0" + +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "05d3df164ca80efbb1d5cf00a06e7ffde102690f0fabafb7d4e9860e461832db" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 00000000..66ae74ea --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,86 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/briandowns/openweathermap" + branch = "master" + +[[constraint]] + name = "github.com/gdamore/tcell" + version = "1.0.0" + +[[constraint]] + name = "github.com/go-test/deep" + version = "1.0.1" + +[[constraint]] + name = "github.com/google/go-github" + branch = "master" + +[[constraint]] + name = "github.com/xanzy/go-gitlab" + branch = "master" + +[[constraint]] + name = "github.com/jessevdk/go-flags" + version = "1.4.0" + +[[constraint]] + branch = "master" + name = "github.com/olebedev/config" + +[[constraint]] + name = "github.com/radovskyb/watcher" + version = "1.0.2" + +[[constraint]] + branch = "master" + name = "github.com/rivo/tview" + +[[constraint]] + branch = "master" + name = "github.com/yfronto/newrelic" + +[[constraint]] + branch = "master" + name = "golang.org/x/oauth2" + +[[constraint]] + branch = "master" + name = "google.golang.org/api" + +[[constraint]] + name = "gopkg.in/yaml.v2" + version = "2.2.1" + +[[constraint]] + branch = "master" + name = "github.com/adlio/trello" + +[prune] + go-tests = true + unused-packages = true diff --git a/LICENSE.md b/LICENSE.md index 7bbd1567..66214a8d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,109 @@ Copyright 2018, Chris Cummer -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Mozilla Public License, version 2.0 1. Definitions 1.1. “Contributor” means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +1.2. “Contributor Version” means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor’s Contribution. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +1.3. “Contribution” means Covered Software of a particular Contributor. + +1.4. “Covered Software” means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. + +1.5. “Incompatible With Secondary Licenses” means + +that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or + +that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. + +1.6. “Executable Form” means any form of the work other than Source Code Form. + +1.7. “Larger Work” means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. + +1.8. “License” means this document. + +1.9. “Licensable” means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. + +1.10. “Modifications” means any of the following: + +any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or + +any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. + +1.12. “Secondary License” means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) means an individual or a legal entity exercising rights under this License. For legal entities, “You” includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, “control” means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. + +2. License Grants and Conditions 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: + +under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and + +under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. + +2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. + +2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: + +for any code that a Contributor has removed from Covered Software; or + +for infringements caused by: (i) Your and any other third party’s modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or + +under Patent Claims infringed by Covered Software in the absence of its Contributions. + +This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). + +2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). + +2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. + +3. Responsibilities 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: + +such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and + +You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients’ rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). + +3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. + +4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + +5. Termination 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. + +6. Disclaimer of Warranty Covered Software is provided under this License on an “as is” basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer. + +7. Limitation of Liability Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party’s negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. + +10. Versions of the License 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. + +10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. + +10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0. diff --git a/Makefile b/Makefile index 0828bf38..19d63ae6 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,15 @@ -BRANCH := `git rev-parse --abbrev-ref HEAD` +.PHONY: contrib_check dependencies install run -.PHONY: dependencies install run +build: + go build -o bin/wtf -dependencies: - go get -v ./... +contrib_check: + npx all-contributors-cli check install: - which wtf | xargs rm || true - go install -ldflags="-X main.version=$(shell git describe --always --abbrev=6)_$(BRANCH) -X main.date=$(shell date +%FT%T%z)" + go clean + go install -ldflags="-X main.version=$(shell git describe --always --abbrev=6) -X main.date=$(shell date +%FT%T%z)" which wtf -run: - wtf +run: build + bin/wtf diff --git a/README.md b/README.md index 6ed53242..1147ee25 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -

- -

+ + + +# WTF A personal terminal-based dashboard utility, designed for displaying infrequently-needed, but very important, daily data. @@ -11,10 +12,7 @@ displaying infrequently-needed, but very important, daily data. ## Quick Start -### Installation from Source - -*Note:* This has only been tested to build against Go 1.9.2. It won't -work with Go versions < 1.7, and only _may_ work on other versions. +[Download and run the latest binary](https://github.com/senorprogrammer/wtf/releases) or install from source: ```bash go get -u github.com/senorprogrammer/wtf @@ -23,12 +21,7 @@ make install make run ``` -Or [download the latest binary](https://github.com/senorprogrammer/wtf/releases). - -## Support - -Chat on Gitter: -[![Join the chat at https://gitter.im/wtfutil/Lobby](https://badges.gitter.im/wtfutil/Lobby.svg)](https://gitter.im/wtfutil/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +**Note:** WTF is _only_ compatible with Go versions **1.9.2** or later. It currently _does not_ compile with `gccgo`. ## Documentation @@ -39,38 +32,33 @@ documentation. Here's some short-cuts: * [Configuration](http://wtfutil.com/posts/configuration/) * [Module Documentation](http://wtfutil.com/posts/modules/) -And a "probably up-to-date" list of currently-implemented modules: - -* [BambooHR](http://wtfutil.com/posts/modules/bamboohr/) -* [World Clocks](http://wtfutil.com/posts/modules/clocks/) -* [Command Runner](http://wtfutil.com/posts/modules/cmdrunner/) -* [Google Calendar](http://wtfutil.com/posts/modules/gcal/) -* [Git](http://wtfutil.com/posts/modules/git/) -* [GitHub](http://wtfutil.com/posts/modules/github/) -* [IPInfo](http://wtfutil.com/posts/modules/ipinfo/) -* [Jira](http://wtfutil.com/posts/modules/jira/) -* [New Relic](http://wtfutil.com/posts/modules/newrelic/) -* [OpsGenie](http://wtfutil.com/posts/modules/opsgenie) -* [Power](http://wtfutil.com/posts/modules/power/) -* [PrettyWeather](http://wtfutil.com/posts/modules/prettyweather/)* -* [Security](http://wtfutil.com/posts/modules/security/) -* [Textfile](http://wtfutil.com/posts/modules/textfile/) -* [Todo List](http://wtfutil.com/posts/modules/todo/) -* [Weather](http://wtfutil.com/posts/modules/weather/) - -*experimental - ## Contributing Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests. -## Authors +### Adding Dependencies -* Chris Cummer, [senorprogrammer](https://github.com/senorprogrammer) +Dependency management in WTF is handled by [dep](https://github.com/golang/dep). See that page for installation and usage details. -## License +If the work you're doing requires the addition of a new dependency, +please be sure to use `dep` to [vendor your dependencies](https://golang.github.io/dep/docs/daily-dep.html#adding-a-new-dependency). -See [LICENSE.md](LICENSE.md) file for details. +## Contributors + + +Thanks goes to these wonderful people: + + + +| [
Chris Cummer](https://twitter.com/senorprogrammer)
| [
Hossein Mehrabi](https://github.com/jeangovil)
| [
FengYa](https://github.com/Fengyalv)
| [
deltax](https://fluxionnetwork.github.io/fluxion/)
| [
Bill Keenan](https://github.com/BillKeenan)
| [
June S](http://blog.sapara.com)
| [
liyiheng](https://github.com/XanthusL)
| +| :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| [
baustinanki](https://github.com/baustinanki)
| [
lucus lee](https://github.com/lixin9311)
| [
Mike Lloyd](https://github.com/mxplusb)
| [
Sergio Rubio](http://rubiojr.rbel.co)
| [
Farhad Farahi](https://github.com/FarhadF)
| [
Lasantha Kularatne](http://lasantha.blogspot.com/)
| [
Mark Old](https://github.com/dlom)
| +| [
flw](http://flw.tools/)
| [
David Barda](https://github.com/davebarda)
| [
Geoff Lee](https://github.com/matrinox)
| [
George Opritescu](http://international.github.io)
| [
Grazfather](https://twitter.com/Grazfather)
| [
Michael Cordell](http://www.mikecordell.com/)
| [
Patrick José Pereira](http://patrick.ibexcps.com)
| +| [
sherod taylor](https://github.com/sherodtaylor)
| [
Andrew Scott](http://cogentia.io)
| [
Anand Sudhir Prayaga](https://github.com/anandsudhir)
| [
Lassi Piironen](https://github.com/lsipii)
| [
BlackWebWolf](https://github.com/BlackWebWolf)
| [
andrewzolotukhin](https://github.com/andrewzolotukhin)
| [
Leon Stigter](https://retgits.github.io)
| +| [
Amr Tamimi](https://tamimi.se)
| + + +This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! ## Acknowledgments diff --git a/_sample_configs/bargraph_config.yml b/_sample_configs/bargraph_config.yml new file mode 100644 index 00000000..ffdf9fe5 --- /dev/null +++ b/_sample_configs/bargraph_config.yml @@ -0,0 +1,21 @@ +wtf: + colors: + border: + focusable: darkslateblue + focused: orange + normal: gray + grid: + columns: [40, 40] + rows: [13, 13, 4] + refreshInterval: 1 + mods: + bargraph: + enabled: true + graphIcon: "🍎" + position: + top: 2 + left: 0 + height: 2 + width: 2 + refreshInterval: 30 + updateInterval: 15 diff --git a/_sample_configs/complex_config.yml b/_sample_configs/complex_config.yml index c21bdb72..5983683e 100644 --- a/_sample_configs/complex_config.yml +++ b/_sample_configs/complex_config.yml @@ -77,8 +77,27 @@ wtf: height: 4 width: 1 refreshInterval: 300 - secretFile: "~/.wtf/gcal/client_secret.json" + secretFile: "~/.config/wtf/gcal/client_secret.json" withLocation: true + gspreadsheets: + colors: + values: "green" + cells: + names: + - "Cell 1 name" + - "Cell 2 name" + addresses: + - "A1" + - "A2" + enabled: true + position: + top: 0 + left: 0 + width: 1 + height: 1 + refreshInterval: "300" + secretFile: "~/.config/wtf/gspreadsheets/client_secret.json" + sheetId: "id_of_google_spreadsheet" git: commitCount: 5 enabled: true @@ -199,3 +218,17 @@ wtf: width: 1 refreshInterval: 90 tempUnit: "C" + blockfolio: + enabled: true + displayHoldings: true + refreshInterval: 400 + device_token: "device token here, you can find how to get it here https://github.com/bob6664569/blockfolio-api-client" + colors: + name: blue + grows: green + drop: red + position: + top: 3 + left: 1 + width: 1 + height: 1 diff --git a/_sample_configs/simple_config.yml b/_sample_configs/simple_config.yml index 3d08666d..34e9de9f 100644 --- a/_sample_configs/simple_config.yml +++ b/_sample_configs/simple_config.yml @@ -1,6 +1,6 @@ wtf: colors: - background: gray + #background: gray border: focusable: darkslateblue focused: orange @@ -56,7 +56,7 @@ wtf: refreshInterval: 3600 textfile: enabled: true - filePath: "~/.wtf/config.yml" + filePath: "~/.config/wtf/config.yml" position: top: 1 left: 1 diff --git a/_site/content/posts/configuration.md b/_site/content/posts/configuration.md index af97ed86..9337d213 100644 --- a/_site/content/posts/configuration.md +++ b/_site/content/posts/configuration.md @@ -12,12 +12,12 @@ draft: false ## Configuration Files -By default WTF looks in a `~/.wtf/` directory for a YAML file called -`config.yml`. If the `~/.wtf/` directory doesn't exist, WTF will create that directory +By default WTF looks in a `~/.config/wtf/` directory for a YAML file called +`config.yml`. If the `~/.config/wtf/` directory doesn't exist, WTF will create that directory on start-up, and then display instructions for creating a new configuration file. -In other words, WTF expects to have a YAML config file at: `~/.wtf/config.yml`. +In other words, WTF expects to have a YAML config file at: `~/.config/wtf/config.yml`. #### Example Configuration Files @@ -25,7 +25,7 @@ A couple of example config files are provided in the `_sample_configs/` directory of the Git repository. To try out WTF quickly, copy -`simple_config.yml` into `~/.wtf/` as `config.yml` and relaunch WTF. You +`simple_config.yml` into `~/.config/wtf/` as `config.yml` and relaunch WTF. You should see the app launch and display the Security, Clocks and Status widgets onscreen. @@ -36,7 +36,7 @@ you can pass the path to a config file via command line arguments on start-up. To load a custom configuration file (ie: one that's not -`~/.wtf/config.yml`), pass in the path to configuration file as a +`~/.config/wtf/config.yml`), pass in the path to configuration file as a parameter on launch: ```bash diff --git a/_site/content/posts/modules/circleci.md b/_site/content/posts/modules/circleci.md new file mode 100644 index 00000000..4a2df2d9 --- /dev/null +++ b/_site/content/posts/modules/circleci.md @@ -0,0 +1,53 @@ +--- +title: "CircleCI" +date: 2018-06-10T19:26:08-04:00 +draft: false +--- + +Added in `v0.0.7`. + +Displays build information for your CircleCI account. + +circleci screenshot + +## Source Code + +```bash +wtf/circleci/ +``` + +## Required ENV Variables + +Key: `WTF_CIRCLE_API_KEY`
+Value: Your CircleCI API +token. + +## Keyboard Commands + +None. + +## Configuration + +```yaml +circleci: + enabled: true + position: + top: 4 + left: 1 + height: 1 + width: 2 + refreshInterval: 900 +``` + +### Attributes + +`enabled`
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: `true`, `false`. + +`position`
+Defines where in the grid this module's widget will be displayed.
+ +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. diff --git a/_site/content/posts/modules/cryptocurrencies/bittrex.md b/_site/content/posts/modules/cryptocurrencies/bittrex.md index df5fc610..8ee4ad37 100644 --- a/_site/content/posts/modules/cryptocurrencies/bittrex.md +++ b/_site/content/posts/modules/cryptocurrencies/bittrex.md @@ -16,7 +16,7 @@ Get the last 24 hour summary of cryptocurrencies market using [Bittrex](https:// wtf/cryptoexchanges/bittrex/ ``` -## Required ENV Vars +## Required ENV Variables None. diff --git a/_site/content/posts/modules/cryptocurrencies/blockfolio.md b/_site/content/posts/modules/cryptocurrencies/blockfolio.md new file mode 100644 index 00000000..06df64cc --- /dev/null +++ b/_site/content/posts/modules/cryptocurrencies/blockfolio.md @@ -0,0 +1,75 @@ +--- +title: "Blockfolio" +date: 2018-06-13T09:29:59-07:00 +draft: false +--- + +Added in `v0.0.8`. + +Display your Blockfolio crypto holdings. + +blockfolio screenshot + +## Source + +```bash +wtf/blockfolio/ +``` + +## Required ENV Variables + +None. + +## Keyboard Commands + +None. + +## Configuration + +```yaml +blockfolio: + colors: + name: blue + grows: green + drop: red + device_token: "device token" + displayHoldings: true + enabled: true + position: + top: 3 + left: 1 + width: 1 + height: 1 + refreshInterval: 400 +``` + +### Attributes + +`colors.name`
+Values: Any X11 +color name. + +`colors.grows`
+Values: Any X11 +color name. + +`colors.drop`
+Values: Any X11 +color name. + +`device_token`
+Value: See [this gist](https://github.com/bob6664569/blockfolio-api-client) for +details on how to get your Blockfolio API token. + +`displayHoldings`
+ +`enabled`
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: `true`, `false`. + +`position`
+Defines where in the grid this module's widget will be displayed.
+ +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. diff --git a/_site/content/posts/modules/gcal.md b/_site/content/posts/modules/gcal.md index ef6a70dd..5dbfa014 100644 --- a/_site/content/posts/modules/gcal.md +++ b/_site/content/posts/modules/gcal.md @@ -19,11 +19,7 @@ wtf/gcal/ ## Required ENV Variables -Key: `WTF_GOOGLE_CAL_CLIENT_ID`
-Value: Your Google API client ID. - -Key: `WTF_GOOGLE_CAL_CLIENT_SECRET`
-Value: Your Google API client secret. +None. ## Keyboard Commands @@ -48,13 +44,14 @@ gcal: email: "chriscummer@me.com" enabled: true eventCount: 12 + multiCalendar: true position: top: 0 left: 0 height: 4 width: 1 refreshInterval: 300 - secretFile: "~/.wtf/gcal/client_secret.json" + secretFile: "~/.config/wtf/gcal/client_secret.json" withLocation: true ``` @@ -109,6 +106,11 @@ Values: `true`, `false`. The number of calendar events to display.
Values: A positive integer, `0..n`. +`multiCalendar`
+Whether or not to display your primary calendar or all calendars you +have access to.
+Values: `true`, or `false` + `position`
Where in the grid this module's widget will be displayed.
diff --git a/_site/content/posts/modules/git.md b/_site/content/posts/modules/git.md index e0a6a1f2..b601bfdd 100644 --- a/_site/content/posts/modules/git.md +++ b/_site/content/posts/modules/git.md @@ -54,6 +54,8 @@ None. ```yaml git: commitCount: 5 + commitFormat: "[forestgreen]%h [grey]%cd [white]%s [grey]%an[white]" + dateFormat: "%H:%M %d %b %y" enabled: true position: top: 0 @@ -72,6 +74,13 @@ git: The number of past commits to display.
Values: A positive integer, `0..n`. +`commitFormat`
+_Optional_ The string format for the commit message.
+ +`dateFormat`
+_Optional_ The string format for the date/time in the commit message. +
+ `enabled`
Determines whether or not this module is executed and if its data displayed onscreen.
Values: `true`, `false`. diff --git a/_site/content/posts/modules/github.md b/_site/content/posts/modules/github.md index 1b201e30..f81a6707 100644 --- a/_site/content/posts/modules/github.md +++ b/_site/content/posts/modules/github.md @@ -1,13 +1,11 @@ --- -title: "Github" +title: "GitHub" date: 2018-05-09T19:20:20-07:00 draft: false --- -Displays information about git repositories hosted on Github: open -review requests, and open pull requests. +Displays information about your git repositories hosted on Github: -github screenshot #### Open Review Requests @@ -17,17 +15,30 @@ All open code review requests assigned to you. All open pull requests created by you. +github screenshot + ## Source Code ```bash wtf/github/ ``` -## Required ENV Variables +## Github Required ENV Variables Key: `WTF_GITHUB_TOKEN`
Action: Your Github API token. +## GitHub Enterprise Required ENV Variables + +Key: `WTF_GITHUB_TOKEN`
+Action: Your Github API token. + +Key: `WTF_GITHUB_BASE_URL`
+Action: Your Github Enterprise API URL. + +Key: `WTF_GITHUB_UPLOAD_URL`
+Action: Your Github Enterprise upload URL (often the same as API URL). + ## Keyboard Commands Key: `/`
diff --git a/_site/content/posts/modules/gitlab.md b/_site/content/posts/modules/gitlab.md new file mode 100644 index 00000000..df9f744f --- /dev/null +++ b/_site/content/posts/modules/gitlab.md @@ -0,0 +1,90 @@ +--- +title: "Gitlab" +date: 2018-06-08T13:14:11-07:00 +draft: false +--- + +Added in `v0.0.8`. + +gitlab screenshot + +Displays information about your projects hosted on Gitlab: + +#### Open Approval Requests + +All open merge requests that are requesting your approval. + +#### Open Merge Requests + +All open merge requests created by you. + +## Source Code + +```bash +wtf/gitlab/ +``` + +## Required ENV Variables + +Key: `WTF_GITLAB_TOKEN`
+Action: A Gitlab personal access token. Requires at least `api` access. + +## Keyboard Commands + +Key: `/`
+Action: Open/close the widget's help window. + +Key: `h`
+Action: Show the previous project. + +Key: `l`
+Action: Show the next project. + +Key: `←`
+Action: Show the previous project. + +Key: `→`
+Action: Show the next project. + +## Configuration + +```yaml +gitlab: + enabled: true + position: + top: 2 + left: 3 + height: 2 + width: 2 + refreshInterval: 300 + projects: + tasks: "gitlab-org/release" + gitlab-ce: "gitlab-org" + username: "senorprogrammer" +``` + +### Attributes + +`enabled`
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: `true`, `false`. + +`position`
+Defines where in the grid this module's widget will be displayed.
+ +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. + +`domain`
+_Optional_. Your Gitlab corporate domain.
+Values: A valid URI. + +`projects`
+A list of key/value pairs each describing a Gitlab project to fetch data +for.
+Key: The name of the project.
+Value: The namespace of the project. + +`username`
+Your Gitlab username. Used to figure out which requests require your approval diff --git a/_site/content/posts/modules/gspreadsheet.md b/_site/content/posts/modules/gspreadsheet.md new file mode 100644 index 00000000..aaea2384 --- /dev/null +++ b/_site/content/posts/modules/gspreadsheet.md @@ -0,0 +1,70 @@ +--- +title: "Google Spreadsheets" +date: 2018-06-10T18:26:26-04:00 +draft: false +--- + +Added in `v0.0.7`. + +Display information from cells in a Google Spreadsheet. + +```bash +wtf/gspreadsheets/ +``` + +## Required ENV Variables + +None. + +## Keyboard Commands + +None. + +## Configuration + +```yaml +gspreadsheets: + colors: + values: "green" + cells: + names: + - "Cell 1 name" + - "Cell 2 name" + addresses: + - "A1" + - "A2" + enabled: true + position: + top: 0 + left: 0 + width: 1 + height: 1 + refreshInterval: "300" + secretFile: "~/.config/wtf/gspreadsheets/client_secret.json" + sheetId: "id_of_google_spreadsheet" +``` + +### Attributes + +`colors.values`
+The color to display the cell values in.
+Values: Any X11 color name. + +`cells.names`
+ +`cells.addresses`
+ +`enabled`
+Whether or not this module is executed and if its data displayed onscreen.
+Values: `true`, `false`. + +`position`
+Where in the grid this module's widget will be displayed.
+ +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. + +`secretFile`
+Your Google client secret JSON file.
+Values: A string representing a file path to the JSON secret file. diff --git a/_site/content/posts/modules/ipapi.md b/_site/content/posts/modules/ipapi.md new file mode 100644 index 00000000..986aa172 --- /dev/null +++ b/_site/content/posts/modules/ipapi.md @@ -0,0 +1,62 @@ +--- +title: "IP-API" +date: 2018-06-10T19:41:52-04:00 +draft: false +--- + +Added in `v0.0.7`. + +Displays your current IP address information, from [IP-APIcom](http://ip-api.com). + +**Note:** IP-API.com has a free-plan rate limit of 120 requests per +minute. + +## Source Code + +```bash +wtf/ipapi/ +``` + +## Required ENV Variables + +None. + +## Keyboard Commands + +None. + +## Configuration + +```yaml +ipinfo: + colors: + name: red + value: white + enabled: true + position: + top: 1 + left: 2 + height: 1 + width: 1 + refreshInterval: 150 +``` +### Attributes + +`colors.name`
+The default colour for the row names.
+Values: Any X11 color name. + +`colors.value`
+The default colour for the row values.
+Values: Any X11 color name. + +`enabled`
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: `true`, `false`. + +`position`
+Defines where in the grid this module's widget will be displayed.
+ +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. diff --git a/_site/content/posts/modules/ipinfo.md b/_site/content/posts/modules/ipinfo.md index b6e2663a..93b8edb2 100644 --- a/_site/content/posts/modules/ipinfo.md +++ b/_site/content/posts/modules/ipinfo.md @@ -6,6 +6,8 @@ draft: false Displays your current IP address information, from ipinfo.io. +**Note:** IPInfo.io has a free-plan rate limit of 1000 requests per day. + ipinfo screenshot ## Source Code @@ -35,7 +37,7 @@ ipinfo: left: 2 height: 1 width: 1 - refreshInterval: 15 + refreshInterval: 150 ``` ### Attributes diff --git a/_site/content/posts/modules/jenkins.md b/_site/content/posts/modules/jenkins.md new file mode 100644 index 00000000..c556998e --- /dev/null +++ b/_site/content/posts/modules/jenkins.md @@ -0,0 +1,63 @@ +--- +title: "Modules: Jenkins" +date: 2018-06-09T20:53:35-07:00 +draft: false +--- + +Added in `v0.0.8`. + +Displays jenkins status of given builds in a project or view + +jenkins screenshot + +## Source Code + +```bash +wtf/jenkins/ +``` + +## Required ENV Variables + +Key: `WTF_JENKINS_API_KEY`
+Value: Your Jenkins API key. + +## Keyboard Commands + +None. + +## Configuration + +```yaml +jenkins: + enabled: true + position: + top: 2 + left: 3 + height: 2 + width: 3 + refreshInterval: 300 + url: "https://jenkins.domain.com/jenkins/view_url" + user: "username" +``` + +### Attributes + +`enabled`
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: `true`, `false`. + +`position`
+Defines where in the grid this module's widget will be displayed. + +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. + +`user`
+Your Jenkins username.
+ +`url`
+The url to your Jenkins project or view.
+Values: A valid URI. + diff --git a/_site/content/posts/modules/jira.md b/_site/content/posts/modules/jira.md index 08479c62..3daf62b7 100644 --- a/_site/content/posts/modules/jira.md +++ b/_site/content/posts/modules/jira.md @@ -25,6 +25,8 @@ None. ## Configuration +### Single Jira Project + ```yaml jira: colors: @@ -40,9 +42,36 @@ jira: left: 1 height: 1 width: 2 - project: "JIRA" + project: "ProjectA" refreshInterval: 900 username: "chris.cummer" + verifyServerCertificate: true +``` + +### Multiple Jira Projects + +If you want to monitor multiple Jira projects, use the following +configuration (note the difference in `project`): + +```yaml +jira: + colors: + rows: + even: "lightblue" + odd: "white" + domain: "https://umbrellacorp.atlassian.net" + email: "chriscummer@me.com" + enabled: true + jql: "issueType = Story" + position: + top: 4 + left: 1 + height: 1 + width: 2 + project: ["ProjectA", "ProjectB"] + refreshInterval: 900 + username: "chris.cummer" + verifyServerCertificate: true ``` ### Attributes @@ -86,3 +115,8 @@ Values: A positive integer, `0..n`. `username`
Your Jira username.
+ +`verifyServerCertificate`
+_Optional_
+Determines whether or not the server's certificate chain and host name are verified.
+Values: `true`, `false`. diff --git a/_site/content/posts/modules/logger.md b/_site/content/posts/modules/logger.md new file mode 100644 index 00000000..23280a4b --- /dev/null +++ b/_site/content/posts/modules/logger.md @@ -0,0 +1,58 @@ +--- +title: "Logger" +date: 2018-06-16T14:22:18-07:00 +draft: false +--- + +Displays the contents of the WTF log file. + +To log to this file in your own modules: + +```golang +require "github.com/senorprogrammer/wtf/logger" + logger.Log("This is a log entry") +``` + +## Source Code + +```bash +wtf/logger/ +``` + +## Required ENV Variables + +None. + +## Keyboard Commands + +Arrow keys scroll through the log file. + +## Configuration + +```yaml +logger: + enabled: true + position: + top: 5 + left: 4 + height: 2 + width: 1 + refreshInterval: 1 +``` + +### Attributes + +`enabled`
+Determines whether or not this module is executed and if its data displayed onscreen.
+**Note:** If you're using logging and logging is _disabled_, your logs +will still be written to file, the widget just won't be shown onscreen. +If you have `logger.Log` calls in your code, regardless of this setting, +they will be written out.
+Values: `true`, `false`. + +`position`
+Defines where in the grid this module's widget will be displayed.
+ +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. diff --git a/_site/content/posts/modules/prettyweather.md b/_site/content/posts/modules/prettyweather.md index 39a08e4b..66a78c1e 100644 --- a/_site/content/posts/modules/prettyweather.md +++ b/_site/content/posts/modules/prettyweather.md @@ -4,8 +4,6 @@ date: 2018-06-02T05:32:04-07:00 draft: false --- -**🔬 Experimental** - Displays weather information as ASCII art from [Wttr.in](http://wttr.in). @@ -38,6 +36,7 @@ None. width: 1 refreshInterval: 300 unit: "c" + view: 0 ``` ### Attributes @@ -62,3 +61,7 @@ Values: A positive integer, `0..n`. _Optional_. It will use metric if you are out of US and imperial for US.
The temperature scale in which to display temperature values.
Values: `F` for Fahrenheit, `C` for Celcius. + +`view`
+_Optional_ Wttr.in view configuration.
+Values: See `curl wttr.in/:help` for more details. diff --git a/_site/content/posts/modules/trello.md b/_site/content/posts/modules/trello.md new file mode 100644 index 00000000..c8649b69 --- /dev/null +++ b/_site/content/posts/modules/trello.md @@ -0,0 +1,87 @@ +--- +title: "Trello" +date: 2018-05-10T10:44:35-07:00 +draft: false +--- + +Displays all Trello cards on specified lists. + +trello screenshot + +## Source Code + +```bash +wtf/trello/ +``` + +## Required ENV Variables + +Key: `WTF_TRELLO_APP_KEY`
+Value: Your Trello App Key.
+Key: `WTF_TRELLO_ACCESS_TOKEN`
+Value: Your Trello Access Token.
+ +_You can get your API key at: trello.com/app-key._ + +## Keyboard Commands + +None. + +## Configuration + +### Single Trello List + +```yaml +trello: + board: Main + enabled: true + list: "Todo" + position: + height: 1 + left: 2 + top: 0 + width: 1 + refreshInterval: 3600 + username: myname +``` + +### Multiple Trello Lists + +If you want to monitor multiple Trello lists, use the following +configuration (note the difference in `list`): + +```yaml +trello: + board: Main + enabled: true + list: ["Todo", "Done"] + position: + height: 1 + left: 2 + top: 0 + width: 1 + refreshInterval: 3600 + username: myname +``` + +### Attributes + +`board`
+The name of the Trello board.
+ +`enabled`
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: `true`, `false`. + +`list`
+The Trello lists to fetch cards from.
+ +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. + +`username`
+Your Trello username.
+ +`position`
+Where in the grid this module's widget will be displayed.
diff --git a/_site/static/imgs/modules/blockfolio.png b/_site/static/imgs/modules/blockfolio.png new file mode 100644 index 00000000..1a820c07 Binary files /dev/null and b/_site/static/imgs/modules/blockfolio.png differ diff --git a/_site/static/imgs/modules/circleci.png b/_site/static/imgs/modules/circleci.png new file mode 100644 index 00000000..e2447b41 Binary files /dev/null and b/_site/static/imgs/modules/circleci.png differ diff --git a/_site/static/imgs/modules/gitlab.png b/_site/static/imgs/modules/gitlab.png new file mode 100644 index 00000000..6e806a41 Binary files /dev/null and b/_site/static/imgs/modules/gitlab.png differ diff --git a/_site/static/imgs/modules/jenkins.png b/_site/static/imgs/modules/jenkins.png new file mode 100644 index 00000000..5074eca1 Binary files /dev/null and b/_site/static/imgs/modules/jenkins.png differ diff --git a/_site/static/imgs/modules/todo.png b/_site/static/imgs/modules/todo.png new file mode 100644 index 00000000..dc1fd744 Binary files /dev/null and b/_site/static/imgs/modules/todo.png differ diff --git a/_site/static/imgs/modules/trello.png b/_site/static/imgs/modules/trello.png new file mode 100644 index 00000000..79fa6965 Binary files /dev/null and b/_site/static/imgs/modules/trello.png differ diff --git a/_site/themes/hyde-hyde/layouts/_default/baseof.html b/_site/themes/hyde-hyde/layouts/_default/baseof.html index 7cacb9f5..8e8ee67e 100644 --- a/_site/themes/hyde-hyde/layouts/_default/baseof.html +++ b/_site/themes/hyde-hyde/layouts/_default/baseof.html @@ -4,6 +4,10 @@ {{ block "header" . -}}{{- end }} + + + {{ partial "sidebar.html" . }}
{{ block "content" . }}{{ end }} @@ -14,6 +18,6 @@ {{ if .Site.GoogleAnalytics -}} {{ template "_internal/google_analytics_async.html" . }} - {{- end }} + {{- end }} diff --git a/_site/themes/hyde-hyde/layouts/index.html b/_site/themes/hyde-hyde/layouts/index.html index 888abc24..a8b97c4e 100644 --- a/_site/themes/hyde-hyde/layouts/index.html +++ b/_site/themes/hyde-hyde/layouts/index.html @@ -15,7 +15,7 @@

- Keep an eye on your OpsGenie schedules, Google Calendar, Git + Keep an eye on your OpsGenie schedules, Google Calendar, Git and Github repositories, and New Relic deployments.

@@ -28,8 +28,9 @@

Download Latest - - On Github + Source on Github + Chat on Gitter + Follow on Twitter

diff --git a/_site/themes/hyde-hyde/layouts/partials/header.html b/_site/themes/hyde-hyde/layouts/partials/header.html index 29764fe6..a64d938b 100644 --- a/_site/themes/hyde-hyde/layouts/partials/header.html +++ b/_site/themes/hyde-hyde/layouts/partials/header.html @@ -47,3 +47,11 @@ {{- end }} + + + + diff --git a/_site/themes/hyde-hyde/layouts/partials/sidebar.html b/_site/themes/hyde-hyde/layouts/partials/sidebar.html index 5d1c6bc4..e51d9f1b 100644 --- a/_site/themes/hyde-hyde/layouts/partials/sidebar.html +++ b/_site/themes/hyde-hyde/layouts/partials/sidebar.html @@ -24,21 +24,29 @@

+ + - + + + + + + - + +
diff --git a/bamboohr/calendar.go b/bamboohr/calendar.go index 2b2dadea..4dcb3840 100644 --- a/bamboohr/calendar.go +++ b/bamboohr/calendar.go @@ -1,7 +1,5 @@ package bamboohr -import () - type Calendar struct { Items []Item `xml:"item"` } diff --git a/bamboohr/employee.go b/bamboohr/employee.go index 02d179d6..7cc655bd 100644 --- a/bamboohr/employee.go +++ b/bamboohr/employee.go @@ -1,7 +1,5 @@ package bamboohr -import () - /* * Note: this currently implements the minimum number of fields to fulfill the Away functionality. * Undoubtedly there are more fields than this to an employee diff --git a/bamboohr/widget.go b/bamboohr/widget.go index 5876f567..bd97ad7a 100644 --- a/bamboohr/widget.go +++ b/bamboohr/widget.go @@ -3,13 +3,9 @@ package bamboohr import ( "fmt" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget } @@ -25,10 +21,6 @@ func NewWidget() *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - client := NewClient("https://api.bamboohr.com/api/gateway.php") todayItems := client.Away( "timeOff", @@ -37,9 +29,9 @@ func (widget *Widget) Refresh() { ) widget.UpdateRefreshedAt() - widget.View.SetTitle(fmt.Sprintf("%s(%d)", widget.Name, len(todayItems))) + widget.View.SetTitle(fmt.Sprintf("%s (%d)", widget.Name, len(todayItems))) - widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(todayItems))) + widget.View.SetText(widget.contentFrom(todayItems)) } /* -------------------- Unexported Functions -------------------- */ diff --git a/bargraph/widget.go b/bargraph/widget.go new file mode 100644 index 00000000..b5b9d9ff --- /dev/null +++ b/bargraph/widget.go @@ -0,0 +1,76 @@ +package bargraph + +/************** +This is a demo bargraph that just populates some random date/val data +*/ + +import ( + "math/rand" + "time" + + "github.com/senorprogrammer/wtf/wtf" +) + +var started = false +var ok = true + +// Widget define wtf widget to register widget later +type Widget struct { + wtf.BarGraph + + // time interval for send http request + updateInterval int +} + +// NewWidget Make new instance of widget +func NewWidget() *Widget { + widget := Widget{ + BarGraph: wtf.NewBarGraph(" Sample Bar Graph", "bargraph", false), + } + + widget.View.SetWrap(true) + widget.View.SetWordWrap(true) + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +// MakeGraph - Load the dead drop stats +func MakeGraph(widget *Widget) { + + //this could come from config + const lineCount = 20 + var stats [lineCount][2]int64 + + for i := lineCount - 1; i >= 0; i-- { + + stats[i][1] = time.Now().AddDate(0, 0, i*-1).Unix() * 1000 + stats[i][0] = int64(rand.Intn(120-5) + 5) + + } + + icon := wtf.Config.UString("wtf.mods.bargraph.graphIcon", "✭ ") + widget.BarGraph.BuildBars(20, icon, stats[:]) + +} + +// Refresh & update after interval time +func (widget *Widget) Refresh() { + + if widget.Disabled() { + return + } + + widget.UpdateRefreshedAt() + widget.View.Clear() + + display(widget) + +} + +/* -------------------- Unexported Functions -------------------- */ + +func display(widget *Widget) { + MakeGraph(widget) +} diff --git a/wtf/config_files.go b/cfg/config_files.go similarity index 66% rename from wtf/config_files.go rename to cfg/config_files.go index ff57654d..5d41bfcd 100644 --- a/wtf/config_files.go +++ b/cfg/config_files.go @@ -1,4 +1,4 @@ -package wtf +package cfg import ( "fmt" @@ -6,10 +6,53 @@ import ( "os" "github.com/olebedev/config" + "github.com/senorprogrammer/wtf/logger" + "github.com/senorprogrammer/wtf/wtf" ) +const CONFIG_DIR_V1 = "~/.wtf/" +const CONFIG_DIR_V2 = "~/.config/wtf/" + +/* -------------------- Config Migration -------------------- */ + +// MigrateOldConfig copies any existing configuration from the old location +// to the new, XDG-compatible location +func MigrateOldConfig() { + srcDir, _ := wtf.ExpandHomeDir(CONFIG_DIR_V1) + destDir, _ := wtf.ExpandHomeDir(CONFIG_DIR_V2) + + // If the old config directory doesn't exist, do not move + if _, err := os.Stat(srcDir); os.IsNotExist(err) { + return + } + + // If the new config directory already exists, do not move + if _, err := os.Stat(destDir); err == nil { + return + } + + // Time to move + err := Copy(srcDir, destDir) + if err != nil { + panic(err) + } else { + logger.Log(fmt.Sprintf("Copied old config from %s to %s", srcDir, destDir)) + } + + // Delete the old directory if the new one exists + if _, err := os.Stat(destDir); err == nil { + err := os.RemoveAll(srcDir) + if err != nil { + logger.Log(err.Error()) + } + } +} + +/* -------------------- Config Migration -------------------- */ + +// ConfigDir returns the absolute path to the configuration directory func ConfigDir() (string, error) { - configDir, err := ExpandHomeDir("~/.wtf/") + configDir, err := wtf.ExpandHomeDir(CONFIG_DIR_V2) if err != nil { return "", err } @@ -17,7 +60,7 @@ func ConfigDir() (string, error) { return configDir, nil } -// CreateConfigDir creates the .wtf directory in the user's home dir +// CreateConfigDir creates the wtf/ directory in the user's home dir func CreateConfigDir() { configDir, _ := ConfigDir() @@ -29,6 +72,25 @@ func CreateConfigDir() { } } +// CreateConfigFile creates a simple config file in the config directory if +// one does not already exist +func CreateConfigFile() { + filePath, err := CreateFile("config.yml") + if err != nil { + panic(err) + } + + // If the file is empty, write to it + file, err := os.Stat(filePath) + + if file.Size() == 0 { + err = ioutil.WriteFile(filePath, []byte(simpleConfig), 0644) + if err != nil { + panic(err) + } + } +} + // CreateFile creates the named file in the config directory, if it does not already exist. // If the file exists it does not recreate it. // If successful, eturns the absolute path to the file @@ -59,11 +121,11 @@ func CreateFile(fileName string) (string, error) { // LoadConfigFile loads the config.yml file to configure the app func LoadConfigFile(filePath string) *config.Config { - absPath, _ := ExpandHomeDir(filePath) + absPath, _ := wtf.ExpandHomeDir(filePath) cfg, err := config.ParseYamlFile(absPath) if err != nil { - fmt.Println("\n\n\033[1m ERROR:\033[0m Could not load '\033[0;33mconfig.yml\033[0m'.\n Please add a \033[0;33mconfig.yml\033[0m file to your \033[0;33m~/.wtf\033[0m directory.\n See \033[1;34mhttps://github.com/senorprogrammer/wtf\033[0m for details.\n") + fmt.Println("\n\n\033[1m ERROR:\033[0m Could not load '\033[0;33mconfig.yml\033[0m'.\n Please add a \033[0;33mconfig.yml\033[0m file to your \033[0;33m~/.wtf\033[0m directory.\n See \033[1;34mhttps://github.com/senorprogrammer/wtf\033[0m for details.") fmt.Printf(" %s\n", err.Error()) os.Exit(1) } @@ -79,7 +141,7 @@ func ReadConfigFile(fileName string) (string, error) { filePath := fmt.Sprintf("%s/%s", configDir, fileName) - fileData, err := ReadFileBytes(filePath) + fileData, err := wtf.ReadFileBytes(filePath) if err != nil { return "", err } @@ -87,25 +149,6 @@ func ReadConfigFile(fileName string) (string, error) { return string(fileData), nil } -// WriteConfigFile creates a simple config file in the config directory if -// one does not already exist -func WriteConfigFile() { - filePath, err := CreateFile("config.yml") - if err != nil { - panic(err) - } - - // If the file is empty, write to it - file, err := os.Stat(filePath) - - if file.Size() == 0 { - err = ioutil.WriteFile(filePath, []byte(simpleConfig), 0644) - if err != nil { - panic(err) - } - } -} - const simpleConfig = `wtf: colors: border: @@ -162,7 +205,7 @@ const simpleConfig = `wtf: refreshInterval: 3600 textfile: enabled: true - filePath: "~/.wtf/config.yml" + filePath: "~/.config/wtf/config.yml" position: top: 1 left: 1 diff --git a/cfg/copy.go b/cfg/copy.go new file mode 100644 index 00000000..6cea318d --- /dev/null +++ b/cfg/copy.go @@ -0,0 +1,75 @@ +// Copied verbatim from: +// +// https://github.com/otiai10/copy/blob/master/copy.go + +package cfg + +import ( + "io" + "io/ioutil" + "os" + "path/filepath" +) + +// Copy copies src to dest, doesn't matter if src is a directory or a file +func Copy(src, dest string) error { + info, err := os.Stat(src) + if err != nil { + return err + } + return copy(src, dest, info) +} + +// "info" must be given here, NOT nil. +func copy(src, dest string, info os.FileInfo) error { + if info.IsDir() { + return dcopy(src, dest, info) + } + return fcopy(src, dest, info) +} + +func fcopy(src, dest string, info os.FileInfo) error { + + f, err := os.Create(dest) + if err != nil { + return err + } + defer f.Close() + + if err = os.Chmod(f.Name(), info.Mode()); err != nil { + return err + } + + s, err := os.Open(src) + if err != nil { + return err + } + defer s.Close() + + _, err = io.Copy(f, s) + return err +} + +func dcopy(src, dest string, info os.FileInfo) error { + + if err := os.MkdirAll(dest, info.Mode()); err != nil { + return err + } + + infos, err := ioutil.ReadDir(src) + if err != nil { + return err + } + + for _, info := range infos { + if err := copy( + filepath.Join(src, info.Name()), + filepath.Join(dest, info.Name()), + info, + ); err != nil { + return err + } + } + + return nil +} diff --git a/circleci/build.go b/circleci/build.go new file mode 100644 index 00000000..270befc2 --- /dev/null +++ b/circleci/build.go @@ -0,0 +1,10 @@ +package circleci + +type Build struct { + AuthorEmail string `json:"author_email"` + AuthorName string `json:"author_name"` + Branch string `json:"branch"` + BuildNum int `json:"build_num"` + Reponame string `json:"reponame"` + Status string `json:"status"` +} diff --git a/circleci/client.go b/circleci/client.go new file mode 100644 index 00000000..16d7eb82 --- /dev/null +++ b/circleci/client.go @@ -0,0 +1,80 @@ +package circleci + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "os" +) + +const APIEnvKey = "WTF_CIRCLE_API_KEY" + +func BuildsFor() ([]*Build, error) { + builds := []*Build{} + + resp, err := circleRequest("recent-builds") + if err != nil { + return builds, err + } + + parseJson(&builds, resp.Body) + + return builds, nil +} + +/* -------------------- Unexported Functions -------------------- */ + +var ( + circleAPIURL = &url.URL{Scheme: "https", Host: "circleci.com", Path: "/api/v1/"} +) + +func circleRequest(path string) (*http.Response, error) { + params := url.Values{} + params.Add("circle-token", apiKey()) + + url := circleAPIURL.ResolveReference(&url.URL{Path: path, RawQuery: params.Encode()}) + + req, err := http.NewRequest("GET", url.String(), nil) + req.Header.Add("Accept", "application/json") + req.Header.Add("Content-Type", "application/json") + if err != nil { + return nil, err + } + + httpClient := &http.Client{} + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode < 200 || resp.StatusCode > 299 { + return nil, fmt.Errorf(resp.Status) + } + + return resp, nil +} + +func apiKey() string { + return os.Getenv(APIEnvKey) +} + +func parseJson(obj interface{}, text io.Reader) { + jsonStream, err := ioutil.ReadAll(text) + if err != nil { + panic(err) + } + + decoder := json.NewDecoder(bytes.NewReader(jsonStream)) + + for { + if err := decoder.Decode(obj); err == io.EOF { + break + } else if err != nil { + panic(err) + } + } +} diff --git a/circleci/widget.go b/circleci/widget.go new file mode 100644 index 00000000..98dbf116 --- /dev/null +++ b/circleci/widget.go @@ -0,0 +1,80 @@ +package circleci + +import ( + "fmt" + "github.com/senorprogrammer/wtf/wtf" +) + +type Widget struct { + wtf.TextWidget +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" CircleCI ", "circleci", false), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + if widget.Disabled() { + return + } + + builds, err := BuildsFor() + + widget.UpdateRefreshedAt() + + widget.View.SetTitle(fmt.Sprintf("%s - Builds", widget.Name)) + + var content string + if err != nil { + widget.View.SetWrap(true) + content = err.Error() + } else { + widget.View.SetWrap(false) + content = widget.contentFrom(builds) + } + + widget.View.SetText(content) +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(builds []*Build) string { + var str string + for idx, build := range builds { + if idx > 10 { + return str + } + + str = str + fmt.Sprintf( + "[%s] %s-%d (%s) [white]%s\n", + buildColor(build), + build.Reponame, + build.BuildNum, + build.Branch, + build.AuthorName, + ) + } + + return str +} + +func buildColor(build *Build) string { + switch build.Status { + case "failed": + return "red" + case "running": + return "yellow" + case "success": + return "green" + case "fixed": + return "green" + default: + return "white" + } +} diff --git a/clocks/clock_collection.go b/clocks/clock_collection.go index a1c226ea..c1ce1a1c 100644 --- a/clocks/clock_collection.go +++ b/clocks/clock_collection.go @@ -3,6 +3,8 @@ package clocks import ( "sort" "time" + + "github.com/senorprogrammer/wtf/wtf" ) type ClockCollection struct { @@ -10,7 +12,7 @@ type ClockCollection struct { } func (clocks *ClockCollection) Sorted() []Clock { - if "chronological" == Config.UString("wtf.mods.clocks.sort", "alphabetical") { + if "chronological" == wtf.Config.UString("wtf.mods.clocks.sort", "alphabetical") { clocks.SortedChronologically() } else { clocks.SortedAlphabetically() diff --git a/clocks/display.go b/clocks/display.go index 6cc7d60f..baad6dac 100644 --- a/clocks/display.go +++ b/clocks/display.go @@ -23,5 +23,5 @@ func (widget *Widget) display(clocks []Clock) { ) } - widget.View.SetText(fmt.Sprintf("%s", str)) + widget.View.SetText(str) } diff --git a/clocks/widget.go b/clocks/widget.go index 0e1a7fdc..551ebda7 100644 --- a/clocks/widget.go +++ b/clocks/widget.go @@ -3,13 +3,9 @@ package clocks import ( "time" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget @@ -21,7 +17,7 @@ func NewWidget() *Widget { TextWidget: wtf.NewTextWidget(" World Clocks ", "clocks", false), } - widget.clockColl = widget.buildClockCollection(Config.UMap("wtf.mods.clocks.locations")) + widget.clockColl = widget.buildClockCollection(wtf.Config.UMap("wtf.mods.clocks.locations")) return &widget } @@ -29,10 +25,6 @@ func NewWidget() *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - widget.UpdateRefreshedAt() widget.display(widget.clockColl.Sorted()) } diff --git a/cmdrunner/widget.go b/cmdrunner/widget.go index 3c80ae5a..62183b4d 100644 --- a/cmdrunner/widget.go +++ b/cmdrunner/widget.go @@ -5,13 +5,9 @@ import ( "os/exec" "strings" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget @@ -24,8 +20,8 @@ func NewWidget() *Widget { widget := Widget{ TextWidget: wtf.NewTextWidget(" CmdRunner ", "cmdrunner", false), - args: wtf.ToStrs(Config.UList("wtf.mods.cmdrunner.args")), - cmd: Config.UString("wtf.mods.cmdrunner.cmd"), + args: wtf.ToStrs(wtf.Config.UList("wtf.mods.cmdrunner.args")), + cmd: wtf.Config.UString("wtf.mods.cmdrunner.cmd"), } widget.View.SetWrap(true) @@ -34,20 +30,18 @@ func NewWidget() *Widget { } func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - widget.UpdateRefreshedAt() widget.execute() - widget.View.SetTitle(fmt.Sprintf(" %s ", widget)) - widget.View.SetText(fmt.Sprintf("%s", widget.result)) + title := wtf.Config.UString("wtf.mods.cmdrunner.title", widget.String()) + widget.View.SetTitle(title) + + widget.View.SetText(widget.result) } func (widget *Widget) String() string { args := strings.Join(widget.args, " ") - return fmt.Sprintf("%s %s", widget.cmd, args) + return fmt.Sprintf(" %s %s ", widget.cmd, args) } func (widget *Widget) execute() { diff --git a/cryptoexchanges/bittrex/display.go b/cryptoexchanges/bittrex/display.go index 2718e0f7..3c8fa6e4 100644 --- a/cryptoexchanges/bittrex/display.go +++ b/cryptoexchanges/bittrex/display.go @@ -8,14 +8,11 @@ import ( func (widget *Widget) display() { if ok == false { - widget.View.SetText(fmt.Sprintf("%s", errorText)) + widget.View.SetText(errorText) return } - str := "" - str += summaryText(&widget.summaryList, &widget.TextColors) - - widget.View.SetText(fmt.Sprintf("%s", str)) + widget.View.SetText(summaryText(&widget.summaryList, &widget.TextColors)) } func summaryText(list *summaryList, colors *TextColors) string { diff --git a/cryptoexchanges/bittrex/widget.go b/cryptoexchanges/bittrex/widget.go index 3f6f4d92..c5892733 100644 --- a/cryptoexchanges/bittrex/widget.go +++ b/cryptoexchanges/bittrex/widget.go @@ -7,13 +7,9 @@ import ( "net/http" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type TextColors struct { base struct { name string @@ -28,7 +24,7 @@ type TextColors struct { var ok = true var errorText = "" -var started = false + var baseURL = "https://bittrex.com/api/v1.1/public/getmarketsummary" // Widget define wtf widget to register widget later @@ -40,13 +36,11 @@ type Widget struct { // NewWidget Make new instance of widget func NewWidget() *Widget { - widget := Widget{ TextWidget: wtf.NewTextWidget(" Bittrex ", "bittrex", false), summaryList: summaryList{}, } - started = false ok = true errorText = "" @@ -57,17 +51,17 @@ func NewWidget() *Widget { } func (widget *Widget) config() { - widget.TextColors.base.name = Config.UString("wtf.mods.bittrex.colors.base.name", "red") - widget.TextColors.base.displayName = Config.UString("wtf.mods.bittrex.colors.base.displayName", "grey") - widget.TextColors.market.name = Config.UString("wtf.mods.bittrex.colors.market.name", "red") - widget.TextColors.market.field = Config.UString("wtf.mods.bittrex.colors.market.field", "coral") - widget.TextColors.market.value = Config.UString("wtf.mods.bittrex.colors.market.value", "white") + widget.TextColors.base.name = wtf.Config.UString("wtf.mods.bittrex.colors.base.name", "red") + widget.TextColors.base.displayName = wtf.Config.UString("wtf.mods.bittrex.colors.base.displayName", "grey") + widget.TextColors.market.name = wtf.Config.UString("wtf.mods.bittrex.colors.market.name", "red") + widget.TextColors.market.field = wtf.Config.UString("wtf.mods.bittrex.colors.market.field", "coral") + widget.TextColors.market.value = wtf.Config.UString("wtf.mods.bittrex.colors.market.value", "white") } func (widget *Widget) setSummaryList() { - sCurrencies, _ := Config.Map("wtf.mods.bittrex.summary") + sCurrencies, _ := wtf.Config.Map("wtf.mods.bittrex.summary") for baseCurrencyName := range sCurrencies { - displayName, _ := Config.String("wtf.mods.bittrex.summary." + baseCurrencyName + ".displayName") + displayName, _ := wtf.Config.String("wtf.mods.bittrex.summary." + baseCurrencyName + ".displayName") mCurrencyList := makeSummaryMarketList(baseCurrencyName) widget.summaryList.addSummaryItem(baseCurrencyName, displayName, mCurrencyList) } @@ -76,7 +70,7 @@ func (widget *Widget) setSummaryList() { func makeSummaryMarketList(currencyName string) []*mCurrency { mCurrencyList := []*mCurrency{} - configMarketList, _ := Config.List("wtf.mods.bittrex.summary." + currencyName + ".market") + configMarketList, _ := wtf.Config.List("wtf.mods.bittrex.summary." + currencyName + ".market") for _, mCurrencyName := range configMarketList { mCurrencyList = append(mCurrencyList, makeMarketCurrency(mCurrencyName.(string))) } @@ -102,24 +96,9 @@ func makeMarketCurrency(name string) *mCurrency { // Refresh & update after interval time func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - - if started == false { - go func() { - for { - widget.updateSummary() - time.Sleep(time.Second * time.Duration(widget.RefreshInterval())) - } - }() - started = true - } - + widget.updateSummary() widget.UpdateRefreshedAt() - widget.display() - } /* -------------------- Unexported Functions -------------------- */ diff --git a/cryptoexchanges/blockfolio/widget.go b/cryptoexchanges/blockfolio/widget.go new file mode 100644 index 00000000..72349738 --- /dev/null +++ b/cryptoexchanges/blockfolio/widget.go @@ -0,0 +1,121 @@ +package blockfolio + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + + "github.com/rivo/tview" + "github.com/senorprogrammer/wtf/wtf" +) + +type Widget struct { + wtf.TextWidget + + app *tview.Application + device_token string +} + +func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" Blockfolio ", "blockfolio", false), + device_token: wtf.Config.UString("wtf.mods.blockfolio.device_token"), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + widget.UpdateRefreshedAt() + widget.View.SetTitle(" Blockfolio ") + + positions, err := Fetch(widget.device_token) + if err != nil { + return + } + + widget.View.SetText(contentFrom(positions)) +} + +/* -------------------- Unexported Functions -------------------- */ +func contentFrom(positions *AllPositionsResponse) string { + res := "" + colorName := wtf.Config.UString("wtf.mods.blockfolio.colors.name") + colorGrows := wtf.Config.UString("wtf.mods.blockfolio.colors.grows") + colorDrop := wtf.Config.UString("wtf.mods.blockfolio.colors.drop") + displayHoldings := wtf.Config.UBool("wtf.mods.blockfolio.displayHoldings") + var totalFiat float32 + totalFiat = 0.0 + for i := 0; i < len(positions.PositionList); i++ { + colorForChange := colorGrows + if positions.PositionList[i].TwentyFourHourPercentChangeFiat <= 0 { + colorForChange = colorDrop + } + totalFiat += positions.PositionList[i].HoldingValueFiat + if displayHoldings { + res = res + fmt.Sprintf("[%s]%-6s - %5.2f ([%s]%.3fk [%s]%.2f%s)\n", colorName, positions.PositionList[i].Coin, positions.PositionList[i].Quantity, colorForChange, positions.PositionList[i].HoldingValueFiat/1000, colorForChange, positions.PositionList[i].TwentyFourHourPercentChangeFiat, "%") + } else { + res = res + fmt.Sprintf("[%s]%-6s - %5.2f ([%s]%.2f%s)\n", colorName, positions.PositionList[i].Coin, positions.PositionList[i].Quantity, colorForChange, positions.PositionList[i].TwentyFourHourPercentChangeFiat, "%") + } + } + if displayHoldings { + res = res + fmt.Sprintf("\n[%s]Total value: $%.3fk", "green", totalFiat/1000) + } + + return res +} + +//always the same +const magic = "edtopjhgn2345piuty89whqejfiobh89-2q453" + +type Position struct { + Coin string `json:coin` + LastPriceFiat float32 `json:lastPriceFiat` + TwentyFourHourPercentChangeFiat float32 `json:twentyFourHourPercentChangeFiat` + Quantity float32 `json:quantity` + HoldingValueFiat float32 `json:holdingValueFiat` +} + +type AllPositionsResponse struct { + PositionList []Position `json:positionList` +} + +func MakeApiRequest(token string, method string) ([]byte, error) { + client := &http.Client{} + url := "https://api-v0.blockfolio.com/rest/" + method + "/" + token + "?use_alias=true&fiat_currency=USD" + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + req.Header.Add("magic", magic) + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return body, err +} + +func GetAllPositions(token string) (*AllPositionsResponse, error) { + jsn, err := MakeApiRequest(token, "get_all_positions") + var parsed AllPositionsResponse + + err = json.Unmarshal(jsn, &parsed) + if err != nil { + log.Fatalf("Failed to parse json %v", err) + return nil, err + } + return &parsed, err +} + +func Fetch(token string) (*AllPositionsResponse, error) { + return GetAllPositions(token) +} diff --git a/docs/404.html b/docs/404.html index ac5e8a16..c4dc9e52 100644 --- a/docs/404.html +++ b/docs/404.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/categories/index.html b/docs/categories/index.html index a544f62c..f6ce7abd 100644 --- a/docs/categories/index.html +++ b/docs/categories/index.html @@ -39,8 +39,20 @@ + + + + + + + - + diff --git a/docs/imgs/modules/blockfolio.png b/docs/imgs/modules/blockfolio.png new file mode 100644 index 00000000..1a820c07 Binary files /dev/null and b/docs/imgs/modules/blockfolio.png differ diff --git a/docs/imgs/modules/circleci.png b/docs/imgs/modules/circleci.png new file mode 100644 index 00000000..e2447b41 Binary files /dev/null and b/docs/imgs/modules/circleci.png differ diff --git a/docs/imgs/modules/gitlab.png b/docs/imgs/modules/gitlab.png new file mode 100644 index 00000000..6e806a41 Binary files /dev/null and b/docs/imgs/modules/gitlab.png differ diff --git a/docs/imgs/modules/jenkins.png b/docs/imgs/modules/jenkins.png new file mode 100644 index 00000000..5074eca1 Binary files /dev/null and b/docs/imgs/modules/jenkins.png differ diff --git a/docs/imgs/modules/trello.png b/docs/imgs/modules/trello.png new file mode 100644 index 00000000..79fa6965 Binary files /dev/null and b/docs/imgs/modules/trello.png differ diff --git a/docs/index.html b/docs/index.html index 24b1eae2..95a69476 100644 --- a/docs/index.html +++ b/docs/index.html @@ -38,8 +38,20 @@ + + + + + + + - + diff --git a/docs/index.xml b/docs/index.xml index 1596a7db..5cc6df8c 100644 --- a/docs/index.xml +++ b/docs/index.xml @@ -6,11 +6,116 @@ Recent content on WTF - A Terminal Dashboard Hugo -- gohugo.io en-us - Mon, 04 Jun 2018 20:06:40 -0700 + Sat, 16 Jun 2018 14:22:18 -0700 + + Logger + https://wtfutil.com/posts/modules/logger/ + Sat, 16 Jun 2018 14:22:18 -0700 + + https://wtfutil.com/posts/modules/logger/ + Displays the contents of the WTF log file. +To log to this file in your own modules: +require &#34;github.com/senorprogrammer/wtf/logger&#34; logger.Log(&#34;This is a log entry&#34;) Source Code wtf/logger/ Required ENV Variables None. +Keyboard Commands Arrow keys scroll through the log file. +Configuration logger:enabled:trueposition:top:5left:4height:2width:1refreshInterval:1 Attributes enabled Determines whether or not this module is executed and if its data displayed onscreen. Note: If you&rsquo;re using logging and logging is disabled, your logs will still be written to file, the widget just won&rsquo;t be shown onscreen. + + + + Blockfolio + https://wtfutil.com/posts/modules/cryptocurrencies/blockfolio/ + Wed, 13 Jun 2018 09:29:59 -0700 + + https://wtfutil.com/posts/modules/cryptocurrencies/blockfolio/ + Added in v0.0.8. +Display your Blockfolio crypto holdings. +Source wtf/blockfolio/ Required ENV Variables None. +Keyboard Commands None. +Configuration blockfolio:colors:name:bluegrows:greendrop:reddevice_token:&#34;device token&#34;displayHoldings:trueenabled:trueposition:top:3left:1width:1height:1refreshInterval:400 Attributes colors.name Values: Any X11 color name. +colors.grows Values: Any X11 color name. +colors.drop Values: Any X11 color name. +device_token Value: See this gist for details on how to get your Blockfolio API token. +displayHoldings enabled Determines whether or not this module is executed and if its data displayed onscreen. + + + + IP-API + https://wtfutil.com/posts/modules/ipapi/ + Sun, 10 Jun 2018 19:41:52 -0400 + + https://wtfutil.com/posts/modules/ipapi/ + Added in v0.0.7. +Displays your current IP address information, from IP-APIcom. +Note: IP-API.com has a free-plan rate limit of 120 requests per minute. +Source Code wtf/ipapi/ Required ENV Variables None. +Keyboard Commands None. +Configuration ipinfo:colors:name:redvalue:whiteenabled:trueposition:top:1left:2height:1width:1refreshInterval:150 Attributes colors.name The default colour for the row names. Values: Any X11 color name. +colors.value The default colour for the row values. Values: Any X11 color name. +enabled Determines whether or not this module is executed and if its data displayed onscreen. + + + + CircleCI + https://wtfutil.com/posts/modules/circleci/ + Sun, 10 Jun 2018 19:26:08 -0400 + + https://wtfutil.com/posts/modules/circleci/ + Added in v0.0.7. +Displays build information for your CircleCI account. +Source Code wtf/circleci/ Required ENV Variables Key: WTF_CIRCLE_API_KEY Value: Your CircleCI API token. +Keyboard Commands None. +Configuration circleci:enabled:trueposition:top:4left:1height:1width:2refreshInterval:900 Attributes enabled Determines whether or not this module is executed and if its data displayed onscreen. Values: true, false. +position Defines where in the grid this module&rsquo;s widget will be displayed. refreshInterval How often, in seconds, this module will update its data. + + + + Google Spreadsheets + https://wtfutil.com/posts/modules/gspreadsheet/ + Sun, 10 Jun 2018 18:26:26 -0400 + + https://wtfutil.com/posts/modules/gspreadsheet/ + Added in v0.0.7. +Display information from cells in a Google Spreadsheet. +wtf/gspreadsheets/ Required ENV Variables None. +Keyboard Commands None. +Configuration gspreadsheets:colors:values:&#34;green&#34;cells:names:-&#34;Cell 1 name&#34;-&#34;Cell 2 name&#34;addresses:-&#34;A1&#34;-&#34;A2&#34;enabled:trueposition:top:0left:0width:1height:1refreshInterval:&#34;300&#34;secretFile:&#34;~/.config/wtf/gspreadsheets/client_secret.json&#34;sheetId:&#34;id_of_google_spreadsheet&#34; Attributes colors.values The color to display the cell values in. Values: Any X11 color name. +cells.names cells.addresses enabled Whether or not this module is executed and if its data displayed onscreen. Values: true, false. +position Where in the grid this module&rsquo;s widget will be displayed. + + + + Modules: Jenkins + https://wtfutil.com/posts/modules/jenkins/ + Sat, 09 Jun 2018 20:53:35 -0700 + + https://wtfutil.com/posts/modules/jenkins/ + Added in v0.0.8. +Displays jenkins status of given builds in a project or view +Source Code wtf/jenkins/ Required ENV Variables Key: WTF_JENKINS_API_KEY Value: Your Jenkins API key. +Keyboard Commands None. +Configuration jenkins:enabled:trueposition:top:2left:3height:2width:3refreshInterval:300url:&#34;https://jenkins.domain.com/jenkins/view_url&#34;user:&#34;username&#34; Attributes enabled Determines whether or not this module is executed and if its data displayed onscreen. Values: true, false. +position Defines where in the grid this module&rsquo;s widget will be displayed. +refreshInterval How often, in seconds, this module will update its data. + + + + Gitlab + https://wtfutil.com/posts/modules/gitlab/ + Fri, 08 Jun 2018 13:14:11 -0700 + + https://wtfutil.com/posts/modules/gitlab/ + Added in v0.0.8. +Displays information about your projects hosted on Gitlab: +Open Approval Requests All open merge requests that are requesting your approval. +Open Merge Requests All open merge requests created by you. +Source Code wtf/gitlab/ Required ENV Variables Key: WTF_GITLAB_TOKEN Action: A Gitlab personal access token. Requires at least api access. +Keyboard Commands Key: / Action: Open/close the widget&rsquo;s help window. +Key: h Action: Show the previous project. + + Bittrex https://wtfutil.com/posts/modules/cryptocurrencies/bittrex/ @@ -19,7 +124,7 @@ https://wtfutil.com/posts/modules/cryptocurrencies/bittrex/ Added in v0.0.5. Get the last 24 hour summary of cryptocurrencies market using Bittrex. -Source Code wtf/cryptoexchanges/bittrex/ Required ENV Vars None. +Source Code wtf/cryptoexchanges/bittrex/ Required ENV Variables None. Keyboard Commands None. Configuration bittrex:enabled:trueposition:top:1left:2height:3width:1refreshInterval:5summary:BTC:displayName:Bitcoinmarket:-LTC-ETHcolors:base:name:orangedisplayName:redmarket:name:redfield:whitevalue:green Attributes colors.base.name Values: Any X11 color name. colors.base.dispayName Values: Any X11 color name. @@ -53,11 +158,10 @@ position Defines where in the grid this module&rsquo;s widget will be displa Sat, 02 Jun 2018 05:32:04 -0700 https://wtfutil.com/posts/modules/prettyweather/ - 🔬 Experimental -Displays weather information as ASCII art from Wttr.in. + Displays weather information as ASCII art from Wttr.in. Source Code wtf/prettyweather/ Required ENV Variables None. Keyboard Commands None. -Configuration prettyweather:enabled:truecity:&#34;tehran&#34;position:top:3left:5height:1width:1refreshInterval:300unit:&#34;c&#34; Attributes city Optional. It will grab the current location from your IP address if omitted. +Configuration prettyweather:enabled:truecity:&#34;tehran&#34;position:top:3left:5height:1width:1refreshInterval:300unit:&#34;c&#34;view:0 Attributes city Optional. It will grab the current location from your IP address if omitted. Values: The name of any city supported by Wttr.in. enabled Determines whether or not this module is executed and if its data displayed onscreen. Values: true, false. position Defines where in the grid this module&rsquo;s widget will be displayed. @@ -70,12 +174,12 @@ position Defines where in the grid this module&rsquo;s widget will be displa https://wtfutil.com/posts/modules/ipinfo/ Displays your current IP address information, from ipinfo.io. +Note: IPInfo.io has a free-plan rate limit of 1000 requests per day. Source Code wtf/ipinfo/ Required ENV Variables None. Keyboard Commands None. -Configuration ipinfo:colors:name:redvalue:whiteenabled:trueposition:top:1left:2height:1width:1refreshInterval:15 Attributes colors.name The default colour for the row names. Values: Any X11 color name. +Configuration ipinfo:colors:name:redvalue:whiteenabled:trueposition:top:1left:2height:1width:1refreshInterval:150 Attributes colors.name The default colour for the row names. Values: Any X11 color name. colors.value The default colour for the row values. Values: Any X11 color name. -enabled Determines whether or not this module is executed and if its data displayed onscreen. Values: true, false. -position Defines where in the grid this module&rsquo;s widget will be displayed. +enabled Determines whether or not this module is executed and if its data displayed onscreen. @@ -175,10 +279,21 @@ Key: j Action: Select the next item in the list. Displays all Jira issues assigned to you for the specified project. Source Code wtf/jira/ Required ENV Variables Key: WTF_JIRA_API_KEY Value: Your Jira API key. Keyboard Commands None. -Configuration jira:colors:rows:even:&#34;lightblue&#34;odd:&#34;white&#34;domain:&#34;https://umbrellacorp.atlassian.net&#34;email:&#34;chriscummer@me.com&#34;enabled:truejql:&#34;issueType = Story&#34;position:top:4left:1height:1width:2project:&#34;JIRA&#34;refreshInterval:900username:&#34;chris.cummer&#34; Attributes colors.rows.even Define the foreground color for even-numbered rows. Values: Any X11 color name. -colors.rows.odd Define the foreground color for odd-numbered rows. Values: Any X11 color name. -domain Your Jira corporate domain. Values: A valid URI. -email The email address associated with your Jira account. +Configuration Single Jira Project jira:colors:rows:even:&#34;lightblue&#34;odd:&#34;white&#34;domain:&#34;https://umbrellacorp.atlassian.net&#34;email:&#34;chriscummer@me.com&#34;enabled:truejql:&#34;issueType = Story&#34;position:top:4left:1height:1width:2project:&#34;ProjectA&#34;refreshInterval:900username:&#34;chris.cummer&#34;verifyServerCertificate:true Multiple Jira Projects If you want to monitor multiple Jira projects, use the following configuration (note the difference in project): +jira:colors:rows:even:&#34;lightblue&#34;odd:&#34;white&#34;domain:&#34;https://umbrellacorp.atlassian.net&#34;email:&#34;chriscummer@me.com&#34;enabled:truejql:&#34;issueType = Story&#34;position:top:4left:1height:1width:2project:[&#34;ProjectA&#34;,&#34;ProjectB&#34;]refreshInterval:900username:&#34;chris.cummer&#34;verifyServerCertificate:true Attributes colors.rows.even Define the foreground color for even-numbered rows. Values: Any X11 color name. + + + + Trello + https://wtfutil.com/posts/modules/trello/ + Thu, 10 May 2018 10:44:35 -0700 + + https://wtfutil.com/posts/modules/trello/ + Displays all Trello cards on specified lists. +Source Code wtf/trello/ Required ENV Variables Key: WTF_TRELLO_APP_KEY Value: Your Trello App Key. Key: WTF_TRELLO_ACCESS_TOKEN Value: Your Trello Access Token. You can get your API key at: trello.com/app-key. +Keyboard Commands None. +Configuration Single Trello List trello:board:Mainenabled:truelist:&#34;Todo&#34;position:height:1left:2top:0width:1refreshInterval:3600username:myname Multiple Trello Lists If you want to monitor multiple Trello lists, use the following configuration (note the difference in list): +trello:board:Mainenabled:truelist:[&#34;Todo&#34;,&#34;Done&#34;]position:height:1left:2top:0width:1refreshInterval:3600username:myname Attributes board The name of the Trello board. @@ -189,24 +304,24 @@ email The email address associated with your Jira account. https://wtfutil.com/posts/modules/gcal/ Displays your upcoming Google calendar events. Not: Setting up access to Google Calendars for Go is a bit unobvious. Check out Google&rsquo;s Go Quickstart first and if you have problems, then take a look at this comment by WesleydeSouza which offers a slightly different approach. -Source Code wtf/gcal/ Required ENV Variables Key: WTF_GOOGLE_CAL_CLIENT_ID Value: Your Google API client ID. -Key: WTF_GOOGLE_CAL_CLIENT_SECRET Value: Your Google API client secret. -Keyboard Commands None. +Source Code wtf/gcal/ Required ENV Variables None. +Keyboard Commands None. +Configuration gcal:colors:title:&#34;red&#34;description:&#34;lightblue&#34;highlights:-[&#39;1on1|1\/11&#39;,&#39;green&#39;]-[&#39;apple|google|aws&#39;,&#39;blue&#39;]-[&#39;interview|meet&#39;,&#39;magenta&#39;]-[&#39;lunch&#39;,&#39;yellow&#39;]past:&#34;gray&#34;conflictIcon:&#34;🚨&#34;currentIcon:&#34;💥&#34;displayResponseStatus:trueemail:&#34;chriscummer@me.com&#34;enabled:trueeventCount:12multiCalendar:trueposition:top:0left:0height:4width:1refreshInterval:300secretFile:&#34;~/.config/wtf/gcal/client_secret.json&#34;withLocation:true Attributes colors.title The default colour for calendar event titles. Values: Any X11 color name. - Github + GitHub https://wtfutil.com/posts/modules/github/ Wed, 09 May 2018 19:20:20 -0700 https://wtfutil.com/posts/modules/github/ - Displays information about git repositories hosted on Github: open review requests, and open pull requests. + Displays information about your git repositories hosted on Github: Open Review Requests All open code review requests assigned to you. Open Pull Requests All open pull requests created by you. -Source Code wtf/github/ Required ENV Variables Key: WTF_GITHUB_TOKEN Action: Your Github API token. -Keyboard Commands Key: / Action: Open/close the widget&rsquo;s help window. -Key: h Action: Show the previous git repository. -Key: l Action: Show the next git repository. +Source Code wtf/github/ Github Required ENV Variables Key: WTF_GITHUB_TOKEN Action: Your Github API token. +GitHub Enterprise Required ENV Variables Key: WTF_GITHUB_TOKEN Action: Your Github API token. +Key: WTF_GITHUB_BASE_URL Action: Your Github Enterprise API URL. +Key: WTF_GITHUB_UPLOAD_URL Action: Your Github Enterprise upload URL (often the same as API URL). @@ -347,8 +462,8 @@ Widgets are defined by a required widget.go file in a Module. Sun, 15 Apr 2018 21:17:16 -0700 https://wtfutil.com/posts/configuration/ - Index Configuration Files Environment (ENV) Variables Grid Layout Configuration Files By default WTF looks in a ~/.wtf/ directory for a YAML file called config.yml. If the ~/.wtf/ directory doesn&rsquo;t exist, WTF will create that directory on start-up, and then display instructions for creating a new configuration file. -In other words, WTF expects to have a YAML config file at: ~/.wtf/config.yml. + Index Configuration Files Environment (ENV) Variables Grid Layout Configuration Files By default WTF looks in a ~/.config/wtf/ directory for a YAML file called config.yml. If the ~/.config/wtf/ directory doesn&rsquo;t exist, WTF will create that directory on start-up, and then display instructions for creating a new configuration file. +In other words, WTF expects to have a YAML config file at: ~/.config/wtf/config.yml. Example Configuration Files A couple of example config files are provided in the _sample_configs/ directory of the Git repository. diff --git a/docs/posts/configuration/attributes/index.html b/docs/posts/configuration/attributes/index.html index f263b231..4693df6e 100644 --- a/docs/posts/configuration/attributes/index.html +++ b/docs/posts/configuration/attributes/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/configuration/index.html b/docs/posts/configuration/index.html index 2e5f8344..03874b43 100644 --- a/docs/posts/configuration/index.html +++ b/docs/posts/configuration/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/configuration/iterm2/index.html b/docs/posts/configuration/iterm2/index.html index 45f31cb8..9c2711fa 100644 --- a/docs/posts/configuration/iterm2/index.html +++ b/docs/posts/configuration/iterm2/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/glossary/index.html b/docs/posts/glossary/index.html index 0d33fa48..3395b0f7 100644 --- a/docs/posts/glossary/index.html +++ b/docs/posts/glossary/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/index.html b/docs/posts/index.html index 15386a6a..a2487887 100644 --- a/docs/posts/index.html +++ b/docs/posts/index.html @@ -39,8 +39,20 @@ + + + + + + + - + diff --git a/docs/posts/index.xml b/docs/posts/index.xml index 49b15fc1..490c9f72 100644 --- a/docs/posts/index.xml +++ b/docs/posts/index.xml @@ -6,11 +6,116 @@ Recent content in Posts on WTF - A Terminal Dashboard Hugo -- gohugo.io en-us - Mon, 04 Jun 2018 20:06:40 -0700 + Sat, 16 Jun 2018 14:22:18 -0700 + + Logger + https://wtfutil.com/posts/modules/logger/ + Sat, 16 Jun 2018 14:22:18 -0700 + + https://wtfutil.com/posts/modules/logger/ + Displays the contents of the WTF log file. +To log to this file in your own modules: +require &#34;github.com/senorprogrammer/wtf/logger&#34; logger.Log(&#34;This is a log entry&#34;) Source Code wtf/logger/ Required ENV Variables None. +Keyboard Commands Arrow keys scroll through the log file. +Configuration logger:enabled:trueposition:top:5left:4height:2width:1refreshInterval:1 Attributes enabled Determines whether or not this module is executed and if its data displayed onscreen. Note: If you&rsquo;re using logging and logging is disabled, your logs will still be written to file, the widget just won&rsquo;t be shown onscreen. + + + + Blockfolio + https://wtfutil.com/posts/modules/cryptocurrencies/blockfolio/ + Wed, 13 Jun 2018 09:29:59 -0700 + + https://wtfutil.com/posts/modules/cryptocurrencies/blockfolio/ + Added in v0.0.8. +Display your Blockfolio crypto holdings. +Source wtf/blockfolio/ Required ENV Variables None. +Keyboard Commands None. +Configuration blockfolio:colors:name:bluegrows:greendrop:reddevice_token:&#34;device token&#34;displayHoldings:trueenabled:trueposition:top:3left:1width:1height:1refreshInterval:400 Attributes colors.name Values: Any X11 color name. +colors.grows Values: Any X11 color name. +colors.drop Values: Any X11 color name. +device_token Value: See this gist for details on how to get your Blockfolio API token. +displayHoldings enabled Determines whether or not this module is executed and if its data displayed onscreen. + + + + IP-API + https://wtfutil.com/posts/modules/ipapi/ + Sun, 10 Jun 2018 19:41:52 -0400 + + https://wtfutil.com/posts/modules/ipapi/ + Added in v0.0.7. +Displays your current IP address information, from IP-APIcom. +Note: IP-API.com has a free-plan rate limit of 120 requests per minute. +Source Code wtf/ipapi/ Required ENV Variables None. +Keyboard Commands None. +Configuration ipinfo:colors:name:redvalue:whiteenabled:trueposition:top:1left:2height:1width:1refreshInterval:150 Attributes colors.name The default colour for the row names. Values: Any X11 color name. +colors.value The default colour for the row values. Values: Any X11 color name. +enabled Determines whether or not this module is executed and if its data displayed onscreen. + + + + CircleCI + https://wtfutil.com/posts/modules/circleci/ + Sun, 10 Jun 2018 19:26:08 -0400 + + https://wtfutil.com/posts/modules/circleci/ + Added in v0.0.7. +Displays build information for your CircleCI account. +Source Code wtf/circleci/ Required ENV Variables Key: WTF_CIRCLE_API_KEY Value: Your CircleCI API token. +Keyboard Commands None. +Configuration circleci:enabled:trueposition:top:4left:1height:1width:2refreshInterval:900 Attributes enabled Determines whether or not this module is executed and if its data displayed onscreen. Values: true, false. +position Defines where in the grid this module&rsquo;s widget will be displayed. refreshInterval How often, in seconds, this module will update its data. + + + + Google Spreadsheets + https://wtfutil.com/posts/modules/gspreadsheet/ + Sun, 10 Jun 2018 18:26:26 -0400 + + https://wtfutil.com/posts/modules/gspreadsheet/ + Added in v0.0.7. +Display information from cells in a Google Spreadsheet. +wtf/gspreadsheets/ Required ENV Variables None. +Keyboard Commands None. +Configuration gspreadsheets:colors:values:&#34;green&#34;cells:names:-&#34;Cell 1 name&#34;-&#34;Cell 2 name&#34;addresses:-&#34;A1&#34;-&#34;A2&#34;enabled:trueposition:top:0left:0width:1height:1refreshInterval:&#34;300&#34;secretFile:&#34;~/.config/wtf/gspreadsheets/client_secret.json&#34;sheetId:&#34;id_of_google_spreadsheet&#34; Attributes colors.values The color to display the cell values in. Values: Any X11 color name. +cells.names cells.addresses enabled Whether or not this module is executed and if its data displayed onscreen. Values: true, false. +position Where in the grid this module&rsquo;s widget will be displayed. + + + + Modules: Jenkins + https://wtfutil.com/posts/modules/jenkins/ + Sat, 09 Jun 2018 20:53:35 -0700 + + https://wtfutil.com/posts/modules/jenkins/ + Added in v0.0.8. +Displays jenkins status of given builds in a project or view +Source Code wtf/jenkins/ Required ENV Variables Key: WTF_JENKINS_API_KEY Value: Your Jenkins API key. +Keyboard Commands None. +Configuration jenkins:enabled:trueposition:top:2left:3height:2width:3refreshInterval:300url:&#34;https://jenkins.domain.com/jenkins/view_url&#34;user:&#34;username&#34; Attributes enabled Determines whether or not this module is executed and if its data displayed onscreen. Values: true, false. +position Defines where in the grid this module&rsquo;s widget will be displayed. +refreshInterval How often, in seconds, this module will update its data. + + + + Gitlab + https://wtfutil.com/posts/modules/gitlab/ + Fri, 08 Jun 2018 13:14:11 -0700 + + https://wtfutil.com/posts/modules/gitlab/ + Added in v0.0.8. +Displays information about your projects hosted on Gitlab: +Open Approval Requests All open merge requests that are requesting your approval. +Open Merge Requests All open merge requests created by you. +Source Code wtf/gitlab/ Required ENV Variables Key: WTF_GITLAB_TOKEN Action: A Gitlab personal access token. Requires at least api access. +Keyboard Commands Key: / Action: Open/close the widget&rsquo;s help window. +Key: h Action: Show the previous project. + + Bittrex https://wtfutil.com/posts/modules/cryptocurrencies/bittrex/ @@ -19,7 +124,7 @@ https://wtfutil.com/posts/modules/cryptocurrencies/bittrex/ Added in v0.0.5. Get the last 24 hour summary of cryptocurrencies market using Bittrex. -Source Code wtf/cryptoexchanges/bittrex/ Required ENV Vars None. +Source Code wtf/cryptoexchanges/bittrex/ Required ENV Variables None. Keyboard Commands None. Configuration bittrex:enabled:trueposition:top:1left:2height:3width:1refreshInterval:5summary:BTC:displayName:Bitcoinmarket:-LTC-ETHcolors:base:name:orangedisplayName:redmarket:name:redfield:whitevalue:green Attributes colors.base.name Values: Any X11 color name. colors.base.dispayName Values: Any X11 color name. @@ -53,11 +158,10 @@ position Defines where in the grid this module&rsquo;s widget will be displa Sat, 02 Jun 2018 05:32:04 -0700 https://wtfutil.com/posts/modules/prettyweather/ - 🔬 Experimental -Displays weather information as ASCII art from Wttr.in. + Displays weather information as ASCII art from Wttr.in. Source Code wtf/prettyweather/ Required ENV Variables None. Keyboard Commands None. -Configuration prettyweather:enabled:truecity:&#34;tehran&#34;position:top:3left:5height:1width:1refreshInterval:300unit:&#34;c&#34; Attributes city Optional. It will grab the current location from your IP address if omitted. +Configuration prettyweather:enabled:truecity:&#34;tehran&#34;position:top:3left:5height:1width:1refreshInterval:300unit:&#34;c&#34;view:0 Attributes city Optional. It will grab the current location from your IP address if omitted. Values: The name of any city supported by Wttr.in. enabled Determines whether or not this module is executed and if its data displayed onscreen. Values: true, false. position Defines where in the grid this module&rsquo;s widget will be displayed. @@ -70,12 +174,12 @@ position Defines where in the grid this module&rsquo;s widget will be displa https://wtfutil.com/posts/modules/ipinfo/ Displays your current IP address information, from ipinfo.io. +Note: IPInfo.io has a free-plan rate limit of 1000 requests per day. Source Code wtf/ipinfo/ Required ENV Variables None. Keyboard Commands None. -Configuration ipinfo:colors:name:redvalue:whiteenabled:trueposition:top:1left:2height:1width:1refreshInterval:15 Attributes colors.name The default colour for the row names. Values: Any X11 color name. +Configuration ipinfo:colors:name:redvalue:whiteenabled:trueposition:top:1left:2height:1width:1refreshInterval:150 Attributes colors.name The default colour for the row names. Values: Any X11 color name. colors.value The default colour for the row values. Values: Any X11 color name. -enabled Determines whether or not this module is executed and if its data displayed onscreen. Values: true, false. -position Defines where in the grid this module&rsquo;s widget will be displayed. +enabled Determines whether or not this module is executed and if its data displayed onscreen. @@ -175,10 +279,21 @@ Key: j Action: Select the next item in the list. Displays all Jira issues assigned to you for the specified project. Source Code wtf/jira/ Required ENV Variables Key: WTF_JIRA_API_KEY Value: Your Jira API key. Keyboard Commands None. -Configuration jira:colors:rows:even:&#34;lightblue&#34;odd:&#34;white&#34;domain:&#34;https://umbrellacorp.atlassian.net&#34;email:&#34;chriscummer@me.com&#34;enabled:truejql:&#34;issueType = Story&#34;position:top:4left:1height:1width:2project:&#34;JIRA&#34;refreshInterval:900username:&#34;chris.cummer&#34; Attributes colors.rows.even Define the foreground color for even-numbered rows. Values: Any X11 color name. -colors.rows.odd Define the foreground color for odd-numbered rows. Values: Any X11 color name. -domain Your Jira corporate domain. Values: A valid URI. -email The email address associated with your Jira account. +Configuration Single Jira Project jira:colors:rows:even:&#34;lightblue&#34;odd:&#34;white&#34;domain:&#34;https://umbrellacorp.atlassian.net&#34;email:&#34;chriscummer@me.com&#34;enabled:truejql:&#34;issueType = Story&#34;position:top:4left:1height:1width:2project:&#34;ProjectA&#34;refreshInterval:900username:&#34;chris.cummer&#34;verifyServerCertificate:true Multiple Jira Projects If you want to monitor multiple Jira projects, use the following configuration (note the difference in project): +jira:colors:rows:even:&#34;lightblue&#34;odd:&#34;white&#34;domain:&#34;https://umbrellacorp.atlassian.net&#34;email:&#34;chriscummer@me.com&#34;enabled:truejql:&#34;issueType = Story&#34;position:top:4left:1height:1width:2project:[&#34;ProjectA&#34;,&#34;ProjectB&#34;]refreshInterval:900username:&#34;chris.cummer&#34;verifyServerCertificate:true Attributes colors.rows.even Define the foreground color for even-numbered rows. Values: Any X11 color name. + + + + Trello + https://wtfutil.com/posts/modules/trello/ + Thu, 10 May 2018 10:44:35 -0700 + + https://wtfutil.com/posts/modules/trello/ + Displays all Trello cards on specified lists. +Source Code wtf/trello/ Required ENV Variables Key: WTF_TRELLO_APP_KEY Value: Your Trello App Key. Key: WTF_TRELLO_ACCESS_TOKEN Value: Your Trello Access Token. You can get your API key at: trello.com/app-key. +Keyboard Commands None. +Configuration Single Trello List trello:board:Mainenabled:truelist:&#34;Todo&#34;position:height:1left:2top:0width:1refreshInterval:3600username:myname Multiple Trello Lists If you want to monitor multiple Trello lists, use the following configuration (note the difference in list): +trello:board:Mainenabled:truelist:[&#34;Todo&#34;,&#34;Done&#34;]position:height:1left:2top:0width:1refreshInterval:3600username:myname Attributes board The name of the Trello board. @@ -189,24 +304,24 @@ email The email address associated with your Jira account. https://wtfutil.com/posts/modules/gcal/ Displays your upcoming Google calendar events. Not: Setting up access to Google Calendars for Go is a bit unobvious. Check out Google&rsquo;s Go Quickstart first and if you have problems, then take a look at this comment by WesleydeSouza which offers a slightly different approach. -Source Code wtf/gcal/ Required ENV Variables Key: WTF_GOOGLE_CAL_CLIENT_ID Value: Your Google API client ID. -Key: WTF_GOOGLE_CAL_CLIENT_SECRET Value: Your Google API client secret. -Keyboard Commands None. +Source Code wtf/gcal/ Required ENV Variables None. +Keyboard Commands None. +Configuration gcal:colors:title:&#34;red&#34;description:&#34;lightblue&#34;highlights:-[&#39;1on1|1\/11&#39;,&#39;green&#39;]-[&#39;apple|google|aws&#39;,&#39;blue&#39;]-[&#39;interview|meet&#39;,&#39;magenta&#39;]-[&#39;lunch&#39;,&#39;yellow&#39;]past:&#34;gray&#34;conflictIcon:&#34;🚨&#34;currentIcon:&#34;💥&#34;displayResponseStatus:trueemail:&#34;chriscummer@me.com&#34;enabled:trueeventCount:12multiCalendar:trueposition:top:0left:0height:4width:1refreshInterval:300secretFile:&#34;~/.config/wtf/gcal/client_secret.json&#34;withLocation:true Attributes colors.title The default colour for calendar event titles. Values: Any X11 color name. - Github + GitHub https://wtfutil.com/posts/modules/github/ Wed, 09 May 2018 19:20:20 -0700 https://wtfutil.com/posts/modules/github/ - Displays information about git repositories hosted on Github: open review requests, and open pull requests. + Displays information about your git repositories hosted on Github: Open Review Requests All open code review requests assigned to you. Open Pull Requests All open pull requests created by you. -Source Code wtf/github/ Required ENV Variables Key: WTF_GITHUB_TOKEN Action: Your Github API token. -Keyboard Commands Key: / Action: Open/close the widget&rsquo;s help window. -Key: h Action: Show the previous git repository. -Key: l Action: Show the next git repository. +Source Code wtf/github/ Github Required ENV Variables Key: WTF_GITHUB_TOKEN Action: Your Github API token. +GitHub Enterprise Required ENV Variables Key: WTF_GITHUB_TOKEN Action: Your Github API token. +Key: WTF_GITHUB_BASE_URL Action: Your Github Enterprise API URL. +Key: WTF_GITHUB_UPLOAD_URL Action: Your Github Enterprise upload URL (often the same as API URL). @@ -347,8 +462,8 @@ Widgets are defined by a required widget.go file in a Module. Sun, 15 Apr 2018 21:17:16 -0700 https://wtfutil.com/posts/configuration/ - Index Configuration Files Environment (ENV) Variables Grid Layout Configuration Files By default WTF looks in a ~/.wtf/ directory for a YAML file called config.yml. If the ~/.wtf/ directory doesn&rsquo;t exist, WTF will create that directory on start-up, and then display instructions for creating a new configuration file. -In other words, WTF expects to have a YAML config file at: ~/.wtf/config.yml. + Index Configuration Files Environment (ENV) Variables Grid Layout Configuration Files By default WTF looks in a ~/.config/wtf/ directory for a YAML file called config.yml. If the ~/.config/wtf/ directory doesn&rsquo;t exist, WTF will create that directory on start-up, and then display instructions for creating a new configuration file. +In other words, WTF expects to have a YAML config file at: ~/.config/wtf/config.yml. Example Configuration Files A couple of example config files are provided in the _sample_configs/ directory of the Git repository. diff --git a/docs/posts/installation/index.html b/docs/posts/installation/index.html index 238d98ad..8f9e574e 100644 --- a/docs/posts/installation/index.html +++ b/docs/posts/installation/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/bamboohr/index.html b/docs/posts/modules/bamboohr/index.html index 1cb3123d..fa4ad8dd 100644 --- a/docs/posts/modules/bamboohr/index.html +++ b/docs/posts/modules/bamboohr/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/circleci/index.html b/docs/posts/modules/circleci/index.html new file mode 100644 index 00000000..fc921b7d --- /dev/null +++ b/docs/posts/modules/circleci/index.html @@ -0,0 +1,187 @@ + + + + + + + + + + + + +CircleCI | WTF - A Terminal Dashboard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

CircleCI

+ +
+ +
+ + + +

Added in v0.0.7.

+ +

Displays build information for your CircleCI account.

+ +

circleci screenshot

+ +

Source Code

+
wtf/circleci/
+

Required ENV Variables

+ +

Key: WTF_CIRCLE_API_KEY
+Value: Your CircleCI API +token.

+ +

Keyboard Commands

+ +

None.

+ +

Configuration

+
circleci:
+  enabled: true
+  position:
+    top: 4
+    left: 1
+    height: 1
+    width: 2
+  refreshInterval: 900
+

Attributes

+ +

enabled
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: true, false.

+ +

position
+Defines where in the grid this module’s widget will be displayed.

+ +

refreshInterval
+How often, in seconds, this module will update its data.
+Values: A positive integer, 0..n.

+ +
+ + +
+ + + + diff --git a/docs/posts/modules/clocks/index.html b/docs/posts/modules/clocks/index.html index fb3630f9..fc7444cf 100644 --- a/docs/posts/modules/clocks/index.html +++ b/docs/posts/modules/clocks/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/cmdrunner/index.html b/docs/posts/modules/cmdrunner/index.html index 8f6b99f8..f73e20a6 100644 --- a/docs/posts/modules/cmdrunner/index.html +++ b/docs/posts/modules/cmdrunner/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/cryptocurrencies/bittrex/index.html b/docs/posts/modules/cryptocurrencies/bittrex/index.html index 805d53b8..d9ad0f03 100644 --- a/docs/posts/modules/cryptocurrencies/bittrex/index.html +++ b/docs/posts/modules/cryptocurrencies/bittrex/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/cryptocurrencies/blockfolio/index.html b/docs/posts/modules/cryptocurrencies/blockfolio/index.html new file mode 100644 index 00000000..fe130623 --- /dev/null +++ b/docs/posts/modules/cryptocurrencies/blockfolio/index.html @@ -0,0 +1,209 @@ + + + + + + + + + + + + +Blockfolio | WTF - A Terminal Dashboard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Blockfolio

+ +
+ +
+ + + +

Added in v0.0.8.

+ +

Display your Blockfolio crypto holdings.

+ +

blockfolio screenshot

+ +

Source

+
wtf/blockfolio/
+

Required ENV Variables

+ +

None.

+ +

Keyboard Commands

+ +

None.

+ +

Configuration

+
blockfolio:
+  colors:
+    name: blue
+    grows: green
+    drop: red
+  device_token: "device token"
+  displayHoldings: true
+  enabled: true
+  position:
+    top: 3
+    left: 1
+    width: 1
+    height: 1
+  refreshInterval: 400
+

Attributes

+ +

colors.name
+Values: Any X11 +color name.

+ +

colors.grows
+Values: Any X11 +color name.

+ +

colors.drop
+Values: Any X11 +color name.

+ +

device_token
+Value: See this gist for +details on how to get your Blockfolio API token.

+ +

displayHoldings

+ +

enabled
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: true, false.

+ +

position
+Defines where in the grid this module’s widget will be displayed.

+ +

refreshInterval
+How often, in seconds, this module will update its data.
+Values: A positive integer, 0..n.

+ +
+ + +
+ + + + diff --git a/docs/posts/modules/cryptocurrencies/cryptolive/index.html b/docs/posts/modules/cryptocurrencies/cryptolive/index.html index 42fa4754..6e5ea50c 100644 --- a/docs/posts/modules/cryptocurrencies/cryptolive/index.html +++ b/docs/posts/modules/cryptocurrencies/cryptolive/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/gcal/index.html b/docs/posts/modules/gcal/index.html index 1d4575fa..89c2960a 100644 --- a/docs/posts/modules/gcal/index.html +++ b/docs/posts/modules/gcal/index.html @@ -37,8 +37,20 @@ + + + + + + +

Attributes

@@ -210,6 +227,11 @@ Values: true, false.

The number of calendar events to display.
Values: A positive integer, 0..n.

+

multiCalendar
+Whether or not to display your primary calendar or all calendars you +have access to.
+Values: true, or false

+

position
Where in the grid this module’s widget will be displayed.

@@ -230,6 +252,6 @@ Values: A string representing a file path to the JSON secret file.

- + diff --git a/docs/posts/modules/git/index.html b/docs/posts/modules/git/index.html index 1af425bb..914e1135 100644 --- a/docs/posts/modules/git/index.html +++ b/docs/posts/modules/git/index.html @@ -37,8 +37,20 @@ + + + + + + +
- + diff --git a/docs/posts/modules/security/index.html b/docs/posts/modules/security/index.html index 0351ea96..844eeab0 100644 --- a/docs/posts/modules/security/index.html +++ b/docs/posts/modules/security/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/textfile/index.html b/docs/posts/modules/textfile/index.html index 8090c985..1575885c 100644 --- a/docs/posts/modules/textfile/index.html +++ b/docs/posts/modules/textfile/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/todo/index.html b/docs/posts/modules/todo/index.html index d482f903..e60fc6c9 100644 --- a/docs/posts/modules/todo/index.html +++ b/docs/posts/modules/todo/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/modules/trello/index.html b/docs/posts/modules/trello/index.html new file mode 100644 index 00000000..e72ba604 --- /dev/null +++ b/docs/posts/modules/trello/index.html @@ -0,0 +1,217 @@ + + + + + + + + + + + + +Trello | WTF - A Terminal Dashboard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Trello

+ +
+ +
+ + + +

Displays all Trello cards on specified lists.

+ +

trello screenshot

+ +

Source Code

+
wtf/trello/
+

Required ENV Variables

+ +

Key: WTF_TRELLO_APP_KEY
+Value: Your Trello App Key.
+Key: WTF_TRELLO_ACCESS_TOKEN
+Value: Your Trello Access Token.

+ +

You can get your API key at: trello.com/app-key.

+ +

Keyboard Commands

+ +

None.

+ +

Configuration

+ +

Single Trello List

+
trello: 
+  board: Main
+  enabled: true
+  list: "Todo"
+  position: 
+    height: 1
+    left: 2
+    top: 0
+    width: 1
+  refreshInterval: 3600
+  username: myname
+

Multiple Trello Lists

+ +

If you want to monitor multiple Trello lists, use the following +configuration (note the difference in list):

+
trello: 
+  board: Main
+  enabled: true
+  list: ["Todo", "Done"]
+  position: 
+    height: 1
+    left: 2
+    top: 0
+    width: 1
+  refreshInterval: 3600
+  username: myname
+

Attributes

+ +

board
+The name of the Trello board.

+ +

enabled
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: true, false.

+ +

list
+The Trello lists to fetch cards from.

+ +

refreshInterval
+How often, in seconds, this module will update its data.
+Values: A positive integer, 0..n.

+ +

username
+Your Trello username.

+ +

position
+Where in the grid this module’s widget will be displayed.

+ +
+ + +
+ + + + diff --git a/docs/posts/modules/weather/index.html b/docs/posts/modules/weather/index.html index 1d10909c..c7daf446 100644 --- a/docs/posts/modules/weather/index.html +++ b/docs/posts/modules/weather/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/posts/overview/index.html b/docs/posts/overview/index.html index c11d60d5..cf0b869e 100644 --- a/docs/posts/overview/index.html +++ b/docs/posts/overview/index.html @@ -37,8 +37,20 @@ + + + + + + + - + diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 64670468..26ce6ad7 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -2,6 +2,41 @@ + + https://wtfutil.com/posts/modules/logger/ + 2018-06-16T14:22:18-07:00 + + + + https://wtfutil.com/posts/modules/cryptocurrencies/blockfolio/ + 2018-06-13T09:29:59-07:00 + + + + https://wtfutil.com/posts/modules/ipapi/ + 2018-06-10T19:41:52-04:00 + + + + https://wtfutil.com/posts/modules/circleci/ + 2018-06-10T19:26:08-04:00 + + + + https://wtfutil.com/posts/modules/gspreadsheet/ + 2018-06-10T18:26:26-04:00 + + + + https://wtfutil.com/posts/modules/jenkins/ + 2018-06-09T20:53:35-07:00 + + + + https://wtfutil.com/posts/modules/gitlab/ + 2018-06-08T13:14:11-07:00 + + https://wtfutil.com/posts/modules/cryptocurrencies/bittrex/ 2018-06-04T20:06:40-07:00 @@ -62,6 +97,11 @@ 2018-05-10T10:44:35-07:00 + + https://wtfutil.com/posts/modules/trello/ + 2018-05-10T10:44:35-07:00 + + https://wtfutil.com/posts/modules/gcal/ 2018-05-10T08:25:33-07:00 @@ -134,7 +174,7 @@ https://wtfutil.com/posts/ - 2018-06-04T20:06:40-07:00 + 2018-06-16T14:22:18-07:00 0 @@ -145,7 +185,7 @@ https://wtfutil.com/ - 2018-06-04T20:06:40-07:00 + 2018-06-16T14:22:18-07:00 0 diff --git a/docs/tags/index.html b/docs/tags/index.html index 29257804..cf7e7563 100644 --- a/docs/tags/index.html +++ b/docs/tags/index.html @@ -39,8 +39,20 @@ + + + + + + + - + diff --git a/flags/flags.go b/flags/flags.go new file mode 100644 index 00000000..62c86aed --- /dev/null +++ b/flags/flags.go @@ -0,0 +1,73 @@ +package flags + +import ( + "fmt" + "os" + "path/filepath" + + goFlags "github.com/jessevdk/go-flags" + "github.com/senorprogrammer/wtf/help" + "github.com/senorprogrammer/wtf/wtf" +) + +type Flags struct { + Config string `short:"c" long:"config" optional:"yes" description:"Path to config file"` + Module string `short:"m" long:"module" optional:"yes" description:"Display info about a specific module, i.e.: 'wtf -m=todo'"` + Version bool `short:"v" long:"version" description:"Show version info"` +} + +func NewFlags() *Flags { + flags := Flags{} + return &flags +} + +/* -------------------- Exported Functions -------------------- */ + +func (flags *Flags) ConfigFilePath() string { + return flags.Config +} + +func (flags *Flags) Display(version string) { + if flags.HasModule() { + help.Display(flags.Module) + os.Exit(0) + } + + if flags.HasVersion() { + fmt.Println(version) + os.Exit(0) + } +} + +func (flags *Flags) HasConfig() bool { + return len(flags.Config) > 0 +} + +func (flags *Flags) HasModule() bool { + return len(flags.Module) > 0 +} + +func (flags *Flags) HasVersion() bool { + return flags.Version == true +} + +func (flags *Flags) Parse() { + parser := goFlags.NewParser(flags, goFlags.Default) + if _, err := parser.Parse(); err != nil { + if flagsErr, ok := err.(*goFlags.Error); ok && flagsErr.Type == goFlags.ErrHelp { + os.Exit(0) + } + } + + // If no config file is explicitly passed in as a param, + // set the flag to the default config file + if !flags.HasConfig() { + homeDir, err := wtf.Home() + if err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } + + flags.Config = filepath.Join(homeDir, ".config", "wtf", "config.yml") + } +} diff --git a/gcal/client.go b/gcal/client.go index de655620..4f100090 100644 --- a/gcal/client.go +++ b/gcal/client.go @@ -16,6 +16,7 @@ import ( "os" "os/user" "path/filepath" + "sort" "time" "github.com/senorprogrammer/wtf/wtf" @@ -29,7 +30,7 @@ import ( func Fetch() (*calendar.Events, error) { ctx := context.Background() - secretPath, _ := wtf.ExpandHomeDir(Config.UString("wtf.mods.gcal.secretFile")) + secretPath, _ := wtf.ExpandHomeDir(wtf.Config.UString("wtf.mods.gcal.secretFile")) b, err := ioutil.ReadFile(secretPath) if err != nil { @@ -47,14 +48,40 @@ func Fetch() (*calendar.Events, error) { return nil, err } + calendarIds, err := getCalendarIdList(srv) + + // Get calendar events + var events calendar.Events + startTime := fromMidnight().Format(time.RFC3339) - eventLimit := int64(Config.UInt("wtf.mods.gcal.eventCount", 10)) - events, err := srv.Events.List("primary").ShowDeleted(false).SingleEvents(true).TimeMin(startTime).MaxResults(eventLimit).OrderBy("startTime").Do() + eventLimit := int64(wtf.Config.UInt("wtf.mods.gcal.eventCount", 10)) + + for _, calendarId := range calendarIds { + calendarEvents, err := srv.Events.List(calendarId).ShowDeleted(false).TimeMin(startTime).MaxResults(eventLimit).SingleEvents(true).OrderBy("startTime").Do() + if err != nil { + break + } + events.Items = append(events.Items, calendarEvents.Items...) + } if err != nil { return nil, err } - return events, err + // Sort events + timeDateChooser := func(event *calendar.Event) (time.Time, error) { + if len(event.Start.Date) > 0 { + return time.Parse("2006-01-02", event.Start.Date) + } else { + return time.Parse(time.RFC3339, event.Start.DateTime) + } + } + sort.Slice(events.Items, func(i, j int) bool { + dateA, _ := timeDateChooser(events.Items[i]) + dateB, _ := timeDateChooser(events.Items[j]) + return dateA.Before(dateB) + }) + + return &events, err } /* -------------------- Unexported Functions -------------------- */ @@ -136,3 +163,33 @@ func saveToken(file string, token *oauth2.Token) { json.NewEncoder(f).Encode(token) } + +func getCalendarIdList(srv *calendar.Service) ([]string, error) { + // Return single calendar if settings specify we should + if !wtf.Config.UBool("wtf.mods.gcal.multiCalendar", false) { + id, err := srv.CalendarList.Get("primary").Do() + if err != nil { + return nil, err + } + return []string{id.Id}, nil + } + + // Get all user calendars with at the least writing access + var calendarIds []string + var pageToken string + for { + calendarList, err := srv.CalendarList.List().ShowHidden(false).MinAccessRole("writer").PageToken(pageToken).Do() + if err != nil { + return nil, err + } + for _, calendarListItem := range calendarList.Items { + calendarIds = append(calendarIds, calendarListItem.Id) + } + + pageToken = calendarList.NextPageToken + if pageToken == "" { + break + } + } + return calendarIds, nil +} diff --git a/gcal/widget.go b/gcal/widget.go index 3b343627..edca17a6 100644 --- a/gcal/widget.go +++ b/gcal/widget.go @@ -4,44 +4,60 @@ import ( "fmt" "regexp" "strings" + "sync" "time" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" "google.golang.org/api/calendar/v3" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget + + events *calendar.Events + ch chan struct{} + mutex sync.Mutex } func NewWidget() *Widget { widget := Widget{ TextWidget: wtf.NewTextWidget(" Calendar ", "gcal", false), + ch: make(chan struct{}), } + go updateLoop(&widget) + return &widget } /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - events, _ := Fetch() + widget.events = events widget.UpdateRefreshedAt() - widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(events))) + widget.display() +} + +func (widget *Widget) Disable() { + close(widget.ch) + widget.TextWidget.Disable() } /* -------------------- Unexported Functions -------------------- */ +func (widget *Widget) display() { + if widget.events == nil || len(widget.events.Items) == 0 { + return + } + + widget.mutex.Lock() + defer widget.mutex.Unlock() + widget.View.SetText(widget.contentFrom(widget.events)) +} + // conflicts returns TRUE if this event conflicts with another, FALSE if it does not func (widget *Widget) conflicts(event *calendar.Event, events *calendar.Events) bool { conflict := false @@ -109,10 +125,10 @@ func (widget *Widget) dayDivider(event, prevEvent *calendar.Event) string { } func (widget *Widget) descriptionColor(event *calendar.Event) string { - color := Config.UString("wtf.mods.gcal.colors.description", "white") + color := wtf.Config.UString("wtf.mods.gcal.colors.description", "white") if widget.eventIsPast(event) { - color = Config.UString("wtf.mods.gcal.colors.past", "gray") + color = wtf.Config.UString("wtf.mods.gcal.colors.past", "gray") } return color @@ -124,21 +140,26 @@ func (widget *Widget) eventSummary(event *calendar.Event, conflict bool) string if widget.eventIsNow(event) { summary = fmt.Sprintf( "%s %s", - Config.UString("wtf.mods.gcal.currentIcon", "🔸"), + wtf.Config.UString("wtf.mods.gcal.currentIcon", "🔸"), event.Summary, ) } if conflict { - return fmt.Sprintf("%s %s", Config.UString("wtf.mods.gcal.conflictIcon", "🚨"), summary) + return fmt.Sprintf("%s %s", wtf.Config.UString("wtf.mods.gcal.conflictIcon", "🚨"), summary) } else { return summary } } func (widget *Widget) eventTimestamp(event *calendar.Event) string { - startTime, _ := time.Parse(time.RFC3339, event.Start.DateTime) - return startTime.Format(wtf.FriendlyDateTimeFormat) + if len(event.Start.Date) > 0 { + startTime, _ := time.Parse("2006-01-02", event.Start.Date) + return startTime.Format(wtf.FriendlyDateFormat) + } else { + startTime, _ := time.Parse(time.RFC3339, event.Start.DateTime) + return startTime.Format(wtf.FriendlyDateTimeFormat) + } } // eventIsNow returns true if the event is happening now, false if it not @@ -155,9 +176,9 @@ func (widget *Widget) eventIsPast(event *calendar.Event) bool { } func (widget *Widget) titleColor(event *calendar.Event) string { - color := Config.UString("wtf.mods.gcal.colors.title", "white") + color := wtf.Config.UString("wtf.mods.gcal.colors.title", "white") - for _, untypedArr := range Config.UList("wtf.mods.gcal.colors.highlights") { + for _, untypedArr := range wtf.Config.UList("wtf.mods.gcal.colors.highlights") { highlightElements := wtf.ToStrs(untypedArr.([]interface{})) match, _ := regexp.MatchString( @@ -171,14 +192,14 @@ func (widget *Widget) titleColor(event *calendar.Event) string { } if widget.eventIsPast(event) { - color = Config.UString("wtf.mods.gcal.colors.past", "gray") + color = wtf.Config.UString("wtf.mods.gcal.colors.past", "gray") } return color } func (widget *Widget) location(event *calendar.Event) string { - if Config.UBool("wtf.mods.gcal.displayLocation", true) == false { + if wtf.Config.UBool("wtf.mods.gcal.displayLocation", true) == false { return "" } @@ -194,14 +215,14 @@ func (widget *Widget) location(event *calendar.Event) string { } func (widget *Widget) responseIcon(event *calendar.Event) string { - if false == Config.UBool("wtf.mods.gcal.displayResponseStatus", true) { + if false == wtf.Config.UBool("wtf.mods.gcal.displayResponseStatus", true) { return "" } response := "" for _, attendee := range event.Attendees { - if attendee.Email == Config.UString("wtf.mods.gcal.email") { + if attendee.Email == wtf.Config.UString("wtf.mods.gcal.email") { response = attendee.ResponseStatus break } @@ -257,3 +278,22 @@ func (widget *Widget) until(event *calendar.Event) string { return "[lightblue]" + untilStr + "[white]" } + +func updateLoop(widget *Widget) { + interval := wtf.Config.UInt("wtf.mods.gcal.textInterval", 30) + if interval == 0 { + return + } + + tick := time.NewTicker(time.Duration(interval) * time.Second) + defer tick.Stop() +outer: + for { + select { + case <-tick.C: + widget.display() + case <-widget.ch: + break outer + } + } +} diff --git a/git/display.go b/git/display.go index 8140615b..33842728 100644 --- a/git/display.go +++ b/git/display.go @@ -9,10 +9,9 @@ import ( ) func (widget *Widget) display() { - repoData := widget.currentData() if repoData == nil { - fmt.Fprintf(widget.View, "%s", " Git repo data is unavailable (1)") + widget.View.SetText(" Git repo data is unavailable ") return } @@ -27,7 +26,7 @@ func (widget *Widget) display() { str = str + "\n" str = str + widget.formatCommits(repoData.Commits) - widget.View.SetText(fmt.Sprintf("%s", str)) + widget.View.SetText(str) } func (widget *Widget) formatChanges(data []string) string { diff --git a/git/git_repo.go b/git/git_repo.go index 3f657732..aed7b59e 100644 --- a/git/git_repo.go +++ b/git/git_repo.go @@ -22,7 +22,7 @@ func NewGitRepo(repoPath string) *GitRepo { repo.Branch = repo.branch() repo.ChangedFiles = repo.changedFiles() repo.Commits = repo.commits() - repo.Repository = repo.repository() + repo.Repository = strings.TrimSpace(repo.repository()) return &repo } @@ -50,9 +50,15 @@ func (repo *GitRepo) changedFiles() []string { } func (repo *GitRepo) commits() []string { - numStr := fmt.Sprintf("-n %d", Config.UInt("wtf.mods.git.commitCount", 10)) + numStr := fmt.Sprintf("-n %d", wtf.Config.UInt("wtf.mods.git.commitCount", 10)) - arg := []string{repo.gitDir(), repo.workTree(), "log", "--date=format:\"%b %d, %Y\"", numStr, "--pretty=format:\"[forestgreen]%h [white]%s [grey]%an on %cd[white]\""} + dateFormat := wtf.Config.UString("wtf.mods.git.dateFormat", "%b %d, %Y") + dateStr := fmt.Sprintf("--date=format:\"%s\"", dateFormat) + + commitFormat := wtf.Config.UString("wtf.mods.git.commitFormat", "[forestgreen]%h [white]%s [grey]%an on %cd[white]") + commitStr := fmt.Sprintf("--pretty=format:\"%s\"", commitFormat) + + arg := []string{repo.gitDir(), repo.workTree(), "log", dateStr, numStr, commitStr} cmd := exec.Command("git", arg...) str := wtf.ExecuteCommand(cmd) diff --git a/git/widget.go b/git/widget.go index 850d3bfd..12a82e1d 100644 --- a/git/widget.go +++ b/git/widget.go @@ -2,14 +2,10 @@ package git import ( "github.com/gdamore/tcell" - "github.com/olebedev/config" "github.com/rivo/tview" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - const HelpText = ` Keyboard commands for Git: @@ -23,6 +19,10 @@ const HelpText = ` arrow right: Next git repository ` +const offscreen = -1000 +const modalWidth = 80 +const modalHeight = 7 + type Widget struct { wtf.TextWidget @@ -49,11 +49,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - - repoPaths := wtf.ToStrs(Config.UList("wtf.mods.git.repositories")) + repoPaths := wtf.ToStrs(wtf.Config.UList("wtf.mods.git.repositories")) widget.UpdateRefreshedAt() widget.Data = widget.gitRepos(repoPaths) @@ -135,11 +131,18 @@ func (widget *Widget) modalForm(lbl, text string) *tview.Form { return form } func (widget *Widget) modalFrame(form *tview.Form) *tview.Frame { - _, _, w, h := widget.View.GetInnerRect() - frame := tview.NewFrame(form).SetBorders(0, 0, 0, 0, 0, 0) + frame.SetRect(offscreen, offscreen, modalWidth, modalHeight) frame.SetBorder(true) - frame.SetRect(w+20, h+2, 80, 7) + frame.SetBorders(1, 1, 0, 0, 1, 1) + + drawFunc := func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) { + w, h := screen.Size() + frame.SetRect((w/2)-(width/2), (h/2)-(height/2), width, height) + return x, y, width, height + } + + frame.SetDrawFunc(drawFunc) return frame } diff --git a/github/display.go b/github/display.go index e9346367..2fa4528e 100644 --- a/github/display.go +++ b/github/display.go @@ -7,10 +7,9 @@ import ( ) func (widget *Widget) display() { - repo := widget.currentGithubRepo() if repo == nil { - fmt.Fprintf(widget.View, "%s", " Github repo data is unavailable (1)") + widget.View.SetText(" GitHub repo data is unavailable ") return } @@ -21,10 +20,10 @@ func (widget *Widget) display() { str = str + widget.displayStats(repo) str = str + "\n" str = str + " [red]Open Review Requests[white]\n" - str = str + widget.displayMyReviewRequests(repo, Config.UString("wtf.mods.github.username")) + str = str + widget.displayMyReviewRequests(repo, wtf.Config.UString("wtf.mods.github.username")) str = str + "\n" str = str + " [red]My Pull Requests[white]\n" - str = str + widget.displayMyPullRequests(repo, Config.UString("wtf.mods.github.username")) + str = str + widget.displayMyPullRequests(repo, wtf.Config.UString("wtf.mods.github.username")) widget.View.SetText(str) } diff --git a/github/github_repo.go b/github/github_repo.go index 7ced9123..af2db77e 100644 --- a/github/github_repo.go +++ b/github/github_repo.go @@ -10,7 +10,9 @@ import ( ) type GithubRepo struct { - apiKey string + apiKey string + baseURL string + uploadURL string Name string Owner string @@ -20,9 +22,12 @@ type GithubRepo struct { func NewGithubRepo(name, owner string) *GithubRepo { repo := GithubRepo{ - apiKey: os.Getenv("WTF_GITHUB_TOKEN"), - Name: name, - Owner: owner, + apiKey: os.Getenv("WTF_GITHUB_TOKEN"), + baseURL: os.Getenv("WTF_GITHUB_BASE_URL"), + uploadURL: os.Getenv("WTF_GITHUB_UPLOAD_URL"), + + Name: name, + Owner: owner, } return &repo @@ -58,6 +63,16 @@ func (repo *GithubRepo) StarCount() int { /* -------------------- Unexported Functions -------------------- */ +func (repo *GithubRepo) isGitHubEnterprise() bool { + if len(repo.baseURL) > 0 { + if len(repo.uploadURL) == 0 { + repo.uploadURL = repo.baseURL + } + return true + } + return false +} + func (repo *GithubRepo) oauthClient() *http.Client { tokenService := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: repo.apiKey}, @@ -66,6 +81,16 @@ func (repo *GithubRepo) oauthClient() *http.Client { return oauth2.NewClient(context.Background(), tokenService) } +func (repo *GithubRepo) githubClient() (*ghb.Client, error) { + oauthClient := repo.oauthClient() + + if repo.isGitHubEnterprise() { + return ghb.NewEnterpriseClient(repo.baseURL, repo.uploadURL, oauthClient) + } + + return ghb.NewClient(oauthClient), nil +} + // myPullRequests returns a list of pull requests created by username on this repo func (repo *GithubRepo) myPullRequests(username string) []*ghb.PullRequest { prs := []*ghb.PullRequest{} @@ -98,8 +123,11 @@ func (repo *GithubRepo) myReviewRequests(username string) []*ghb.PullRequest { } func (repo *GithubRepo) loadPullRequests() ([]*ghb.PullRequest, error) { - oauthClient := repo.oauthClient() - github := ghb.NewClient(oauthClient) + github, err := repo.githubClient() + + if err != nil { + return nil, err + } opts := &ghb.PullRequestListOptions{} @@ -113,8 +141,11 @@ func (repo *GithubRepo) loadPullRequests() ([]*ghb.PullRequest, error) { } func (repo *GithubRepo) loadRemoteRepository() (*ghb.Repository, error) { - oauthClient := repo.oauthClient() - github := ghb.NewClient(oauthClient) + github, err := repo.githubClient() + + if err != nil { + return nil, err + } repository, _, err := github.Repositories.Get(context.Background(), repo.Owner, repo.Name) diff --git a/github/widget.go b/github/widget.go index ad186310..c86917cb 100644 --- a/github/widget.go +++ b/github/widget.go @@ -2,14 +2,10 @@ package github import ( "github.com/gdamore/tcell" - "github.com/olebedev/config" "github.com/rivo/tview" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - const HelpText = ` Keyboard commands for Github: @@ -41,7 +37,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { pages: pages, } - widget.GithubRepos = widget.buildRepoCollection(Config.UMap("wtf.mods.github.repositories")) + widget.GithubRepos = widget.buildRepoCollection(wtf.Config.UMap("wtf.mods.github.repositories")) widget.View.SetInputCapture(widget.keyboardIntercept) @@ -51,10 +47,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - for _, repo := range widget.GithubRepos { repo.Refresh() } diff --git a/gitlab/display.go b/gitlab/display.go new file mode 100644 index 00000000..4b268044 --- /dev/null +++ b/gitlab/display.go @@ -0,0 +1,75 @@ +package gitlab + +import ( + "fmt" + + "github.com/senorprogrammer/wtf/wtf" +) + +func (widget *Widget) display() { + + project := widget.currentGitlabProject() + if project == nil { + widget.View.SetText(" Gitlab project data is unavailable ") + return + } + + widget.View.SetTitle(fmt.Sprintf("%s- %s", widget.Name, widget.title(project))) + + str := wtf.SigilStr(len(widget.GitlabProjects), widget.Idx, widget.View) + "\n" + str = str + " [red]Stats[white]\n" + str = str + widget.displayStats(project) + str = str + "\n" + str = str + " [red]Open Approval Requests[white]\n" + str = str + widget.displayMyApprovalRequests(project, wtf.Config.UString("wtf.mods.gitlab.username")) + str = str + "\n" + str = str + " [red]My Merge Requests[white]\n" + str = str + widget.displayMyMergeRequests(project, wtf.Config.UString("wtf.mods.gitlab.username")) + + widget.View.SetText(str) +} + +func (widget *Widget) displayMyMergeRequests(project *GitlabProject, username string) string { + mrs := project.myMergeRequests(username) + + if len(mrs) == 0 { + return " [grey]none[white]\n" + } + + str := "" + for _, mr := range mrs { + str = str + fmt.Sprintf(" [green]%4d[white] %s\n", mr.IID, mr.Title) + } + + return str +} + +func (widget *Widget) displayMyApprovalRequests(project *GitlabProject, username string) string { + mrs := project.myApprovalRequests(username) + + if len(mrs) == 0 { + return " [grey]none[white]\n" + } + + str := "" + for _, mr := range mrs { + str = str + fmt.Sprintf(" [green]%4d[white] %s\n", mr.IID, mr.Title) + } + + return str +} + +func (widget *Widget) displayStats(project *GitlabProject) string { + str := fmt.Sprintf( + " MRs: %d Issues: %d Stars: %d\n", + project.MergeRequestCount(), + project.IssueCount(), + project.StarCount(), + ) + + return str +} + +func (widget *Widget) title(project *GitlabProject) string { + return fmt.Sprintf("[green]%s [white]", project.Path) +} diff --git a/gitlab/gitlab_repo.go b/gitlab/gitlab_repo.go new file mode 100644 index 00000000..1af7e00c --- /dev/null +++ b/gitlab/gitlab_repo.go @@ -0,0 +1,113 @@ +package gitlab + +import ( + glb "github.com/xanzy/go-gitlab" +) + +type GitlabProject struct { + gitlab *glb.Client + Path string + + MergeRequests []*glb.MergeRequest + RemoteProject *glb.Project +} + +func NewGitlabProject(name string, namespace string, gitlab *glb.Client) *GitlabProject { + path := namespace + "/" + name + project := GitlabProject{ + gitlab: gitlab, + Path: path, + } + + return &project +} + +// Refresh reloads the gitlab data via the Gitlab API +func (project *GitlabProject) Refresh() { + project.MergeRequests, _ = project.loadMergeRequests() + project.RemoteProject, _ = project.loadRemoteProject() +} + +/* -------------------- Counts -------------------- */ + +func (project *GitlabProject) IssueCount() int { + if project.RemoteProject == nil { + return 0 + } + + return project.RemoteProject.OpenIssuesCount +} + +func (project *GitlabProject) MergeRequestCount() int { + return len(project.MergeRequests) +} + +func (project *GitlabProject) StarCount() int { + if project.RemoteProject == nil { + return 0 + } + + return project.RemoteProject.StarCount +} + +/* -------------------- Unexported Functions -------------------- */ + +// myMergeRequests returns a list of merge requests created by username on this project +func (project *GitlabProject) myMergeRequests(username string) []*glb.MergeRequest { + mrs := []*glb.MergeRequest{} + + for _, mr := range project.MergeRequests { + user := mr.Author + + if user.Username == username { + mrs = append(mrs, mr) + } + } + + return mrs +} + +// myApprovalRequests returns a list of merge requests for which username has been +// requested to approve +func (project *GitlabProject) myApprovalRequests(username string) []*glb.MergeRequest { + mrs := []*glb.MergeRequest{} + + for _, mr := range project.MergeRequests { + approvers, _, err := project.gitlab.MergeRequests.GetMergeRequestApprovals(project.Path, mr.IID) + if err != nil { + continue + } + for _, approver := range approvers.Approvers { + if approver.User.Username == username { + mrs = append(mrs, mr) + } + } + } + + return mrs +} + +func (project *GitlabProject) loadMergeRequests() ([]*glb.MergeRequest, error) { + state := "opened" + opts := glb.ListProjectMergeRequestsOptions{ + State: &state, + } + + mrs, _, err := project.gitlab.MergeRequests.ListProjectMergeRequests(project.Path, &opts) + + if err != nil { + return nil, err + } + + return mrs, nil +} + +func (project *GitlabProject) loadRemoteProject() (*glb.Project, error) { + projectsitory, _, err := project.gitlab.Projects.GetProject(project.Path) + + if err != nil { + return nil, err + } + + return projectsitory, nil +} diff --git a/gitlab/widget.go b/gitlab/widget.go new file mode 100644 index 00000000..c7c3f96f --- /dev/null +++ b/gitlab/widget.go @@ -0,0 +1,154 @@ +package gitlab + +import ( + "os" + + "github.com/gdamore/tcell" + "github.com/rivo/tview" + "github.com/senorprogrammer/wtf/wtf" + glb "github.com/xanzy/go-gitlab" +) + +const HelpText = ` + Keyboard commands for Gitlab: + + /: Show/hide this help window + h: Previous project + l: Next project + r: Refresh the data + + arrow left: Previous project + arrow right: Next project +` + +type Widget struct { + wtf.TextWidget + + app *tview.Application + pages *tview.Pages + + gitlab *glb.Client + + GitlabProjects []*GitlabProject + Idx int +} + +func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { + apiKey := os.Getenv("WTF_GITLAB_TOKEN") + baseURL := wtf.Config.UString("wtf.mods.gitlab.domain") + gitlab := glb.NewClient(nil, apiKey) + if baseURL != "" { + gitlab.SetBaseURL(baseURL) + } + + widget := Widget{ + TextWidget: wtf.NewTextWidget(" Gitlab ", "gitlab", true), + + app: app, + pages: pages, + + gitlab: gitlab, + + Idx: 0, + } + + widget.GitlabProjects = widget.buildProjectCollection(wtf.Config.UMap("wtf.mods.gitlab.projects")) + + widget.View.SetInputCapture(widget.keyboardIntercept) + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + for _, project := range widget.GitlabProjects { + project.Refresh() + } + + widget.UpdateRefreshedAt() + widget.display() +} + +func (widget *Widget) Next() { + widget.Idx = widget.Idx + 1 + if widget.Idx == len(widget.GitlabProjects) { + widget.Idx = 0 + } + + widget.display() +} + +func (widget *Widget) Prev() { + widget.Idx = widget.Idx - 1 + if widget.Idx < 0 { + widget.Idx = len(widget.GitlabProjects) - 1 + } + + widget.display() +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) buildProjectCollection(projectData map[string]interface{}) []*GitlabProject { + gitlabProjects := []*GitlabProject{} + + for name, namespace := range projectData { + project := NewGitlabProject(name, namespace.(string), widget.gitlab) + gitlabProjects = append(gitlabProjects, project) + } + + return gitlabProjects +} + +func (widget *Widget) currentGitlabProject() *GitlabProject { + if len(widget.GitlabProjects) == 0 { + return nil + } + + if widget.Idx < 0 || widget.Idx >= len(widget.GitlabProjects) { + return nil + } + + return widget.GitlabProjects[widget.Idx] +} + +func (widget *Widget) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey { + switch string(event.Rune()) { + case "/": + widget.showHelp() + return nil + case "h": + widget.Prev() + return nil + case "l": + widget.Next() + return nil + case "r": + widget.Refresh() + return nil + } + + switch event.Key() { + case tcell.KeyLeft: + widget.Prev() + return nil + case tcell.KeyRight: + widget.Next() + return nil + default: + return event + } +} + +func (widget *Widget) showHelp() { + closeFunc := func() { + widget.pages.RemovePage("help") + widget.app.SetFocus(widget.View) + } + + modal := wtf.NewBillboardModal(HelpText, closeFunc) + + widget.pages.AddPage("help", modal, false, true) + widget.app.SetFocus(modal) +} diff --git a/gspreadsheets/client.go b/gspreadsheets/client.go new file mode 100644 index 00000000..4b0b31a6 --- /dev/null +++ b/gspreadsheets/client.go @@ -0,0 +1,145 @@ +/* +* This butt-ugly code is direct from Google itself +* https://developers.google.com/sheets/api/quickstart/go + */ + +package gspreadsheets + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "net/url" + "os" + "os/user" + "path/filepath" + "strings" + + "github.com/senorprogrammer/wtf/wtf" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + sheets "google.golang.org/api/sheets/v4" +) + +/* -------------------- Exported Functions -------------------- */ + +func Fetch() ([]*sheets.ValueRange, error) { + ctx := context.Background() + + secretPath, _ := wtf.ExpandHomeDir(wtf.Config.UString("wtf.mods.gspreadsheets.secretFile")) + + b, err := ioutil.ReadFile(secretPath) + if err != nil { + log.Fatalf("Unable to read secretPath. %v", err) + return nil, err + } + + config, err := google.ConfigFromJSON(b, "https://www.googleapis.com/auth/spreadsheets.readonly") + + if err != nil { + log.Fatalf("Unable to get config from JSON. %v", err) + return nil, err + } + client := getClient(ctx, config) + + srv, err := sheets.New(client) + if err != nil { + log.Fatalf("Unable to get create server. %v", err) + return nil, err + } + + cells := wtf.ToStrs(wtf.Config.UList("wtf.mods.gspreadsheets.cells.addresses")) + documentId := wtf.Config.UString("wtf.mods.gspreadsheets.sheetId") + addresses := strings.Join(cells[:], ";") + + responses := make([]*sheets.ValueRange, len(cells)) + + for i := 0; i < len(cells); i++ { + resp, err := srv.Spreadsheets.Values.Get(documentId, cells[i]).Do() + if err != nil { + log.Fatalf("Error fetching cells %s", addresses) + return nil, err + } + responses[i] = resp + } + + return responses, err +} + +/* -------------------- Unexported Functions -------------------- */ + +// getClient uses a Context and Config to retrieve a Token +// then generate a Client. It returns the generated Client. +func getClient(ctx context.Context, config *oauth2.Config) *http.Client { + cacheFile, err := tokenCacheFile() + if err != nil { + log.Fatalf("Unable to get path to cached credential file. %v", err) + } + tok, err := tokenFromFile(cacheFile) + if err != nil { + tok = getTokenFromWeb(config) + saveToken(cacheFile, tok) + } + return config.Client(ctx, tok) +} + +// getTokenFromWeb uses Config to request a Token. +// It returns the retrieved Token. +func getTokenFromWeb(config *oauth2.Config) *oauth2.Token { + authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) + fmt.Printf("Go to the following link in your browser then type the "+ + "authorization code: \n%v\n", authURL) + + var code string + if _, err := fmt.Scan(&code); err != nil { + log.Fatalf("Unable to read authorization code %v", err) + } + + tok, err := config.Exchange(oauth2.NoContext, code) + if err != nil { + log.Fatalf("Unable to retrieve token from web %v", err) + } + return tok +} + +// tokenCacheFile generates credential file path/filename. +// It returns the generated credential path/filename. +func tokenCacheFile() (string, error) { + usr, err := user.Current() + if err != nil { + return "", err + } + tokenCacheDir := filepath.Join(usr.HomeDir, ".credentials") + os.MkdirAll(tokenCacheDir, 0700) + return filepath.Join(tokenCacheDir, + url.QueryEscape("spreadsheets-go-quickstart.json")), err +} + +// tokenFromFile retrieves a Token from a given file path. +// It returns the retrieved Token and any read error encountered. +func tokenFromFile(file string) (*oauth2.Token, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + t := &oauth2.Token{} + err = json.NewDecoder(f).Decode(t) + defer f.Close() + return t, err +} + +// saveToken uses a file path to create a file and store the +// token in it. +func saveToken(file string, token *oauth2.Token) { + fmt.Printf("Saving credential file to: %s\n", file) + f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + log.Fatalf("Unable to cache oauth token: %v", err) + } + defer f.Close() + + json.NewEncoder(f).Encode(token) +} diff --git a/gspreadsheets/widget.go b/gspreadsheets/widget.go new file mode 100644 index 00000000..ddd246d9 --- /dev/null +++ b/gspreadsheets/widget.go @@ -0,0 +1,48 @@ +package gspreadsheets + +import ( + "fmt" + + "github.com/senorprogrammer/wtf/wtf" + sheets "google.golang.org/api/sheets/v4" +) + +type Widget struct { + wtf.TextWidget +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" Google Spreadsheets ", "gspreadsheets", false), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + cells, _ := Fetch() + + widget.UpdateRefreshedAt() + + widget.View.SetText(widget.contentFrom(cells)) +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(valueRanges []*sheets.ValueRange) string { + if valueRanges == nil { + return "error 1" + } + + valuesColor := wtf.Config.UString("wtf.mods.gspreadsheets.colors.values", "green") + res := "" + + cells := wtf.ToStrs(wtf.Config.UList("wtf.mods.gspreadsheets.cells.names")) + for i := 0; i < len(valueRanges); i++ { + res = res + fmt.Sprintf("%s\t[%s]%s\n", cells[i], valuesColor, valueRanges[i].Values[0][0]) + } + + return res +} diff --git a/help/help.go b/help/help.go index cf79c930..b77035ea 100644 --- a/help/help.go +++ b/help/help.go @@ -2,23 +2,20 @@ package help import ( "fmt" - "os" "github.com/senorprogrammer/wtf/git" "github.com/senorprogrammer/wtf/github" "github.com/senorprogrammer/wtf/textfile" "github.com/senorprogrammer/wtf/todo" - "github.com/senorprogrammer/wtf/weather" + "github.com/senorprogrammer/wtf/weatherservices/weather" ) -func DisplayModuleInfo(moduleName string) { - if moduleName != "" { - fmt.Printf("%s\n", helpFor(moduleName)) - } else { +func Display(moduleName string) { + if moduleName == "" { fmt.Println("\n --module takes a module name as an argument, i.e: '--module=github'") + } else { + fmt.Printf("%s\n", helpFor(moduleName)) } - - os.Exit(0) } func helpFor(moduleName string) string { diff --git a/ipaddresses/ipapi/widget.go b/ipaddresses/ipapi/widget.go new file mode 100644 index 00000000..42730662 --- /dev/null +++ b/ipaddresses/ipapi/widget.go @@ -0,0 +1,127 @@ +package ipapi + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + "text/template" + + "bytes" + + "github.com/senorprogrammer/wtf/wtf" +) + +// Widget widget struct +type Widget struct { + wtf.TextWidget + result string + colors struct { + name, value string + } +} + +type ipinfo struct { + Query string `json:"query"` + ISP string `json:"isp"` + AS string `json:"as"` + City string `json:"city"` + Region string `json:"region"` + Country string `json:"country"` + CountryCode string `json:"countryCode"` + Latitude float64 `json:"lat"` + Longitude float64 `json:"lon"` + PostalCode string `json:"zip"` + Organization string `json:"org"` + Timezone string `json:"timezone"` +} + +// NewWidget constructor +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" IPInfo ", "ipapi", false), + } + + widget.View.SetWrap(false) + + widget.config() + + return &widget +} + +// Refresh refresh the module +func (widget *Widget) Refresh() { + widget.UpdateRefreshedAt() + widget.ipinfo() + widget.View.SetText(widget.result) +} + +//this method reads the config and calls ipinfo for ip information +func (widget *Widget) ipinfo() { + client := &http.Client{} + req, err := http.NewRequest("GET", "http://ip-api.com/json", nil) + if err != nil { + widget.result = err.Error() + return + } + req.Header.Set("User-Agent", "curl") + response, err := client.Do(req) + if err != nil { + widget.result = err.Error() + return + } + defer response.Body.Close() + var info ipinfo + err = json.NewDecoder(response.Body).Decode(&info) + if err != nil { + widget.result = err.Error() + return + } + + widget.setResult(&info) +} + +// read module configs +func (widget *Widget) config() { + nameColor, valueColor := wtf.Config.UString("wtf.mods.ipinfo.colors.name", "red"), wtf.Config.UString("wtf.mods.ipinfo.colors.value", "white") + widget.colors.name = nameColor + widget.colors.value = valueColor +} + +func (widget *Widget) setResult(info *ipinfo) { + resultTemplate, _ := template.New("ipinfo_result").Parse( + formatableText("IP Address", "Ip") + + formatableText("ISP", "ISP") + + formatableText("AS", "AS") + + formatableText("City", "City") + + formatableText("Region", "Region") + + formatableText("Country", "Country") + + formatableText("Coordinates", "Coordinates") + + formatableText("Postal Code", "PostalCode") + + formatableText("Organization", "Organization") + + formatableText("Timezone", "Timezone"), + ) + + resultBuffer := new(bytes.Buffer) + + resultTemplate.Execute(resultBuffer, map[string]string{ + "nameColor": widget.colors.name, + "valueColor": widget.colors.value, + "Ip": info.Query, + "ISP": info.ISP, + "AS": info.AS, + "City": info.City, + "Region": info.Region, + "Country": info.Country, + "Coordinates": strconv.FormatFloat(info.Latitude, 'f', 6, 64) + "," + strconv.FormatFloat(info.Longitude, 'f', 6, 64), + "PostalCode": info.PostalCode, + "Organization": info.Organization, + "Timezone": info.Timezone, + }) + + widget.result = resultBuffer.String() +} + +func formatableText(key, value string) string { + return fmt.Sprintf(" [{{.nameColor}}]%s: [{{.valueColor}}]{{.%s}}\n", key, value) +} diff --git a/ipinfo/widget.go b/ipaddresses/ipinfo/widget.go similarity index 83% rename from ipinfo/widget.go rename to ipaddresses/ipinfo/widget.go index 95257c45..031dc032 100644 --- a/ipinfo/widget.go +++ b/ipaddresses/ipinfo/widget.go @@ -8,13 +8,9 @@ import ( "bytes" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget result string @@ -47,10 +43,6 @@ func NewWidget() *Widget { } func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - widget.UpdateRefreshedAt() widget.ipinfo() widget.View.Clear() @@ -63,24 +55,21 @@ func (widget *Widget) ipinfo() { client := &http.Client{} req, err := http.NewRequest("GET", "https://ipinfo.io/", nil) if err != nil { - widget.result = fmt.Sprintf("%s", err.Error()) + widget.result = err.Error() return } req.Header.Set("User-Agent", "curl") response, err := client.Do(req) if err != nil { - widget.result = fmt.Sprintf("%s", err.Error()) + widget.result = err.Error() return } defer response.Body.Close() - if err != nil { - widget.result = fmt.Sprintf("%s", err.Error()) - return - } + var info ipinfo err = json.NewDecoder(response.Body).Decode(&info) if err != nil { - widget.result = fmt.Sprintf("%s", err.Error()) + widget.result = err.Error() return } @@ -89,7 +78,7 @@ func (widget *Widget) ipinfo() { // read module configs func (widget *Widget) config() { - nameColor, valueColor := Config.UString("wtf.mods.ipinfo.colors.name", "red"), Config.UString("wtf.mods.ipinfo.colors.value", "white") + nameColor, valueColor := wtf.Config.UString("wtf.mods.ipinfo.colors.name", "red"), wtf.Config.UString("wtf.mods.ipinfo.colors.value", "white") widget.colors.name = nameColor widget.colors.value = valueColor } diff --git a/jenkins/client.go b/jenkins/client.go new file mode 100644 index 00000000..e599b9f7 --- /dev/null +++ b/jenkins/client.go @@ -0,0 +1,64 @@ +package jenkins + +import ( + "bytes" + "encoding/json" + "io" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + +func Create(jenkinsURL string, username string, apiKey string) (*View, error) { + const apiSuffix = "api/json?pretty=true" + parsedSuffix, err := url.Parse(apiSuffix) + if err != nil { + return &View{}, err + } + + parsedJenkinsURL, err := url.Parse(ensureLastSlash(jenkinsURL)) + if err != nil { + return &View{}, err + } + jenkinsAPIURL := parsedJenkinsURL.ResolveReference(parsedSuffix) + + req, err := http.NewRequest("GET", jenkinsAPIURL.String(), nil) + req.SetBasicAuth(username, apiKey) + + httpClient := &http.Client{} + resp, err := httpClient.Do(req) + + if err != nil { + return &View{}, err + } + + view := &View{} + parseJson(view, resp.Body) + + return view, nil +} + +func ensureLastSlash(URL string) string { + return strings.TrimRight(URL, "/") + "/" +} + +/* -------------------- Unexported Functions -------------------- */ + + +func parseJson(obj interface{}, text io.Reader) { + jsonStream, err := ioutil.ReadAll(text) + if err != nil { + panic(err) + } + + decoder := json.NewDecoder(bytes.NewReader(jsonStream)) + + for { + if err := decoder.Decode(obj); err == io.EOF { + break + } else if err != nil { + panic(err) + } + } +} diff --git a/jenkins/job.go b/jenkins/job.go new file mode 100644 index 00000000..e360e0f6 --- /dev/null +++ b/jenkins/job.go @@ -0,0 +1,8 @@ +package jenkins + +type Job struct { + Class string `json:"_class"` + Name string `json:"name"` + Url string `json:"url"` + Color string `json:"color"` +} diff --git a/jenkins/view.go b/jenkins/view.go new file mode 100644 index 00000000..03a7f6ed --- /dev/null +++ b/jenkins/view.go @@ -0,0 +1,10 @@ +package jenkins + +type View struct { + Class string `json:"_class"` + Description string `json:"description"` + Jobs []Job `json:"jobs"` + Name string `json:"name"` + Property []string `json:"property"` + url string `json:"url"` +} diff --git a/jenkins/widget.go b/jenkins/widget.go new file mode 100644 index 00000000..262da966 --- /dev/null +++ b/jenkins/widget.go @@ -0,0 +1,76 @@ +package jenkins + +import ( + "fmt" + "github.com/senorprogrammer/wtf/wtf" + "os" +) + +type Widget struct { + wtf.TextWidget +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget("Jenkins", "jenkins", false), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + if widget.Disabled() { + return + } + + view, err := Create( + wtf.Config.UString("wtf.mods.jenkins.url"), + wtf.Config.UString("wtf.mods.jenkins.user"), + os.Getenv("WTF_JENKINS_API_KEY"), + ) + + widget.UpdateRefreshedAt() + //widget.View.Clear() + + var content string + if err != nil { + widget.View.SetWrap(true) + widget.View.SetTitle(fmt.Sprintf(" %s ", widget.Name)) + content = err.Error() + } else { + widget.View.SetWrap(false) + widget.View.SetTitle(fmt.Sprintf(" %s: [green] ", widget.Name)) + content = widget.contentFrom(view) + } + + widget.View.SetText(content) +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(view *View) string { + str := fmt.Sprintf(" [red]%s[white]\n", view.Name) + + for _, job := range view.Jobs { + str = str + fmt.Sprintf( + " [%s]%-6s[white]\n", + widget.jobColor(&job), + job.Name, + ) + } + + return str +} + +func (widget *Widget) jobColor(job *Job) string { + switch job.Color { + case "blue": + return "blue" + case "red": + return "red" + default: + return "white" + } +} diff --git a/jira/client.go b/jira/client.go index b7903018..b28ec616 100644 --- a/jira/client.go +++ b/jira/client.go @@ -2,6 +2,7 @@ package jira import ( "bytes" + "crypto/tls" "encoding/json" "fmt" "io" @@ -10,13 +11,16 @@ import ( "net/url" "os" "strings" + + "github.com/senorprogrammer/wtf/wtf" ) -func IssuesFor(username string, project string, jql string) (*SearchResult, error) { +func IssuesFor(username string, projects []string, jql string) (*SearchResult, error) { query := []string{} - if project != "" { - query = append(query, buildJql("project", project)) + var projQuery = getProjectQuery(projects) + if projQuery != "" { + query = append(query, projQuery) } if username != "" { @@ -51,15 +55,21 @@ func buildJql(key string, value string) string { /* -------------------- Unexported Functions -------------------- */ func jiraRequest(path string) (*http.Response, error) { - url := fmt.Sprintf("%s%s", Config.UString("wtf.mods.jira.domain"), path) + url := fmt.Sprintf("%s%s", wtf.Config.UString("wtf.mods.jira.domain"), path) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } - req.SetBasicAuth(Config.UString("wtf.mods.jira.email"), os.Getenv("WTF_JIRA_API_KEY")) + req.SetBasicAuth(wtf.Config.UString("wtf.mods.jira.email"), os.Getenv("WTF_JIRA_API_KEY")) - httpClient := &http.Client{} + verifyServerCertificate := wtf.Config.UBool("wtf.mods.jira.verifyServerCertificate", true) + httpClient := &http.Client{Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: !verifyServerCertificate, + }, + }, + } resp, err := httpClient.Do(req) if err != nil { return nil, err @@ -88,3 +98,18 @@ func parseJson(obj interface{}, text io.Reader) { } } } + +func getProjectQuery(projects []string) string { + singleEmptyProject := len(projects) == 1 && len(projects[0]) == 0 + if len(projects) == 0 || singleEmptyProject { + return "" + } else if len(projects) == 1 { + return buildJql("project", projects[0]) + } + + quoted := make([]string, len(projects)) + for i := range projects { + quoted[i] = fmt.Sprintf("\"%s\"", projects[i]) + } + return fmt.Sprintf("project in (%s)", strings.Join(quoted, ", ")) +} diff --git a/jira/issues.go b/jira/issues.go index ecaceb92..a8ad546f 100644 --- a/jira/issues.go +++ b/jira/issues.go @@ -1,8 +1,5 @@ package jira -import ( -) - type Issue struct { Expand string `json:"expand"` ID string `json:"id"` diff --git a/jira/search_result.go b/jira/search_result.go index 66a3f1a8..7febef6d 100644 --- a/jira/search_result.go +++ b/jira/search_result.go @@ -1,7 +1,5 @@ package jira -import () - type SearchResult struct { StartAt int `json:"startAt"` MaxResults int `json:"maxResults"` diff --git a/jira/widget.go b/jira/widget.go index d9fe19f1..9ca26540 100644 --- a/jira/widget.go +++ b/jira/widget.go @@ -3,13 +3,9 @@ package jira import ( "fmt" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget } @@ -25,29 +21,32 @@ func NewWidget() *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - - searchResult, err := IssuesFor(Config.UString("wtf.mods.jira.username"), Config.UString("wtf.mods.jira.project", ""), Config.UString("wtf.mods.jira.jql", "")) + searchResult, err := IssuesFor( + wtf.Config.UString("wtf.mods.jira.username"), + getProjects(), + wtf.Config.UString("wtf.mods.jira.jql", ""), + ) widget.UpdateRefreshedAt() + var content string if err != nil { widget.View.SetWrap(true) - widget.View.SetTitle(fmt.Sprintf("%s", widget.Name)) - fmt.Fprintf(widget.View, "%v", err) + widget.View.SetTitle(widget.Name) + content = err.Error() } else { widget.View.SetWrap(false) widget.View.SetTitle( fmt.Sprintf( "%s- [green]%s[white]", widget.Name, - Config.UString("wtf.mods.jira.project"), + wtf.Config.UString("wtf.mods.jira.project"), ), ) - widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(searchResult))) + content = widget.contentFrom(searchResult) } + + widget.View.SetText(content) } /* -------------------- Unexported Functions -------------------- */ @@ -70,18 +69,32 @@ func (widget *Widget) contentFrom(searchResult *SearchResult) string { } func (widget *Widget) issueTypeColor(issue *Issue) string { - var color string - switch issue.IssueFields.IssueType.Name { case "Bug": - color = "red" + return "red" case "Story": - color = "blue" + return "blue" case "Task": - color = "orange" + return "orange" default: - color = "white" + return "white" } - - return color +} + +func getProjects() []string { + // see if project is set to a single string + configPath := "wtf.mods.jira.project" + singleProject, err := wtf.Config.String(configPath) + if err == nil { + return []string{singleProject} + } + // else, assume list + projList := wtf.Config.UList(configPath) + var ret []string + for _, proj := range projList { + if str, ok := proj.(string); ok { + ret = append(ret, str) + } + } + return ret } diff --git a/logger/log.go b/logger/log.go new file mode 100644 index 00000000..69b5fceb --- /dev/null +++ b/logger/log.go @@ -0,0 +1,130 @@ +package logger + +import ( + "fmt" + //"io/ioutil" + "log" + "os" + "path/filepath" + "strings" + + "github.com/senorprogrammer/wtf/wtf" +) + +const maxBufferSize int64 = 1024 + +type Widget struct { + wtf.TextWidget + + filePath string +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" Logs ", "logger", true), + + filePath: logFilePath(), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func Log(msg string) { + if logFileMissing() { + return + } + + f, err := os.OpenFile(logFilePath(), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + log.Fatalf("error opening file: %v", err) + } + defer f.Close() + + log.SetOutput(f) + log.Println(msg) +} + +func (widget *Widget) Refresh() { + if logFileMissing() { + return + } + + widget.UpdateRefreshedAt() + widget.View.SetTitle(widget.Name) + + logLines := widget.tailFile() + widget.View.SetText(widget.contentFrom(logLines)) +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(logLines []string) string { + str := "" + + for _, line := range logLines { + chunks := strings.Split(line, " ") + + if len(chunks) >= 4 { + str = str + fmt.Sprintf( + "[green]%s[white] [yellow]%s[white] %s\n", + chunks[0], + chunks[1], + strings.Join(chunks[3:], " "), + ) + } + } + + return str +} + +func logFileMissing() bool { + return logFilePath() == "" +} + +func logFilePath() string { + dir, err := wtf.Home() + if err != nil { + return "" + } + + return filepath.Join(dir, ".config", "wtf", "log.txt") +} + +func (widget *Widget) tailFile() []string { + file, err := os.Open(widget.filePath) + if err != nil { + return []string{} + } + defer file.Close() + + stat, err := file.Stat() + if err != nil { + return []string{} + } + + bufferSize := maxBufferSize + if maxBufferSize > stat.Size() { + bufferSize = stat.Size() + } + + startPos := stat.Size() - bufferSize + + buff := make([]byte, bufferSize) + _, err = file.ReadAt(buff, startPos) + if err != nil { + return []string{} + } + + logLines := strings.Split(string(buff), "\n") + + // Reverse the array of lines + // Offset by two to account for the blank line at the end + last := len(logLines) - 2 + for i := 0; i < len(logLines)/2; i++ { + logLines[i], logLines[last-i] = logLines[last-i], logLines[i] + } + + return logLines +} diff --git a/newrelic/client.go b/newrelic/client.go index c5d3f9a9..f88d4e3e 100644 --- a/newrelic/client.go +++ b/newrelic/client.go @@ -3,13 +3,14 @@ package newrelic import ( "os" + "github.com/senorprogrammer/wtf/wtf" nr "github.com/yfronto/newrelic" ) func Application() (*nr.Application, error) { client := nr.NewClient(os.Getenv("WTF_NEW_RELIC_API_KEY")) - application, err := client.GetApplication(Config.UInt("wtf.mods.newrelic.applicationId")) + application, err := client.GetApplication(wtf.Config.UInt("wtf.mods.newrelic.applicationId")) if err != nil { return nil, err } @@ -21,7 +22,7 @@ func Deployments() ([]nr.ApplicationDeployment, error) { client := nr.NewClient(os.Getenv("WTF_NEW_RELIC_API_KEY")) opts := &nr.ApplicationDeploymentOptions{Page: 1} - deployments, err := client.GetApplicationDeployments(Config.UInt("wtf.mods.newrelic.applicationId"), opts) + deployments, err := client.GetApplicationDeployments(wtf.Config.UInt("wtf.mods.newrelic.applicationId"), opts) if err != nil { return nil, err } diff --git a/newrelic/widget.go b/newrelic/widget.go index 2831ea08..2ab2928a 100644 --- a/newrelic/widget.go +++ b/newrelic/widget.go @@ -3,14 +3,10 @@ package newrelic import ( "fmt" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" nr "github.com/yfronto/newrelic" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget } @@ -26,10 +22,6 @@ func NewWidget() *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - app, appErr := Application() deploys, depErr := Deployments() @@ -42,13 +34,16 @@ func (widget *Widget) Refresh() { widget.View.SetTitle(fmt.Sprintf("%s- [green]%s[white]", widget.Name, appName)) widget.View.Clear() + var content string if depErr != nil { widget.View.SetWrap(true) - widget.View.SetText(fmt.Sprintf("%s", depErr)) + content = depErr.Error() } else { widget.View.SetWrap(false) - widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(deploys))) + content = widget.contentFrom(deploys) } + + widget.View.SetText(content) } /* -------------------- Unexported Functions -------------------- */ @@ -68,7 +63,7 @@ func (widget *Widget) contentFrom(deploys []nr.ApplicationDeployment) string { lineColor = "lightblue" } - var revLen = 8 + revLen := 8 if revLen > len(deploy.Revision) { revLen = len(deploy.Revision) } @@ -83,7 +78,7 @@ func (widget *Widget) contentFrom(deploys []nr.ApplicationDeployment) string { revisions = append(revisions, deploy.Revision) - if len(revisions) == Config.UInt("wtf.mods.newrelic.deployCount", 5) { + if len(revisions) == wtf.Config.UInt("wtf.mods.newrelic.deployCount", 5) { break } } diff --git a/opsgenie/widget.go b/opsgenie/widget.go index bf72c006..7ca23621 100644 --- a/opsgenie/widget.go +++ b/opsgenie/widget.go @@ -4,13 +4,9 @@ import ( "fmt" "strings" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget } @@ -26,22 +22,21 @@ func NewWidget() *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - data, err := Fetch() widget.UpdateRefreshedAt() widget.View.SetTitle(widget.Name) + var content string if err != nil { widget.View.SetWrap(true) - widget.View.SetText(fmt.Sprintf("%s", err)) + content = err.Error() } else { widget.View.SetWrap(false) - widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(data))) + content = widget.contentFrom(data) } + + widget.View.SetText(content) } /* -------------------- Unexported Functions -------------------- */ @@ -49,7 +44,7 @@ func (widget *Widget) Refresh() { func (widget *Widget) contentFrom(onCallResponse *OnCallResponse) string { str := "" - displayEmpty := Config.UBool("wtf.mods.opsgenie.displayEmpty", true) + displayEmpty := wtf.Config.UBool("wtf.mods.opsgenie.displayEmpty", true) for _, data := range onCallResponse.OnCallData { if (len(data.Recipients) == 0) && (displayEmpty == false) { diff --git a/power/battery.go b/power/battery.go index c837b7f8..08b7fdfe 100644 --- a/power/battery.go +++ b/power/battery.go @@ -1,3 +1,5 @@ +// +build !linux + package power import ( diff --git a/power/battery_linux.go b/power/battery_linux.go new file mode 100644 index 00000000..693d95b6 --- /dev/null +++ b/power/battery_linux.go @@ -0,0 +1,112 @@ +// +build linux + +package power + +import ( + "fmt" + "os/exec" + "strconv" + "strings" + + "github.com/senorprogrammer/wtf/wtf" +) + +var batteryState string + +type Battery struct { + args []string + cmd string + result string + + Charge string + Remaining string +} + +func NewBattery() *Battery { + return &Battery{} +} + +/* -------------------- Exported Functions -------------------- */ + +func (battery *Battery) Refresh() { + data := battery.execute() + battery.result = battery.parse(data) +} + +func (battery *Battery) String() string { + return battery.result +} + +/* -------------------- Unexported Functions -------------------- */ + +func (battery *Battery) execute() string { + cmd := exec.Command("upower", "-e") + lines := strings.Split(wtf.ExecuteCommand(cmd), "\n") + var target string + for _, l := range lines { + if strings.Contains(l, "/battery") { + target = l + break + } + } + cmd = exec.Command("upower", "-i", target) + return wtf.ExecuteCommand(cmd) +} + +func (battery *Battery) parse(data string) string { + lines := strings.Split(data, "\n") + if len(lines) < 2 { + return "unknown" + } + table := make(map[string]string) + for _, line := range lines { + parts := strings.Split(line, ":") + if len(parts) < 2 { + continue + } + table[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) + } + if s := table["time to empty"]; s == "" { + table["time to empty"] = "∞" + } + str := "" + str = str + fmt.Sprintf(" %10s: %s\n", "Charge", battery.formatCharge(table["percentage"])) + str = str + fmt.Sprintf(" %10s: %s\n", "Remaining", table["time to empty"]) + str = str + fmt.Sprintf(" %10s: %s\n", "State", battery.formatState(table["state"])) + if s := table["time to full"]; s != "" { + str = str + fmt.Sprintf(" %10s: %s\n", "TimeToFull", table["time to full"]) + } + batteryState = table["state"] + return str +} + +func (battery *Battery) formatCharge(data string) string { + percent, _ := strconv.ParseFloat(strings.Replace(data, "%", "", -1), 32) + color := "" + + switch { + case percent >= 70: + color = "[green]" + case percent >= 35: + color = "[yellow]" + default: + color = "[red]" + } + + return color + data + "[white]" +} + +func (battery *Battery) formatState(data string) string { + color := "" + + switch data { + case "charging": + color = "[green]" + case "discharging": + color = "[yellow]" + default: + color = "[white]" + } + + return color + data + "[white]" +} diff --git a/power/source.go b/power/source.go index b5f0faff..e6eff36c 100644 --- a/power/source.go +++ b/power/source.go @@ -1,3 +1,5 @@ +// +build !linux + package power import ( diff --git a/power/source_linux.go b/power/source_linux.go new file mode 100644 index 00000000..a28368c8 --- /dev/null +++ b/power/source_linux.go @@ -0,0 +1,15 @@ +// +build linux + +package power + +// powerSource returns the name of the current power source, probably one of +// "AC Power" or "Battery Power" +func powerSource() string { + switch batteryState { + case "charging", "fully-charged": + return "AC Power" + case "discharging": + return "Battery Power" + } + return batteryState +} diff --git a/power/widget.go b/power/widget.go index dc98d6ae..47e7d73c 100644 --- a/power/widget.go +++ b/power/widget.go @@ -3,13 +3,9 @@ package power import ( "fmt" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget @@ -28,17 +24,13 @@ func NewWidget() *Widget { } func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - widget.UpdateRefreshedAt() widget.Battery.Refresh() - str := "" - str = str + fmt.Sprintf(" %10s: %s\n", "Source", powerSource()) - str = str + "\n" - str = str + widget.Battery.String() + content := "" + content = content + fmt.Sprintf(" %10s: %s\n", "Source", powerSource()) + content = content + "\n" + content = content + widget.Battery.String() - widget.View.SetText(fmt.Sprintf("%s", str)) + widget.View.SetText(content) } diff --git a/security/dns.go b/security/dns.go index 2408c2c1..2064ecf7 100644 --- a/security/dns.go +++ b/security/dns.go @@ -1,3 +1,5 @@ +// +build !windows + package security import ( diff --git a/security/dns_windows.go b/security/dns_windows.go new file mode 100644 index 00000000..dae7966c --- /dev/null +++ b/security/dns_windows.go @@ -0,0 +1,14 @@ +// +build windows + +package security + +import ( + "os/exec" + + "github.com/senorprogrammer/wtf/wtf" +) + +func DnsServers() []string { + cmd := exec.Command("powershell.exe", "Get-DnsClientServerAddress | Select-Object –ExpandProperty ServerAddresses") + return []string{wtf.ExecuteCommand(cmd)} +} diff --git a/security/users.go b/security/users.go index b8fe5164..41068b3e 100644 --- a/security/users.go +++ b/security/users.go @@ -1,3 +1,5 @@ +// +build !windows + package security // http://applehelpwriter.com/2017/05/21/how-to-reveal-hidden-users/ diff --git a/security/users_windows.go b/security/users_windows.go new file mode 100644 index 00000000..38c77d9f --- /dev/null +++ b/security/users_windows.go @@ -0,0 +1,25 @@ +// +build windows + +package security + +import ( + "os/exec" + "strings" + + "github.com/senorprogrammer/wtf/wtf" +) + +func LoggedInUsers() []string { + cmd := exec.Command("powershell.exe", "(query user) -replace '\\s{2,}', ','") + users := wtf.ExecuteCommand(cmd) + return cleanUsers(strings.Split(users, "\n")[1:]) +} + +func cleanUsers(users []string) []string { + cleaned := make([]string, 0) + for _, user := range users { + usr := strings.Split(user, ",") + cleaned = append(cleaned, usr[0]) + } + return cleaned +} diff --git a/security/widget.go b/security/widget.go index a6161fd9..b95e8354 100644 --- a/security/widget.go +++ b/security/widget.go @@ -1,16 +1,14 @@ +// +build !windows + package security import ( "fmt" "strings" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget } @@ -26,16 +24,11 @@ func NewWidget() *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - data := NewSecurityData() data.Fetch() widget.UpdateRefreshedAt() - - widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(data))) + widget.View.SetText(widget.contentFrom(data)) } /* -------------------- Unexported Functions -------------------- */ diff --git a/security/widget_windows.go b/security/widget_windows.go new file mode 100644 index 00000000..c46dc6f7 --- /dev/null +++ b/security/widget_windows.go @@ -0,0 +1,53 @@ +// +build windows + +package security + +import ( + "fmt" + "strings" + + "github.com/senorprogrammer/wtf/wtf" +) + +type Widget struct { + wtf.TextWidget +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" Security ", "security", false), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + if widget.Disabled() { + return + } + + data := NewSecurityData() + data.Fetch() + + widget.UpdateRefreshedAt() + widget.View.SetText(widget.contentFrom(data)) +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(data *SecurityData) string { + str := " [red]WiFi[white]\n" + str = str + fmt.Sprintf(" %8s: %s\n", "Network", data.WifiName) + str = str + fmt.Sprintf(" %8s: %s\n", "Crypto", data.WifiEncryption) + str = str + "\n" + str = str + " [red]Firewall[white] [red]DNS[white]\n" + str = str + fmt.Sprintf(" %8s: %4s %12s\n", "Enabled", data.FirewallEnabled, data.DnsAt(0)) + str = str + fmt.Sprintf(" %8s: %4s %12s\n", "Stealth", data.FirewallStealth, data.DnsAt(1)) + str = str + "\n" + str = str + " [red]Users[white]\n" + str = str + fmt.Sprintf(" %s", strings.Join(data.LoggedInUsers, ",")) + + return str +} diff --git a/status/widget.go b/status/widget.go index 6550fe5f..9fb1191b 100644 --- a/status/widget.go +++ b/status/widget.go @@ -1,15 +1,9 @@ package status import ( - "fmt" - - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget @@ -28,24 +22,14 @@ func NewWidget() *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - widget.UpdateRefreshedAt() - - widget.View.SetText( - fmt.Sprintf( - "\n%s", - widget.animation(), - ), - ) + widget.View.SetText(widget.animation()) } /* -------------------- Unexported Functions -------------------- */ func (widget *Widget) animation() string { - icons := []string{"👍", "🤜", "🤙", "🤜", "🤘", "🤜", "✊", "🤜", "👌", "🤜"} + icons := []string{"|", "/", "-", "\\", "|"} next := icons[widget.CurrentIcon] widget.CurrentIcon = widget.CurrentIcon + 1 diff --git a/system/system_info.go b/system/system_info.go index 63fa6770..a2a26ece 100644 --- a/system/system_info.go +++ b/system/system_info.go @@ -1,3 +1,5 @@ +// +build !windows + package system import ( @@ -22,7 +24,8 @@ func NewSystemInfo() *SystemInfo { var cmd *exec.Cmd switch runtime.GOOS { case "linux": - cmd = exec.Command("uname -a", arg...) + arg = append(arg, "-a") + cmd = exec.Command("lsb_release", arg...) case "darwin": cmd = exec.Command("sw_vers", arg...) default: @@ -33,7 +36,6 @@ func NewSystemInfo() *SystemInfo { for _, row := range strings.Split(raw, "\n") { parts := strings.Split(row, ":") - if len(parts) < 2 { continue } @@ -49,12 +51,6 @@ func NewSystemInfo() *SystemInfo { ProductVersion: m["Description"], BuildVersion: m["Release"], } - case "darwin": - sysInfo = &SystemInfo{ - ProductName: m["ProductName"], - ProductVersion: m["ProductVersion"], - BuildVersion: m["BuildVersion"], - } default: sysInfo = &SystemInfo{ ProductName: m["ProductName"], diff --git a/system/system_info_windows.go b/system/system_info_windows.go new file mode 100644 index 00000000..0b10c703 --- /dev/null +++ b/system/system_info_windows.go @@ -0,0 +1,36 @@ +// +build windows + +package system + +import ( + "os/exec" + "strings" +) + +type SystemInfo struct { + ProductName string + ProductVersion string + BuildVersion string +} + +func NewSystemInfo() *SystemInfo { + m := make(map[string]string) + + cmd := exec.Command("powershell.exe", "(Get-CimInstance Win32_OperatingSystem).version") + out, err := cmd.Output() + if err != nil { + panic(err) + } + s := strings.Split(string(out), ".") + m["ProductName"] = "Windows" + m["ProductVersion"] = "Windows " + s[0] + "." + s[1] + m["BuildVersion"] = s[2] + + sysInfo := SystemInfo{ + ProductName: m["ProductName"], + ProductVersion: m["ProductVersion"], + BuildVersion: m["BuildVersion"], + } + + return &sysInfo +} diff --git a/system/widget.go b/system/widget.go index 29f9efd0..39d1853a 100644 --- a/system/widget.go +++ b/system/widget.go @@ -4,13 +4,9 @@ import ( "fmt" "time" - "github.com/olebedev/config" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - type Widget struct { wtf.TextWidget @@ -33,10 +29,6 @@ func NewWidget(date, version string) *Widget { } func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - widget.UpdateRefreshedAt() widget.View.SetText( diff --git a/textfile/widget.go b/textfile/widget.go index d581dc4f..e9147706 100644 --- a/textfile/widget.go +++ b/textfile/widget.go @@ -5,14 +5,10 @@ import ( "io/ioutil" "github.com/gdamore/tcell" - "github.com/olebedev/config" "github.com/rivo/tview" "github.com/senorprogrammer/wtf/wtf" ) -// Config is a pointer to the global config object -var Config *config.Config - const HelpText = ` Keyboard commands for Textfile: @@ -33,7 +29,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { TextWidget: wtf.NewTextWidget(" Text File ", "textfile", true), app: app, - filePath: Config.UString("wtf.mods.textfile.filePath"), + filePath: wtf.Config.UString("wtf.mods.textfile.filePath"), pages: pages, } @@ -48,10 +44,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - widget.UpdateRefreshedAt() widget.View.SetTitle(fmt.Sprintf("%s %s", widget.Name, widget.filePath)) @@ -63,9 +55,9 @@ func (widget *Widget) Refresh() { } if err != nil { - widget.View.SetText(fmt.Sprintf("%s", err)) + widget.View.SetText(err.Error()) } else { - widget.View.SetText(fmt.Sprintf("%s", string(fileData))) + widget.View.SetText(string(fileData)) } } diff --git a/todo/display.go b/todo/display.go index d25d20cb..8757bad4 100644 --- a/todo/display.go +++ b/todo/display.go @@ -29,19 +29,19 @@ func (widget *Widget) display() { widget.SetList(&newList) widget.View.Clear() - widget.View.SetText(fmt.Sprintf("%s", str)) + widget.View.SetText(str) } func (widget *Widget) formattedItemLine(item *Item, selectedItem *Item, maxLen int) string { - foreColor, backColor := "white", Config.UString("wtf.colors.background", "black") + foreColor, backColor := "white", wtf.Config.UString("wtf.colors.background", "black") if item.Checked { - foreColor = Config.UString("wtf.mods.todo.colors.checked", "white") + foreColor = wtf.Config.UString("wtf.mods.todo.colors.checked", "white") } if widget.View.HasFocus() && (item == selectedItem) { - foreColor = Config.UString("wtf.mods.todo.colors.highlight.fore", "black") - backColor = Config.UString("wtf.mods.todo.colors.highlight.back", "white") + foreColor = wtf.Config.UString("wtf.mods.todo.colors.highlight.fore", "black") + backColor = wtf.Config.UString("wtf.mods.todo.colors.highlight.back", "white") } str := fmt.Sprintf( diff --git a/todo/item.go b/todo/item.go index aa77f41e..f546b124 100644 --- a/todo/item.go +++ b/todo/item.go @@ -1,6 +1,8 @@ package todo -import () +import ( + "github.com/senorprogrammer/wtf/wtf" +) type Item struct { Checked bool @@ -9,7 +11,7 @@ type Item struct { func (item *Item) CheckMark() string { if item.Checked { - return Config.UString("wtf.mods.todo.checkedIcon", "x") + return wtf.Config.UString("wtf.mods.todo.checkedIcon", "x") } else { return " " } diff --git a/todo/widget.go b/todo/widget.go index f0b15503..6bebc605 100644 --- a/todo/widget.go +++ b/todo/widget.go @@ -5,15 +5,12 @@ import ( "io/ioutil" "github.com/gdamore/tcell" - "github.com/olebedev/config" "github.com/rivo/tview" + "github.com/senorprogrammer/wtf/cfg" "github.com/senorprogrammer/wtf/wtf" "gopkg.in/yaml.v2" ) -// Config is a pointer to the global config object -var Config *config.Config - const HelpText = ` Keyboard commands for Todo: @@ -33,6 +30,10 @@ const HelpText = ` space: Check the selected item on or off ` +const offscreen = -1000 +const modalWidth = 80 +const modalHeight = 7 + type Widget struct { wtf.TextWidget @@ -47,7 +48,7 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { TextWidget: wtf.NewTextWidget(" Todo ", "todo", true), app: app, - filePath: Config.UString("wtf.mods.todo.filename"), + filePath: wtf.Config.UString("wtf.mods.todo.filename"), list: &List{selected: -1}, pages: pages, } @@ -61,10 +62,6 @@ func NewWidget(app *tview.Application, pages *tview.Pages) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - widget.UpdateRefreshedAt() widget.load() widget.display() @@ -99,7 +96,7 @@ func (widget *Widget) editItem() { } func (widget *Widget) init() { - _, err := wtf.CreateFile(widget.filePath) + _, err := cfg.CreateFile(widget.filePath) if err != nil { panic(err) } @@ -181,7 +178,7 @@ func (widget *Widget) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey { // Loads the todo list from Yaml file func (widget *Widget) load() { - confDir, _ := wtf.ConfigDir() + confDir, _ := cfg.ConfigDir() filePath := fmt.Sprintf("%s/%s", confDir, widget.filePath) fileData, _ := wtf.ReadFileBytes(filePath) @@ -207,7 +204,7 @@ func (widget *Widget) newItem() { // persist writes the todo list to Yaml file func (widget *Widget) persist() { - confDir, _ := wtf.ConfigDir() + confDir, _ := cfg.ConfigDir() filePath := fmt.Sprintf("%s/%s", confDir, widget.filePath) fileData, _ := yaml.Marshal(&widget.list) @@ -270,11 +267,18 @@ func (widget *Widget) modalForm(lbl, text string) *tview.Form { } func (widget *Widget) modalFrame(form *tview.Form) *tview.Frame { - _, _, w, h := widget.View.GetInnerRect() - frame := tview.NewFrame(form).SetBorders(0, 0, 0, 0, 0, 0) + frame.SetRect(offscreen, offscreen, modalWidth, modalHeight) frame.SetBorder(true) - frame.SetRect(w+20, h+2, 80, 7) + frame.SetBorders(1, 1, 0, 0, 1, 1) + + drawFunc := func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) { + w, h := screen.Size() + frame.SetRect((w/2)-(width/2), (h/2)-(height/2), width, height) + return x, y, width, height + } + + frame.SetDrawFunc(drawFunc) return frame } diff --git a/trello/card.go b/trello/card.go new file mode 100644 index 00000000..e1487c94 --- /dev/null +++ b/trello/card.go @@ -0,0 +1,8 @@ +package trello + +type TrelloCard struct { + ID string + Name string + List string + Description string +} diff --git a/trello/client.go b/trello/client.go new file mode 100644 index 00000000..dcccaf55 --- /dev/null +++ b/trello/client.go @@ -0,0 +1,98 @@ +package trello + +import ( + "fmt" + + "github.com/adlio/trello" + "github.com/senorprogrammer/wtf/wtf" +) + +func GetCards(client *trello.Client, lists map[string]string) (*SearchResult, error) { + boardID, err := getBoardID(client) + if err != nil { + return nil, err + } + + lists, err = getListIDs(client, boardID, lists) + if err != nil { + return nil, err + } + + searchResult := &SearchResult{Total: 0} + searchResult.TrelloCards = make(map[string][]TrelloCard) + + for listName, listID := range lists { + cards, err := getCardsOnList(client, listID) + if err != nil { + return nil, err + } + searchResult.Total = searchResult.Total + len(cards) + cardArray := make([]TrelloCard, 0) + for _, card := range cards { + trelloCard := TrelloCard{ + ID: card.ID, + List: listName, + Name: card.Name, + Description: card.Desc, + } + cardArray = append(cardArray, trelloCard) + } + searchResult.TrelloCards[listName] = cardArray + } + + return searchResult, nil +} + +func getBoardID(client *trello.Client) (string, error) { + member, err := client.GetMember(wtf.Config.UString("wtf.mods.trello.username"), trello.Defaults()) + if err != nil { + return "", err + } + + boards, err := member.GetBoards(trello.Defaults()) + if err != nil { + return "", err + } + + for _, board := range boards { + if board.Name == wtf.Config.UString("wtf.mods.trello.board") { + return board.ID, nil + } + } + + return "", fmt.Errorf("could not find board with name %s", wtf.Config.UString("wtf.mods.trello.board")) +} + +func getListIDs(client *trello.Client, boardID string, lists map[string]string) (map[string]string, error) { + board, err := client.GetBoard(boardID, trello.Defaults()) + if err != nil { + return nil, err + } + + boardLists, err := board.GetLists(trello.Defaults()) + if err != nil { + return nil, err + } + + for _, list := range boardLists { + if _, ok := lists[list.Name]; ok { + lists[list.Name] = list.ID + } + } + + return lists, nil +} + +func getCardsOnList(client *trello.Client, listID string) ([]*trello.Card, error) { + list, err := client.GetList(listID, trello.Defaults()) + if err != nil { + return nil, err + } + + cards, err := list.GetCards(trello.Defaults()) + if err != nil { + return nil, err + } + + return cards, nil +} diff --git a/trello/search_result.go b/trello/search_result.go new file mode 100644 index 00000000..44ca8dc7 --- /dev/null +++ b/trello/search_result.go @@ -0,0 +1,6 @@ +package trello + +type SearchResult struct { + Total int + TrelloCards map[string][]TrelloCard +} diff --git a/trello/widget.go b/trello/widget.go new file mode 100644 index 00000000..068e7377 --- /dev/null +++ b/trello/widget.go @@ -0,0 +1,84 @@ +package trello + +import ( + "fmt" + "os" + + "github.com/adlio/trello" + "github.com/senorprogrammer/wtf/wtf" +) + +type Widget struct { + wtf.TextWidget +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" Trello ", "trello", false), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + client := trello.NewClient(os.Getenv("WTF_TRELLO_APP_KEY"), os.Getenv("WTF_TRELLO_ACCESS_TOKEN")) + + // Get the cards + searchResult, err := GetCards(client, getLists()) + widget.UpdateRefreshedAt() + + var content string + if err != nil { + widget.View.SetWrap(true) + widget.View.SetTitle(widget.Name) + content = err.Error() + } else { + widget.View.SetWrap(false) + widget.View.SetTitle( + fmt.Sprintf( + "[white]%s: [green]%s ", + widget.Name, + wtf.Config.UString("wtf.mods.trello.board"), + ), + ) + content = widget.contentFrom(searchResult) + } + + widget.View.SetText(content) +} + +/* -------------------- Unexported Functions -------------------- */ +func (widget *Widget) contentFrom(searchResult *SearchResult) string { + str := "" + + for list, cardArray := range searchResult.TrelloCards { + str = fmt.Sprintf("%s [red]Cards in %s[white]\n", str, list) + for _, card := range cardArray { + str = fmt.Sprintf("%s [green]%s[white]\n", str, card.Name) + } + str = fmt.Sprintf("%s\n", str) + } + + return str +} + +func getLists() map[string]string { + list := make(map[string]string) + // see if project is set to a single string + configPath := "wtf.mods.trello.list" + singleList, err := wtf.Config.String(configPath) + if err == nil { + list[singleList] = "" + return list + } + // else, assume list + multiList := wtf.Config.UList(configPath) + for _, proj := range multiList { + if str, ok := proj.(string); ok { + list[str] = "" + } + } + return list +} diff --git a/vendor/cloud.google.com/go/AUTHORS b/vendor/cloud.google.com/go/AUTHORS new file mode 100644 index 00000000..c364af1d --- /dev/null +++ b/vendor/cloud.google.com/go/AUTHORS @@ -0,0 +1,15 @@ +# This is the official list of cloud authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as: +# Name or Organization +# The email address is not required for organizations. + +Filippo Valsorda +Google Inc. +Ingo Oeser +Palm Stone Games, Inc. +Paweł Knap +Péter Szilágyi +Tyler Treat diff --git a/vendor/cloud.google.com/go/CONTRIBUTORS b/vendor/cloud.google.com/go/CONTRIBUTORS new file mode 100644 index 00000000..3b3cbed9 --- /dev/null +++ b/vendor/cloud.google.com/go/CONTRIBUTORS @@ -0,0 +1,40 @@ +# People who have agreed to one of the CLAs and can contribute patches. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# https://developers.google.com/open-source/cla/individual +# https://developers.google.com/open-source/cla/corporate +# +# Names should be added to this file as: +# Name + +# Keep the list alphabetically sorted. + +Alexis Hunt +Andreas Litt +Andrew Gerrand +Brad Fitzpatrick +Burcu Dogan +Dave Day +David Sansome +David Symonds +Filippo Valsorda +Glenn Lewis +Ingo Oeser +James Hall +Johan Euphrosine +Jonathan Amsterdam +Kunpei Sakai +Luna Duclos +Magnus Hiie +Mario Castro +Michael McGreevy +Omar Jarjur +Paweł Knap +Péter Szilágyi +Sarah Adams +Thanatat Tamtan +Toby Burress +Tuo Shan +Tyler Treat diff --git a/vendor/cloud.google.com/go/LICENSE b/vendor/cloud.google.com/go/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/vendor/cloud.google.com/go/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/cloud.google.com/go/compute/metadata/metadata.go b/vendor/cloud.google.com/go/compute/metadata/metadata.go new file mode 100644 index 00000000..e708c031 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/metadata.go @@ -0,0 +1,437 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package metadata provides access to Google Compute Engine (GCE) +// metadata and API service accounts. +// +// This package is a wrapper around the GCE metadata service, +// as documented at https://developers.google.com/compute/docs/metadata. +package metadata // import "cloud.google.com/go/compute/metadata" + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net" + "net/http" + "net/url" + "os" + "runtime" + "strings" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/context/ctxhttp" +) + +const ( + // metadataIP is the documented metadata server IP address. + metadataIP = "169.254.169.254" + + // metadataHostEnv is the environment variable specifying the + // GCE metadata hostname. If empty, the default value of + // metadataIP ("169.254.169.254") is used instead. + // This is variable name is not defined by any spec, as far as + // I know; it was made up for the Go package. + metadataHostEnv = "GCE_METADATA_HOST" + + userAgent = "gcloud-golang/0.1" +) + +type cachedValue struct { + k string + trim bool + mu sync.Mutex + v string +} + +var ( + projID = &cachedValue{k: "project/project-id", trim: true} + projNum = &cachedValue{k: "project/numeric-project-id", trim: true} + instID = &cachedValue{k: "instance/id", trim: true} +) + +var ( + metaClient = &http.Client{ + Transport: &http.Transport{ + Dial: (&net.Dialer{ + Timeout: 2 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + ResponseHeaderTimeout: 2 * time.Second, + }, + } + subscribeClient = &http.Client{ + Transport: &http.Transport{ + Dial: (&net.Dialer{ + Timeout: 2 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + }, + } +) + +// NotDefinedError is returned when requested metadata is not defined. +// +// The underlying string is the suffix after "/computeMetadata/v1/". +// +// This error is not returned if the value is defined to be the empty +// string. +type NotDefinedError string + +func (suffix NotDefinedError) Error() string { + return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix)) +} + +// Get returns a value from the metadata service. +// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/". +// +// If the GCE_METADATA_HOST environment variable is not defined, a default of +// 169.254.169.254 will be used instead. +// +// If the requested metadata is not defined, the returned error will +// be of type NotDefinedError. +func Get(suffix string) (string, error) { + val, _, err := getETag(metaClient, suffix) + return val, err +} + +// getETag returns a value from the metadata service as well as the associated +// ETag using the provided client. This func is otherwise equivalent to Get. +func getETag(client *http.Client, suffix string) (value, etag string, err error) { + // Using a fixed IP makes it very difficult to spoof the metadata service in + // a container, which is an important use-case for local testing of cloud + // deployments. To enable spoofing of the metadata service, the environment + // variable GCE_METADATA_HOST is first inspected to decide where metadata + // requests shall go. + host := os.Getenv(metadataHostEnv) + if host == "" { + // Using 169.254.169.254 instead of "metadata" here because Go + // binaries built with the "netgo" tag and without cgo won't + // know the search suffix for "metadata" is + // ".google.internal", and this IP address is documented as + // being stable anyway. + host = metadataIP + } + url := "http://" + host + "/computeMetadata/v1/" + suffix + req, _ := http.NewRequest("GET", url, nil) + req.Header.Set("Metadata-Flavor", "Google") + req.Header.Set("User-Agent", userAgent) + res, err := client.Do(req) + if err != nil { + return "", "", err + } + defer res.Body.Close() + if res.StatusCode == http.StatusNotFound { + return "", "", NotDefinedError(suffix) + } + if res.StatusCode != 200 { + return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url) + } + all, err := ioutil.ReadAll(res.Body) + if err != nil { + return "", "", err + } + return string(all), res.Header.Get("Etag"), nil +} + +func getTrimmed(suffix string) (s string, err error) { + s, err = Get(suffix) + s = strings.TrimSpace(s) + return +} + +func (c *cachedValue) get() (v string, err error) { + defer c.mu.Unlock() + c.mu.Lock() + if c.v != "" { + return c.v, nil + } + if c.trim { + v, err = getTrimmed(c.k) + } else { + v, err = Get(c.k) + } + if err == nil { + c.v = v + } + return +} + +var ( + onGCEOnce sync.Once + onGCE bool +) + +// OnGCE reports whether this process is running on Google Compute Engine. +func OnGCE() bool { + onGCEOnce.Do(initOnGCE) + return onGCE +} + +func initOnGCE() { + onGCE = testOnGCE() +} + +func testOnGCE() bool { + // The user explicitly said they're on GCE, so trust them. + if os.Getenv(metadataHostEnv) != "" { + return true + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + resc := make(chan bool, 2) + + // Try two strategies in parallel. + // See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194 + go func() { + req, _ := http.NewRequest("GET", "http://"+metadataIP, nil) + req.Header.Set("User-Agent", userAgent) + res, err := ctxhttp.Do(ctx, metaClient, req) + if err != nil { + resc <- false + return + } + defer res.Body.Close() + resc <- res.Header.Get("Metadata-Flavor") == "Google" + }() + + go func() { + addrs, err := net.LookupHost("metadata.google.internal") + if err != nil || len(addrs) == 0 { + resc <- false + return + } + resc <- strsContains(addrs, metadataIP) + }() + + tryHarder := systemInfoSuggestsGCE() + if tryHarder { + res := <-resc + if res { + // The first strategy succeeded, so let's use it. + return true + } + // Wait for either the DNS or metadata server probe to + // contradict the other one and say we are running on + // GCE. Give it a lot of time to do so, since the system + // info already suggests we're running on a GCE BIOS. + timer := time.NewTimer(5 * time.Second) + defer timer.Stop() + select { + case res = <-resc: + return res + case <-timer.C: + // Too slow. Who knows what this system is. + return false + } + } + + // There's no hint from the system info that we're running on + // GCE, so use the first probe's result as truth, whether it's + // true or false. The goal here is to optimize for speed for + // users who are NOT running on GCE. We can't assume that + // either a DNS lookup or an HTTP request to a blackholed IP + // address is fast. Worst case this should return when the + // metaClient's Transport.ResponseHeaderTimeout or + // Transport.Dial.Timeout fires (in two seconds). + return <-resc +} + +// systemInfoSuggestsGCE reports whether the local system (without +// doing network requests) suggests that we're running on GCE. If this +// returns true, testOnGCE tries a bit harder to reach its metadata +// server. +func systemInfoSuggestsGCE() bool { + if runtime.GOOS != "linux" { + // We don't have any non-Linux clues available, at least yet. + return false + } + slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name") + name := strings.TrimSpace(string(slurp)) + return name == "Google" || name == "Google Compute Engine" +} + +// Subscribe subscribes to a value from the metadata service. +// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/". +// The suffix may contain query parameters. +// +// Subscribe calls fn with the latest metadata value indicated by the provided +// suffix. If the metadata value is deleted, fn is called with the empty string +// and ok false. Subscribe blocks until fn returns a non-nil error or the value +// is deleted. Subscribe returns the error value returned from the last call to +// fn, which may be nil when ok == false. +func Subscribe(suffix string, fn func(v string, ok bool) error) error { + const failedSubscribeSleep = time.Second * 5 + + // First check to see if the metadata value exists at all. + val, lastETag, err := getETag(subscribeClient, suffix) + if err != nil { + return err + } + + if err := fn(val, true); err != nil { + return err + } + + ok := true + if strings.ContainsRune(suffix, '?') { + suffix += "&wait_for_change=true&last_etag=" + } else { + suffix += "?wait_for_change=true&last_etag=" + } + for { + val, etag, err := getETag(subscribeClient, suffix+url.QueryEscape(lastETag)) + if err != nil { + if _, deleted := err.(NotDefinedError); !deleted { + time.Sleep(failedSubscribeSleep) + continue // Retry on other errors. + } + ok = false + } + lastETag = etag + + if err := fn(val, ok); err != nil || !ok { + return err + } + } +} + +// ProjectID returns the current instance's project ID string. +func ProjectID() (string, error) { return projID.get() } + +// NumericProjectID returns the current instance's numeric project ID. +func NumericProjectID() (string, error) { return projNum.get() } + +// InternalIP returns the instance's primary internal IP address. +func InternalIP() (string, error) { + return getTrimmed("instance/network-interfaces/0/ip") +} + +// ExternalIP returns the instance's primary external (public) IP address. +func ExternalIP() (string, error) { + return getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip") +} + +// Hostname returns the instance's hostname. This will be of the form +// ".c..internal". +func Hostname() (string, error) { + return getTrimmed("instance/hostname") +} + +// InstanceTags returns the list of user-defined instance tags, +// assigned when initially creating a GCE instance. +func InstanceTags() ([]string, error) { + var s []string + j, err := Get("instance/tags") + if err != nil { + return nil, err + } + if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil { + return nil, err + } + return s, nil +} + +// InstanceID returns the current VM's numeric instance ID. +func InstanceID() (string, error) { + return instID.get() +} + +// InstanceName returns the current VM's instance ID string. +func InstanceName() (string, error) { + host, err := Hostname() + if err != nil { + return "", err + } + return strings.Split(host, ".")[0], nil +} + +// Zone returns the current VM's zone, such as "us-central1-b". +func Zone() (string, error) { + zone, err := getTrimmed("instance/zone") + // zone is of the form "projects//zones/". + if err != nil { + return "", err + } + return zone[strings.LastIndex(zone, "/")+1:], nil +} + +// InstanceAttributes returns the list of user-defined attributes, +// assigned when initially creating a GCE VM instance. The value of an +// attribute can be obtained with InstanceAttributeValue. +func InstanceAttributes() ([]string, error) { return lines("instance/attributes/") } + +// ProjectAttributes returns the list of user-defined attributes +// applying to the project as a whole, not just this VM. The value of +// an attribute can be obtained with ProjectAttributeValue. +func ProjectAttributes() ([]string, error) { return lines("project/attributes/") } + +func lines(suffix string) ([]string, error) { + j, err := Get(suffix) + if err != nil { + return nil, err + } + s := strings.Split(strings.TrimSpace(j), "\n") + for i := range s { + s[i] = strings.TrimSpace(s[i]) + } + return s, nil +} + +// InstanceAttributeValue returns the value of the provided VM +// instance attribute. +// +// If the requested attribute is not defined, the returned error will +// be of type NotDefinedError. +// +// InstanceAttributeValue may return ("", nil) if the attribute was +// defined to be the empty string. +func InstanceAttributeValue(attr string) (string, error) { + return Get("instance/attributes/" + attr) +} + +// ProjectAttributeValue returns the value of the provided +// project attribute. +// +// If the requested attribute is not defined, the returned error will +// be of type NotDefinedError. +// +// ProjectAttributeValue may return ("", nil) if the attribute was +// defined to be the empty string. +func ProjectAttributeValue(attr string) (string, error) { + return Get("project/attributes/" + attr) +} + +// Scopes returns the service account scopes for the given account. +// The account may be empty or the string "default" to use the instance's +// main account. +func Scopes(serviceAccount string) ([]string, error) { + if serviceAccount == "" { + serviceAccount = "default" + } + return lines("instance/service-accounts/" + serviceAccount + "/scopes") +} + +func strsContains(ss []string, s string) bool { + for _, v := range ss { + if v == s { + return true + } + } + return false +} diff --git a/vendor/github.com/adlio/trello/.gitignore b/vendor/github.com/adlio/trello/.gitignore new file mode 100644 index 00000000..431d6df1 --- /dev/null +++ b/vendor/github.com/adlio/trello/.gitignore @@ -0,0 +1,28 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +coverage.sh +coverage.out +coverage.html diff --git a/vendor/github.com/adlio/trello/.travis.yml b/vendor/github.com/adlio/trello/.travis.yml new file mode 100644 index 00000000..2e184ac4 --- /dev/null +++ b/vendor/github.com/adlio/trello/.travis.yml @@ -0,0 +1,11 @@ +language: go +sudo: false +go: + - 1.7 + - 1.8 + - tip +before_install: + - go get github.com/mattn/goveralls +script: + - $HOME/gopath/bin/goveralls -service=travis-ci + diff --git a/vendor/github.com/adlio/trello/LICENSE b/vendor/github.com/adlio/trello/LICENSE new file mode 100644 index 00000000..50bcc92a --- /dev/null +++ b/vendor/github.com/adlio/trello/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Aaron Longwell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/adlio/trello/README.md b/vendor/github.com/adlio/trello/README.md new file mode 100644 index 00000000..08c26324 --- /dev/null +++ b/vendor/github.com/adlio/trello/README.md @@ -0,0 +1,232 @@ +Go Trello API +================ + +[![Trello Logo](https://raw.githubusercontent.com/adlio/trello/master/trello-logo.png)](https://www.trello.com) + +[![GoDoc](https://godoc.org/github.com/adlio/trello?status.svg)](http://godoc.org/github.com/adlio/trello) +[![Build Status](https://travis-ci.org/adlio/trello.svg)](https://travis-ci.org/adlio/trello) +[![Coverage Status](https://coveralls.io/repos/github/adlio/trello/badge.svg?branch=master)](https://coveralls.io/github/adlio/trello?branch=master) + +A #golang package to access the [Trello API](https://developers.trello.com/v1.0/reference). Nearly 100% of the +read-only surface area of the API is covered, as is creation and modification of Cards. +Low-level infrastructure for features to modify Lists and Boards are easy to add... just not +done yet. + +Pull requests are welcome for missing features. + +My current development focus is documentation, especially enhancing this README.md with more +example use cases. + +## Installation + +The Go Trello API has been Tested compatible with Go 1.7 on up. Its only dependency is +the `github.com/pkg/errors` package. It otherwise relies only on the Go standard library. + +``` +go get github.com/adlio/trello +``` + +## Basic Usage + +All interaction starts with a `trello.Client`. Create one with your appKey and token: + +```Go +client := trello.NewClient(appKey, token) +``` + +All API requests accept a trello.Arguments object. This object is a simple +`map[string]string`, converted to query string arguments in the API call. +Trello has sane defaults on API calls. We have a `trello.Defaults()` utility function +which can be used when you desire the default Trello arguments. Internally, +`trello.Defaults()` is an empty map, which translates to an empty query string. + +```Go +board, err := client.GetBoard("bOaRdID", trello.Defaults()) +if err != nil { + // Handle error +} +``` + +## Client Longevity + +When getting Lists from Boards or Cards from Lists, the original `trello.Client` pointer +is carried along in returned child objects. It's important to realize that this enables +you to make additional API calls via functions invoked on the objects you receive: + +```Go +client := trello.NewClient(appKey, token) +board, err := client.GetBoard("ID", trello.Defaults()) + +// GetLists makes an API call to /boards/:id/lists using credentials from `client` +lists, err := board.GetLists(trello.Defaults()) + +for _, list := range lists { + // GetCards makes an API call to /lists/:id/cards using credentials from `client` + cards, err := list.GetCards(trello.Defaults()) +} +``` + +## Get Trello Boards for a User + +Boards can be retrieved directly by their ID (see example above), or by asking +for all boards for a member: + +```Go +member, err := client.GetMember("usernameOrId", trello.Defaults()) +if err != nil { + // Handle error +} + +boards, err := member.GetBoards(trello.Defaults()) +if err != nil { + // Handle error +} +``` + +## Get Trello Lists on a Board + +```Go +board, err := client.GetBoard("bOaRdID", trello.Defaults()) +if err != nil { + // Handle error +} + +lists, err := board.GetLists(trello.Defaults()) +if err != nil { + // Handle error +} +``` + +## Get Trello Cards on a Board + +```Go +board, err := client.GetBoard("bOaRdID", trello.Defaults()) +if err != nil { + // Handle error +} + +cards, err := board.GetCards(trello.Defaults()) +if err != nil { + // Handle error +} +``` + +## Get Trello Cards on a List + +```Go +list, err := client.GetList("lIsTID", trello.Defaults()) +if err != nil { + // Handle error +} + +cards, err := list.GetCards(trello.Defaults()) +if err != nil { + // Handle error +} +``` + +## Creating a Card + +The API provides several mechanisms for creating new cards. + +### Creating Cards from Scratch on the Client + +This approach requires the most input data on the card: + +```Go +card := trello.Card{ + Name: "Card Name", + Desc: "Card description", + Pos: 12345.678, + IDList: "iDOfaLiSt", + IDLabels: []string{"labelID1", "labelID2"}, +} +err := client.CreateCard(card, trello.Defaults()) +``` + + +### Creating Cards On a List + +```Go +list, err := client.GetList("lIsTID", trello.Defaults()) +list.AddCard(trello.Card{ Name: "Card Name", Description: "Card description" }, trello.Defaults()) +``` + +### Creating a Card by Copying Another Card + +```Go +err := card.CopyToList("listIdNUmber", trello.Defaults()) +``` + +## Get Actions on a Board + +```Go +board, err := client.GetBoard("bOaRdID", trello.Defaults()) +if err != nil { + // Handle error +} + +actions, err := board.GetActions(trello.Defaults()) +if err != nil { + // Handle error +} +``` + +## Get Actions on a Card + +```Go +card, err := client.GetCard("cArDID", trello.Defaults()) +if err != nil { + // Handle error +} + +actions, err := card.GetActions(trello.Defaults()) +if err != nil { + // Handle error +} +``` + +## Rearrange Cards Within a List + +```Go +err := card.MoveToTopOfList() +err = card.MoveToBottomOfList() +err = card.SetPos(12345.6789) +``` + + +## Moving a Card to Another List + +```Go +err := card.MoveToList("listIdNUmber", trello.Defaults()) +``` + + +## Card Ancestry + +Trello provides ancestry tracking when cards are created as copies of other cards. This package +provides functions for working with this data: + +```Go + +// ancestors will hold a slice of *trello.Cards, with the first +// being the card's parent, and the last being parent's parent's parent... +ancestors, err := card.GetAncestorCards(trello.Defaults()) + +// GetOriginatingCard() is an alias for the last element in the slice +// of ancestor cards. +ultimateParentCard, err := card.GetOriginatingCard(trello.Defaults()) + +``` + +## Debug Logging + +If you'd like to see all API calls logged, you can attach a `.Logger` (implementing `Debugf(string, ...interface{})`) +to your client. The interface for the logger mimics logrus. Example usage: + +```Go +logger := logrus.New() +logger.SetLevel(logrus.DebugLevel) +client := trello.NewClient(appKey, token) +client.Logger = logger +``` diff --git a/vendor/github.com/adlio/trello/TODO.txt b/vendor/github.com/adlio/trello/TODO.txt new file mode 100644 index 00000000..c363ff9d --- /dev/null +++ b/vendor/github.com/adlio/trello/TODO.txt @@ -0,0 +1,5 @@ +- Create List +- Delete Card +- Archive Card +- Reorder Cards in List + diff --git a/vendor/github.com/adlio/trello/action-collection.go b/vendor/github.com/adlio/trello/action-collection.go new file mode 100644 index 00000000..9b6632f2 --- /dev/null +++ b/vendor/github.com/adlio/trello/action-collection.go @@ -0,0 +1,57 @@ +package trello + +import ( + "sort" +) + +// ActionCollection is an alias of []*Action, which sorts by the Action's ID. +// Which is the same as sorting by the Action's time of occurrence +type ActionCollection []*Action + +func (c ActionCollection) Len() int { return len(c) } +func (c ActionCollection) Swap(i, j int) { c[i], c[j] = c[j], c[i] } +func (c ActionCollection) Less(i, j int) bool { return c[i].ID < c[j].ID } + +func (actions ActionCollection) FirstCardCreateAction() *Action { + sort.Sort(actions) + for _, action := range actions { + if action.DidCreateCard() { + return action + } + } + return nil +} + +func (actions ActionCollection) ContainsCardCreation() bool { + return actions.FirstCardCreateAction() != nil +} + +func (c ActionCollection) FilterToCardCreationActions() ActionCollection { + newSlice := make(ActionCollection, 0, len(c)) + for _, action := range c { + if action.DidCreateCard() { + newSlice = append(newSlice, action) + } + } + return newSlice +} + +func (c ActionCollection) FilterToListChangeActions() ActionCollection { + newSlice := make(ActionCollection, 0, len(c)) + for _, action := range c { + if action.DidChangeListForCard() { + newSlice = append(newSlice, action) + } + } + return newSlice +} + +func (c ActionCollection) FilterToCardMembershipChangeActions() ActionCollection { + newSlice := make(ActionCollection, 0, len(c)) + for _, action := range c { + if action.DidChangeCardMembership() || action.DidArchiveCard() || action.DidUnarchiveCard() { + newSlice = append(newSlice, action) + } + } + return newSlice +} diff --git a/vendor/github.com/adlio/trello/action.go b/vendor/github.com/adlio/trello/action.go new file mode 100644 index 00000000..20f6d8fc --- /dev/null +++ b/vendor/github.com/adlio/trello/action.go @@ -0,0 +1,148 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "fmt" + "time" +) + +type Action struct { + ID string `json:"id"` + IDMemberCreator string `json:"idMemberCreator"` + Type string `json:"type"` + Date time.Time `json:"date"` + Data *ActionData `json:"data,omitempty"` + MemberCreator *Member `json:"memberCreator,omitempty"` + Member *Member `json:"member,omitempty"` +} + +type ActionData struct { + Text string `json:"text,omitempty"` + List *List `json:"list,omitempty"` + Card *Card `json:"card,omitempty"` + CardSource *Card `json:"cardSource,omitempty"` + Board *Board `json:"board,omitempty"` + Old *Card `json:"old,omitempty"` + ListBefore *List `json:"listBefore,omitempty"` + ListAfter *List `json:"listAfter,omitempty"` + DateLastEdited time.Time `json:"dateLastEdited"` + + CheckItem *CheckItem `json:"checkItem"` + Checklist *Checklist `json:"checklist"` +} + +func (b *Board) GetActions(args Arguments) (actions ActionCollection, err error) { + path := fmt.Sprintf("boards/%s/actions", b.ID) + err = b.client.Get(path, args, &actions) + return +} + +func (l *List) GetActions(args Arguments) (actions ActionCollection, err error) { + path := fmt.Sprintf("lists/%s/actions", l.ID) + err = l.client.Get(path, args, &actions) + return +} + +func (c *Card) GetActions(args Arguments) (actions ActionCollection, err error) { + path := fmt.Sprintf("cards/%s/actions", c.ID) + err = c.client.Get(path, args, &actions) + return +} + +// GetListChangeActions retrieves a slice of Actions which resulted in changes +// to the card's active List. This includes the createCard and copyCard action (which +// place the card in its first list, and the updateCard:closed action, which remove it +// from its last list. +// +// This function is just an alias for: +// card.GetActions(Arguments{"filter": "createCard,copyCard,updateCard:idList,updateCard:closed", "limit": "1000"}) +// +func (c *Card) GetListChangeActions() (actions ActionCollection, err error) { + return c.GetActions(Arguments{"filter": "createCard,copyCard,updateCard:idList,updateCard:closed"}) +} + +func (c *Card) GetMembershipChangeActions() (actions ActionCollection, err error) { + // We include updateCard:closed as if the member is implicitly removed from the card when it's closed. + // This allows us to "close out" the duration length. + return c.GetActions(Arguments{"filter": "addMemberToCard,removeMemberFromCard,updateCard:closed"}) +} + +// DidCreateCard() returns true if this action created a card, false otherwise. +func (a *Action) DidCreateCard() bool { + switch a.Type { + case "createCard", "emailCard", "copyCard", "convertToCardFromCheckItem": + return true + case "moveCardToBoard": + return true // Unsure about this one + default: + return false + } +} + +func (a *Action) DidArchiveCard() bool { + return (a.Type == "updateCard") && a.Data != nil && a.Data.Card != nil && a.Data.Card.Closed +} + +func (a *Action) DidUnarchiveCard() bool { + return (a.Type == "updateCard") && a.Data != nil && a.Data.Old != nil && a.Data.Old.Closed +} + +// Returns true if this action created the card (in which case it caused it to enter its +// first list), archived the card (in which case it caused it to leave its last List), +// or was an updateCard action involving a change to the list. This is supporting +// functionality for ListDuration. +// +func (a *Action) DidChangeListForCard() bool { + if a.DidCreateCard() { + return true + } + if a.DidArchiveCard() { + return true + } + if a.DidUnarchiveCard() { + return true + } + if a.Type == "updateCard" { + if a.Data != nil && a.Data.ListAfter != nil { + return true + } + } + return false +} + +func (a *Action) DidChangeCardMembership() bool { + switch a.Type { + case "addMemberToCard": + return true + case "removeMemberFromCard": + return true + default: + return false + } +} + +// ListAfterAction calculates which List the card ended up in after this action +// completed. Returns nil when the action resulted in the card being archived (in +// which case we consider it to not be in a list anymore), or when the action isn't +// related to a list at all (in which case this is a nonsensical question to ask). +// +func ListAfterAction(a *Action) *List { + switch a.Type { + case "createCard", "copyCard", "emailCard", "convertToCardFromCheckItem": + return a.Data.List + case "updateCard": + if a.DidArchiveCard() { + return nil + } else if a.DidUnarchiveCard() { + return a.Data.List + } + if a.Data.ListAfter != nil { + return a.Data.ListAfter + } + } + return nil +} diff --git a/vendor/github.com/adlio/trello/arguments.go b/vendor/github.com/adlio/trello/arguments.go new file mode 100644 index 00000000..8bceca16 --- /dev/null +++ b/vendor/github.com/adlio/trello/arguments.go @@ -0,0 +1,24 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "net/url" +) + +type Arguments map[string]string + +func Defaults() Arguments { + return make(Arguments) +} + +func (args Arguments) ToURLValues() url.Values { + v := url.Values{} + for key, value := range args { + v.Set(key, value) + } + return v +} diff --git a/vendor/github.com/adlio/trello/attachment.go b/vendor/github.com/adlio/trello/attachment.go new file mode 100644 index 00000000..e735a3f2 --- /dev/null +++ b/vendor/github.com/adlio/trello/attachment.go @@ -0,0 +1,29 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +type Attachment struct { + ID string `json:"id"` + Name string `json:"name"` + Pos float32 `json:"pos"` + Bytes int `json:"int"` + Date string `json:"date"` + EdgeColor string `json:"edgeColor"` + IDMember string `json:"idMember"` + IsUpload bool `json:"isUpload"` + MimeType string `json:"mimeType"` + Previews []AttachmentPreview `json:"previews"` + URL string `json:"url"` +} + +type AttachmentPreview struct { + ID string `json:"_id"` + URL string `json:"url"` + Width int `json:"width"` + Height int `json:"height"` + Bytes int `json:"bytes"` + Scaled bool `json:"scaled"` +} diff --git a/vendor/github.com/adlio/trello/board.go b/vendor/github.com/adlio/trello/board.go new file mode 100644 index 00000000..cc8617ef --- /dev/null +++ b/vendor/github.com/adlio/trello/board.go @@ -0,0 +1,89 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "fmt" + "time" +) + +type Board struct { + client *Client + ID string `json:"id"` + Name string `json:"name"` + Desc string `json:"desc"` + Closed bool `json:"closed"` + IdOrganization string `json:"idOrganization"` + Pinned bool `json:"pinned"` + Url string `json:"url"` + ShortUrl string `json:"shortUrl"` + Prefs struct { + PermissionLevel string `json:"permissionLevel"` + Voting string `json:"voting"` + Comments string `json:"comments"` + Invitations string `json:"invitations"` + SelfJoin bool `json:"selfjoin"` + CardCovers bool `json:"cardCovers"` + CardAging string `json:"cardAging"` + CalendarFeedEnabled bool `json:"calendarFeedEnabled"` + Background string `json:"background"` + BackgroundColor string `json:"backgroundColor"` + BackgroundImage string `json:"backgroundImage"` + BackgroundImageScaled []BackgroundImage `json:"backgroundImageScaled"` + BackgroundTile bool `json:"backgroundTile"` + BackgroundBrightness string `json:"backgroundBrightness"` + CanBePublic bool `json:"canBePublic"` + CanBeOrg bool `json:"canBeOrg"` + CanBePrivate bool `json:"canBePrivate"` + CanInvite bool `json:"canInvite"` + } `json:"prefs"` + LabelNames struct { + Black string `json:"black,omitempty"` + Blue string `json:"blue,omitempty"` + Green string `json:"green,omitempty"` + Lime string `json:"lime,omitempty"` + Orange string `json:"orange,omitempty"` + Pink string `json:"pink,omitempty"` + Purple string `json:"purple,omitempty"` + Red string `json:"red,omitempty"` + Sky string `json:"sky,omitempty"` + Yellow string `json:"yellow,omitempty"` + } `json:"labelNames"` + Lists []*List `json:"lists"` + Actions []*Action `json:"actions"` +} + +type BackgroundImage struct { + Width int `json:"width"` + Height int `json:"height"` + URL string `json:"url"` +} + +func (b *Board) CreatedAt() time.Time { + t, _ := IDToTime(b.ID) + return t +} + +/** + * Board retrieves a Trello board by its ID. + */ +func (c *Client) GetBoard(boardID string, args Arguments) (board *Board, err error) { + path := fmt.Sprintf("boards/%s", boardID) + err = c.Get(path, args, &board) + if board != nil { + board.client = c + } + return +} + +func (m *Member) GetBoards(args Arguments) (boards []*Board, err error) { + path := fmt.Sprintf("members/%s/boards", m.ID) + err = m.client.Get(path, args, &boards) + for i := range boards { + boards[i].client = m.client + } + return +} diff --git a/vendor/github.com/adlio/trello/card.go b/vendor/github.com/adlio/trello/card.go new file mode 100644 index 00000000..23960fd0 --- /dev/null +++ b/vendor/github.com/adlio/trello/card.go @@ -0,0 +1,388 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "fmt" + "strconv" + "strings" + "time" + + "github.com/pkg/errors" +) + +type Card struct { + client *Client + + // Key metadata + ID string `json:"id"` + IDShort int `json:"idShort"` + Name string `json:"name"` + Pos float64 `json:"pos"` + Email string `json:"email"` + ShortLink string `json:"shortLink"` + ShortUrl string `json:"shortUrl"` + Url string `json:"url"` + Desc string `json:"desc"` + Due *time.Time `json:"due"` + DueComplete bool `json:"dueComplete"` + Closed bool `json:"closed"` + Subscribed bool `json:"subscribed"` + DateLastActivity *time.Time `json:"dateLastActivity"` + + // Board + Board *Board + IDBoard string `json:"idBoard"` + + // List + List *List + IDList string `json:"idList"` + + // Badges + Badges struct { + Votes int `json:"votes"` + ViewingMemberVoted bool `json:"viewingMemberVoted"` + Subscribed bool `json:"subscribed"` + Fogbugz string `json:"fogbugz,omitempty"` + CheckItems int `json:"checkItems"` + CheckItemsChecked int `json:"checkItemsChecked"` + Comments int `json:"comments"` + Attachments int `json:"attachments"` + Description bool `json:"description"` + Due *time.Time `json:"due,omitempty"` + } `json:"badges"` + + // Actions + Actions ActionCollection `json:"actions,omitempty"` + + // Checklists + IDCheckLists []string `json:"idCheckLists"` + Checklists []*Checklist `json:"checklists,omitempty"` + CheckItemStates []*CheckItemState `json:"checkItemStates,omitempty"` + + // Members + IDMembers []string `json:"idMembers,omitempty"` + IDMembersVoted []string `json:"idMembersVoted,omitempty"` + Members []*Member `json:"members,omitempty"` + + // Attachments + IDAttachmentCover string `json:"idAttachmentCover"` + ManualCoverAttachment bool `json:"manualCoverAttachment"` + Attachments []*Attachment `json:"attachments,omitempty"` + + // Labels + IDLabels []string `json:"idLabels,omitempty"` + Labels []*Label `json:"labels,omitempty"` +} + +func (c *Card) CreatedAt() time.Time { + t, _ := IDToTime(c.ID) + return t +} + +func (c *Card) MoveToList(listID string, args Arguments) error { + path := fmt.Sprintf("cards/%s", c.ID) + args["idList"] = listID + return c.client.Put(path, args, &c) +} + +func (c *Card) SetPos(newPos float64) error { + path := fmt.Sprintf("cards/%s", c.ID) + return c.client.Put(path, Arguments{"pos": fmt.Sprintf("%f", newPos)}, c) +} + +func (c *Card) RemoveMember(memberID string) error { + path := fmt.Sprintf("cards/%s/idMembers/%s", c.ID, memberID) + return c.client.Delete(path, Defaults(), nil) +} + +func (c *Card) AddMemberID(memberID string) (member []*Member, err error) { + path := fmt.Sprintf("cards/%s/idMembers", c.ID) + err = c.client.Post(path, Arguments{"value": memberID}, &member) + return member, err +} + +func (c *Card) MoveToTopOfList() error { + path := fmt.Sprintf("cards/%s", c.ID) + return c.client.Put(path, Arguments{"pos": "top"}, c) +} + +func (c *Card) MoveToBottomOfList() error { + path := fmt.Sprintf("cards/%s", c.ID) + return c.client.Put(path, Arguments{"pos": "bottom"}, c) +} + +func (c *Card) Update(args Arguments) error { + path := fmt.Sprintf("cards/%s", c.ID) + return c.client.Put(path, args, c) +} + +func (c *Client) CreateCard(card *Card, extraArgs Arguments) error { + path := "cards" + args := Arguments{ + "name": card.Name, + "desc": card.Desc, + "pos": strconv.FormatFloat(card.Pos, 'g', -1, 64), + "idList": card.IDList, + "idMembers": strings.Join(card.IDMembers, ","), + "idLabels": strings.Join(card.IDLabels, ","), + } + if card.Due != nil { + args["due"] = card.Due.Format(time.RFC3339) + } + // Allow overriding the creation position with 'top' or 'botttom' + if pos, ok := extraArgs["pos"]; ok { + args["pos"] = pos + } + err := c.Post(path, args, &card) + if err == nil { + card.client = c + } + return err +} + +func (l *List) AddCard(card *Card, extraArgs Arguments) error { + path := fmt.Sprintf("lists/%s/cards", l.ID) + args := Arguments{ + "name": card.Name, + "desc": card.Desc, + "idMembers": strings.Join(card.IDMembers, ","), + "idLabels": strings.Join(card.IDLabels, ","), + } + if card.Due != nil { + args["due"] = card.Due.Format(time.RFC3339) + } + // Allow overwriting the creation position with 'top' or 'bottom' + if pos, ok := extraArgs["pos"]; ok { + args["pos"] = pos + } + err := l.client.Post(path, args, &card) + if err == nil { + card.client = l.client + } else { + err = errors.Wrapf(err, "Error adding card to list %s", l.ID) + } + return err +} + +// Try these Arguments +// +// Arguments["keepFromSource"] = "all" +// Arguments["keepFromSource"] = "none" +// Arguments["keepFromSource"] = "attachments,checklists,comments" +// +func (c *Card) CopyToList(listID string, args Arguments) (*Card, error) { + path := "cards" + args["idList"] = listID + args["idCardSource"] = c.ID + newCard := Card{} + err := c.client.Post(path, args, &newCard) + if err == nil { + newCard.client = c.client + } else { + err = errors.Wrapf(err, "Error copying card '%s' to list '%s'.", c.ID, listID) + } + return &newCard, err +} + +func (c *Card) AddComment(comment string, args Arguments) (*Action, error) { + path := fmt.Sprintf("cards/%s/actions/comments", c.ID) + args["text"] = comment + action := Action{} + err := c.client.Post(path, args, &action) + if err != nil { + err = errors.Wrapf(err, "Error commenting on card %s", c.ID) + } + return &action, err +} + +// If this Card was created from a copy of another Card, this func retrieves +// the originating Card. Returns an error only when a low-level failure occurred. +// If this Card has no parent, a nil card and nil error are returned. In other words, the +// non-existence of a parent is not treated as an error. +// +func (c *Card) GetParentCard(args Arguments) (*Card, error) { + + // Hopefully the card came pre-loaded with Actions including the card creation + action := c.Actions.FirstCardCreateAction() + + if action == nil { + // No luck. Go get copyCard actions for this card. + c.client.log("Creation action wasn't supplied before GetParentCard() on '%s'. Getting copyCard actions.", c.ID) + actions, err := c.GetActions(Arguments{"filter": "copyCard"}) + if err != nil { + err = errors.Wrapf(err, "GetParentCard() failed to GetActions() for card '%s'", c.ID) + return nil, err + } + action = actions.FirstCardCreateAction() + } + + if action != nil && action.Data != nil && action.Data.CardSource != nil { + card, err := c.client.GetCard(action.Data.CardSource.ID, args) + return card, err + } + + return nil, nil +} + +func (c *Card) GetAncestorCards(args Arguments) (ancestors []*Card, err error) { + + // Get the first parent + parent, err := c.GetParentCard(args) + if IsNotFound(err) || IsPermissionDenied(err) { + c.client.log("[trello] Can't get details about the parent of card '%s' due to lack of permissions or card deleted.", c.ID) + return ancestors, nil + } + + for parent != nil { + ancestors = append(ancestors, parent) + parent, err = parent.GetParentCard(args) + if IsNotFound(err) || IsPermissionDenied(err) { + c.client.log("[trello] Can't get details about the parent of card '%s' due to lack of permissions or card deleted.", c.ID) + return ancestors, nil + } else if err != nil { + return ancestors, err + } + } + + return ancestors, err +} + +func (c *Card) GetOriginatingCard(args Arguments) (*Card, error) { + ancestors, err := c.GetAncestorCards(args) + if err != nil { + return c, err + } + if len(ancestors) > 0 { + return ancestors[len(ancestors)-1], nil + } else { + return c, nil + } +} + +func (c *Card) CreatorMember() (*Member, error) { + var actions ActionCollection + var err error + + if len(c.Actions) == 0 { + c.Actions, err = c.GetActions(Arguments{"filter": "all", "limit": "1000", "memberCreator_fields": "all"}) + if err != nil { + err = errors.Wrapf(err, "GetActions() call failed.") + return nil, err + } + } + actions = c.Actions.FilterToCardCreationActions() + + if len(actions) > 0 { + return actions[0].MemberCreator, nil + } + return nil, errors.Errorf("No card creation actions on Card %s with a .MemberCreator", c.ID) +} + +func (c *Card) CreatorMemberID() (string, error) { + + var actions ActionCollection + var err error + + if len(c.Actions) == 0 { + c.client.log("[trello] CreatorMemberID() called on card '%s' without any Card.Actions. Fetching fresh.", c.ID) + c.Actions, err = c.GetActions(Defaults()) + if err != nil { + err = errors.Wrapf(err, "GetActions() call failed.") + } + } + actions = c.Actions.FilterToCardCreationActions() + + if len(actions) > 0 { + if actions[0].IDMemberCreator != "" { + return actions[0].IDMemberCreator, err + } + } + + return "", errors.Wrapf(err, "No Actions on card '%s' could be used to find its creator.", c.ID) +} + +func (b *Board) ContainsCopyOfCard(cardID string, args Arguments) (bool, error) { + args["filter"] = "copyCard" + actions, err := b.GetActions(args) + if err != nil { + err := errors.Wrapf(err, "GetCards() failed inside ContainsCopyOf() for board '%s' and card '%s'.", b.ID, cardID) + return false, err + } + for _, action := range actions { + if action.Data != nil && action.Data.CardSource != nil && action.Data.CardSource.ID == cardID { + return true, nil + } + } + return false, nil +} + +func (c *Client) GetCard(cardID string, args Arguments) (card *Card, err error) { + path := fmt.Sprintf("cards/%s", cardID) + err = c.Get(path, args, &card) + if card != nil { + card.client = c + } + return card, err +} + +/** + * Retrieves all Cards on a Board + * + * If before + */ +func (b *Board) GetCards(args Arguments) (cards []*Card, err error) { + path := fmt.Sprintf("boards/%s/cards", b.ID) + + err = b.client.Get(path, args, &cards) + + // Naive implementation would return here. To make sure we get all + // cards, we begin + if len(cards) > 0 { + moreCards := true + for moreCards == true { + nextCardBatch := make([]*Card, 0) + args["before"] = EarliestCardID(cards) + err = b.client.Get(path, args, &nextCardBatch) + if len(nextCardBatch) > 0 { + cards = append(cards, nextCardBatch...) + } else { + moreCards = false + } + } + } + + for i := range cards { + cards[i].client = b.client + } + + return +} + +/** + * Retrieves all Cards in a List + */ +func (l *List) GetCards(args Arguments) (cards []*Card, err error) { + path := fmt.Sprintf("lists/%s/cards", l.ID) + err = l.client.Get(path, args, &cards) + for i := range cards { + cards[i].client = l.client + } + return +} + +func EarliestCardID(cards []*Card) string { + if len(cards) == 0 { + return "" + } + earliest := cards[0].ID + for _, card := range cards { + if card.ID < earliest { + earliest = card.ID + } + } + return earliest +} diff --git a/vendor/github.com/adlio/trello/checklist.go b/vendor/github.com/adlio/trello/checklist.go new file mode 100644 index 00000000..698dfa3c --- /dev/null +++ b/vendor/github.com/adlio/trello/checklist.go @@ -0,0 +1,30 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +type Checklist struct { + ID string `json:"id"` + Name string `json:"name"` + IDBoard string `json:"idBoard,omitempty"` + IDCard string `json:"idCard,omitempty"` + Pos float64 `json:"pos,omitempty"` + CheckItems []CheckItem `json:"checkItems,omitempty"` +} + +type CheckItem struct { + ID string `json:"id"` + Name string `json:"name"` + State string `json:"state"` + IDChecklist string `json:"idChecklist,omitempty"` + Pos float64 `json:"pos,omitempty"` +} + +// Manifestation of CheckItem when it appears in CheckItemStates +// on a Card. +type CheckItemState struct { + IDCheckItem string `json:"idCheckItem"` + State string `json:"state"` +} diff --git a/vendor/github.com/adlio/trello/client.go b/vendor/github.com/adlio/trello/client.go new file mode 100644 index 00000000..6e9df9b0 --- /dev/null +++ b/vendor/github.com/adlio/trello/client.go @@ -0,0 +1,239 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "time" + + "github.com/pkg/errors" +) + +const DEFAULT_BASEURL = "https://api.trello.com/1" + +type Client struct { + Client *http.Client + Logger logger + BaseURL string + Key string + Token string + throttle <-chan time.Time + testMode bool + ctx context.Context +} + +type logger interface { + Debugf(string, ...interface{}) +} + +func NewClient(key, token string) *Client { + return &Client{ + Client: http.DefaultClient, + BaseURL: DEFAULT_BASEURL, + Key: key, + Token: token, + throttle: time.Tick(time.Second / 8), // Actually 10/second, but we're extra cautious + testMode: false, + ctx: context.Background(), + } +} + +func (c *Client) WithContext(ctx context.Context) *Client { + newC := *c + newC.ctx = ctx + return &newC +} + +func (c *Client) Throttle() { + if !c.testMode { + <-c.throttle + } +} + +func (c *Client) Get(path string, args Arguments, target interface{}) error { + + // Trello prohibits more than 10 seconds/second per token + c.Throttle() + + params := args.ToURLValues() + c.log("[trello] GET %s?%s", path, params.Encode()) + + if c.Key != "" { + params.Set("key", c.Key) + } + + if c.Token != "" { + params.Set("token", c.Token) + } + + url := fmt.Sprintf("%s/%s", c.BaseURL, path) + urlWithParams := fmt.Sprintf("%s?%s", url, params.Encode()) + + req, err := http.NewRequest("GET", urlWithParams, nil) + if err != nil { + return errors.Wrapf(err, "Invalid GET request %s", url) + } + req = req.WithContext(c.ctx) + + resp, err := c.Client.Do(req) + if err != nil { + return errors.Wrapf(err, "HTTP request failure on %s", url) + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return makeHttpClientError(url, resp) + } + + decoder := json.NewDecoder(resp.Body) + err = decoder.Decode(target) + if err != nil { + return errors.Wrapf(err, "JSON decode failed on %s", url) + } + + return nil +} + +func (c *Client) Put(path string, args Arguments, target interface{}) error { + + // Trello prohibits more than 10 seconds/second per token + c.Throttle() + + params := args.ToURLValues() + c.log("[trello] PUT %s?%s", path, params.Encode()) + + if c.Key != "" { + params.Set("key", c.Key) + } + + if c.Token != "" { + params.Set("token", c.Token) + } + + url := fmt.Sprintf("%s/%s", c.BaseURL, path) + urlWithParams := fmt.Sprintf("%s?%s", url, params.Encode()) + + req, err := http.NewRequest("PUT", urlWithParams, nil) + if err != nil { + return errors.Wrapf(err, "Invalid PUT request %s", url) + } + + resp, err := c.Client.Do(req) + if err != nil { + return errors.Wrapf(err, "HTTP request failure on %s", url) + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return makeHttpClientError(url, resp) + } + + decoder := json.NewDecoder(resp.Body) + err = decoder.Decode(target) + if err != nil { + return errors.Wrapf(err, "JSON decode failed on %s", url) + } + + return nil +} + +func (c *Client) Post(path string, args Arguments, target interface{}) error { + + // Trello prohibits more than 10 seconds/second per token + c.Throttle() + + params := args.ToURLValues() + c.log("[trello] POST %s?%s", path, params.Encode()) + + if c.Key != "" { + params.Set("key", c.Key) + } + + if c.Token != "" { + params.Set("token", c.Token) + } + + url := fmt.Sprintf("%s/%s", c.BaseURL, path) + urlWithParams := fmt.Sprintf("%s?%s", url, params.Encode()) + + req, err := http.NewRequest("POST", urlWithParams, nil) + if err != nil { + return errors.Wrapf(err, "Invalid POST request %s", url) + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + resp, err := c.Client.Do(req) + if err != nil { + return errors.Wrapf(err, "HTTP request failure on %s", url) + } + + defer resp.Body.Close() + + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return errors.Wrapf(err, "HTTP Read error on response for %s", url) + } + + decoder := json.NewDecoder(bytes.NewBuffer(b)) + err = decoder.Decode(target) + if err != nil { + return errors.Wrapf(err, "JSON decode failed on %s:\n%s", url, string(b)) + } + + return nil +} + +func (c *Client) Delete(path string, args Arguments, target interface{}) error { + + c.Throttle() + + params := args.ToURLValues() + c.log("[trello] DELETE %s?%s", path, params.Encode()) + + if c.Key != "" { + params.Set("key", c.Key) + } + + if c.Token != "" { + params.Set("token", c.Token) + } + + url := fmt.Sprintf("%s/%s", c.BaseURL, path) + urlWithParams := fmt.Sprintf("%s?%s", url, params.Encode()) + + req, err := http.NewRequest("DELETE", urlWithParams, nil) + if err != nil { + return errors.Wrapf(err, "Invalid DELETE request %s", url) + } + + resp, err := c.Client.Do(req) + if err != nil { + return errors.Wrapf(err, "HTTP request failure on %s", url) + } + defer resp.Body.Close() + + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return errors.Wrapf(err, "HTTP Read error on response for %s", url) + } + + decoder := json.NewDecoder(bytes.NewBuffer(b)) + err = decoder.Decode(target) + if err != nil { + return errors.Wrapf(err, "JSON decode failed on %s:\n%s", url, string(b)) + } + + return nil +} + +func (c *Client) log(format string, args ...interface{}) { + if c.Logger != nil { + c.Logger.Debugf(format, args) + } +} diff --git a/vendor/github.com/adlio/trello/errors.go b/vendor/github.com/adlio/trello/errors.go new file mode 100644 index 00000000..9c93fcdd --- /dev/null +++ b/vendor/github.com/adlio/trello/errors.go @@ -0,0 +1,55 @@ +package trello + +import ( + "fmt" + "io/ioutil" + "net/http" +) + +type notFoundError interface { + IsNotFound() bool +} + +type rateLimitError interface { + IsRateLimit() bool +} + +type permissionDeniedError interface { + IsPermissionDenied() bool +} + +type httpClientError struct { + msg string + code int +} + +func makeHttpClientError(url string, resp *http.Response) error { + + body, _ := ioutil.ReadAll(resp.Body) + msg := fmt.Sprintf("HTTP request failure on %s:\n%d: %s", url, resp.StatusCode, string(body)) + + return &httpClientError{ + msg: msg, + code: resp.StatusCode, + } +} + +func (e *httpClientError) Error() string { return e.msg } +func (e *httpClientError) IsRateLimit() bool { return e.code == 429 } +func (e *httpClientError) IsNotFound() bool { return e.code == 404 } +func (e *httpClientError) IsPermissionDenied() bool { return e.code == 401 } + +func IsRateLimit(err error) bool { + re, ok := err.(rateLimitError) + return ok && re.IsRateLimit() +} + +func IsNotFound(err error) bool { + nf, ok := err.(notFoundError) + return ok && nf.IsNotFound() +} + +func IsPermissionDenied(err error) bool { + pd, ok := err.(permissionDeniedError) + return ok && pd.IsPermissionDenied() +} diff --git a/vendor/github.com/adlio/trello/label.go b/vendor/github.com/adlio/trello/label.go new file mode 100644 index 00000000..b60faa7a --- /dev/null +++ b/vendor/github.com/adlio/trello/label.go @@ -0,0 +1,14 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +type Label struct { + ID string `json:"id"` + IDBoard string `json:"idBoard"` + Name string `json:"name"` + Color string `json:"color"` + Uses int `json:"uses"` +} diff --git a/vendor/github.com/adlio/trello/list-duration-sort.go b/vendor/github.com/adlio/trello/list-duration-sort.go new file mode 100644 index 00000000..2695ff42 --- /dev/null +++ b/vendor/github.com/adlio/trello/list-duration-sort.go @@ -0,0 +1,9 @@ +package trello + +type ByFirstEntered []*ListDuration + +func (durs ByFirstEntered) Len() int { return len(durs) } +func (durs ByFirstEntered) Less(i, j int) bool { + return durs[i].FirstEntered.Before(durs[j].FirstEntered) +} +func (durs ByFirstEntered) Swap(i, j int) { durs[i], durs[j] = durs[j], durs[i] } diff --git a/vendor/github.com/adlio/trello/list-duration.go b/vendor/github.com/adlio/trello/list-duration.go new file mode 100644 index 00000000..42825703 --- /dev/null +++ b/vendor/github.com/adlio/trello/list-duration.go @@ -0,0 +1,82 @@ +package trello + +import ( + "sort" + "time" + + "github.com/pkg/errors" +) + +type ListDuration struct { + ListID string + ListName string + Duration time.Duration + FirstEntered time.Time + TimesInList int +} + +func (l *ListDuration) AddDuration(d time.Duration) { + l.Duration = l.Duration + d + l.TimesInList++ +} + +// Analytzes a Cards actions to figure out how long it was in each List +func (c *Card) GetListDurations() (durations []*ListDuration, err error) { + + var actions ActionCollection + if len(c.Actions) == 0 { + // Get all actions which affected the Card's List + c.client.log("[trello] GetListDurations() called on card '%s' without any Card.Actions. Fetching fresh.", c.ID) + actions, err = c.GetListChangeActions() + if err != nil { + err = errors.Wrap(err, "GetListChangeActions() call failed.") + return + } + } else { + actions = c.Actions.FilterToListChangeActions() + } + + return actions.GetListDurations() +} + +func (actions ActionCollection) GetListDurations() (durations []*ListDuration, err error) { + sort.Sort(actions) + + var prevTime time.Time + var prevList *List + + durs := make(map[string]*ListDuration) + for _, action := range actions { + if action.DidChangeListForCard() { + if prevList != nil { + duration := action.Date.Sub(prevTime) + _, durExists := durs[prevList.ID] + if !durExists { + durs[prevList.ID] = &ListDuration{ListID: prevList.ID, ListName: prevList.Name, Duration: duration, TimesInList: 1, FirstEntered: prevTime} + } else { + durs[prevList.ID].AddDuration(duration) + } + } + prevList = ListAfterAction(action) + prevTime = action.Date + } + } + + if prevList != nil { + duration := time.Now().Sub(prevTime) + _, durExists := durs[prevList.ID] + if !durExists { + durs[prevList.ID] = &ListDuration{ListID: prevList.ID, ListName: prevList.Name, Duration: duration, TimesInList: 1, FirstEntered: prevTime} + } else { + durs[prevList.ID].AddDuration(duration) + } + } + + durations = make([]*ListDuration, 0, len(durs)) + for _, ld := range durs { + durations = append(durations, ld) + } + sort.Sort(ByFirstEntered(durations)) + + return durations, nil +} diff --git a/vendor/github.com/adlio/trello/list.go b/vendor/github.com/adlio/trello/list.go new file mode 100644 index 00000000..6e26be1c --- /dev/null +++ b/vendor/github.com/adlio/trello/list.go @@ -0,0 +1,51 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "fmt" + "time" +) + +type List struct { + client *Client + ID string `json:"id"` + Name string `json:"name"` + IDBoard string `json:"idBoard,omitempty"` + Closed bool `json:"closed"` + Pos float32 `json:"pos,omitempty"` + Board *Board `json:"board,omitempty"` + Cards []*Card `json:"cards,omitempty"` +} + +func (l *List) CreatedAt() time.Time { + t, _ := IDToTime(l.ID) + return t +} + +func (c *Client) GetList(listID string, args Arguments) (list *List, err error) { + path := fmt.Sprintf("lists/%s", listID) + err = c.Get(path, args, &list) + if list != nil { + list.client = c + for i := range list.Cards { + list.Cards[i].client = c + } + } + return +} + +func (b *Board) GetLists(args Arguments) (lists []*List, err error) { + path := fmt.Sprintf("boards/%s/lists", b.ID) + err = b.client.Get(path, args, &lists) + for i := range lists { + lists[i].client = b.client + for j := range lists[i].Cards { + lists[i].Cards[j].client = b.client + } + } + return +} diff --git a/vendor/github.com/adlio/trello/member-duration.go b/vendor/github.com/adlio/trello/member-duration.go new file mode 100644 index 00000000..e5344d9b --- /dev/null +++ b/vendor/github.com/adlio/trello/member-duration.go @@ -0,0 +1,118 @@ +package trello + +import ( + "sort" + "time" + + "github.com/pkg/errors" +) + +// Used to track the periods of time which a user (member) is attached to a card. +// +type MemberDuration struct { + MemberID string + MemberName string + FirstAdded time.Time + Duration time.Duration + active bool + lastAdded time.Time +} + +type ByLongestDuration []*MemberDuration + +func (d ByLongestDuration) Len() int { return len(d) } +func (d ByLongestDuration) Less(i, j int) bool { return d[i].Duration > d[j].Duration } +func (d ByLongestDuration) Swap(i, j int) { d[i], d[j] = d[j], d[i] } + +func (d *MemberDuration) addAsOf(t time.Time) { + d.active = true + if d.FirstAdded.IsZero() { + d.FirstAdded = t + } + d.startTimerAsOf(t) +} + +func (d *MemberDuration) startTimerAsOf(t time.Time) { + if d.active { + d.lastAdded = t + } +} + +func (d *MemberDuration) removeAsOf(t time.Time) { + d.stopTimerAsOf(t) + d.active = false + d.lastAdded = time.Time{} +} + +func (d *MemberDuration) stopTimerAsOf(t time.Time) { + if d.active { + d.Duration = d.Duration + t.Sub(d.lastAdded) + } +} + +func (c *Card) GetMemberDurations() (durations []*MemberDuration, err error) { + var actions ActionCollection + if len(c.Actions) == 0 { + c.client.log("[trello] GetMemberDurations() called on card '%s' without any Card.Actions. Fetching fresh.", c.ID) + actions, err = c.GetMembershipChangeActions() + if err != nil { + err = errors.Wrap(err, "GetMembershipChangeActions() call failed.") + return + } + } else { + actions = c.Actions.FilterToCardMembershipChangeActions() + } + + return actions.GetMemberDurations() +} + +// Similar to GetListDurations(), this function returns a slice of MemberDuration objects, +// which describes the length of time each member was attached to this card. Durations are +// calculated such that being added to a card starts a timer for that member, and being removed +// starts it again (so that if a person is added and removed multiple times, the duration +// captures only the times which they were attached). Archiving the card also stops the timer. +// +func (actions ActionCollection) GetMemberDurations() (durations []*MemberDuration, err error) { + sort.Sort(actions) + durs := make(map[string]*MemberDuration) + for _, action := range actions { + if action.DidChangeCardMembership() { + _, durExists := durs[action.Member.ID] + if !durExists { + switch action.Type { + case "addMemberToCard": + durs[action.Member.ID] = &MemberDuration{MemberID: action.Member.ID, MemberName: action.Member.FullName} + durs[action.Member.ID].addAsOf(action.Date) + case "removeMemberFromCard": + // Surprisingly, this is possible. If a card was copied, and members were preserved, those + // members exist on the card without a corresponding addMemberToCard action. + t, _ := IDToTime(action.Data.Card.ID) + durs[action.Member.ID] = &MemberDuration{MemberID: action.Member.ID, MemberName: action.Member.FullName, lastAdded: t} + durs[action.Member.ID].removeAsOf(action.Date) + } + } else { + switch action.Type { + case "addMemberToCard": + durs[action.Member.ID].addAsOf(action.Date) + case "removeMemberFromCard": + durs[action.Member.ID].removeAsOf(action.Date) + } + } + } else if action.DidArchiveCard() { + for id, _ := range durs { + durs[id].stopTimerAsOf(action.Date) + } + } else if action.DidUnarchiveCard() { + for id, _ := range durs { + durs[id].startTimerAsOf(action.Date) + } + } + } + + durations = make([]*MemberDuration, 0, len(durs)) + for _, md := range durs { + durations = append(durations, md) + } + // sort.Sort(ByLongestDuration(durations)) + return durations, nil +} diff --git a/vendor/github.com/adlio/trello/member.go b/vendor/github.com/adlio/trello/member.go new file mode 100644 index 00000000..721d8746 --- /dev/null +++ b/vendor/github.com/adlio/trello/member.go @@ -0,0 +1,56 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "fmt" +) + +type Member struct { + client *Client + ID string `json:"id"` + Username string `json:"username"` + FullName string `json:"fullName"` + Initials string `json:"initials"` + AvatarHash string `json:"avatarHash"` + Email string `json:"email"` +} + +func (c *Client) GetMember(memberID string, args Arguments) (member *Member, err error) { + path := fmt.Sprintf("members/%s", memberID) + err = c.Get(path, args, &member) + if err == nil { + member.client = c + } + return +} + +func (o *Organization) GetMembers(args Arguments) (members []*Member, err error) { + path := fmt.Sprintf("organizations/%s/members", o.ID) + err = o.client.Get(path, args, &members) + for i := range members { + members[i].client = o.client + } + return +} + +func (b *Board) GetMembers(args Arguments) (members []*Member, err error) { + path := fmt.Sprintf("boards/%s/members", b.ID) + err = b.client.Get(path, args, &members) + for i := range members { + members[i].client = b.client + } + return +} + +func (c *Card) GetMembers(args Arguments) (members []*Member, err error) { + path := fmt.Sprintf("cards/%s/members", c.ID) + err = c.client.Get(path, args, &members) + for i := range members { + members[i].client = c.client + } + return +} diff --git a/vendor/github.com/adlio/trello/organization.go b/vendor/github.com/adlio/trello/organization.go new file mode 100644 index 00000000..d873a22b --- /dev/null +++ b/vendor/github.com/adlio/trello/organization.go @@ -0,0 +1,31 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "fmt" +) + +type Organization struct { + client *Client + ID string `json:"id"` + Name string `json:"name"` + DisplayName string `json:"displayName"` + Desc string `json:"desc"` + URL string `json:"url"` + Website string `json:"website"` + Products []string `json:"products"` + PowerUps []string `json:"powerUps"` +} + +func (c *Client) GetOrganization(orgID string, args Arguments) (organization *Organization, err error) { + path := fmt.Sprintf("organizations/%s", orgID) + err = c.Get(path, args, &organization) + if organization != nil { + organization.client = c + } + return +} diff --git a/vendor/github.com/adlio/trello/search.go b/vendor/github.com/adlio/trello/search.go new file mode 100644 index 00000000..5f04e415 --- /dev/null +++ b/vendor/github.com/adlio/trello/search.go @@ -0,0 +1,57 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +type SearchResult struct { + Options SearchOptions `json:"options"` + Actions []*Action `json:"actions,omitempty"` + Cards []*Card `json:"cards,omitempty"` + Boards []*Board `json:"boards,omitempty"` + Members []*Member `json:"members,omitempty"` +} + +type SearchOptions struct { + Terms []SearchTerm `json:"terms"` + Modifiers []SearchModifier `json:"modifiers,omitempty"` + ModelTypes []string `json:"modelTypes,omitempty"` + Partial bool `json:"partial"` +} + +type SearchModifier struct { + Text string `json:"text"` +} + +type SearchTerm struct { + Text string `json:"text"` + Negated bool `json:"negated,omitempty"` +} + +func (c *Client) SearchCards(query string, args Arguments) (cards []*Card, err error) { + args["query"] = query + args["modelTypes"] = "cards" + res := SearchResult{} + err = c.Get("search", args, &res) + cards = res.Cards + return +} + +func (c *Client) SearchBoards(query string, args Arguments) (boards []*Board, err error) { + args["query"] = query + args["modelTypes"] = "boards" + res := SearchResult{} + err = c.Get("search", args, &res) + boards = res.Boards + for _, board := range boards { + board.client = c + } + return +} + +func (c *Client) SearchMembers(query string, args Arguments) (members []*Member, err error) { + args["query"] = query + err = c.Get("search/members", args, &members) + return +} diff --git a/vendor/github.com/adlio/trello/token.go b/vendor/github.com/adlio/trello/token.go new file mode 100644 index 00000000..49f4ce54 --- /dev/null +++ b/vendor/github.com/adlio/trello/token.go @@ -0,0 +1,37 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "fmt" + "time" +) + +type Token struct { + client *Client + ID string `json:"id"` + DateCreated time.Time `json:"dateCreated"` + DateExpires *time.Time `json:"dateExpires"` + IDMember string `json:"idMember"` + Identifier string `json:"identifier"` + Permissions []Permission `json:"permissions"` +} + +type Permission struct { + IDModel string `json:"idModel"` + ModelType string `json:"modelType"` + Read bool `json:"read"` + Write bool `json:"write"` +} + +func (c *Client) GetToken(tokenID string, args Arguments) (token *Token, err error) { + path := fmt.Sprintf("tokens/%s", tokenID) + err = c.Get(path, args, &token) + if token != nil { + token.client = c + } + return +} diff --git a/vendor/github.com/adlio/trello/trello-logo.png b/vendor/github.com/adlio/trello/trello-logo.png new file mode 100644 index 00000000..1aeeff35 Binary files /dev/null and b/vendor/github.com/adlio/trello/trello-logo.png differ diff --git a/vendor/github.com/adlio/trello/trello.go b/vendor/github.com/adlio/trello/trello.go new file mode 100644 index 00000000..d07511d7 --- /dev/null +++ b/vendor/github.com/adlio/trello/trello.go @@ -0,0 +1,27 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "strconv" + "time" + + "github.com/pkg/errors" +) + +func IDToTime(id string) (t time.Time, err error) { + if id == "" { + return time.Time{}, nil + } + // The first 8 characters in the object ID are a Unix timestamp + ts, err := strconv.ParseUint(id[:8], 16, 64) + if err != nil { + err = errors.Wrapf(err, "ID '%s' failed to convert to timestamp.", id) + } else { + t = time.Unix(int64(ts), 0) + } + return +} diff --git a/vendor/github.com/adlio/trello/webhook.go b/vendor/github.com/adlio/trello/webhook.go new file mode 100644 index 00000000..4cf9d2b2 --- /dev/null +++ b/vendor/github.com/adlio/trello/webhook.go @@ -0,0 +1,111 @@ +// Copyright © 2016 Aaron Longwell +// +// Use of this source code is governed by an MIT licese. +// Details in the LICENSE file. + +package trello + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/pkg/errors" +) + +// Webhook is the Go representation of a webhook registered in Trello's systems. +// Used when creating, modifying or deleting webhooks. +// +type Webhook struct { + client *Client + ID string `json:"id,omitempty"` + IDModel string `json:"idModel"` + Description string `json:"description"` + CallbackURL string `json:"callbackURL"` + Active bool `json:"active"` +} + +// BoardWebhookRequest is the object sent by Trello to a Webhook for Board-triggered +// webhooks. +// +type BoardWebhookRequest struct { + Model *Board + Action *Action +} + +// ListWebhookRequest is the object sent by Trello to a Webhook for List-triggered +// webhooks. +// +type ListWebhookRequest struct { + Model *List + Action *Action +} + +// CardWebhookRequest is the object sent by Trello to a Webhook for Card-triggered +// webhooks. +// +type CardWebhookRequest struct { + Model *Card + Action *Action +} + +func (c *Client) CreateWebhook(webhook *Webhook) error { + path := "webhooks" + args := Arguments{"idModel": webhook.IDModel, "description": webhook.Description, "callbackURL": webhook.CallbackURL} + err := c.Post(path, args, webhook) + if err == nil { + webhook.client = c + } + return err +} + +func (c *Client) GetWebhook(webhookID string, args Arguments) (webhook *Webhook, err error) { + path := fmt.Sprintf("webhooks/%s", webhookID) + err = c.Get(path, args, &webhook) + if webhook != nil { + webhook.client = c + } + return +} + +func (t *Token) GetWebhooks(args Arguments) (webhooks []*Webhook, err error) { + path := fmt.Sprintf("tokens/%s/webhooks", t.ID) + err = t.client.Get(path, args, &webhooks) + return +} + +func GetBoardWebhookRequest(r *http.Request) (whr *BoardWebhookRequest, err error) { + if r.Method == "HEAD" { + return &BoardWebhookRequest{}, nil + } + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(&whr) + if err != nil { + err = errors.Wrapf(err, "GetBoardWebhookRequest() failed to decode '%s'.", r.URL) + } + return +} + +func GetListWebhookRequest(r *http.Request) (whr *ListWebhookRequest, err error) { + if r.Method == "HEAD" { + return &ListWebhookRequest{}, nil + } + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(&whr) + if err != nil { + err = errors.Wrapf(err, "GetListWebhookRequest() failed to decode '%s'.", r.URL) + } + return +} + +func GetCardWebhookRequest(r *http.Request) (whr *CardWebhookRequest, err error) { + if r.Method == "HEAD" { + return &CardWebhookRequest{}, nil + } + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(&whr) + if err != nil { + err = errors.Wrapf(err, "GetCardWebhookRequest() failed to decode '%s'.", r.URL) + } + return +} diff --git a/vendor/github.com/briandowns/openweathermap/.gitignore b/vendor/github.com/briandowns/openweathermap/.gitignore new file mode 100644 index 00000000..850006e4 --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/.gitignore @@ -0,0 +1,31 @@ +# Created by .gitignore support plugin (hsz.mobi) +### Go template +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +.idea +*.iml + +coverage.* diff --git a/vendor/github.com/briandowns/openweathermap/.travis.yml b/vendor/github.com/briandowns/openweathermap/.travis.yml new file mode 100644 index 00000000..28614c4e --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/.travis.yml @@ -0,0 +1,29 @@ +language: go +go: + - 1.5.4 + - 1.6.2 +env: + - GOARCH: amd64 + - GOARCH: 386 +addons: + hosts: + - api.openweathermap.org +before_install: + - sudo apt-get -qq update + - sudo apt-get install -y socat + - cat /etc/hosts + - wget http://ipinfo.io/ip -qO - + - sudo socat TCP-LISTEN:80,fork TCP:${RTCP_HOST}:${RTCP_PORT} > /tmp/socat.log 2>&1 & + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - make test + - $HOME/gopath/bin/goveralls -service=travis-ci -repotoken $COVERALLS_TOKEN +notifications: + email: + recipients: + - brian.downs@gmail.com + on_success: change + on_failure: always + after_success: + - coveralls diff --git a/vendor/github.com/briandowns/openweathermap/CONTRIBUTING.md b/vendor/github.com/briandowns/openweathermap/CONTRIBUTING.md new file mode 100644 index 00000000..f6d0aa74 --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/CONTRIBUTING.md @@ -0,0 +1,14 @@ +# Contributing to openweathermap + +## Issues + +### Reporting an Issue + +* Please add an issue [here](https://github.com/briandowns/openweathermap/issues) and utilize the appropriate label. + +## Fixing Problems and/or Adding Features + +* Feel free to fork and fix an issue(s) or add a feature. +* Please provide tests for the submitted code. +* Run `go fmt` and `go vet` +* Once the pull request is submitted, it'll be tested and merged. diff --git a/vendor/github.com/briandowns/openweathermap/LICENSE b/vendor/github.com/briandowns/openweathermap/LICENSE new file mode 100644 index 00000000..dd5b3a58 --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/LICENSE @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/vendor/github.com/briandowns/openweathermap/Makefile b/vendor/github.com/briandowns/openweathermap/Makefile new file mode 100644 index 00000000..b390203b --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/Makefile @@ -0,0 +1,19 @@ +GOCMD = go +GOBUILD = $(GOCMD) build +GOGET = $(GOCMD) get -v +GOCLEAN = $(GOCMD) clean +GOINSTALL = $(GOCMD) install +GOTEST = $(GOCMD) test + +.PHONY: all + +all: test + +test: + $(GOTEST) -v -covermode=count -coverprofile=coverage.out ./... + +build: test + $(GOBUILD) + +install: test + $(GOINSTALL) diff --git a/vendor/github.com/briandowns/openweathermap/README.md b/vendor/github.com/briandowns/openweathermap/README.md new file mode 100644 index 00000000..cfe1db19 --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/README.md @@ -0,0 +1,279 @@ +# OpenWeatherMap Go API + +[![GoDoc](https://godoc.org/github.com/briandowns/openweathermap?status.svg)](https://godoc.org/github.com/briandowns/openweathermap) [![Build Status](https://travis-ci.org/briandowns/openweathermap.svg?branch=master)](https://travis-ci.org/briandowns/openweathermap) [![Coverage Status](https://coveralls.io/repos/github/briandowns/openweathermap/badge.svg?branch=master)](https://coveralls.io/github/briandowns/openweathermap?branch=master) + +Go (golang) package for use with openweathermap.org's API. + +For more detail about the library and its features, reference your local godoc once installed. + +[Website](https://briandowns.github.io/openweathermap)! + +To use the OpenweatherMap API, you need to obtain an API key. Sign up [here](http://home.openweathermap.org/users/sign_up). Once you have your key, create an environment variable called `OWM_API_KEY`. Start coding! + +[Slack Channel](https://openweathermapgolang.slack.com/messages/general) + +Contributions welcome! + +## Features + +### Current Weather Conditions + +- By City +- By City,St (State) +- By City,Co (Country) +- By City ID +- By Zip,Co (Country) +- By Longitude and Latitude + +## Forecast + +Get the weather conditions for a given number of days. + +- By City +- By City,St (State) +- By City,Co (Country) +- By City ID +- By Longitude and Latitude + +### Access to Condition Codes and Icons + +Gain access to OpenWeatherMap icons and condition codes. + +- Thunderstorms +- Drizzle +- Rain +- Snow +- Atmosphere +- Clouds +- Extreme +- Additional + +### Data Available in Multiple Measurement Systems + +- Fahrenheit (OpenWeatherMap API - imperial) +- Celsius (OpenWeatherMap API - metric) +- Kelvin (OpenWeatherMap API - internal) + +### UV Index Data + +- Current +- Historical + +### Pollution Data + +- Current + +## Historical Conditions + +- By Name +- By ID +- By Coordinates + +## Supported Languages + +English - en, Russian - ru, Italian - it, Spanish - es (or sp), Ukrainian - uk (or ua), German - de, Portuguese - pt, Romanian - ro, Polish - pl, Finnish - fi, Dutch - nl, French - fr, Bulgarian - bg, Swedish - sv (or se), Chinese Traditional - zh_tw, Chinese Simplified - zh (or zh_cn), Turkish - tr, Croatian - hr, Catalan - ca + +## Installation + +```bash +go get github.com/briandowns/openweathermap +``` + +## Examples + +There are a few full examples in the examples directory that can be referenced. 1 is a command line application and 1 is a simple web application. + +```Go +package main + +import ( + "log" + "fmt" + "os" + + // Shortening the import reference name seems to make it a bit easier + owm "github.com/briandowns/openweathermap" +) + +var apiKey = os.Getenv("OWM_API_KEY") + +func main() { + w, err := owm.NewCurrent("F", "ru", apiKey) // fahrenheit (imperial) with Russian output + if err != nil { + log.Fatalln(err) + } + + w.CurrentByName("Phoenix") + fmt.Println(w) +} + +``` + +### Current Conditions by location name + +```Go +func main() { + w, err := owm.NewCurrent("K", "EN", apiKey) // (internal - OpenWeatherMap reference for kelvin) with English output + if err != nil { + log.Fatalln(err) + } + + w.CurrentByName("Phoenix,AZ") + fmt.Println(w) +} +``` + +### Forecast Conditions in imperial (fahrenheit) by coordinates + +```Go +func main() { + w, err := owm.NewForecast("5", "F", "FI", apiKey) // valid options for first parameter are "5" and "16" + if err != nil { + log.Fatalln(err) + } + + w.DailyByCoordinates( + &owm.Coordinates{ + Longitude: -112.07, + Latitude: 33.45, + }, + 5 // five days forecast + ) + fmt.Println(w) +} +``` + +### Current conditions in metric (celsius) by location ID + +```Go +func main() { + w, err := owm.NewCurrent("C", "PL", apiKey) + if err != nil { + log.Fatalln(err) + } + + w.CurrentByID(2172797) + fmt.Println(w) +} +``` + +### Current conditions by zip code. 2 character country code required + +```Go +func main() { + w, err := owm.NewCurrent("F", "EN", apiKey) + if err != nil { + log.Fatalln(err) + } + + w.CurrentByZip(19125, "US") + fmt.Println(w) +} +``` + +### Configure http client + +```Go +func main() { + client := &http.Client{} + w, err := owm.NewCurrent("F", "EN", apiKey, owm.WithHttpClient(client)) + if err != nil { + log.Fatalln(err) + } +} +``` + +### Current UV conditions + +```Go +func main() { + uv, err := owm.NewUV(apiKey) + if err != nil { + log.Fatalln(err) + } + + coord := &owm.Coordinates{ + Longitude: 53.343497, + Latitude: -6.288379, + } + + if err := uv.Current(coord); err != nil { + log.Fatalln(err) + } + + fmt.Println(coord) +} +``` + +### Historical UV conditions + +```Go +func main() { + uv, err := owm.NewUV(apiKey) + if err != nil { + log.Fatalln(err) + } + + coord := &owm.Coordinates{ + Longitude: 54.995656, + Latitude: -7.326834, + } + + end := time.Now().UTC() + start := time.Now().UTC().Add(-time.Hour * time.Duration(24)) + + if err := uv.Historical(coord, start, end); err != nil { + log.Fatalln(err) + } +} +``` + +### UV Information + +```Go +func main() { + uv, err := owm.NewUV(apiKey) + if err != nil { + log.Fatalln(err) + } + + coord := &owm.Coordinates{ + Longitude: 53.343497, + Latitude: -6.288379, + } + + if err := uv.Current(coord); err != nil { + log.Fatalln(err) + } + + info, err := uv.UVInformation() + if err != nil { + log.Fatalln(err) + } + + fmt.Println(info) +} +``` + +### Pollution Information + +```Go +func main() { + pollution, err := owm.NewPollution(apiKey) + if err != nil { + log.Fatalln(err) + } + + params := &owm.PollutionParameters{ + Location: owm.Coordinates{ + Latitude: 0.0, + Longitude: 10.0, + }, + Datetime: "current", + } + + if err := pollution.PollutionByParams(params); err != nil { + log.Fatalln(err) + } +} +``` diff --git a/vendor/github.com/briandowns/openweathermap/conditions.go b/vendor/github.com/briandowns/openweathermap/conditions.go new file mode 100644 index 00000000..e73ececc --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/conditions.go @@ -0,0 +1,185 @@ +// Copyright 2015 Brian J. Downs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openweathermap + +import ( + "fmt" + "io" + "net/http" + "os" +) + +// IconData holds the relevant info for linking icons to conditions. +type IconData struct { + Condition string + Day string + Night string +} + +// ConditionData holds data structure for weather conditions information. +type ConditionData struct { + ID int + Meaning string + Icon1 string + Icon2 string +} + +// RetrieveIcon will get the specified icon from the API. +func RetrieveIcon(destination, iconFile string) (int64, error) { + fullFilePath := fmt.Sprintf("%s/%s", destination, iconFile) + + // Check to see if we've already gotten that icon file. If so, use it + // rather than getting it again. + if _, err := os.Stat(fullFilePath); err != nil { + response, err := http.Get(fmt.Sprintf(iconURL, iconFile)) + if err != nil { + return 0, err + } + defer response.Body.Close() + + // Create the icon file + out, err := os.Create(fullFilePath) + if err != nil { + return 0, err + } + defer out.Close() + + // Fill the empty file with the actual content + n, err := io.Copy(out, response.Body) + if err != nil { + return 0, err + } + return n, nil + } + return 0, nil +} + +// IconList is a slice of IconData pointers +var IconList = []*IconData{ + {Condition: "clear sky", Day: "01d.png", Night: "01n.png"}, + {Condition: "few clouds", Day: "02d.png", Night: "02n.png"}, + {Condition: "scattered clouds", Day: "03d.png", Night: "03n.png"}, + {Condition: "broken clouds", Day: "04d.png", Night: "04n.png"}, + {Condition: "shower rain", Day: "09d.png", Night: "09n.png"}, + {Condition: "rain", Day: "10d.png", Night: "10n.png"}, + {Condition: "thunderstorm", Day: "11d.png", Night: "11n.png"}, + {Condition: "snow", Day: "13d.png", Night: "13n.png"}, + {Condition: "mist", Day: "50d.png", Night: "50n.png"}, +} + +// ThunderstormConditions is a slice of ConditionData pointers +var ThunderstormConditions = []*ConditionData{ + {ID: 200, Meaning: "thunderstorm with light rain", Icon1: "11d.png"}, + {ID: 201, Meaning: "thunderstorm with rain", Icon1: "11d.png"}, + {ID: 202, Meaning: "thunderstorm with heavy rain", Icon1: "11d.png"}, + {ID: 210, Meaning: "light thunderstorm", Icon1: "11d.png"}, + {ID: 211, Meaning: "thunderstorm", Icon1: "11d.png"}, + {ID: 212, Meaning: "heavy thunderstorm", Icon1: "11d.png"}, + {ID: 221, Meaning: "ragged thunderstorm", Icon1: "11d.png"}, + {ID: 230, Meaning: "thunderstorm with light drizzle", Icon1: "11d.png"}, + {ID: 231, Meaning: "thunderstorm with drizzle", Icon1: "11d.png"}, + {ID: 232, Meaning: "thunderstorm with heavy drizzle", Icon1: "11d.png"}, +} + +// DrizzleConditions is a slice of ConditionData pointers +var DrizzleConditions = []*ConditionData{ + {ID: 300, Meaning: "light intensity drizzle", Icon1: "09d.png"}, + {ID: 301, Meaning: "drizzle", Icon1: "09d.png"}, + {ID: 302, Meaning: "heavy intensity drizzle", Icon1: "09d.png"}, + {ID: 310, Meaning: "light intensity drizzle rain", Icon1: "09d.png"}, + {ID: 311, Meaning: "drizzle rain", Icon1: "09d.png"}, + {ID: 312, Meaning: "heavy intensity drizzle rain", Icon1: "09d.png"}, + {ID: 313, Meaning: "shower rain and drizzle", Icon1: "09d.png"}, + {ID: 314, Meaning: "heavy shower rain and drizzle", Icon1: "09d.png"}, + {ID: 321, Meaning: "shower drizzle", Icon1: "09d.png"}, +} + +// RainConditions is a slice of ConditionData pointers +var RainConditions = []*ConditionData{ + {ID: 500, Meaning: "light rain", Icon1: "09d.png"}, + {ID: 501, Meaning: "moderate rain", Icon1: "09d.png"}, + {ID: 502, Meaning: "heavy intensity rain", Icon1: "09d.png"}, + {ID: 503, Meaning: "very heavy rain", Icon1: "09d.png"}, + {ID: 504, Meaning: "extreme rain", Icon1: "09d.png"}, + {ID: 511, Meaning: "freezing rain", Icon1: "13d.png"}, + {ID: 520, Meaning: "light intensity shower rain", Icon1: "09d.png"}, + {ID: 521, Meaning: "shower rain", Icon1: "09d.png"}, + {ID: 522, Meaning: "heavy intensity shower rain", Icon1: "09d.png"}, + {ID: 531, Meaning: "ragged shower rain", Icon1: "09d.png"}, +} + +// SnowConditions is a slice of ConditionData pointers +var SnowConditions = []*ConditionData{ + {ID: 600, Meaning: "light snow", Icon1: "13d.png"}, + {ID: 601, Meaning: "snow", Icon1: "13d.png"}, + {ID: 602, Meaning: "heavy snow", Icon1: "13d.png"}, + {ID: 611, Meaning: "sleet", Icon1: "13d.png"}, + {ID: 612, Meaning: "shower sleet", Icon1: "13d.png"}, + {ID: 615, Meaning: "light rain and snow", Icon1: "13d.png"}, + {ID: 616, Meaning: "rain and snow", Icon1: "13d.png"}, + {ID: 620, Meaning: "light shower snow", Icon1: "13d.png"}, + {ID: 621, Meaning: "shower snow", Icon1: "13d.png"}, + {ID: 622, Meaning: "heavy shower snow", Icon1: "13d.png"}, +} + +// AtmosphereConditions is a slice of ConditionData pointers +var AtmosphereConditions = []*ConditionData{ + {ID: 701, Meaning: "mist", Icon1: "50d.png"}, + {ID: 711, Meaning: "smoke", Icon1: "50d.png"}, + {ID: 721, Meaning: "haze", Icon1: "50d.png"}, + {ID: 731, Meaning: "sand, dust whirls", Icon1: "50d.png"}, + {ID: 741, Meaning: "fog", Icon1: "50d.png"}, + {ID: 751, Meaning: "sand", Icon1: "50d.png"}, + {ID: 761, Meaning: "dust", Icon1: "50d.png"}, + {ID: 762, Meaning: "volcanic ash", Icon1: "50d.png"}, + {ID: 771, Meaning: "squalls", Icon1: "50d.png"}, + {ID: 781, Meaning: "tornado", Icon1: "50d.png"}, +} + +// CloudConditions is a slice of ConditionData pointers +var CloudConditions = []*ConditionData{ + {ID: 800, Meaning: "clear sky", Icon1: "01d.png", Icon2: "01n.png"}, + {ID: 801, Meaning: "few clouds", Icon1: "02d.png", Icon2: " 02n.png"}, + {ID: 802, Meaning: "scattered clouds", Icon1: "03d.png", Icon2: "03d.png"}, + {ID: 803, Meaning: "broken clouds", Icon1: "04d.png", Icon2: "03d.png"}, + {ID: 804, Meaning: "overcast clouds", Icon1: "04d.png", Icon2: "04d.png"}, +} + +// ExtremeConditions is a slice of ConditionData pointers +var ExtremeConditions = []*ConditionData{ + {ID: 900, Meaning: "tornado", Icon1: ""}, + {ID: 901, Meaning: "tropical storm", Icon1: ""}, + {ID: 902, Meaning: "hurricane", Icon1: ""}, + {ID: 903, Meaning: "cold", Icon1: ""}, + {ID: 904, Meaning: "hot", Icon1: ""}, + {ID: 905, Meaning: "windy", Icon1: ""}, + {ID: 906, Meaning: "hail", Icon1: ""}, +} + +// AdditionalConditions is a slive of ConditionData pointers +var AdditionalConditions = []*ConditionData{ + {ID: 951, Meaning: "calm", Icon1: ""}, + {ID: 952, Meaning: "light breeze", Icon1: ""}, + {ID: 953, Meaning: "gentle breeze", Icon1: ""}, + {ID: 954, Meaning: "moderate breeze", Icon1: ""}, + {ID: 955, Meaning: "fresh breeze", Icon1: ""}, + {ID: 956, Meaning: "strong breeze", Icon1: ""}, + {ID: 957, Meaning: "high wind, near gale", Icon1: ""}, + {ID: 958, Meaning: "gale", Icon1: ""}, + {ID: 959, Meaning: "severe gale", Icon1: ""}, + {ID: 960, Meaning: "storm", Icon1: ""}, + {ID: 961, Meaning: "violent storm", Icon1: ""}, + {ID: 962, Meaning: "hurricane", Icon1: ""}, +} diff --git a/vendor/github.com/briandowns/openweathermap/current.go b/vendor/github.com/briandowns/openweathermap/current.go new file mode 100644 index 00000000..52941b71 --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/current.go @@ -0,0 +1,143 @@ +// Copyright 2015 Brian J. Downs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openweathermap + +import ( + "encoding/json" + "fmt" + "net/url" + "strings" +) + +// CurrentWeatherData struct contains an aggregate view of the structs +// defined above for JSON to be unmarshaled into. +type CurrentWeatherData struct { + GeoPos Coordinates `json:"coord"` + Sys Sys `json:"sys"` + Base string `json:"base"` + Weather []Weather `json:"weather"` + Main Main `json:"main"` + Wind Wind `json:"wind"` + Clouds Clouds `json:"clouds"` + Rain Rain `json:"rain"` + Snow Snow `json:"snow"` + Dt int `json:"dt"` + ID int `json:"id"` + Name string `json:"name"` + Cod int `json:"cod"` + Unit string + Lang string + Key string + *Settings +} + +// NewCurrent returns a new CurrentWeatherData pointer with the supplied parameters +func NewCurrent(unit, lang, key string, options ...Option) (*CurrentWeatherData, error) { + unitChoice := strings.ToUpper(unit) + langChoice := strings.ToUpper(lang) + + c := &CurrentWeatherData{ + Settings: NewSettings(), + } + + if ValidDataUnit(unitChoice) { + c.Unit = DataUnits[unitChoice] + } else { + return nil, errUnitUnavailable + } + + if ValidLangCode(langChoice) { + c.Lang = langChoice + } else { + return nil, errLangUnavailable + } + var err error + c.Key, err = setKey(key) + if err != nil { + return nil, err + } + + if err := setOptions(c.Settings, options); err != nil { + return nil, err + } + return c, nil +} + +// CurrentByName will provide the current weather with the provided +// location name. +func (w *CurrentWeatherData) CurrentByName(location string) error { + response, err := w.client.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&q=%s&units=%s&lang=%s"), w.Key, url.QueryEscape(location), w.Unit, w.Lang)) + if err != nil { + return err + } + defer response.Body.Close() + + if err := json.NewDecoder(response.Body).Decode(&w); err != nil { + return err + } + + return nil +} + +// CurrentByCoordinates will provide the current weather with the +// provided location coordinates. +func (w *CurrentWeatherData) CurrentByCoordinates(location *Coordinates) error { + response, err := w.client.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&lat=%f&lon=%f&units=%s&lang=%s"), w.Key, location.Latitude, location.Longitude, w.Unit, w.Lang)) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&w); err != nil { + return err + } + + return nil +} + +// CurrentByID will provide the current weather with the +// provided location ID. +func (w *CurrentWeatherData) CurrentByID(id int) error { + response, err := w.client.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&id=%d&units=%s&lang=%s"), w.Key, id, w.Unit, w.Lang)) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&w); err != nil { + return err + } + + return nil +} + +// CurrentByZip will provide the current weather for the +// provided zip code. +func (w *CurrentWeatherData) CurrentByZip(zip int, countryCode string) error { + response, err := w.client.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "appid=%s&zip=%d,%s&units=%s&lang=%s"), w.Key, zip, countryCode, w.Unit, w.Lang)) + if err != nil { + return err + } + defer response.Body.Close() + if err = json.NewDecoder(response.Body).Decode(&w); err != nil { + return err + } + + return nil +} + +// CurrentByArea will provide the current weather for the +// provided area. +func (w *CurrentWeatherData) CurrentByArea() {} diff --git a/vendor/github.com/briandowns/openweathermap/doc.go b/vendor/github.com/briandowns/openweathermap/doc.go new file mode 100644 index 00000000..39a41ffb --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/doc.go @@ -0,0 +1,18 @@ +// Copyright 2015 Brian J. Downs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package openweathermap is a library for use to access the +// http://openweathermap.org API. JSON is the only return format supported +// at this time. +package openweathermap diff --git a/vendor/github.com/briandowns/openweathermap/forecast.go b/vendor/github.com/briandowns/openweathermap/forecast.go new file mode 100644 index 00000000..ebba0273 --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/forecast.go @@ -0,0 +1,151 @@ +// Copyright 2015 Brian J. Downs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openweathermap + +import ( + "fmt" + "io" + "net/url" + "strconv" + "strings" +) + +// ForecastSys area population +type ForecastSys struct { + Population int `json:"population"` +} + +// Temperature holds returned termperate sure stats +type Temperature struct { + Day float64 `json:"day"` + Min float64 `json:"min"` + Max float64 `json:"max"` + Night float64 `json:"night"` + Eve float64 `json:"eve"` + Morn float64 `json:"morn"` +} + +// City data for given location +type City struct { + ID int `json:"id"` + Name string `json:"name"` + Coord Coordinates `json:"coord"` + Country string `json:"country"` + Population int `json:"population"` + Sys ForecastSys `json:"sys"` +} + +type ForecastWeather interface { + DailyByName(location string, days int) error + DailyByCoordinates(location *Coordinates, days int) error + DailyByID(id, days int) error +} + +// json served by OWM API can take different forms, so all of them must be matched +// by corresponding data type and unmarshall method +type ForecastWeatherJson interface { + Decode(r io.Reader) error +} + +type ForecastWeatherData struct { + Unit string + Lang string + Key string + baseURL string + *Settings + ForecastWeatherJson +} + +// NewForecast returns a new HistoricalWeatherData pointer with +// the supplied arguments. +func NewForecast(forecastType, unit, lang, key string, options ...Option) (*ForecastWeatherData, error) { + unitChoice := strings.ToUpper(unit) + langChoice := strings.ToUpper(lang) + + if forecastType != "16" && forecastType != "5" { + return nil, errForecastUnavailable + } + + if !ValidDataUnit(unitChoice) { + return nil, errUnitUnavailable + } + + if !ValidLangCode(langChoice) { + return nil, errLangUnavailable + } + + settings := NewSettings() + if err := setOptions(settings, options); err != nil { + return nil, err + } + + var err error + k, err := setKey(key) + if err != nil { + return nil, err + } + forecastData := ForecastWeatherData{ + Unit: DataUnits[unitChoice], + Lang: langChoice, + Key: k, + Settings: settings, + } + + if forecastType == "16" { + forecastData.baseURL = forecast16Base + forecastData.ForecastWeatherJson = &Forecast16WeatherData{} + } else { + forecastData.baseURL = forecast5Base + forecastData.ForecastWeatherJson = &Forecast5WeatherData{} + } + + return &forecastData, nil +} + +// DailyByName will provide a forecast for the location given for the +// number of days given. +func (f *ForecastWeatherData) DailyByName(location string, days int) error { + response, err := f.client.Get(fmt.Sprintf(f.baseURL, f.Key, fmt.Sprintf("%s=%s", "q", url.QueryEscape(location)), f.Unit, f.Lang, days)) + if err != nil { + return err + } + defer response.Body.Close() + + return f.ForecastWeatherJson.Decode(response.Body) +} + +// DailyByCoordinates will provide a forecast for the coordinates ID give +// for the number of days given. +func (f *ForecastWeatherData) DailyByCoordinates(location *Coordinates, days int) error { + response, err := f.client.Get(fmt.Sprintf(f.baseURL, f.Key, fmt.Sprintf("lat=%f&lon=%f", location.Latitude, location.Longitude), f.Unit, f.Lang, days)) + if err != nil { + return err + } + defer response.Body.Close() + + return f.ForecastWeatherJson.Decode(response.Body) +} + +// DailyByID will provide a forecast for the location ID give for the +// number of days given. +func (f *ForecastWeatherData) DailyByID(id, days int) error { + response, err := f.client.Get(fmt.Sprintf(f.baseURL, f.Key, fmt.Sprintf("%s=%s", "id", strconv.Itoa(id)), f.Unit, f.Lang, days)) + if err != nil { + return err + } + defer response.Body.Close() + + return f.ForecastWeatherJson.Decode(response.Body) +} diff --git a/vendor/github.com/briandowns/openweathermap/forecast16.go b/vendor/github.com/briandowns/openweathermap/forecast16.go new file mode 100644 index 00000000..3ba9f513 --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/forecast16.go @@ -0,0 +1,36 @@ +package openweathermap + +import ( + "encoding/json" + "io" +) + +// Forecast16WeatherList holds specific query data +type Forecast16WeatherList struct { + Dt int `json:"dt"` + Temp Temperature `json:"temp"` + Pressure float64 `json:"pressure"` + Humidity int `json:"humidity"` + Weather []Weather `json:"weather"` + Speed float64 `json:"speed"` + Deg int `json:"deg"` + Clouds int `json:"clouds"` + Snow float64 `json:"snow"` + Rain float64 `json:"rain"` +} + +// Forecast16WeatherData will hold returned data from queries +type Forecast16WeatherData struct { + COD int `json:"cod"` + Message string `json:"message"` + City City `json:"city"` + Cnt int `json:"cnt"` + List []Forecast16WeatherList `json:"list"` +} + +func (f *Forecast16WeatherData) Decode(r io.Reader) error { + if err := json.NewDecoder(r).Decode(&f); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/briandowns/openweathermap/forecast5.go b/vendor/github.com/briandowns/openweathermap/forecast5.go new file mode 100644 index 00000000..9e52c20a --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/forecast5.go @@ -0,0 +1,50 @@ +package openweathermap + +import ( + "encoding/json" + "io" + "strings" + "time" +) + +type DtTxt struct { + time.Time +} + +func (dt *DtTxt) UnmarshalJSON(b []byte) error { + t, err := time.Parse("2006-01-02 15:04:05", strings.Trim(string(b), "\"")) + dt.Time = t + return err +} + +func (t *DtTxt) MarshalJSON() ([]byte, error) { + return json.Marshal(t) +} + +// Forecast5WeatherList holds specific query data +type Forecast5WeatherList struct { + Dt int `json:"dt"` + Main Main `json:"main"` + Weather []Weather `json:"weather"` + Clouds Clouds `json:"clouds"` + Wind Wind `json:"wind"` + Rain Rain `json:"rain"` + Snow Snow `json:"snow"` + DtTxt DtTxt `json:"dt_txt"` +} + +// Forecast5WeatherData will hold returned data from queries +type Forecast5WeatherData struct { + // COD string `json:"cod"` + // Message float64 `json:"message"` + City City `json:"city"` + Cnt int `json:"cnt"` + List []Forecast5WeatherList `json:"list"` +} + +func (f *Forecast5WeatherData) Decode(r io.Reader) error { + if err := json.NewDecoder(r).Decode(&f); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/briandowns/openweathermap/history.go b/vendor/github.com/briandowns/openweathermap/history.go new file mode 100644 index 00000000..bba6c83d --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/history.go @@ -0,0 +1,147 @@ +// Copyright 2015 Brian J. Downs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openweathermap + +import ( + "encoding/json" + "fmt" + "net/url" + "strings" +) + +// HistoricalParameters struct holds the (optional) fields to be +// supplied for historical data requests. +type HistoricalParameters struct { + Start int64 // Data start (unix time, UTC time zone) + End int64 // Data end (unix time, UTC time zone) + Cnt int // Amount of returned data (one per hour, can be used instead of Data end) +} + +// Rain struct contains 3 hour data +type Rain struct { + ThreeH float64 `json:"3h"` +} + +// Snow struct contains 3 hour data +type Snow struct { + ThreeH float64 `json:"3h"` +} + +// WeatherHistory struct contains aggregate fields from the above +// structs. +type WeatherHistory struct { + Main Main `json:"main"` + Wind Wind `json:"wind"` + Clouds Clouds `json:"clouds"` + Weather []Weather `json:"weather"` + Rain Rain `json:"rain"` + Dt int `json:"dt"` +} + +// HistoricalWeatherData struct is where the JSON is unmarshaled to +// when receiving data for a historical request. +type HistoricalWeatherData struct { + Message string `json:"message"` + Cod int `json:"cod"` + CityData int `json:"city_data"` + CalcTime float64 `json:"calctime"` + Cnt int `json:"cnt"` + List []WeatherHistory `json:"list"` + Unit string + Key string + *Settings +} + +// NewHistorical returns a new HistoricalWeatherData pointer with +//the supplied arguments. +func NewHistorical(unit, key string, options ...Option) (*HistoricalWeatherData, error) { + h := &HistoricalWeatherData{ + Settings: NewSettings(), + } + + unitChoice := strings.ToUpper(unit) + if !ValidDataUnit(unitChoice) { + return nil, errUnitUnavailable + } + h.Unit = DataUnits[unitChoice] + + var err error + h.Key, err = setKey(key) + if err != nil { + return nil, err + } + + if err := setOptions(h.Settings, options); err != nil { + return nil, err + } + return h, nil +} + +// HistoryByName will return the history for the provided location +func (h *HistoricalWeatherData) HistoryByName(location string) error { + response, err := h.client.Get(fmt.Sprintf(fmt.Sprintf(historyURL, "city?appid=%s&q=%s"), h.Key, url.QueryEscape(location))) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&h); err != nil { + return err + } + + return nil +} + +// HistoryByID will return the history for the provided location ID +func (h *HistoricalWeatherData) HistoryByID(id int, hp ...*HistoricalParameters) error { + if len(hp) > 0 { + response, err := h.client.Get(fmt.Sprintf(fmt.Sprintf(historyURL, "city?appid=%s&id=%d&type=hour&start%d&end=%d&cnt=%d"), h.Key, id, hp[0].Start, hp[0].End, hp[0].Cnt)) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&h); err != nil { + return err + } + } + + response, err := h.client.Get(fmt.Sprintf(fmt.Sprintf(historyURL, "city?appid=%s&id=%d"), h.Key, id)) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&h); err != nil { + return err + } + + return nil +} + +// HistoryByCoord will return the history for the provided coordinates +func (h *HistoricalWeatherData) HistoryByCoord(location *Coordinates, hp *HistoricalParameters) error { + response, err := h.client.Get(fmt.Sprintf(fmt.Sprintf(historyURL, "appid=%s&lat=%f&lon=%f&start=%d&end=%d"), h.Key, location.Latitude, location.Longitude, hp.Start, hp.End)) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&h); err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/briandowns/openweathermap/openweathermap.go b/vendor/github.com/briandowns/openweathermap/openweathermap.go new file mode 100644 index 00000000..b256c27d --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/openweathermap.go @@ -0,0 +1,228 @@ +// Copyright 2015 Brian J. Downs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openweathermap + +import ( + "errors" + "net/http" +) + +var errUnitUnavailable = errors.New("unit unavailable") +var errLangUnavailable = errors.New("language unavailable") +var errInvalidKey = errors.New("invalid api key") +var errInvalidOption = errors.New("invalid option") +var errInvalidHttpClient = errors.New("invalid http client") +var errForecastUnavailable = errors.New("forecast unavailable") + +// DataUnits represents the character chosen to represent the temperature notation +var DataUnits = map[string]string{"C": "metric", "F": "imperial", "K": "internal"} +var ( + baseURL = "http://api.openweathermap.org/data/2.5/weather?%s" + iconURL = "http://openweathermap.org/img/w/%s" + stationURL = "http://api.openweathermap.org/data/2.5/station?id=%d" + forecast5Base = "http://api.openweathermap.org/data/2.5/forecast?appid=%s&%s&mode=json&units=%s&lang=%s&cnt=%d" + forecast16Base = "http://api.openweathermap.org/data/2.5/forecast/daily?appid=%s&%s&mode=json&units=%s&lang=%s&cnt=%d" + historyURL = "http://api.openweathermap.org/data/2.5/history/%s" + pollutionURL = "http://api.openweathermap.org/pollution/v1/co/" + uvURL = "http://api.openweathermap.org/data/2.5/" + dataPostURL = "http://openweathermap.org/data/post" +) + +// LangCodes holds all supported languages to be used +// inspried and sourced from @bambocher (github.com/bambocher) +var LangCodes = map[string]string{ + "EN": "English", + "RU": "Russian", + "IT": "Italian", + "ES": "Spanish", + "SP": "Spanish", + "UK": "Ukrainian", + "UA": "Ukrainian", + "DE": "German", + "PT": "Portuguese", + "RO": "Romanian", + "PL": "Polish", + "FI": "Finnish", + "NL": "Dutch", + "FR": "French", + "BG": "Bulgarian", + "SV": "Swedish", + "SE": "Swedish", + "TR": "Turkish", + "HR": "Croatian", + "CA": "Catalan", + "ZH_TW": "Chinese Traditional", + "ZH": "Chinese Simplified", + "ZH_CN": "Chinese Simplified", +} + +// Config will hold default settings to be passed into the +// "NewCurrent, NewForecast, etc}" functions. +type Config struct { + Mode string // user choice of JSON or XML + Unit string // measurement for results to be displayed. F, C, or K + Lang string // should reference a key in the LangCodes map + APIKey string // API Key for connecting to the OWM + Username string // Username for posting data + Password string // Pasword for posting data +} + +// APIError returned on failed API calls. +type APIError struct { + Message string `json:"message"` + COD string `json:"cod"` +} + +// Coordinates struct holds longitude and latitude data in returned +// JSON or as parameter data for requests using longitude and latitude. +type Coordinates struct { + Longitude float64 `json:"lon"` + Latitude float64 `json:"lat"` +} + +// Sys struct contains general information about the request +// and the surrounding area for where the request was made. +type Sys struct { + Type int `json:"type"` + ID int `json:"id"` + Message float64 `json:"message"` + Country string `json:"country"` + Sunrise int `json:"sunrise"` + Sunset int `json:"sunset"` +} + +// Wind struct contains the speed and degree of the wind. +type Wind struct { + Speed float64 `json:"speed"` + Deg float64 `json:"deg"` +} + +// Weather struct holds high-level, basic info on the returned +// data. +type Weather struct { + ID int `json:"id"` + Main string `json:"main"` + Description string `json:"description"` + Icon string `json:"icon"` +} + +// Main struct contains the temperates, humidity, pressure for the request. +type Main struct { + Temp float64 `json:"temp"` + TempMin float64 `json:"temp_min"` + TempMax float64 `json:"temp_max"` + Pressure float64 `json:"pressure"` + SeaLevel float64 `json:"sea_level"` + GrndLevel float64 `json:"grnd_level"` + Humidity int `json:"humidity"` +} + +// Clouds struct holds data regarding cloud cover. +type Clouds struct { + All int `json:"all"` +} + +// return key +// } +func setKey(key string) (string, error) { + if err := ValidAPIKey(key); err != nil { + return "", err + } + return key, nil +} + +// ValidDataUnit makes sure the string passed in is an accepted +// unit of measure to be used for the return data. +func ValidDataUnit(u string) bool { + for d := range DataUnits { + if u == d { + return true + } + } + return false +} + +// ValidLangCode makes sure the string passed in is an +// acceptable lang code. +func ValidLangCode(c string) bool { + for d := range LangCodes { + if c == d { + return true + } + } + return false +} + +// ValidDataUnitSymbol makes sure the string passed in is an +// acceptable data unit symbol. +func ValidDataUnitSymbol(u string) bool { + for _, d := range DataUnits { + if u == d { + return true + } + } + return false +} + +// ValidAPIKey makes sure that the key given is a valid one +func ValidAPIKey(key string) error { + if len(key) != 32 { + return errors.New("invalid key") + } + return nil +} + +// CheckAPIKeyExists will see if an API key has been set. +func (c *Config) CheckAPIKeyExists() bool { return len(c.APIKey) > 1 } + +// Settings holds the client settings +type Settings struct { + client *http.Client +} + +// NewSettings returns a new Setting pointer with default http client. +func NewSettings() *Settings { + return &Settings{ + client: http.DefaultClient, + } +} + +// Optional client settings +type Option func(s *Settings) error + +// WithHttpClient sets custom http client when creating a new Client. +func WithHttpClient(c *http.Client) Option { + return func(s *Settings) error { + if c == nil { + return errInvalidHttpClient + } + s.client = c + return nil + } +} + +// setOptions sets Optional client settings to the Settings pointer +func setOptions(settings *Settings, options []Option) error { + for _, option := range options { + if option == nil { + return errInvalidOption + } + err := option(settings) + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/briandowns/openweathermap/pollution.go b/vendor/github.com/briandowns/openweathermap/pollution.go new file mode 100644 index 00000000..abb5b2dd --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/pollution.go @@ -0,0 +1,82 @@ +package openweathermap + +import ( + "encoding/json" + "fmt" + "strconv" +) + +// DateTimeAliases holds the alias the pollution API supports in lieu +// of an ISO 8601 timestamp +var DateTimeAliases = []string{"current"} + +// ValidAlias checks to make sure the given alias is a valid one +func ValidAlias(alias string) bool { + for _, i := range DateTimeAliases { + if i == alias { + return true + } + } + return false +} + +// PollutionData holds the pollution specific data from the call +type PollutionData struct { + Precision float64 `json:"precision"` + Pressure float64 `json:"pressure"` + Value float64 `json:"value"` +} + +// PollutionParameters holds the parameters needed to make +// a call to the pollution API +type PollutionParameters struct { + Location Coordinates + Datetime string // this should be either ISO 8601 or an alias +} + +// Pollution holds the data returnd from the pollution API +type Pollution struct { + Time string `json:"time"` + Location Coordinates `json:"location"` + Data []PollutionData `json:"data"` + Key string + *Settings +} + +// NewPollution creates a new reference to Pollution +func NewPollution(key string, options ...Option) (*Pollution, error) { + k, err := setKey(key) + if err != nil { + return nil, err + } + p := &Pollution{ + Key: k, + Settings: NewSettings(), + } + + if err := setOptions(p.Settings, options); err != nil { + return nil, err + } + return p, nil +} + +// PollutionByParams gets the pollution data based on the given parameters +func (p *Pollution) PollutionByParams(params *PollutionParameters) error { + url := fmt.Sprintf("%s%s,%s/%s.json?appid=%s", + pollutionURL, + strconv.FormatFloat(params.Location.Latitude, 'f', -1, 64), + strconv.FormatFloat(params.Location.Longitude, 'f', -1, 64), + params.Datetime, + p.Key) + response, err := p.client.Get(url) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&p); err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/briandowns/openweathermap/station.go b/vendor/github.com/briandowns/openweathermap/station.go new file mode 100644 index 00000000..731cf08e --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/station.go @@ -0,0 +1,80 @@ +// Copyright 2015 Brian J. Downs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openweathermap + +import ( + "fmt" + "net/http" + "net/url" +) + +// Slice of type string of the valid parameters to be sent from a station. +// The API refers to this data as the "Weather station data transmission protocol" +var StationDataParameters = []string{ + "wind_dir", // Wind direction + "wind_speed", // Wind speed + "wind_gust", // Wind gust speed + "temp", // Temperature + "humidity", // Relative humidty + "pressure", // Atmospheric pressure + "rain_1h", // Rain in the last hour + "rain_24h", // Rain in the last 24 hours + "rain_today", // Rain since midnight + "snow", // Snow in the last 24 hours + "lum", // Brightness + "lat", // Latitude + "long", // Longitude + "alt", // Altitude + "radiation", // Radiation + "dewpoint", // Dew point + "uv", // UV index + "name", // Weather station name +} + +// ValidateStationDataParameter will make sure that whatever parameter +// supplied is one that can actually be used in the POST request. +func ValidateStationDataParameter(param string) bool { + for _, p := range StationDataParameters { + if param == p { + return true + } + } + + return false +} + +// ConvertToURLValues will convert a map to a url.Values instance. We're +// taking a map[string]string instead of something more type specific since +// the url.Values instance only takes strings to create the URL values. +func ConvertToURLValues(data map[string]string) string { + v := url.Values{} + + for key, val := range data { + v.Set(key, val) + } + + return v.Encode() +} + +// SendStationData will send an instance the provided url.Values to the +// provided URL. +func SendStationData(data url.Values) { + resp, err := http.PostForm(dataPostURL, data) + if err != nil { + fmt.Println(err) + } + + fmt.Println(resp.Body) +} diff --git a/vendor/github.com/briandowns/openweathermap/uv.go b/vendor/github.com/briandowns/openweathermap/uv.go new file mode 100644 index 00000000..2b10b9d1 --- /dev/null +++ b/vendor/github.com/briandowns/openweathermap/uv.go @@ -0,0 +1,170 @@ +package openweathermap + +import ( + "encoding/json" + "errors" + "fmt" + "time" +) + +var errInvalidUVIndex = errors.New("invalid UV index value") + +// UVDataPoints holds the UV specific data +type UVDataPoints struct { + DT int64 `json:"dt"` + Value float64 `json:"value"` +} + +// UV contains the response from the OWM UV API +type UV struct { + Coord []float64 `json:"coord"` + Data []UVDataPoints `json:"data,omitempty"` + /*Data []struct { + DT int64 `json:"dt"` + Value float64 `json:"value"` + } `json:"data,omitempty"`*/ + DT int64 `json:"dt,omitempty"` + Value float64 `json:"value,omitempty"` + Key string + *Settings +} + +// NewUV creates a new reference to UV +func NewUV(key string, options ...Option) (*UV, error) { + k, err := setKey(key) + if err != nil { + return nil, err + } + u := &UV{ + Key: k, + Settings: NewSettings(), + } + + if err := setOptions(u.Settings, options); err != nil { + return nil, err + } + return u, nil +} + +// Current gets the current UV data for the given coordinates +func (u *UV) Current(coord *Coordinates) error { + response, err := u.client.Get(fmt.Sprintf("%suvi?lat=%f&lon=%f&appid=%s", uvURL, coord.Latitude, coord.Longitude, u.Key)) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&u); err != nil { + return err + } + + return nil +} + +// Historical gets the historical UV data for the coordinates and times +func (u *UV) Historical(coord *Coordinates, start, end time.Time) error { + response, err := u.client.Get(fmt.Sprintf("%shistory?lat=%f&lon=%f&start=%d&end=%d&appid=%s", uvURL, coord.Latitude, coord.Longitude, start.Unix(), end.Unix(), u.Key)) + if err != nil { + return err + } + defer response.Body.Close() + + if err = json.NewDecoder(response.Body).Decode(&u); err != nil { + return err + } + + return nil +} + +// UVIndexInfo +type UVIndexInfo struct { + // UVIndex holds the range of the index + UVIndex []float64 + + // MGC represents the Media graphic color + MGC string + + // Risk of harm from unprotected sun exposure, for the average adult + Risk string + + // RecommendedProtection contains information on what a person should + // do when outside in the associated UVIndex + RecommendedProtection string +} + +// UVData contains data in regards to UV index ranges, rankings, and steps for protection +var UVData = []UVIndexInfo{ + { + UVIndex: []float64{0, 2.9}, + MGC: "Green", + Risk: "Low", + RecommendedProtection: "Wear sunglasses on bright days; use sunscreen if there is snow on the ground, which reflects UV radiation, or if you have particularly fair skin.", + }, + { + UVIndex: []float64{3, 5.9}, + MGC: "Yellow", + Risk: "Moderate", + RecommendedProtection: "Take precautions, such as covering up, if you will be outside. Stay in shade near midday when the sun is strongest.", + }, + { + UVIndex: []float64{6, 7.9}, + MGC: "Orange", + Risk: "High", + RecommendedProtection: "Cover the body with sun protective clothing, use SPF 30+ sunscreen, wear a hat, reduce time in the sun within three hours of solar noon, and wear sunglasses.", + }, + { + UVIndex: []float64{8, 10.9}, + MGC: "Red", + Risk: "Very high", + RecommendedProtection: "Wear SPF 30+ sunscreen, a shirt, sunglasses, and a wide-brimmed hat. Do not stay in the sun for too long.", + }, + { + UVIndex: []float64{11}, + MGC: "Violet", + Risk: "Extreme", + RecommendedProtection: "Take all precautions: Wear SPF 30+ sunscreen, a long-sleeved shirt and trousers, sunglasses, and a very broad hat. Avoid the sun within three hours of solar noon.", + }, +} + +// UVInformation provides information on the given UV data which includes the severity +// and "Recommended protection" +func (u *UV) UVInformation() ([]UVIndexInfo, error) { + switch { + case u.Value != 0: + switch { + case u.Value < 2.9: + return []UVIndexInfo{UVData[0]}, nil + case u.Value > 3 && u.Value < 5.9: + return []UVIndexInfo{UVData[1]}, nil + case u.Value > 6 && u.Value < 7.9: + return []UVIndexInfo{UVData[2]}, nil + case u.Value > 8 && u.Value < 10.9: + return []UVIndexInfo{UVData[3]}, nil + case u.Value >= 11: + return []UVIndexInfo{UVData[4]}, nil + default: + return nil, errInvalidUVIndex + } + + case len(u.Data) > 0: + var uvi []UVIndexInfo + for _, i := range u.Data { + switch { + case i.Value < 2.9: + uvi = append(uvi, UVData[0]) + case i.Value > 3 && u.Value < 5.9: + uvi = append(uvi, UVData[1]) + case i.Value > 6 && u.Value < 7.9: + uvi = append(uvi, UVData[2]) + case i.Value > 8 && u.Value < 10.9: + uvi = append(uvi, UVData[3]) + case i.Value >= 11: + uvi = append(uvi, UVData[4]) + default: + return nil, errInvalidUVIndex + } + } + } + + return nil, nil +} diff --git a/vendor/github.com/gdamore/encoding/.appveyor.yml b/vendor/github.com/gdamore/encoding/.appveyor.yml new file mode 100644 index 00000000..19a4c5dd --- /dev/null +++ b/vendor/github.com/gdamore/encoding/.appveyor.yml @@ -0,0 +1,13 @@ +version: 1.0.{build} +clone_folder: c:\gopath\src\github.com\gdamore\encoding +environment: + GOPATH: c:\gopath +build_script: +- go version +- go env +- SET PATH=%LOCALAPPDATA%\atom\bin;%GOPATH%\bin;%PATH% +- go get -t ./... +- go build +- go install ./... +test_script: +- go test ./... diff --git a/vendor/github.com/gdamore/encoding/.travis.yml b/vendor/github.com/gdamore/encoding/.travis.yml new file mode 100644 index 00000000..cfc7547b --- /dev/null +++ b/vendor/github.com/gdamore/encoding/.travis.yml @@ -0,0 +1,6 @@ +language: go + +go: + - 1.3 + - 1.5 + - tip diff --git a/vendor/github.com/gdamore/encoding/LICENSE b/vendor/github.com/gdamore/encoding/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/vendor/github.com/gdamore/encoding/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/gdamore/encoding/README.md b/vendor/github.com/gdamore/encoding/README.md new file mode 100644 index 00000000..3db2b4c5 --- /dev/null +++ b/vendor/github.com/gdamore/encoding/README.md @@ -0,0 +1,19 @@ +## encoding + +[![Linux Status](https://img.shields.io/travis/gdamore/encoding.svg?label=linux)](https://travis-ci.org/gdamore/encoding) +[![Windows Status](https://img.shields.io/appveyor/ci/gdamore/encoding.svg?label=windows)](https://ci.appveyor.com/project/gdamore/encoding) +[![Apache License](https://img.shields.io/badge/license-APACHE2-blue.svg)](https://github.com/gdamore/encoding/blob/master/LICENSE) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/gdamore/encoding) +[![Go Report Card](http://goreportcard.com/badge/gdamore/encoding)](http://goreportcard.com/report/gdamore/encoding) + +Package encoding provides a number of encodings that are missing from the +standard Go [encoding]("https://godoc.org/golang.org/x/text/encoding") package. + +We hope that we can contribute these to the standard Go library someday. It +turns out that some of these are useful for dealing with I/O streams coming +from non-UTF friendly sources. + +The UTF8 Encoder is also useful for situations where valid UTF-8 might be +carried in streams that contain non-valid UTF; in particular I use it for +helping me cope with terminals that embed escape sequences in otherwise +valid UTF-8. diff --git a/vendor/github.com/gdamore/encoding/ascii.go b/vendor/github.com/gdamore/encoding/ascii.go new file mode 100644 index 00000000..b7321f43 --- /dev/null +++ b/vendor/github.com/gdamore/encoding/ascii.go @@ -0,0 +1,36 @@ +// Copyright 2015 Garrett D'Amore +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encoding + +import ( + "golang.org/x/text/encoding" +) + +// ASCII represents the 7-bit US-ASCII scheme. It decodes directly to +// UTF-8 without change, as all ASCII values are legal UTF-8. +// Unicode values less than 128 (i.e. 7 bits) map 1:1 with ASCII. +// It encodes runes outside of that to 0x1A, the ASCII substitution character. +var ASCII encoding.Encoding + +func init() { + amap := make(map[byte]rune) + for i := 128; i <= 255; i++ { + amap[byte(i)] = RuneError + } + + cm := &Charmap{Map: amap} + cm.Init() + ASCII = cm +} diff --git a/vendor/github.com/gdamore/encoding/charmap.go b/vendor/github.com/gdamore/encoding/charmap.go new file mode 100644 index 00000000..e64eaed1 --- /dev/null +++ b/vendor/github.com/gdamore/encoding/charmap.go @@ -0,0 +1,192 @@ +// Copyright 2015 Garrett D'Amore +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encoding + +import ( + "sync" + "unicode/utf8" + + "golang.org/x/text/transform" + "golang.org/x/text/encoding" +) + +const ( + // RuneError is an alias for the UTF-8 replacement rune, '\uFFFD'. + RuneError = '\uFFFD' + + // RuneSelf is the rune below which UTF-8 and the Unicode values are + // identical. Its also the limit for ASCII. + RuneSelf = 0x80 + + // ASCIISub is the ASCII substitution character. + ASCIISub = '\x1a' +) + +// Charmap is a structure for setting up encodings for 8-bit character sets, +// for transforming between UTF8 and that other character set. It has some +// ideas borrowed from golang.org/x/text/encoding/charmap, but it uses a +// different implementation. This implementation uses maps, and supports +// user-defined maps. +// +// We do assume that a character map has a reasonable substitution character, +// and that valid encodings are stable (exactly a 1:1 map) and stateless +// (that is there is no shift character or anything like that.) Hence this +// approach will not work for many East Asian character sets. +// +// Measurement shows little or no measurable difference in the performance of +// the two approaches. The difference was down to a couple of nsec/op, and +// no consistent pattern as to which ran faster. With the conversion to +// UTF-8 the code takes about 25 nsec/op. The conversion in the reverse +// direction takes about 100 nsec/op. (The larger cost for conversion +// from UTF-8 is most likely due to the need to convert the UTF-8 byte stream +// to a rune before conversion. +// +type Charmap struct { + transform.NopResetter + bytes map[rune]byte + runes [256][]byte + once sync.Once + + // The map between bytes and runes. To indicate that a specific + // byte value is invalid for a charcter set, use the rune + // utf8.RuneError. Values that are absent from this map will + // be assumed to have the identity mapping -- that is the default + // is to assume ISO8859-1, where all 8-bit characters have the same + // numeric value as their Unicode runes. (Not to be confused with + // the UTF-8 values, which *will* be different for non-ASCII runes.) + // + // If no values less than RuneSelf are changed (or have non-identity + // mappings), then the character set is assumed to be an ASCII + // superset, and certain assumptions and optimizations become + // available for ASCII bytes. + Map map[byte]rune + + // The ReplacementChar is the byte value to use for substitution. + // It should normally be ASCIISub for ASCII encodings. This may be + // unset (left to zero) for mappings that are strictly ASCII supersets. + // In that case ASCIISub will be assumed instead. + ReplacementChar byte +} + +type cmapDecoder struct { + transform.NopResetter + runes [256][]byte +} + +type cmapEncoder struct { + transform.NopResetter + bytes map[rune]byte + replace byte +} + +// Init initializes internal values of a character map. This should +// be done early, to minimize the cost of allocation of transforms +// later. It is not strictly necessary however, as the allocation +// functions will arrange to call it if it has not already been done. +func (c *Charmap) Init() { + c.once.Do(c.initialize) +} + +func (c *Charmap) initialize() { + c.bytes = make(map[rune]byte) + ascii := true + + for i := 0; i < 256; i++ { + r, ok := c.Map[byte(i)] + if !ok { + r = rune(i) + } + if r < 128 && r != rune(i) { + ascii = false + } + if r != RuneError { + c.bytes[r] = byte(i) + } + utf := make([]byte, utf8.RuneLen(r)) + utf8.EncodeRune(utf, r) + c.runes[i] = utf + } + if ascii && c.ReplacementChar == '\x00' { + c.ReplacementChar = ASCIISub + } +} + +// NewDecoder returns a Decoder the converts from the 8-bit +// character set to UTF-8. Unknown mappings, if any, are mapped +// to '\uFFFD'. +func (c *Charmap) NewDecoder() *encoding.Decoder { + c.Init() + return &encoding.Decoder{Transformer: &cmapDecoder{runes: c.runes}} +} + +// NewEncoder returns a Transformer that converts from UTF8 to the +// 8-bit character set. Unknown mappings are mapped to 0x1A. +func (c *Charmap) NewEncoder() *encoding.Encoder { + c.Init() + return &encoding.Encoder{Transformer: + &cmapEncoder{bytes: c.bytes, replace: c.ReplacementChar}} +} + +func (d *cmapDecoder) Transform(dst, src []byte, atEOF bool) (int, int, error) { + var e error + var ndst, nsrc int + + for _, c := range src { + b := d.runes[c] + l := len(b) + + if ndst+l > len(dst) { + e = transform.ErrShortDst + break + } + for i := 0; i < l; i++ { + dst[ndst] = b[i] + ndst++ + } + nsrc++ + } + return ndst, nsrc, e +} + +func (d *cmapEncoder) Transform(dst, src []byte, atEOF bool) (int, int, error) { + var e error + var ndst, nsrc int + for nsrc < len(src) { + if ndst >= len(dst) { + e = transform.ErrShortDst + break + } + + r, sz := utf8.DecodeRune(src[nsrc:]) + if r == utf8.RuneError && sz == 1 { + // If its inconclusive due to insufficient data in + // in the source, report it + if !atEOF && !utf8.FullRune(src[nsrc:]) { + e = transform.ErrShortSrc + break + } + } + + if c, ok := d.bytes[r]; ok { + dst[ndst] = c + } else { + dst[ndst] = d.replace + } + nsrc += sz + ndst++ + } + + return ndst, nsrc, e +} diff --git a/vendor/github.com/gdamore/encoding/doc.go b/vendor/github.com/gdamore/encoding/doc.go new file mode 100644 index 00000000..8a7b48d7 --- /dev/null +++ b/vendor/github.com/gdamore/encoding/doc.go @@ -0,0 +1,17 @@ +// Copyright 2015 Garrett D'Amore +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package encoding provides a few of the encoding structures that are +// missing from the Go x/text/encoding tree. +package encoding diff --git a/vendor/github.com/gdamore/encoding/ebcdic.go b/vendor/github.com/gdamore/encoding/ebcdic.go new file mode 100644 index 00000000..8e13f1a9 --- /dev/null +++ b/vendor/github.com/gdamore/encoding/ebcdic.go @@ -0,0 +1,273 @@ +// Copyright 2015 Garrett D'Amore +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encoding + +import ( + "golang.org/x/text/encoding" +) + +// EBCDIC represents the 8-bit EBCDIC scheme, found in some mainframe +// environments. If you don't know what this is, consider yourself lucky. +var EBCDIC encoding.Encoding + +func init() { + cm := &Charmap{ + ReplacementChar: '\x3f', + Map: map[byte]rune{ + // 0x00-0x03 match + 0x04: RuneError, + 0x05: '\t', + 0x06: RuneError, + 0x07: '\x7f', + 0x08: RuneError, + 0x09: RuneError, + 0x0a: RuneError, + // 0x0b-0x13 match + 0x14: RuneError, + 0x15: '\x85', // Not in any ISO code + 0x16: '\x08', + 0x17: RuneError, + // 0x18-0x19 match + 0x1a: RuneError, + 0x1b: RuneError, + // 0x1c-0x1f match + 0x20: RuneError, + 0x21: RuneError, + 0x22: RuneError, + 0x23: RuneError, + 0x24: RuneError, + 0x25: '\n', + 0x26: '\x17', + 0x27: '\x1b', + 0x28: RuneError, + 0x29: RuneError, + 0x2a: RuneError, + 0x2b: RuneError, + 0x2c: RuneError, + 0x2d: '\x05', + 0x2e: '\x06', + 0x2f: '\x07', + 0x30: RuneError, + 0x31: RuneError, + 0x32: '\x16', + 0x33: RuneError, + 0x34: RuneError, + 0x35: RuneError, + 0x36: RuneError, + 0x37: '\x04', + 0x38: RuneError, + 0x39: RuneError, + 0x3a: RuneError, + 0x3b: RuneError, + 0x3c: '\x14', + 0x3d: '\x15', + 0x3e: RuneError, + 0x3f: '\x1a', // also replacement char + 0x40: ' ', + 0x41: '\xa0', + 0x42: RuneError, + 0x43: RuneError, + 0x44: RuneError, + 0x45: RuneError, + 0x46: RuneError, + 0x47: RuneError, + 0x48: RuneError, + 0x49: RuneError, + 0x4a: RuneError, + 0x4b: '.', + 0x4c: '<', + 0x4d: '(', + 0x4e: '+', + 0x4f: '|', + 0x50: '&', + 0x51: RuneError, + 0x52: RuneError, + 0x53: RuneError, + 0x54: RuneError, + 0x55: RuneError, + 0x56: RuneError, + 0x57: RuneError, + 0x58: RuneError, + 0x59: RuneError, + 0x5a: '!', + 0x5b: '$', + 0x5c: '*', + 0x5d: ')', + 0x5e: ';', + 0x5f: '¬', + 0x60: '-', + 0x61: '/', + 0x62: RuneError, + 0x63: RuneError, + 0x64: RuneError, + 0x65: RuneError, + 0x66: RuneError, + 0x67: RuneError, + 0x68: RuneError, + 0x69: RuneError, + 0x6a: '¦', + 0x6b: ',', + 0x6c: '%', + 0x6d: '_', + 0x6e: '>', + 0x6f: '?', + 0x70: RuneError, + 0x71: RuneError, + 0x72: RuneError, + 0x73: RuneError, + 0x74: RuneError, + 0x75: RuneError, + 0x76: RuneError, + 0x77: RuneError, + 0x78: RuneError, + 0x79: '`', + 0x7a: ':', + 0x7b: '#', + 0x7c: '@', + 0x7d: '\'', + 0x7e: '=', + 0x7f: '"', + 0x80: RuneError, + 0x81: 'a', + 0x82: 'b', + 0x83: 'c', + 0x84: 'd', + 0x85: 'e', + 0x86: 'f', + 0x87: 'g', + 0x88: 'h', + 0x89: 'i', + 0x8a: RuneError, + 0x8b: RuneError, + 0x8c: RuneError, + 0x8d: RuneError, + 0x8e: RuneError, + 0x8f: '±', + 0x90: RuneError, + 0x91: 'j', + 0x92: 'k', + 0x93: 'l', + 0x94: 'm', + 0x95: 'n', + 0x96: 'o', + 0x97: 'p', + 0x98: 'q', + 0x99: 'r', + 0x9a: RuneError, + 0x9b: RuneError, + 0x9c: RuneError, + 0x9d: RuneError, + 0x9e: RuneError, + 0x9f: RuneError, + 0xa0: RuneError, + 0xa1: '~', + 0xa2: 's', + 0xa3: 't', + 0xa4: 'u', + 0xa5: 'v', + 0xa6: 'w', + 0xa7: 'x', + 0xa8: 'y', + 0xa9: 'z', + 0xaa: RuneError, + 0xab: RuneError, + 0xac: RuneError, + 0xad: RuneError, + 0xae: RuneError, + 0xaf: RuneError, + 0xb0: '^', + 0xb1: RuneError, + 0xb2: RuneError, + 0xb3: RuneError, + 0xb4: RuneError, + 0xb5: RuneError, + 0xb6: RuneError, + 0xb7: RuneError, + 0xb8: RuneError, + 0xb9: RuneError, + 0xba: '[', + 0xbb: ']', + 0xbc: RuneError, + 0xbd: RuneError, + 0xbe: RuneError, + 0xbf: RuneError, + 0xc0: '{', + 0xc1: 'A', + 0xc2: 'B', + 0xc3: 'C', + 0xc4: 'D', + 0xc5: 'E', + 0xc6: 'F', + 0xc7: 'G', + 0xc8: 'H', + 0xc9: 'I', + 0xca: '\xad', // NB: soft hyphen + 0xcb: RuneError, + 0xcc: RuneError, + 0xcd: RuneError, + 0xce: RuneError, + 0xcf: RuneError, + 0xd0: '}', + 0xd1: 'J', + 0xd2: 'K', + 0xd3: 'L', + 0xd4: 'M', + 0xd5: 'N', + 0xd6: 'O', + 0xd7: 'P', + 0xd8: 'Q', + 0xd9: 'R', + 0xda: RuneError, + 0xdb: RuneError, + 0xdc: RuneError, + 0xdd: RuneError, + 0xde: RuneError, + 0xdf: RuneError, + 0xe0: '\\', + 0xe1: '\u2007', // Non-breaking space + 0xe2: 'S', + 0xe3: 'T', + 0xe4: 'U', + 0xe5: 'V', + 0xe6: 'W', + 0xe7: 'X', + 0xe8: 'Y', + 0xe9: 'Z', + 0xea: RuneError, + 0xeb: RuneError, + 0xec: RuneError, + 0xed: RuneError, + 0xee: RuneError, + 0xef: RuneError, + 0xf0: '0', + 0xf1: '1', + 0xf2: '2', + 0xf3: '3', + 0xf4: '4', + 0xf5: '5', + 0xf6: '6', + 0xf7: '7', + 0xf8: '8', + 0xf9: '9', + 0xfa: RuneError, + 0xfb: RuneError, + 0xfc: RuneError, + 0xfd: RuneError, + 0xfe: RuneError, + 0xff: RuneError, + }} + cm.Init() + EBCDIC = cm +} diff --git a/vendor/github.com/gdamore/encoding/latin1.go b/vendor/github.com/gdamore/encoding/latin1.go new file mode 100644 index 00000000..226bf01d --- /dev/null +++ b/vendor/github.com/gdamore/encoding/latin1.go @@ -0,0 +1,33 @@ +// Copyright 2015 Garrett D'Amore +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encoding + +import ( + "golang.org/x/text/encoding" +) + +// ISO8859_1 represents the 8-bit ISO8859-1 scheme. It decodes directly to +// UTF-8 without change, as all ISO8859-1 values are legal UTF-8. +// Unicode values less than 256 (i.e. 8 bits) map 1:1 with 8859-1. +// It encodes runes outside of that to 0x1A, the ASCII substitution character. +var ISO8859_1 encoding.Encoding + +func init() { + cm := &Charmap{} + cm.Init() + + // 8859-1 is the 8-bit identity map for Unicode. + ISO8859_1 = cm +} diff --git a/vendor/github.com/gdamore/encoding/latin5.go b/vendor/github.com/gdamore/encoding/latin5.go new file mode 100644 index 00000000..c75ecf27 --- /dev/null +++ b/vendor/github.com/gdamore/encoding/latin5.go @@ -0,0 +1,35 @@ +// Copyright 2015 Garrett D'Amore +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encoding + +import ( + "golang.org/x/text/encoding" +) + +// ISO8859_9 represents the 8-bit ISO8859-9 scheme. +var ISO8859_9 encoding.Encoding + +func init() { + cm := &Charmap{Map: map[byte]rune{ + 0xD0: 'Ğ', + 0xDD: 'İ', + 0xDE: 'Ş', + 0xF0: 'ğ', + 0xFD: 'ı', + 0xFE: 'ş', + }} + cm.Init() + ISO8859_9 = cm +} diff --git a/vendor/github.com/gdamore/encoding/utf8.go b/vendor/github.com/gdamore/encoding/utf8.go new file mode 100644 index 00000000..2d59f4b3 --- /dev/null +++ b/vendor/github.com/gdamore/encoding/utf8.go @@ -0,0 +1,35 @@ +// Copyright 2015 Garrett D'Amore +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encoding + +import ( + "golang.org/x/text/encoding" +) + +type validUtf8 struct{} + +// UTF8 is an encoding for UTF-8. All it does is verify that the UTF-8 +// in is valid. The main reason for its existence is that it will detect +// and report ErrSrcShort or ErrDstShort, whereas the Nop encoding just +// passes every byte, blithely. +var UTF8 encoding.Encoding = validUtf8{} + +func (validUtf8) NewDecoder() *encoding.Decoder { + return &encoding.Decoder{Transformer: encoding.UTF8Validator} +} + +func (validUtf8) NewEncoder() *encoding.Encoder { + return &encoding.Encoder{Transformer: encoding.UTF8Validator} +} diff --git a/vendor/github.com/gdamore/tcell/.appveyor.yml b/vendor/github.com/gdamore/tcell/.appveyor.yml new file mode 100644 index 00000000..435dfe3a --- /dev/null +++ b/vendor/github.com/gdamore/tcell/.appveyor.yml @@ -0,0 +1,13 @@ +version: 1.0.{build} +clone_folder: c:\gopath\src\github.com\gdamore\tcell +environment: + GOPATH: c:\gopath +build_script: +- go version +- go env +- SET PATH=%LOCALAPPDATA%\atom\bin;%GOPATH%\bin;%PATH% +- go get -t ./... +- go build +- go install ./... +test_script: +- go test ./... diff --git a/vendor/github.com/gdamore/tcell/.gitignore b/vendor/github.com/gdamore/tcell/.gitignore new file mode 100644 index 00000000..c57100a5 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/.gitignore @@ -0,0 +1 @@ +coverage.txt diff --git a/vendor/github.com/gdamore/tcell/.travis.yml b/vendor/github.com/gdamore/tcell/.travis.yml new file mode 100644 index 00000000..d3fc7d43 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/.travis.yml @@ -0,0 +1,17 @@ +language: go + +go: + - 1.5.x + - 1.6.x + - 1.7.x + - 1.8.x + - master + +before_install: + - go get -t -v ./... + +script: + - go test -race -coverprofile=coverage.txt -covermode=atomic + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/gdamore/tcell/AUTHORS b/vendor/github.com/gdamore/tcell/AUTHORS new file mode 100644 index 00000000..53f87ee6 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/AUTHORS @@ -0,0 +1,4 @@ +Garrett D'Amore +Zachary Yedidia +Junegunn Choi +Staysail Systems, Inc. diff --git a/vendor/github.com/gdamore/tcell/LICENSE b/vendor/github.com/gdamore/tcell/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/gdamore/tcell/README.md b/vendor/github.com/gdamore/tcell/README.md new file mode 100644 index 00000000..b3fcba90 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/README.md @@ -0,0 +1,262 @@ +## tcell + +[![Linux Status](https://img.shields.io/travis/gdamore/tcell.svg?label=linux)](https://travis-ci.org/gdamore/tcell) +[![Windows Status](https://img.shields.io/appveyor/ci/gdamore/tcell.svg?label=windows)](https://ci.appveyor.com/project/gdamore/tcell) +[![Apache License](https://img.shields.io/badge/license-APACHE2-blue.svg)](https://github.com/gdamore/tcell/blob/master/LICENSE) +[![Gitter](https://img.shields.io/badge/gitter-join-brightgreen.svg)](https://gitter.im/gdamore/tcell) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/gdamore/tcell) +[![Go Report Card](http://goreportcard.com/badge/gdamore/tcell)](http://goreportcard.com/report/gdamore/tcell) +[![codecov](https://codecov.io/gh/gdamore/tcell/branch/master/graph/badge.svg)](https://codecov.io/gh/gdamore/tcell) + + +> _Tcell is a work in progress (Gamma). +> Please use with caution; interfaces may change in before final release. +> That said, our confidence in Tcell's stability is increasing. If you +> would like to use it in your own application, it is recommended that +> you drop a message to garrett@damore.org before commitment._ + +Package tcell provides a cell based view for text terminals, like xterm. +It was inspired by termbox, but differs from termbox in some important +ways. It also adds substantial functionality beyond termbox. + +## Examples + +* [proxima5](https://github.com/gdamore/proxima5) - space shooter ([video](https://youtu.be/jNxKTCmY_bQ)) +* [govisor](https://github.com/gdamore/govisor) - service management UI ([screenshot](http://2.bp.blogspot.com/--OsvnfzSNow/Vf7aqMw3zXI/AAAAAAAAARo/uOMtOvw4Sbg/s1600/Screen%2BShot%2B2015-09-20%2Bat%2B9.08.41%2BAM.png)) +* mouse demo - [screenshot](http://2.bp.blogspot.com/-fWvW5opT0es/VhIdItdKqJI/AAAAAAAAATE/7Ojc0L1SpB0/s1600/Screen%2BShot%2B2015-10-04%2Bat%2B11.47.13%2BPM.png) - included mouse test +* [gomatrix](https://github.com/gdamore/gomatrix) - converted from Termbox +* [micro](https://github.com/zyedidia/micro/) - lightweight text editor with syntax-highlighting and themes +* [godu](https://github.com/viktomas/godu) - simple golang utility helping to discover large files/folders. + +## Pure Go Terminfo Database + +First, it includes a full parser and expander for terminfo capability strings, +so that it can avoid hard coding escape strings for formatting. It also favors +portability, and includes support for all POSIX systems, at the slight expense +of needing cgo support for terminal initializations. (This may be corrected +when Go provides standard support for terminal handling via termio ioctls on +all POSIX platforms.) The database itself, while built using CGO, as well +as the parser for it, is implemented in Pure Go. + +The database is also flexible & extensible, and can modified by either running a +program to build the database, or hand editing of simple JSON files. + +## More Portable + +Tcell is portable to a wider variety of systems. It relies on standard +POSIX supported function calls (on POSIX platforms) for setting terminal +modes, which leads to improved support for a broader array of platforms. +This does come at the cost of requiring your code to be able to use CGO, but +we believe that the vastly improved portability justifies this +requirement. Note that the functions called are part of the standard C +library, so there shouldn't be any additional external requirements beyond +that required for every POSIX program. + +## No async IO + +Tcell is able to operate without requiring SIGIO signals (unlike Termbox), +or asynchronous I/O, and can instead use standard Go file +objects and Go routines. This means it should be safe, especially for +use with programs that use exec, or otherwise need to manipulate the +tty streams. This model is also much closer to idiomatic Go, leading +to fewer surprises. + +## Richer Unicode & non-Unicode support + +Tcell includes enhanced support for Unicode, include wide characters and +combining characters, provided your terminal can support them. Note that +Windows terminals generally don't support the full Unicode repertoire. + +It will also convert to and from Unicode locales, so that the program +can work with UTF-8 internally, and get reasonable output in other locales. +We try hard to convert to native characters on both input and output, and +on output Tcell even makes use of the alternate character set to facilitate +drawing certain characters. + +## More Function Keys + +It also has richer support for a larger number of +special keys that some terminals can send. + +## Better color handling + +Tcell will respect your terminal's color space as specified within your terminfo +entries, so that for example attempts to emit color sequences on VT100 terminals +won't result in unintended consequences. + +In Windows mode, Tcell supports 16 colors, bold, dim, and reverse, +instead of just termbox's 8 colors with reverse. (Note that there is some +conflation with bold/dim and colors.) + +Tcell maps 16 colors down to 8, for Terminals that need it. (The upper +8 colors are just brighter versions of the lower 8.) + +## Better mouse support + +Tcell supports enhanced mouse tracking mode, so your application can receive +regular mouse motion events, and wheel events, if your terminal supports it. + +## Why not just patch termbox-go? + +I started this project originally by submitting patches to the author of +go-termbox, but due to some fundamental differences of opinion, I thought +it might be simpler just to start from scratch. At this point, Tcell has +far exceeded the capabilities of termbox. + +## Termbox compatibility + +A compatibility layer for termbox is provided in the compat +directory. To use it, try importing "github.com/gdamore/tcell/termbox" +instead. Most termbox-go programs will probably work without further +modification. + +## Working With Unicode + +Internally Tcell uses UTF-8, just like Go. However, Tcell understands how to +convert to and from other character sets, using the capabilities of +the golang.org/x/text/encoding packages. Your application must supply +them, as the full set of the most common ones bloats the program by about +2MB. If you're lazy, and want them all anyway, see the encoding +sub-directory. + +## Wide & Combining Characters + +The SetContent() API takes a primary rune, and an optional list of combining +runes. If any of the runes is a wide (East Asian) rune occupying two cells, +then the library will skip output from the following cell, but care must be +taken in the application to avoid explicitly attempting to set content in the +next cell, otherwise the results are undefined. (Normally wide character +is displayed, and the other character is not; do not depend on that behavior.) + +Experience has shown that the vanilla Windows 8 console application does not +support any of these characters properly, but at least some options like +ConEmu do support Wide characters at least. + +## Colors + +Tcell assumes the ANSI/XTerm color model, including the 256 color map that +XTerm uses when it supports 256 colors. The terminfo guidance will be +honored, with respect to the number of colors supported. Also, only +terminals which expose ANSI style setaf and setab will support color; +if you have a color terminal that only has setf and setb, please let me +know; it wouldn't be hard to add that if there is need. + +## 24-bit Color + +Tcell _supports true color_! (That is, if your terminal can support it, +Tcell can accurately display 24-bit color.) + +To use 24-bit color, you need to use a terminal that supports it. Modern +xterm and similar teminal emulators can support this. As terminfo lacks any +way to describe this capability, we fabricate the capability for +terminals with names ending in *-truecolor. The stock distribution ships +with a database that defines xterm-truecolor. To try it out, set your +TERM variable to xterm-truecolor. + +When using TrueColor, programs will display the colors that the programmer +intended, overriding any "themes" you may have set in your terminal +emulator. (For some cases, accurate color fidelity is more important +than respecting themes. For other cases, such as typical text apps that +only use a few colors, its more desirable to respect the themes that +the user has established.) + +If you find this undesirable, you can either use a TERM variable +that lacks the TRUECOLOR setting, or set TCELL_TRUECOLOR=disable in your +environment. + +## Performance + +Reasonable attempts have been made to minimize sending data to terminals, +avoiding repeated sequences or drawing the same cell on refresh updates. + +## Terminfo + +(Not relevent for Windows users.) + +The Terminfo implementation operates with two forms of database. The first +is the database.go file, which contains a number of real database entries +that are compiled into the program directly. This should minimize calling +out to database file searches. + +The second is a JSON file, that contains the same information, which can +be located either by the $TCELLDB environment file, $HOME/.tcelldb, or is +located in the Go source directory as database.json. + +These files (both the Go database.go and the database.json) file can be +generated using the mkinfo.go program. If you need to regnerate the +entire set for some reason, run the mkdatabase.sh file. The generation +uses the terminfo routines on the system to populate the data files. + +The mkinfo.go program can also be used to generate specific database entries +for named terminals, in case your favorite terminal is missing. (If you +find that this is the case, please let me know and I'll try to add it!) + +Tcell requires that the terminal support the 'cup' mode of cursor addressing. +Terminals without absolute cursor addressability are not supported. +This is unlikely to be a problem; such terminals have not been mass produced +since the early 1970s. + +## Mouse Support + +Mouse support is detected via the "kmous" terminfo variable, however, +enablement/disablement and decoding mouse events is done using hard coded +sequences based on the XTerm X11 model. As of this writing all popular +terminals with mouse tracking support this model. (Full terminfo support +is not possible as terminfo sequences are not defined.) + +On Windows, the mouse works normally. + +Mouse wheel buttons on various terminals are known to work, but the support +in terminal emulators, as well as support for various buttons and +live mouse tracking, varies widely. As a particular datum, MacOS X Terminal +does not support Mouse events at all (as of MacOS 10.10, aka Yosemite.) The +excellent iTerm application is fully supported, as is vanilla XTerm. + +Mouse tracking with live tracking also varies widely. Current XTerm +implementations, as well as current Screen and iTerm2, and Windows +consoles, all support this quite nicely. On other platforms you might +find that only mouse click and release events are reported, with +no intervening motion events. It really depends on your terminal. + +## Testablity + +There is a SimulationScreen, that can be used to simulate a real screen +for automated testing. The supplied tests do this. The simulation contains +event delivery, screen resizing support, and capabilities to inject events +and examine "physical" screen contents. + +## Platforms + +### Systems (Linux, FreeBSD, MacOS, Solaris, etc.) + +On POSIX systems, a POSIX termios implementation with /dev/tty is required. +On a small subset of these platforms (such as Solaris/illumos), we require +cgo to run, in order to access termios. (Note that Linux and BSD systems +do not require CGO for most purposes.) + +(Note: CGO support is required if you wish to rebuild the terminal database +from the system's native terminfo binary files. This is because we use the +system's native libterminfo to access that binary data. We probably could +eliminate that in the future by using a terminfo decompiler such as infocmp.) + +### Windows + +Windows console mode applications are supported. Unfortunately mintty +and other cygwin style applications are not supported. + +Modern console applications like ConEmu support all the good features +(resize, mouse tracking, etc.) + +I haven't figured out how to cleanly resolve the dichotomy between cygwin +style termios and the Windows Console API; it seems that perhaps nobody else +has either. If anyone has suggestions, let me know! Really, if you're +using a Windows application, you should use the native Windows console or a +fully compatible console implementation. Hopefully the Windows 10 console +is more functional in this regard. + +### Plan9 and Native Client (Nacl) + +The nacl and plan9 platforms won't work, but compilation stubs are supplied +for folks that want to include parts of this in software targetting those +platforms. The Simulation screen works, but as Tcell doesn't know how to +allocate a real screen object on those platforms, NewScreen() will fail. diff --git a/vendor/github.com/gdamore/tcell/attr.go b/vendor/github.com/gdamore/tcell/attr.go new file mode 100644 index 00000000..866c0ebd --- /dev/null +++ b/vendor/github.com/gdamore/tcell/attr.go @@ -0,0 +1,32 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +// AttrMask represents a mask of text attributes, apart from color. +// Note that support for attributes may vary widely across terminals. +type AttrMask int + +// Attributes are not colors, but affect the display of text. They can +// be combined. +const ( + AttrBold AttrMask = 1 << (25 + iota) + AttrBlink + AttrReverse + AttrUnderline + AttrDim + AttrNone AttrMask = 0 // Just normal text. +) + +const attrAll = AttrBold | AttrBlink | AttrReverse | AttrUnderline | AttrDim diff --git a/vendor/github.com/gdamore/tcell/cell.go b/vendor/github.com/gdamore/tcell/cell.go new file mode 100644 index 00000000..b54abcbc --- /dev/null +++ b/vendor/github.com/gdamore/tcell/cell.go @@ -0,0 +1,186 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "github.com/mattn/go-runewidth" +) + +type cell struct { + currMain rune + currComb []rune + currStyle Style + lastMain rune + lastStyle Style + lastComb []rune + width int +} + +// CellBuffer represents a two dimensional array of character cells. +// This is primarily intended for use by Screen implementors; it +// contains much of the common code they need. To create one, just +// declare a variable of its type; no explicit initialization is necessary. +// +// CellBuffer is not thread safe. +type CellBuffer struct { + w int + h int + cells []cell +} + +// SetContent sets the contents (primary rune, combining runes, +// and style) for a cell at a given location. +func (cb *CellBuffer) SetContent(x int, y int, + mainc rune, combc []rune, style Style) { + + if x >= 0 && y >= 0 && x < cb.w && y < cb.h { + c := &cb.cells[(y*cb.w)+x] + + i := 0 + for i < len(combc) { + r := combc[i] + if runewidth.RuneWidth(r) != 0 { + // not a combining character, yank it + combc = append(combc[:i-1], combc[i+1:]...) + continue + } + i++ + } + + if c.currMain != mainc { + c.width = runewidth.RuneWidth(mainc) + } + c.currMain = mainc + c.currComb = combc + c.currStyle = style + } +} + +// GetContent returns the contents of a character cell, including the +// primary rune, any combining character runes (which will usually be +// nil), the style, and the display width in cells. (The width can be +// either 1, normally, or 2 for East Asian full-width characters.) +func (cb *CellBuffer) GetContent(x, y int) (rune, []rune, Style, int) { + var mainc rune + var combc []rune + var style Style + var width int + if x >= 0 && y >= 0 && x < cb.w && y < cb.h { + c := &cb.cells[(y*cb.w)+x] + mainc, combc, style = c.currMain, c.currComb, c.currStyle + if width = c.width; width == 0 || mainc < ' ' { + width = 1 + mainc = ' ' + } + } + return mainc, combc, style, width +} + +// Size returns the (width, height) in cells of the buffer. +func (cb *CellBuffer) Size() (int, int) { + return cb.w, cb.h +} + +// Invalidate marks all characters within the buffer as dirty. +func (cb *CellBuffer) Invalidate() { + for i := range cb.cells { + cb.cells[i].lastMain = rune(0) + } +} + +// Dirty checks if a character at the given location needs an +// to be refreshed on the physical display. This returns true +// if the cell content is different since the last time it was +// marked clean. +func (cb *CellBuffer) Dirty(x, y int) bool { + if x >= 0 && y >= 0 && x < cb.w && y < cb.h { + c := &cb.cells[(y*cb.w)+x] + if c.lastMain == rune(0) { + return true + } + if c.lastMain != c.currMain { + return true + } + if c.lastStyle != c.currStyle { + return true + } + if len(c.lastComb) != len(c.currComb) { + return true + } + for i := range c.lastComb { + if c.lastComb[i] != c.currComb[i] { + return true + } + } + } + return false +} + +// SetDirty is normally used to indicate that a cell has +// been displayed (in which case dirty is false), or to manually +// force a cell to be marked dirty. +func (cb *CellBuffer) SetDirty(x, y int, dirty bool) { + if x >= 0 && y >= 0 && x < cb.w && y < cb.h { + c := &cb.cells[(y*cb.w)+x] + if dirty { + c.lastMain = rune(0) + } else { + if c.currMain == rune(0) { + c.currMain = ' ' + } + c.lastMain = c.currMain + c.lastComb = c.currComb + c.lastStyle = c.currStyle + } + } +} + +// Resize is used to resize the cells array, with different dimensions, +// while preserving the original contents. The cells will be invalidated +// so that they can be redrawn. +func (cb *CellBuffer) Resize(w, h int) { + + if cb.h == h && cb.w == w { + return + } + + newc := make([]cell, w*h) + for y := 0; y < h && y < cb.h; y++ { + for x := 0; x < w && x < cb.w; x++ { + oc := &cb.cells[(y*cb.w)+x] + nc := &newc[(y*w)+x] + nc.currMain = oc.currMain + nc.currComb = oc.currComb + nc.currStyle = oc.currStyle + nc.width = oc.width + nc.lastMain = rune(0) + } + } + cb.cells = newc + cb.h = h + cb.w = w +} + +// Fill fills the entire cell buffer array with the specified character +// and style. Normally choose ' ' to clear the screen. This API doesn't +// support combining characters. +func (cb *CellBuffer) Fill(r rune, style Style) { + for i := range cb.cells { + c := &cb.cells[i] + c.currMain = r + c.currComb = nil + c.currStyle = style + } +} diff --git a/vendor/github.com/gdamore/tcell/charset_stub.go b/vendor/github.com/gdamore/tcell/charset_stub.go new file mode 100644 index 00000000..c1c1594c --- /dev/null +++ b/vendor/github.com/gdamore/tcell/charset_stub.go @@ -0,0 +1,21 @@ +// +build plan9 nacl + +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +func getCharset() string { + return "" +} diff --git a/vendor/github.com/gdamore/tcell/charset_unix.go b/vendor/github.com/gdamore/tcell/charset_unix.go new file mode 100644 index 00000000..d9f9d8e1 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/charset_unix.go @@ -0,0 +1,49 @@ +// +build !windows,!nacl,!plan9 + +// Copyright 2016 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "os" + "strings" +) + +func getCharset() string { + // Determine the character set. This can help us later. + // Per POSIX, we search for LC_ALL first, then LC_CTYPE, and + // finally LANG. First one set wins. + locale := "" + if locale = os.Getenv("LC_ALL"); locale == "" { + if locale = os.Getenv("LC_CTYPE"); locale == "" { + locale = os.Getenv("LANG") + } + } + if locale == "POSIX" || locale == "C" { + return "US-ASCII" + } + if i := strings.IndexRune(locale, '@'); i >= 0 { + locale = locale[:i] + } + if i := strings.IndexRune(locale, '.'); i >= 0 { + locale = locale[i+1:] + } else { + // Default assumption, and on Linux we can see LC_ALL + // without a character set, which we assume implies UTF-8. + return "UTF-8" + } + // XXX: add support for aliases + return locale +} diff --git a/vendor/github.com/gdamore/tcell/charset_windows.go b/vendor/github.com/gdamore/tcell/charset_windows.go new file mode 100644 index 00000000..2400aa8a --- /dev/null +++ b/vendor/github.com/gdamore/tcell/charset_windows.go @@ -0,0 +1,21 @@ +// +build windows + +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +func getCharset() string { + return "UTF-16" +} diff --git a/vendor/github.com/gdamore/tcell/color.go b/vendor/github.com/gdamore/tcell/color.go new file mode 100644 index 00000000..2e096c70 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/color.go @@ -0,0 +1,1019 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import "strconv" + +// Color represents a color. The low numeric values are the same as used +// by ECMA-48, and beyond that XTerm. A 24-bit RGB value may be used by +// adding in the ColorIsRGB flag. For Color names we use the W3C approved +// color names. +// +// Note that on various terminals colors may be approximated however, or +// not supported at all. If no suitable representation for a color is known, +// the library will simply not set any color, deferring to whatever default +// attributes the terminal uses. +type Color int32 + +const ( + // ColorDefault is used to leave the Color unchanged from whatever + // system or teminal default may exist. + ColorDefault Color = -1 + + // ColorIsRGB is used to indicate that the numeric value is not + // a known color constant, but rather an RGB value. The lower + // order 3 bytes are RGB. + ColorIsRGB Color = 1 << 24 +) + +// Note that the order of these options is important -- it follows the +// definitions used by ECMA and XTerm. Hence any further named colors +// must begin at a value not less than 256. +const ( + ColorBlack Color = iota + ColorMaroon + ColorGreen + ColorOlive + ColorNavy + ColorPurple + ColorTeal + ColorSilver + ColorGray + ColorRed + ColorLime + ColorYellow + ColorBlue + ColorFuchsia + ColorAqua + ColorWhite + Color16 + Color17 + Color18 + Color19 + Color20 + Color21 + Color22 + Color23 + Color24 + Color25 + Color26 + Color27 + Color28 + Color29 + Color30 + Color31 + Color32 + Color33 + Color34 + Color35 + Color36 + Color37 + Color38 + Color39 + Color40 + Color41 + Color42 + Color43 + Color44 + Color45 + Color46 + Color47 + Color48 + Color49 + Color50 + Color51 + Color52 + Color53 + Color54 + Color55 + Color56 + Color57 + Color58 + Color59 + Color60 + Color61 + Color62 + Color63 + Color64 + Color65 + Color66 + Color67 + Color68 + Color69 + Color70 + Color71 + Color72 + Color73 + Color74 + Color75 + Color76 + Color77 + Color78 + Color79 + Color80 + Color81 + Color82 + Color83 + Color84 + Color85 + Color86 + Color87 + Color88 + Color89 + Color90 + Color91 + Color92 + Color93 + Color94 + Color95 + Color96 + Color97 + Color98 + Color99 + Color100 + Color101 + Color102 + Color103 + Color104 + Color105 + Color106 + Color107 + Color108 + Color109 + Color110 + Color111 + Color112 + Color113 + Color114 + Color115 + Color116 + Color117 + Color118 + Color119 + Color120 + Color121 + Color122 + Color123 + Color124 + Color125 + Color126 + Color127 + Color128 + Color129 + Color130 + Color131 + Color132 + Color133 + Color134 + Color135 + Color136 + Color137 + Color138 + Color139 + Color140 + Color141 + Color142 + Color143 + Color144 + Color145 + Color146 + Color147 + Color148 + Color149 + Color150 + Color151 + Color152 + Color153 + Color154 + Color155 + Color156 + Color157 + Color158 + Color159 + Color160 + Color161 + Color162 + Color163 + Color164 + Color165 + Color166 + Color167 + Color168 + Color169 + Color170 + Color171 + Color172 + Color173 + Color174 + Color175 + Color176 + Color177 + Color178 + Color179 + Color180 + Color181 + Color182 + Color183 + Color184 + Color185 + Color186 + Color187 + Color188 + Color189 + Color190 + Color191 + Color192 + Color193 + Color194 + Color195 + Color196 + Color197 + Color198 + Color199 + Color200 + Color201 + Color202 + Color203 + Color204 + Color205 + Color206 + Color207 + Color208 + Color209 + Color210 + Color211 + Color212 + Color213 + Color214 + Color215 + Color216 + Color217 + Color218 + Color219 + Color220 + Color221 + Color222 + Color223 + Color224 + Color225 + Color226 + Color227 + Color228 + Color229 + Color230 + Color231 + Color232 + Color233 + Color234 + Color235 + Color236 + Color237 + Color238 + Color239 + Color240 + Color241 + Color242 + Color243 + Color244 + Color245 + Color246 + Color247 + Color248 + Color249 + Color250 + Color251 + Color252 + Color253 + Color254 + Color255 + ColorAliceBlue + ColorAntiqueWhite + ColorAquaMarine + ColorAzure + ColorBeige + ColorBisque + ColorBlanchedAlmond + ColorBlueViolet + ColorBrown + ColorBurlyWood + ColorCadetBlue + ColorChartreuse + ColorChocolate + ColorCoral + ColorCornflowerBlue + ColorCornsilk + ColorCrimson + ColorDarkBlue + ColorDarkCyan + ColorDarkGoldenrod + ColorDarkGray + ColorDarkGreen + ColorDarkKhaki + ColorDarkMagenta + ColorDarkOliveGreen + ColorDarkOrange + ColorDarkOrchid + ColorDarkRed + ColorDarkSalmon + ColorDarkSeaGreen + ColorDarkSlateBlue + ColorDarkSlateGray + ColorDarkTurquoise + ColorDarkViolet + ColorDeepPink + ColorDeepSkyBlue + ColorDimGray + ColorDodgerBlue + ColorFireBrick + ColorFloralWhite + ColorForestGreen + ColorGainsboro + ColorGhostWhite + ColorGold + ColorGoldenrod + ColorGreenYellow + ColorHoneydew + ColorHotPink + ColorIndianRed + ColorIndigo + ColorIvory + ColorKhaki + ColorLavender + ColorLavenderBlush + ColorLawnGreen + ColorLemonChiffon + ColorLightBlue + ColorLightCoral + ColorLightCyan + ColorLightGoldenrodYellow + ColorLightGray + ColorLightGreen + ColorLightPink + ColorLightSalmon + ColorLightSeaGreen + ColorLightSkyBlue + ColorLightSlateGray + ColorLightSteelBlue + ColorLightYellow + ColorLimeGreen + ColorLinen + ColorMediumAquamarine + ColorMediumBlue + ColorMediumOrchid + ColorMediumPurple + ColorMediumSeaGreen + ColorMediumSlateBlue + ColorMediumSpringGreen + ColorMediumTurquoise + ColorMediumVioletRed + ColorMidnightBlue + ColorMintCream + ColorMistyRose + ColorMoccasin + ColorNavajoWhite + ColorOldLace + ColorOliveDrab + ColorOrange + ColorOrangeRed + ColorOrchid + ColorPaleGoldenrod + ColorPaleGreen + ColorPaleTurquoise + ColorPaleVioletRed + ColorPapayaWhip + ColorPeachPuff + ColorPeru + ColorPink + ColorPlum + ColorPowderBlue + ColorRebeccaPurple + ColorRosyBrown + ColorRoyalBlue + ColorSaddleBrown + ColorSalmon + ColorSandyBrown + ColorSeaGreen + ColorSeashell + ColorSienna + ColorSkyblue + ColorSlateBlue + ColorSlateGray + ColorSnow + ColorSpringGreen + ColorSteelBlue + ColorTan + ColorThistle + ColorTomato + ColorTurquoise + ColorViolet + ColorWheat + ColorWhiteSmoke + ColorYellowGreen +) + +// These are aliases for the color gray, because some of us spell +// it as grey. +const ( + ColorGrey = ColorGray + ColorDimGrey = ColorDimGray + ColorDarkGrey = ColorDarkGray + ColorDarkSlateGrey = ColorDarkSlateGray + ColorLightGrey = ColorLightGray + ColorLightSlateGrey = ColorLightSlateGray + ColorSlateGrey = ColorSlateGray +) + +// ColorValues maps color constants to their RGB values. +var ColorValues = map[Color]int32{ + ColorBlack: 0x000000, + ColorMaroon: 0x800000, + ColorGreen: 0x008000, + ColorOlive: 0x808000, + ColorNavy: 0x000080, + ColorPurple: 0x800080, + ColorTeal: 0x008080, + ColorSilver: 0xC0C0C0, + ColorGray: 0x808080, + ColorRed: 0xFF0000, + ColorLime: 0x00FF00, + ColorYellow: 0xFFFF00, + ColorBlue: 0x0000FF, + ColorFuchsia: 0xFF00FF, + ColorAqua: 0x00FFFF, + ColorWhite: 0xFFFFFF, + Color16: 0x000000, // black + Color17: 0x00005F, + Color18: 0x000087, + Color19: 0x0000AF, + Color20: 0x0000D7, + Color21: 0x0000FF, // blue + Color22: 0x005F00, + Color23: 0x005F5F, + Color24: 0x005F87, + Color25: 0x005FAF, + Color26: 0x005FD7, + Color27: 0x005FFF, + Color28: 0x008700, + Color29: 0x00875F, + Color30: 0x008787, + Color31: 0x0087Af, + Color32: 0x0087D7, + Color33: 0x0087FF, + Color34: 0x00AF00, + Color35: 0x00AF5F, + Color36: 0x00AF87, + Color37: 0x00AFAF, + Color38: 0x00AFD7, + Color39: 0x00AFFF, + Color40: 0x00D700, + Color41: 0x00D75F, + Color42: 0x00D787, + Color43: 0x00D7AF, + Color44: 0x00D7D7, + Color45: 0x00D7FF, + Color46: 0x00FF00, // lime + Color47: 0x00FF5F, + Color48: 0x00FF87, + Color49: 0x00FFAF, + Color50: 0x00FFd7, + Color51: 0x00FFFF, // aqua + Color52: 0x5F0000, + Color53: 0x5F005F, + Color54: 0x5F0087, + Color55: 0x5F00AF, + Color56: 0x5F00D7, + Color57: 0x5F00FF, + Color58: 0x5F5F00, + Color59: 0x5F5F5F, + Color60: 0x5F5F87, + Color61: 0x5F5FAF, + Color62: 0x5F5FD7, + Color63: 0x5F5FFF, + Color64: 0x5F8700, + Color65: 0x5F875F, + Color66: 0x5F8787, + Color67: 0x5F87AF, + Color68: 0x5F87D7, + Color69: 0x5F87FF, + Color70: 0x5FAF00, + Color71: 0x5FAF5F, + Color72: 0x5FAF87, + Color73: 0x5FAFAF, + Color74: 0x5FAFD7, + Color75: 0x5FAFFF, + Color76: 0x5FD700, + Color77: 0x5FD75F, + Color78: 0x5FD787, + Color79: 0x5FD7AF, + Color80: 0x5FD7D7, + Color81: 0x5FD7FF, + Color82: 0x5FFF00, + Color83: 0x5FFF5F, + Color84: 0x5FFF87, + Color85: 0x5FFFAF, + Color86: 0x5FFFD7, + Color87: 0x5FFFFF, + Color88: 0x870000, + Color89: 0x87005F, + Color90: 0x870087, + Color91: 0x8700AF, + Color92: 0x8700D7, + Color93: 0x8700FF, + Color94: 0x875F00, + Color95: 0x875F5F, + Color96: 0x875F87, + Color97: 0x875FAF, + Color98: 0x875FD7, + Color99: 0x875FFF, + Color100: 0x878700, + Color101: 0x87875F, + Color102: 0x878787, + Color103: 0x8787AF, + Color104: 0x8787D7, + Color105: 0x8787FF, + Color106: 0x87AF00, + Color107: 0x87AF5F, + Color108: 0x87AF87, + Color109: 0x87AFAF, + Color110: 0x87AFD7, + Color111: 0x87AFFF, + Color112: 0x87D700, + Color113: 0x87D75F, + Color114: 0x87D787, + Color115: 0x87D7AF, + Color116: 0x87D7D7, + Color117: 0x87D7FF, + Color118: 0x87FF00, + Color119: 0x87FF5F, + Color120: 0x87FF87, + Color121: 0x87FFAF, + Color122: 0x87FFD7, + Color123: 0x87FFFF, + Color124: 0xAF0000, + Color125: 0xAF005F, + Color126: 0xAF0087, + Color127: 0xAF00AF, + Color128: 0xAF00D7, + Color129: 0xAF00FF, + Color130: 0xAF5F00, + Color131: 0xAF5F5F, + Color132: 0xAF5F87, + Color133: 0xAF5FAF, + Color134: 0xAF5FD7, + Color135: 0xAF5FFF, + Color136: 0xAF8700, + Color137: 0xAF875F, + Color138: 0xAF8787, + Color139: 0xAF87AF, + Color140: 0xAF87D7, + Color141: 0xAF87FF, + Color142: 0xAFAF00, + Color143: 0xAFAF5F, + Color144: 0xAFAF87, + Color145: 0xAFAFAF, + Color146: 0xAFAFD7, + Color147: 0xAFAFFF, + Color148: 0xAFD700, + Color149: 0xAFD75F, + Color150: 0xAFD787, + Color151: 0xAFD7AF, + Color152: 0xAFD7D7, + Color153: 0xAFD7FF, + Color154: 0xAFFF00, + Color155: 0xAFFF5F, + Color156: 0xAFFF87, + Color157: 0xAFFFAF, + Color158: 0xAFFFD7, + Color159: 0xAFFFFF, + Color160: 0xD70000, + Color161: 0xD7005F, + Color162: 0xD70087, + Color163: 0xD700AF, + Color164: 0xD700D7, + Color165: 0xD700FF, + Color166: 0xD75F00, + Color167: 0xD75F5F, + Color168: 0xD75F87, + Color169: 0xD75FAF, + Color170: 0xD75FD7, + Color171: 0xD75FFF, + Color172: 0xD78700, + Color173: 0xD7875F, + Color174: 0xD78787, + Color175: 0xD787AF, + Color176: 0xD787D7, + Color177: 0xD787FF, + Color178: 0xD7AF00, + Color179: 0xD7AF5F, + Color180: 0xD7AF87, + Color181: 0xD7AFAF, + Color182: 0xD7AFD7, + Color183: 0xD7AFFF, + Color184: 0xD7D700, + Color185: 0xD7D75F, + Color186: 0xD7D787, + Color187: 0xD7D7AF, + Color188: 0xD7D7D7, + Color189: 0xD7D7FF, + Color190: 0xD7FF00, + Color191: 0xD7FF5F, + Color192: 0xD7FF87, + Color193: 0xD7FFAF, + Color194: 0xD7FFD7, + Color195: 0xD7FFFF, + Color196: 0xFF0000, // red + Color197: 0xFF005F, + Color198: 0xFF0087, + Color199: 0xFF00AF, + Color200: 0xFF00D7, + Color201: 0xFF00FF, // fuchsia + Color202: 0xFF5F00, + Color203: 0xFF5F5F, + Color204: 0xFF5F87, + Color205: 0xFF5FAF, + Color206: 0xFF5FD7, + Color207: 0xFF5FFF, + Color208: 0xFF8700, + Color209: 0xFF875F, + Color210: 0xFF8787, + Color211: 0xFF87AF, + Color212: 0xFF87D7, + Color213: 0xFF87FF, + Color214: 0xFFAF00, + Color215: 0xFFAF5F, + Color216: 0xFFAF87, + Color217: 0xFFAFAF, + Color218: 0xFFAFD7, + Color219: 0xFFAFFF, + Color220: 0xFFD700, + Color221: 0xFFD75F, + Color222: 0xFFD787, + Color223: 0xFFD7AF, + Color224: 0xFFD7D7, + Color225: 0xFFD7FF, + Color226: 0xFFFF00, // yellow + Color227: 0xFFFF5F, + Color228: 0xFFFF87, + Color229: 0xFFFFAF, + Color230: 0xFFFFD7, + Color231: 0xFFFFFF, // white + Color232: 0x080808, + Color233: 0x121212, + Color234: 0x1C1C1C, + Color235: 0x262626, + Color236: 0x303030, + Color237: 0x3A3A3A, + Color238: 0x444444, + Color239: 0x4E4E4E, + Color240: 0x585858, + Color241: 0x626262, + Color242: 0x6C6C6C, + Color243: 0x767676, + Color244: 0x808080, // grey + Color245: 0x8A8A8A, + Color246: 0x949494, + Color247: 0x9E9E9E, + Color248: 0xA8A8A8, + Color249: 0xB2B2B2, + Color250: 0xBCBCBC, + Color251: 0xC6C6C6, + Color252: 0xD0D0D0, + Color253: 0xDADADA, + Color254: 0xE4E4E4, + Color255: 0xEEEEEE, + ColorAliceBlue: 0xF0F8FF, + ColorAntiqueWhite: 0xFAEBD7, + ColorAquaMarine: 0x7FFFD4, + ColorAzure: 0xF0FFFF, + ColorBeige: 0xF5F5DC, + ColorBisque: 0xFFE4C4, + ColorBlanchedAlmond: 0xFFEBCD, + ColorBlueViolet: 0x8A2BE2, + ColorBrown: 0xA52A2A, + ColorBurlyWood: 0xDEB887, + ColorCadetBlue: 0x5F9EA0, + ColorChartreuse: 0x7FFF00, + ColorChocolate: 0xD2691E, + ColorCoral: 0xFF7F50, + ColorCornflowerBlue: 0x6495ED, + ColorCornsilk: 0xFFF8DC, + ColorCrimson: 0xDC143C, + ColorDarkBlue: 0x00008B, + ColorDarkCyan: 0x008B8B, + ColorDarkGoldenrod: 0xB8860B, + ColorDarkGray: 0xA9A9A9, + ColorDarkGreen: 0x006400, + ColorDarkKhaki: 0xBDB76B, + ColorDarkMagenta: 0x8B008B, + ColorDarkOliveGreen: 0x556B2F, + ColorDarkOrange: 0xFF8C00, + ColorDarkOrchid: 0x9932CC, + ColorDarkRed: 0x8B0000, + ColorDarkSalmon: 0xE9967A, + ColorDarkSeaGreen: 0x8FBC8F, + ColorDarkSlateBlue: 0x483D8B, + ColorDarkSlateGray: 0x2F4F4F, + ColorDarkTurquoise: 0x00CED1, + ColorDarkViolet: 0x9400D3, + ColorDeepPink: 0xFF1493, + ColorDeepSkyBlue: 0x00BFFF, + ColorDimGray: 0x696969, + ColorDodgerBlue: 0x1E90FF, + ColorFireBrick: 0xB22222, + ColorFloralWhite: 0xFFFAF0, + ColorForestGreen: 0x228B22, + ColorGainsboro: 0xDCDCDC, + ColorGhostWhite: 0xF8F8FF, + ColorGold: 0xFFD700, + ColorGoldenrod: 0xDAA520, + ColorGreenYellow: 0xADFF2F, + ColorHoneydew: 0xF0FFF0, + ColorHotPink: 0xFF69B4, + ColorIndianRed: 0xCD5C5C, + ColorIndigo: 0x4B0082, + ColorIvory: 0xFFFFF0, + ColorKhaki: 0xF0E68C, + ColorLavender: 0xE6E6FA, + ColorLavenderBlush: 0xFFF0F5, + ColorLawnGreen: 0x7CFC00, + ColorLemonChiffon: 0xFFFACD, + ColorLightBlue: 0xADD8E6, + ColorLightCoral: 0xF08080, + ColorLightCyan: 0xE0FFFF, + ColorLightGoldenrodYellow: 0xFAFAD2, + ColorLightGray: 0xD3D3D3, + ColorLightGreen: 0x90EE90, + ColorLightPink: 0xFFB6C1, + ColorLightSalmon: 0xFFA07A, + ColorLightSeaGreen: 0x20B2AA, + ColorLightSkyBlue: 0x87CEFA, + ColorLightSlateGray: 0x778899, + ColorLightSteelBlue: 0xB0C4DE, + ColorLightYellow: 0xFFFFE0, + ColorLimeGreen: 0x32CD32, + ColorLinen: 0xFAF0E6, + ColorMediumAquamarine: 0x66CDAA, + ColorMediumBlue: 0x0000CD, + ColorMediumOrchid: 0xBA55D3, + ColorMediumPurple: 0x9370DB, + ColorMediumSeaGreen: 0x3CB371, + ColorMediumSlateBlue: 0x7B68EE, + ColorMediumSpringGreen: 0x00FA9A, + ColorMediumTurquoise: 0x48D1CC, + ColorMediumVioletRed: 0xC71585, + ColorMidnightBlue: 0x191970, + ColorMintCream: 0xF5FFFA, + ColorMistyRose: 0xFFE4E1, + ColorMoccasin: 0xFFE4B5, + ColorNavajoWhite: 0xFFDEAD, + ColorOldLace: 0xFDF5E6, + ColorOliveDrab: 0x6B8E23, + ColorOrange: 0xFFA500, + ColorOrangeRed: 0xFF4500, + ColorOrchid: 0xDA70D6, + ColorPaleGoldenrod: 0xEEE8AA, + ColorPaleGreen: 0x98FB98, + ColorPaleTurquoise: 0xAFEEEE, + ColorPaleVioletRed: 0xDB7093, + ColorPapayaWhip: 0xFFEFD5, + ColorPeachPuff: 0xFFDAB9, + ColorPeru: 0xCD853F, + ColorPink: 0xFFC0CB, + ColorPlum: 0xDDA0DD, + ColorPowderBlue: 0xB0E0E6, + ColorRebeccaPurple: 0x663399, + ColorRosyBrown: 0xBC8F8F, + ColorRoyalBlue: 0x4169E1, + ColorSaddleBrown: 0x8B4513, + ColorSalmon: 0xFA8072, + ColorSandyBrown: 0xF4A460, + ColorSeaGreen: 0x2E8B57, + ColorSeashell: 0xFFF5EE, + ColorSienna: 0xA0522D, + ColorSkyblue: 0x87CEEB, + ColorSlateBlue: 0x6A5ACD, + ColorSlateGray: 0x708090, + ColorSnow: 0xFFFAFA, + ColorSpringGreen: 0x00FF7F, + ColorSteelBlue: 0x4682B4, + ColorTan: 0xD2B48C, + ColorThistle: 0xD8BFD8, + ColorTomato: 0xFF6347, + ColorTurquoise: 0x40E0D0, + ColorViolet: 0xEE82EE, + ColorWheat: 0xF5DEB3, + ColorWhiteSmoke: 0xF5F5F5, + ColorYellowGreen: 0x9ACD32, +} + +// ColorNames holds the written names of colors. Useful to present a list of +// recognized named colors. +var ColorNames = map[string]Color{ + "black": ColorBlack, + "maroon": ColorMaroon, + "green": ColorGreen, + "olive": ColorOlive, + "navy": ColorNavy, + "purple": ColorPurple, + "teal": ColorTeal, + "silver": ColorSilver, + "gray": ColorGray, + "red": ColorRed, + "lime": ColorLime, + "yellow": ColorYellow, + "blue": ColorBlue, + "fuchsia": ColorFuchsia, + "aqua": ColorAqua, + "white": ColorWhite, + "aliceblue": ColorAliceBlue, + "antiquewhite": ColorAntiqueWhite, + "aquamarine": ColorAquaMarine, + "azure": ColorAzure, + "beige": ColorBeige, + "bisque": ColorBisque, + "blanchedalmond": ColorBlanchedAlmond, + "blueviolet": ColorBlueViolet, + "brown": ColorBrown, + "burlywood": ColorBurlyWood, + "cadetblue": ColorCadetBlue, + "chartreuse": ColorChartreuse, + "chocolate": ColorChocolate, + "coral": ColorCoral, + "cornflowerblue": ColorCornflowerBlue, + "cornsilk": ColorCornsilk, + "crimson": ColorCrimson, + "darkblue": ColorDarkBlue, + "darkcyan": ColorDarkCyan, + "darkgoldenrod": ColorDarkGoldenrod, + "darkgray": ColorDarkGray, + "darkgreen": ColorDarkGreen, + "darkkhaki": ColorDarkKhaki, + "darkmagenta": ColorDarkMagenta, + "darkolivegreen": ColorDarkOliveGreen, + "darkorange": ColorDarkOrange, + "darkorchid": ColorDarkOrchid, + "darkred": ColorDarkRed, + "darksalmon": ColorDarkSalmon, + "darkseagreen": ColorDarkSeaGreen, + "darkslateblue": ColorDarkSlateBlue, + "darkslategray": ColorDarkSlateGray, + "darkturquoise": ColorDarkTurquoise, + "darkviolet": ColorDarkViolet, + "deeppink": ColorDeepPink, + "deepskyblue": ColorDeepSkyBlue, + "dimgray": ColorDimGray, + "dodgerblue": ColorDodgerBlue, + "firebrick": ColorFireBrick, + "floralwhite": ColorFloralWhite, + "forestgreen": ColorForestGreen, + "gainsboro": ColorGainsboro, + "ghostwhite": ColorGhostWhite, + "gold": ColorGold, + "goldenrod": ColorGoldenrod, + "greenyellow": ColorGreenYellow, + "honeydew": ColorHoneydew, + "hotpink": ColorHotPink, + "indianred": ColorIndianRed, + "indigo": ColorIndigo, + "ivory": ColorIvory, + "khaki": ColorKhaki, + "lavender": ColorLavender, + "lavenderblush": ColorLavenderBlush, + "lawngreen": ColorLawnGreen, + "lemonchiffon": ColorLemonChiffon, + "lightblue": ColorLightBlue, + "lightcoral": ColorLightCoral, + "lightcyan": ColorLightCyan, + "lightgoldenrodyellow": ColorLightGoldenrodYellow, + "lightgray": ColorLightGray, + "lightgreen": ColorLightGreen, + "lightpink": ColorLightPink, + "lightsalmon": ColorLightSalmon, + "lightseagreen": ColorLightSeaGreen, + "lightskyblue": ColorLightSkyBlue, + "lightslategray": ColorLightSlateGray, + "lightsteelblue": ColorLightSteelBlue, + "lightyellow": ColorLightYellow, + "limegreen": ColorLimeGreen, + "linen": ColorLinen, + "mediumaquamarine": ColorMediumAquamarine, + "mediumblue": ColorMediumBlue, + "mediumorchid": ColorMediumOrchid, + "mediumpurple": ColorMediumPurple, + "mediumseagreen": ColorMediumSeaGreen, + "mediumslateblue": ColorMediumSlateBlue, + "mediumspringgreen": ColorMediumSpringGreen, + "mediumturquoise": ColorMediumTurquoise, + "mediumvioletred": ColorMediumVioletRed, + "midnightblue": ColorMidnightBlue, + "mintcream": ColorMintCream, + "mistyrose": ColorMistyRose, + "moccasin": ColorMoccasin, + "navajowhite": ColorNavajoWhite, + "oldlace": ColorOldLace, + "olivedrab": ColorOliveDrab, + "orange": ColorOrange, + "orangered": ColorOrangeRed, + "orchid": ColorOrchid, + "palegoldenrod": ColorPaleGoldenrod, + "palegreen": ColorPaleGreen, + "paleturquoise": ColorPaleTurquoise, + "palevioletred": ColorPaleVioletRed, + "papayawhip": ColorPapayaWhip, + "peachpuff": ColorPeachPuff, + "peru": ColorPeru, + "pink": ColorPink, + "plum": ColorPlum, + "powderblue": ColorPowderBlue, + "rebeccapurple": ColorRebeccaPurple, + "rosybrown": ColorRosyBrown, + "royalblue": ColorRoyalBlue, + "saddlebrown": ColorSaddleBrown, + "salmon": ColorSalmon, + "sandybrown": ColorSandyBrown, + "seagreen": ColorSeaGreen, + "seashell": ColorSeashell, + "sienna": ColorSienna, + "skyblue": ColorSkyblue, + "slateblue": ColorSlateBlue, + "slategray": ColorSlateGray, + "snow": ColorSnow, + "springgreen": ColorSpringGreen, + "steelblue": ColorSteelBlue, + "tan": ColorTan, + "thistle": ColorThistle, + "tomato": ColorTomato, + "turquoise": ColorTurquoise, + "violet": ColorViolet, + "wheat": ColorWheat, + "whitesmoke": ColorWhiteSmoke, + "yellowgreen": ColorYellowGreen, + "grey": ColorGray, + "dimgrey": ColorDimGray, + "darkgrey": ColorDarkGray, + "darkslategrey": ColorDarkSlateGray, + "lightgrey": ColorLightGray, + "lightslategrey": ColorLightSlateGray, + "slategrey": ColorSlateGray, +} + +// Hex returns the color's hexadecimal RGB 24-bit value with each component +// consisting of a single byte, ala R << 16 | G << 8 | B. If the color +// is unknown or unset, -1 is returned. +func (c Color) Hex() int32 { + if c&ColorIsRGB != 0 { + return (int32(c) & 0xffffff) + } + if v, ok := ColorValues[c]; ok { + return v + } + return -1 +} + +// RGB returns the red, green, and blue components of the color, with +// each component represented as a value 0-255. In the event that the +// color cannot be broken up (not set usually), -1 is returned for each value. +func (c Color) RGB() (int32, int32, int32) { + v := c.Hex() + if v < 0 { + return -1, -1, -1 + } + return (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff +} + +// NewRGBColor returns a new color with the given red, green, and blue values. +// Each value must be represented in the range 0-255. +func NewRGBColor(r, g, b int32) Color { + return NewHexColor(((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff)) +} + +// NewHexColor returns a color using the given 24-bit RGB value. +func NewHexColor(v int32) Color { + return ColorIsRGB | Color(v) +} + +// GetColor creates a Color from a color name (W3C name). A hex value may +// be supplied as a string in the format "#ffffff". +func GetColor(name string) Color { + if c, ok := ColorNames[name]; ok { + return c + } + if len(name) == 7 && name[0] == '#' { + if v, e := strconv.ParseInt(name[1:], 16, 32); e == nil { + return NewHexColor(int32(v)) + } + } + return ColorDefault +} diff --git a/vendor/github.com/gdamore/tcell/colorfit.go b/vendor/github.com/gdamore/tcell/colorfit.go new file mode 100644 index 00000000..b7740b8a --- /dev/null +++ b/vendor/github.com/gdamore/tcell/colorfit.go @@ -0,0 +1,52 @@ +// Copyright 2016 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "github.com/lucasb-eyer/go-colorful" + "math" +) + +// FindColor attempts to find a given color, or the best match possible for it, +// from the palette given. This is an expensive operation, so results should +// be cached by the caller. +func FindColor(c Color, palette []Color) Color { + match := ColorDefault + dist := float64(0) + r, g, b := c.RGB() + c1 := colorful.Color{ + R: float64(r) / 255.0, + G: float64(g) / 255.0, + B: float64(b) / 255.0, + } + for _, d := range palette { + r, g, b = d.RGB() + c2 := colorful.Color{ + R: float64(r) / 255.0, + G: float64(g) / 255.0, + B: float64(b) / 255.0, + } + // CIE94 is more accurate, but really really expensive. + nd := c1.DistanceCIE76(c2) + if math.IsNaN(nd) { + nd = math.Inf(1) + } + if match == ColorDefault || nd < dist { + match = d + dist = nd + } + } + return match +} diff --git a/vendor/github.com/gdamore/tcell/console_stub.go b/vendor/github.com/gdamore/tcell/console_stub.go new file mode 100644 index 00000000..fda2f092 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/console_stub.go @@ -0,0 +1,23 @@ +// +build !windows + +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +// NewConsoleScreen returns a console based screen. This platform +// doesn't have support for any, so it returns nil and a suitable error. +func NewConsoleScreen() (Screen, error) { + return nil, ErrNoScreen +} diff --git a/vendor/github.com/gdamore/tcell/console_win.go b/vendor/github.com/gdamore/tcell/console_win.go new file mode 100644 index 00000000..e27bf6a3 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/console_win.go @@ -0,0 +1,1025 @@ +// +build windows + +// Copyright 2016 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "sync" + "syscall" + "unicode/utf16" + "unsafe" + "errors" +) + +type cScreen struct { + in syscall.Handle + out syscall.Handle + cancelflag syscall.Handle + scandone chan struct{} + evch chan Event + quit chan struct{} + curx int + cury int + style Style + clear bool + fini bool + + w int + h int + + oscreen consoleInfo + ocursor cursorInfo + oimode uint32 + oomode uint32 + cells CellBuffer + colors map[Color]Color + + sync.Mutex +} + +var winLock sync.Mutex + +var winPalette = []Color{ + ColorBlack, + ColorMaroon, + ColorGreen, + ColorNavy, + ColorOlive, + ColorPurple, + ColorTeal, + ColorSilver, + ColorGray, + ColorRed, + ColorLime, + ColorBlue, + ColorYellow, + ColorFuchsia, + ColorAqua, + ColorWhite, +} + +var winColors = map[Color]Color{ + ColorBlack: ColorBlack, + ColorMaroon: ColorMaroon, + ColorGreen: ColorGreen, + ColorNavy: ColorNavy, + ColorOlive: ColorOlive, + ColorPurple: ColorPurple, + ColorTeal: ColorTeal, + ColorSilver: ColorSilver, + ColorGray: ColorGray, + ColorRed: ColorRed, + ColorLime: ColorLime, + ColorBlue: ColorBlue, + ColorYellow: ColorYellow, + ColorFuchsia: ColorFuchsia, + ColorAqua: ColorAqua, + ColorWhite: ColorWhite, +} + +var k32 = syscall.NewLazyDLL("kernel32.dll") + +// We have to bring in the kernel32.dll directly, so we can get access to some +// system calls that the core Go API lacks. +// +// Note that Windows appends some functions with W to indicate that wide +// characters (Unicode) are in use. The documentation refers to them +// without this suffix, as the resolution is made via preprocessor. +var ( + procReadConsoleInput = k32.NewProc("ReadConsoleInputW") + procWaitForMultipleObjects = k32.NewProc("WaitForMultipleObjects") + procCreateEvent = k32.NewProc("CreateEventW") + procSetEvent = k32.NewProc("SetEvent") + procGetConsoleCursorInfo = k32.NewProc("GetConsoleCursorInfo") + procSetConsoleCursorInfo = k32.NewProc("SetConsoleCursorInfo") + procSetConsoleCursorPosition = k32.NewProc("SetConsoleCursorPosition") + procSetConsoleMode = k32.NewProc("SetConsoleMode") + procGetConsoleMode = k32.NewProc("GetConsoleMode") + procGetConsoleScreenBufferInfo = k32.NewProc("GetConsoleScreenBufferInfo") + procFillConsoleOutputAttribute = k32.NewProc("FillConsoleOutputAttribute") + procFillConsoleOutputCharacter = k32.NewProc("FillConsoleOutputCharacterW") + procSetConsoleWindowInfo = k32.NewProc("SetConsoleWindowInfo") + procSetConsoleScreenBufferSize = k32.NewProc("SetConsoleScreenBufferSize") + procSetConsoleTextAttribute = k32.NewProc("SetConsoleTextAttribute") +) + +const ( + w32Infinite = ^uintptr(0) + w32WaitObject0 = uintptr(0) +) + +// NewConsoleScreen returns a Screen for the Windows console associated +// with the current process. The Screen makes use of the Windows Console +// API to display content and read events. +func NewConsoleScreen() (Screen, error) { + return &cScreen{}, nil +} + +func (s *cScreen) Init() error { + s.evch = make(chan Event, 10) + s.quit = make(chan struct{}) + s.scandone = make(chan struct{}) + + in, e := syscall.Open("CONIN$", syscall.O_RDWR, 0) + if e != nil { + return e + } + s.in = in + out, e := syscall.Open("CONOUT$", syscall.O_RDWR, 0) + if e != nil { + syscall.Close(s.in) + return e + } + s.out = out + + cf, _, e := procCreateEvent.Call( + uintptr(0), + uintptr(1), + uintptr(0), + uintptr(0)) + if cf == uintptr(0) { + return e + } + s.cancelflag = syscall.Handle(cf) + + s.Lock() + + s.curx = -1 + s.cury = -1 + s.style = StyleDefault + s.getCursorInfo(&s.ocursor) + s.getConsoleInfo(&s.oscreen) + s.getOutMode(&s.oomode) + s.getInMode(&s.oimode) + s.resize() + + s.fini = false + s.setInMode(modeResizeEn) + s.setOutMode(0) + s.clearScreen(s.style) + s.hideCursor() + s.Unlock() + go s.scanInput() + + return nil +} + +func (s *cScreen) CharacterSet() string { + // We are always UTF-16LE on Windows + return "UTF-16LE" +} + +func (s *cScreen) EnableMouse() { + s.setInMode(modeResizeEn | modeMouseEn) +} + +func (s *cScreen) DisableMouse() { + s.setInMode(modeResizeEn) +} + +func (s *cScreen) Fini() { + s.Lock() + s.style = StyleDefault + s.curx = -1 + s.cury = -1 + s.fini = true + s.Unlock() + + s.setCursorInfo(&s.ocursor) + s.setInMode(s.oimode) + s.setOutMode(s.oomode) + s.setBufferSize(int(s.oscreen.size.x), int(s.oscreen.size.y)) + s.clearScreen(StyleDefault) + s.setCursorPos(0, 0) + procSetConsoleTextAttribute.Call( + uintptr(s.out), + uintptr(s.mapStyle(StyleDefault))) + + close(s.quit) + procSetEvent.Call(uintptr(s.cancelflag)) + // Block until scanInput returns; this prevents a race condition on Win 8+ + // which causes syscall.Close to block until another keypress is read. + <-s.scandone + syscall.Close(s.in) + syscall.Close(s.out) +} + +func (s *cScreen) PostEventWait(ev Event) { + s.evch <- ev +} + +func (s *cScreen) PostEvent(ev Event) error { + select { + case s.evch <- ev: + return nil + default: + return ErrEventQFull + } +} + +func (s *cScreen) PollEvent() Event { + select { + case <-s.quit: + return nil + case ev := <-s.evch: + return ev + } +} + +type cursorInfo struct { + size uint32 + visible uint32 +} + +type coord struct { + x int16 + y int16 +} + +func (c coord) uintptr() uintptr { + // little endian, put x first + return uintptr(c.x) | (uintptr(c.y) << 16) +} + +type rect struct { + left int16 + top int16 + right int16 + bottom int16 +} + +func (s *cScreen) showCursor() { + s.setCursorInfo(&cursorInfo{size: 100, visible: 1}) +} + +func (s *cScreen) hideCursor() { + s.setCursorInfo(&cursorInfo{size: 1, visible: 0}) +} + +func (s *cScreen) ShowCursor(x, y int) { + s.Lock() + if !s.fini { + s.curx = x + s.cury = y + } + s.doCursor() + s.Unlock() +} + +func (s *cScreen) doCursor() { + x, y := s.curx, s.cury + + if x < 0 || y < 0 || x >= s.w || y >= s.h { + s.setCursorPos(0, 0) + s.hideCursor() + } else { + s.setCursorPos(x, y) + s.showCursor() + } +} + +func (s *cScreen) HideCursor() { + s.ShowCursor(-1, -1) +} + +type charInfo struct { + ch uint16 + attr uint16 +} + +type inputRecord struct { + typ uint16 + _ uint16 + data [16]byte +} + +const ( + keyEvent uint16 = 1 + mouseEvent uint16 = 2 + resizeEvent uint16 = 4 + menuEvent uint16 = 8 // don't use + focusEvent uint16 = 16 // don't use +) + +type mouseRecord struct { + x int16 + y int16 + btns uint32 + mod uint32 + flags uint32 +} + +const ( + mouseDoubleClick uint32 = 0x2 + mouseHWheeled uint32 = 0x8 + mouseVWheeled uint32 = 0x4 + mouseMoved uint32 = 0x1 +) + +type resizeRecord struct { + x int16 + y int16 +} + +type keyRecord struct { + isdown int32 + repeat uint16 + kcode uint16 + scode uint16 + ch uint16 + mod uint32 +} + +const ( + // Constants per Microsoft. We don't put the modifiers + // here. + vkCancel = 0x03 + vkBack = 0x08 // Backspace + vkTab = 0x09 + vkClear = 0x0c + vkReturn = 0x0d + vkPause = 0x13 + vkEscape = 0x1b + vkSpace = 0x20 + vkPrior = 0x21 // PgUp + vkNext = 0x22 // PgDn + vkEnd = 0x23 + vkHome = 0x24 + vkLeft = 0x25 + vkUp = 0x26 + vkRight = 0x27 + vkDown = 0x28 + vkPrint = 0x2a + vkPrtScr = 0x2c + vkInsert = 0x2d + vkDelete = 0x2e + vkHelp = 0x2f + vkF1 = 0x70 + vkF2 = 0x71 + vkF3 = 0x72 + vkF4 = 0x73 + vkF5 = 0x74 + vkF6 = 0x75 + vkF7 = 0x76 + vkF8 = 0x77 + vkF9 = 0x78 + vkF10 = 0x79 + vkF11 = 0x7a + vkF12 = 0x7b + vkF13 = 0x7c + vkF14 = 0x7d + vkF15 = 0x7e + vkF16 = 0x7f + vkF17 = 0x80 + vkF18 = 0x81 + vkF19 = 0x82 + vkF20 = 0x83 + vkF21 = 0x84 + vkF22 = 0x85 + vkF23 = 0x86 + vkF24 = 0x87 +) + +var vkKeys = map[uint16]Key{ + vkCancel: KeyCancel, + vkBack: KeyBackspace, + vkTab: KeyTab, + vkClear: KeyClear, + vkPause: KeyPause, + vkPrint: KeyPrint, + vkPrtScr: KeyPrint, + vkPrior: KeyPgUp, + vkNext: KeyPgDn, + vkReturn: KeyEnter, + vkEnd: KeyEnd, + vkHome: KeyHome, + vkLeft: KeyLeft, + vkUp: KeyUp, + vkRight: KeyRight, + vkDown: KeyDown, + vkInsert: KeyInsert, + vkDelete: KeyDelete, + vkHelp: KeyHelp, + vkF1: KeyF1, + vkF2: KeyF2, + vkF3: KeyF3, + vkF4: KeyF4, + vkF5: KeyF5, + vkF6: KeyF6, + vkF7: KeyF7, + vkF8: KeyF8, + vkF9: KeyF9, + vkF10: KeyF10, + vkF11: KeyF11, + vkF12: KeyF12, + vkF13: KeyF13, + vkF14: KeyF14, + vkF15: KeyF15, + vkF16: KeyF16, + vkF17: KeyF17, + vkF18: KeyF18, + vkF19: KeyF19, + vkF20: KeyF20, + vkF21: KeyF21, + vkF22: KeyF22, + vkF23: KeyF23, + vkF24: KeyF24, +} + +// NB: All Windows platforms are little endian. We assume this +// never, ever change. The following code is endian safe. and does +// not use unsafe pointers. +func getu32(v []byte) uint32 { + return uint32(v[0]) + (uint32(v[1]) << 8) + (uint32(v[2]) << 16) + (uint32(v[3]) << 24) +} +func geti32(v []byte) int32 { + return int32(getu32(v)) +} +func getu16(v []byte) uint16 { + return uint16(v[0]) + (uint16(v[1]) << 8) +} +func geti16(v []byte) int16 { + return int16(getu16(v)) +} + +// Convert windows dwControlKeyState to modifier mask +func mod2mask(cks uint32) ModMask { + mm := ModNone + // Left or right control + if (cks & (0x0008 | 0x0004)) != 0 { + mm |= ModCtrl + } + // Left or right alt + if (cks & (0x0002 | 0x0001)) != 0 { + mm |= ModAlt + } + // Any shift + if (cks & 0x0010) != 0 { + mm |= ModShift + } + return mm +} + +func mrec2btns(mbtns, flags uint32) ButtonMask { + btns := ButtonNone + if mbtns&0x1 != 0 { + btns |= Button1 + } + if mbtns&0x2 != 0 { + btns |= Button2 + } + if mbtns&0x4 != 0 { + btns |= Button3 + } + if mbtns&0x8 != 0 { + btns |= Button4 + } + if mbtns&0x10 != 0 { + btns |= Button5 + } + if mbtns&0x20 != 0 { + btns |= Button6 + } + if mbtns&0x40 != 0 { + btns |= Button7 + } + if mbtns&0x80 != 0 { + btns |= Button8 + } + + if flags&mouseVWheeled != 0 { + if mbtns&0x80000000 == 0 { + btns |= WheelUp + } else { + btns |= WheelDown + } + } + if flags&mouseHWheeled != 0 { + if mbtns&0x80000000 == 0 { + btns |= WheelRight + } else { + btns |= WheelLeft + } + } + return btns +} + +func (s *cScreen) getConsoleInput() error { + // cancelFlag comes first as WaitForMultipleObjects returns the lowest index + // in the event that both events are signalled. + waitObjects := []syscall.Handle{s.cancelflag, s.in} + // As arrays are contiguous in memory, a pointer to the first object is the + // same as a pointer to the array itself. + pWaitObjects := unsafe.Pointer(&waitObjects[0]) + + rv, _, er := procWaitForMultipleObjects.Call( + uintptr(len(waitObjects)), + uintptr(pWaitObjects), + uintptr(0), + w32Infinite) + // WaitForMultipleObjects returns WAIT_OBJECT_0 + the index. + switch rv { + case w32WaitObject0: // s.cancelFlag + return errors.New("cancelled") + case w32WaitObject0 + 1: // s.in + rec := &inputRecord{} + var nrec int32 + rv, _, er := procReadConsoleInput.Call( + uintptr(s.in), + uintptr(unsafe.Pointer(rec)), + uintptr(1), + uintptr(unsafe.Pointer(&nrec))) + if rv == 0 { + return er + } + if nrec != 1 { + return nil + } + switch rec.typ { + case keyEvent: + krec := &keyRecord{} + krec.isdown = geti32(rec.data[0:]) + krec.repeat = getu16(rec.data[4:]) + krec.kcode = getu16(rec.data[6:]) + krec.scode = getu16(rec.data[8:]) + krec.ch = getu16(rec.data[10:]) + krec.mod = getu32(rec.data[12:]) + + if krec.isdown == 0 || krec.repeat < 1 { + // its a key release event, ignore it + return nil + } + if krec.ch != 0 { + // synthesized key code + for krec.repeat > 0 { + s.PostEvent(NewEventKey(KeyRune, rune(krec.ch), + mod2mask(krec.mod))) + krec.repeat-- + } + return nil + } + key := KeyNUL // impossible on Windows + ok := false + if key, ok = vkKeys[krec.kcode]; !ok { + return nil + } + for krec.repeat > 0 { + s.PostEvent(NewEventKey(key, rune(krec.ch), + mod2mask(krec.mod))) + krec.repeat-- + } + + case mouseEvent: + var mrec mouseRecord + mrec.x = geti16(rec.data[0:]) + mrec.y = geti16(rec.data[2:]) + mrec.btns = getu32(rec.data[4:]) + mrec.mod = getu32(rec.data[8:]) + mrec.flags = getu32(rec.data[12:]) + btns := mrec2btns(mrec.btns, mrec.flags) + // we ignore double click, events are delivered normally + s.PostEvent(NewEventMouse(int(mrec.x), int(mrec.y), btns, + mod2mask(mrec.mod))) + + case resizeEvent: + var rrec resizeRecord + rrec.x = geti16(rec.data[0:]) + rrec.y = geti16(rec.data[2:]) + s.PostEvent(NewEventResize(int(rrec.x), int(rrec.y))) + + default: + } + default: + return er + } + + return nil +} + +func (s *cScreen) scanInput() { + for { + if e := s.getConsoleInput(); e != nil { + close(s.scandone) + return + } + } +} + +// Windows console can display 8 characters, in either low or high intensity +func (s *cScreen) Colors() int { + return 16 +} + +var vgaColors = map[Color]uint16{ + ColorBlack: 0, + ColorMaroon: 0x4, + ColorGreen: 0x2, + ColorNavy: 0x1, + ColorOlive: 0x6, + ColorPurple: 0x5, + ColorTeal: 0x3, + ColorSilver: 0x7, + ColorGrey: 0x8, + ColorRed: 0xc, + ColorLime: 0xa, + ColorBlue: 0x9, + ColorYellow: 0xe, + ColorFuchsia: 0xd, + ColorAqua: 0xb, + ColorWhite: 0xf, +} + +// Windows uses RGB signals +func mapColor2RGB(c Color) uint16 { + winLock.Lock() + if v, ok := winColors[c]; ok { + c = v + } else { + v = FindColor(c, winPalette) + winColors[c] = v + c = v + } + winLock.Unlock() + + if vc, ok := vgaColors[c]; ok { + return vc + } + return 0 +} + +// Map a tcell style to Windows attributes +func (s *cScreen) mapStyle(style Style) uint16 { + f, b, a := style.Decompose() + fa := s.oscreen.attrs & 0xf + ba := (s.oscreen.attrs) >> 4 & 0xf + if f != ColorDefault { + fa = mapColor2RGB(f) + } + if b != ColorDefault { + ba = mapColor2RGB(b) + } + var attr uint16 + // We simulate reverse by doing the color swap ourselves. + // Apparently windows cannot really do this except in DBCS + // views. + if a&AttrReverse != 0 { + attr = ba + attr |= (fa << 4) + } else { + attr = fa + attr |= (ba << 4) + } + if a&AttrBold != 0 { + attr |= 0x8 + } + if a&AttrDim != 0 { + attr &^= 0x8 + } + if a&AttrUnderline != 0 { + // Best effort -- doesn't seem to work though. + attr |= 0x8000 + } + // Blink is unsupported + return attr +} + +func (s *cScreen) SetCell(x, y int, style Style, ch ...rune) { + if len(ch) > 0 { + s.SetContent(x, y, ch[0], ch[1:], style) + } else { + s.SetContent(x, y, ' ', nil, style) + } +} + +func (s *cScreen) SetContent(x, y int, mainc rune, combc []rune, style Style) { + s.Lock() + if !s.fini { + s.cells.SetContent(x, y, mainc, combc, style) + } + s.Unlock() +} + +func (s *cScreen) GetContent(x, y int) (rune, []rune, Style, int) { + s.Lock() + mainc, combc, style, width := s.cells.GetContent(x, y) + s.Unlock() + return mainc, combc, style, width +} + +func (s *cScreen) writeString(x, y int, style Style, ch []uint16) { + // we assume the caller has hidden the cursor + if len(ch) == 0 { + return + } + nw := uint32(len(ch)) + procSetConsoleTextAttribute.Call( + uintptr(s.out), + uintptr(s.mapStyle(style))) + s.setCursorPos(x, y) + syscall.WriteConsole(s.out, &ch[0], nw, &nw, nil) +} + +func (s *cScreen) draw() { + // allocate a scratch line bit enough for no combining chars. + // if you have combining characters, you may pay for extra allocs. + if s.clear { + s.clearScreen(s.style) + s.clear = false + s.cells.Invalidate() + } + buf := make([]uint16, 0, s.w) + wcs := buf[:] + lstyle := Style(-1) // invalid attribute + + lx, ly := -1, -1 + ra := make([]rune, 1) + + for y := 0; y < int(s.h); y++ { + for x := 0; x < int(s.w); x++ { + mainc, combc, style, width := s.cells.GetContent(x, y) + dirty := s.cells.Dirty(x, y) + if style == StyleDefault { + style = s.style + } + + if !dirty || style != lstyle { + // write out any data queued thus far + // because we are going to skip over some + // cells, or because we need to change styles + s.writeString(lx, ly, lstyle, wcs) + wcs = buf[0:0] + lstyle = Style(-1) + if !dirty { + continue + } + } + if x > s.w-width { + mainc = ' ' + combc = nil + width = 1 + } + if len(wcs) == 0 { + lstyle = style + lx = x + ly = y + } + ra[0] = mainc + wcs = append(wcs, utf16.Encode(ra)...) + if len(combc) != 0 { + wcs = append(wcs, utf16.Encode(combc)...) + } + s.cells.SetDirty(x, y, false) + x += width - 1 + } + s.writeString(lx, ly, lstyle, wcs) + wcs = buf[0:0] + lstyle = Style(-1) + } +} + +func (s *cScreen) Show() { + s.Lock() + if !s.fini { + s.hideCursor() + s.resize() + s.draw() + s.doCursor() + } + s.Unlock() +} + +func (s *cScreen) Sync() { + s.Lock() + if !s.fini { + s.cells.Invalidate() + s.hideCursor() + s.resize() + s.draw() + s.doCursor() + } + s.Unlock() +} + +type consoleInfo struct { + size coord + pos coord + attrs uint16 + win rect + maxsz coord +} + +func (s *cScreen) getConsoleInfo(info *consoleInfo) { + procGetConsoleScreenBufferInfo.Call( + uintptr(s.out), + uintptr(unsafe.Pointer(info))) +} + +func (s *cScreen) getCursorInfo(info *cursorInfo) { + procGetConsoleCursorInfo.Call( + uintptr(s.out), + uintptr(unsafe.Pointer(info))) +} + +func (s *cScreen) setCursorInfo(info *cursorInfo) { + procSetConsoleCursorInfo.Call( + uintptr(s.out), + uintptr(unsafe.Pointer(info))) +} + +func (s *cScreen) setCursorPos(x, y int) { + procSetConsoleCursorPosition.Call( + uintptr(s.out), + coord{int16(x), int16(y)}.uintptr()) +} + +func (s *cScreen) setBufferSize(x, y int) { + procSetConsoleScreenBufferSize.Call( + uintptr(s.out), + coord{int16(x), int16(y)}.uintptr()) +} + +func (s *cScreen) Size() (int, int) { + s.Lock() + w, h := s.w, s.h + s.Unlock() + + return w, h +} + +func (s *cScreen) resize() { + info := consoleInfo{} + s.getConsoleInfo(&info) + + w := int((info.win.right - info.win.left) + 1) + h := int((info.win.bottom - info.win.top) + 1) + + if s.w == w && s.h == h { + return + } + + s.cells.Resize(w, h) + s.w = w + s.h = h + + r := rect{0, 0, int16(w - 1), int16(h - 1)} + procSetConsoleWindowInfo.Call( + uintptr(s.out), + uintptr(1), + uintptr(unsafe.Pointer(&r))) + + s.setBufferSize(w, h) + + s.PostEvent(NewEventResize(w, h)) +} + +func (s *cScreen) Clear() { + s.Fill(' ', s.style) +} + +func (s *cScreen) Fill(r rune, style Style) { + s.Lock() + if !s.fini { + s.cells.Fill(r, style) + s.clear = true + } + s.Unlock() +} + +func (s *cScreen) clearScreen(style Style) { + pos := coord{0, 0} + attr := s.mapStyle(style) + x, y := s.w, s.h + scratch := uint32(0) + count := uint32(x * y) + + procFillConsoleOutputAttribute.Call( + uintptr(s.out), + uintptr(attr), + uintptr(count), + pos.uintptr(), + uintptr(unsafe.Pointer(&scratch))) + procFillConsoleOutputCharacter.Call( + uintptr(s.out), + uintptr(' '), + uintptr(count), + pos.uintptr(), + uintptr(unsafe.Pointer(&scratch))) +} + +const ( + modeMouseEn uint32 = 0x0010 + modeResizeEn uint32 = 0x0008 + modeWrapEOL uint32 = 0x0002 + modeCooked uint32 = 0x0001 +) + +func (s *cScreen) setInMode(mode uint32) error { + rv, _, err := procSetConsoleMode.Call( + uintptr(s.in), + uintptr(mode)) + if rv == 0 { + return err + } + return nil +} + +func (s *cScreen) setOutMode(mode uint32) error { + rv, _, err := procSetConsoleMode.Call( + uintptr(s.out), + uintptr(mode)) + if rv == 0 { + return err + } + return nil +} + +func (s *cScreen) getInMode(v *uint32) { + procGetConsoleMode.Call( + uintptr(s.in), + uintptr(unsafe.Pointer(v))) +} + +func (s *cScreen) getOutMode(v *uint32) { + procGetConsoleMode.Call( + uintptr(s.out), + uintptr(unsafe.Pointer(v))) +} + +func (s *cScreen) SetStyle(style Style) { + s.Lock() + s.style = style + s.Unlock() +} + +// No fallback rune support, since we have Unicode. Yay! + +func (s *cScreen) RegisterRuneFallback(r rune, subst string) { +} + +func (s *cScreen) UnregisterRuneFallback(r rune) { +} + +func (s *cScreen) CanDisplay(r rune, checkFallbacks bool) bool { + // We presume we can display anything -- we're Unicode. + // (Sadly this not precisely true. Combinings are especially + // poorly supported under Windows.) + return true +} + +func (s *cScreen) HasMouse() bool { + return true +} + +func (s *cScreen) Resize(int, int, int, int) {} + +func (s *cScreen) HasKey(k Key) bool { + // Microsoft has codes for some keys, but they are unusual, + // so we don't include them. We include all the typical + // 101, 105 key layout keys. + valid := map[Key]bool{ + KeyBackspace: true, + KeyTab: true, + KeyEscape: true, + KeyPause: true, + KeyPrint: true, + KeyPgUp: true, + KeyPgDn: true, + KeyEnter: true, + KeyEnd: true, + KeyHome: true, + KeyLeft: true, + KeyUp: true, + KeyRight: true, + KeyDown: true, + KeyInsert: true, + KeyDelete: true, + KeyF1: true, + KeyF2: true, + KeyF3: true, + KeyF4: true, + KeyF5: true, + KeyF6: true, + KeyF7: true, + KeyF8: true, + KeyF9: true, + KeyF10: true, + KeyF11: true, + KeyF12: true, + KeyRune: true, + } + + return valid[k] +} diff --git a/vendor/github.com/gdamore/tcell/database.json b/vendor/github.com/gdamore/tcell/database.json new file mode 100644 index 00000000..2769591a --- /dev/null +++ b/vendor/github.com/gdamore/tcell/database.json @@ -0,0 +1,1351 @@ +{"name":"rxvt-unicode","cols":80,"lines":24,"colors":88,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[r\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[38;5;%p1%dm","setbg":"\u001b[48;5;%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~-A.B+C,D0EhFiG","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[38;5;%p1%d;48;5;%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-unicode-256color","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[r\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[38;5;%p1%dm","setbg":"\u001b[48;5;%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~-A.B+C,D0EhFiG","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[38;5;%p1%d;48;5;%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"Eterm","aliases":["Eterm-color"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"Eterm-256color","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"Eterm-88color","cols":80,"lines":24,"colors":88,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"NCR260VT300WPP","aliases":["ncr260vt300wpp"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"aaa","aliases":["aaa-30","ambas","ambassador"],"cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[30;0;0;30p","rmcup":"\u001b[60;0;0;30p\u001b[30;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa+unk","aliases":["aaa-unk"],"cols":80,"lines":-1,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-18","cols":80,"lines":18,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[18;0;0;18p","rmcup":"\u001b[60;0;0;18p\u001b[60;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-18-rv","cols":80,"lines":18,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[18;0;0;18p","rmcup":"\u001b[60;0;0;18p\u001b[60;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-20","cols":80,"lines":20,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[20;0;0;20p","rmcup":"\u001b[60;0;0;20p\u001b[60;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-22","cols":80,"lines":22,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[22;0;0;22p","rmcup":"\u001b[60;0;0;22p\u001b[60;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-24","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[24;0;0;24p","rmcup":"\u001b[60;0;0;24p\u001b[60;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-24-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[24;0;0;24p","rmcup":"\u001b[60;0;0;24p\u001b[60;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-26","cols":80,"lines":26,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[26;0;0;26p","rmcup":"\u001b[60;0;0;26p\u001b[26;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-28","cols":80,"lines":28,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[28;0;0;28p","rmcup":"\u001b[60;0;0;28p\u001b[28;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-30-ctxt","aliases":["aaa-ctxt"],"cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[30;0;0;30p","rmcup":"\u001b[60;0;0;30p\u001b[60;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-30-rv","aliases":["aaa-rv"],"cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[30;0;0;30p","rmcup":"\u001b[60;0;0;30p\u001b[30;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-30-rv-ctxt","aliases":["aaa-rv-ctxt"],"cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[30;0;0;30p","rmcup":"\u001b[60;0;0;30p\u001b[60;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-30-s","aliases":["aaa-s"],"cols":80,"lines":29,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[30;1;0;30p\u001b[30;1H\u001b[K","rmcup":"\u001b[60;1;0;30p\u001b[29;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-30-s-rv","aliases":["aaa-s-rv"],"cols":80,"lines":29,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[30;1;0;30p\u001b[30;1H\u001b[K","rmcup":"\u001b[60;1;0;30p\u001b[29;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-36","cols":80,"lines":36,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[36;0;0;36p","rmcup":"\u001b[60;0;0;36p\u001b[36;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-36-rv","cols":80,"lines":36,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[36;0;0;36p","rmcup":"\u001b[60;0;0;36p\u001b[36;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-40","cols":80,"lines":40,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[40;0;0;40p","rmcup":"\u001b[60;0;0;40p\u001b[40;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-40-rv","cols":80,"lines":40,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[40;0;0;40p","rmcup":"\u001b[60;0;0;40p\u001b[40;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-48","cols":80,"lines":48,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[48;0;0;48p","rmcup":"\u001b[60;0;0;48p\u001b[48;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-48-rv","cols":80,"lines":48,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[48;0;0;48p","rmcup":"\u001b[60;0;0;48p\u001b[48;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-60","cols":80,"lines":60,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-60-dec-rv","cols":80,"lines":59,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J","acsc":"aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}","smacs":"\u000f","rmacs":"\u000e","enacs":"\u001b(0"} +{"name":"aaa-60-rv","cols":80,"lines":60,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-60-s","cols":80,"lines":59,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-60-s-rv","cols":80,"lines":59,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-db","cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[30;0;0;30p","rmcup":"\u001b[60;0;0;30p\u001b[30;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-s-ctxt","aliases":["aaa-30-s-ctxt"],"cols":80,"lines":29,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[30;1H\u001b[K\u001b[30;1;0;30p","rmcup":"\u001b[60;1;0;30p\u001b[59;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"aaa-s-rv-ctxt","aliases":["aaa-30-s-rv-ct"],"cols":80,"lines":29,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[30;1H\u001b[K\u001b[30;1;0;30p","rmcup":"\u001b[60;1;0;30p\u001b[59;1H\u001b[K","sgr0":"\u001b[7m\u000e","smul":"\u001b[4;7m","bold":"\u001b[1;7m","blink":"\u001b[5;7m","rev":"\u001b[m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"abm80","cols":80,"lines":24,"clear":"\u001b\u001c","cup":"\u001b\u0011%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001b\u000c","pad":"\u0000"} +{"name":"abm85","cols":80,"lines":24,"clear":"\u001b*","smul":"\u001bl","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"abm85e","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001b(\u001bk","smul":"\u001bl","rev":"\u001bj","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"abm85h","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","cnorm":"\u001b.4","sgr0":"\u001b(\u001bG0","smul":"\u001bG8","rev":"\u001bG4","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"abm85h-old","aliases":["o85h","oabm85h"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001b(\u001bk","smul":"\u001bl","rev":"\u001bj","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"act4","aliases":["microterm"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c12/\u003e","cup":"\u0014%p1%{24}%+%c%p2%p2%?%'/'%\u003e%t%'0'%+%;%'P'%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"act5","aliases":["microterm5"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c12/\u003e","cup":"\u0014%p1%{24}%+%c%p2%p2%?%'/'%\u003e%t%'0'%+%;%'P'%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"adds980","aliases":["a980"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c1\u003e\u000b@","sgr0":"\u000f","cup":"\u000b%p1%'@'%+%c\u001b\u0005%p2%2d","cub1":"\u0008","pad":"\u0000","kf1":"\u001b1","kf2":"\u001b2","kf3":"\u001b3","kf4":"\u001b4","kf5":"\u001b5","kf6":"\u001b6","kf7":"\u001b7","kf8":"\u001b8","kf9":"\u001b9"} +{"name":"adm11","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm1178","aliases":["1178"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+","sgr0":"\u001b)","smul":"\u001bG1","bold":"\u001b(","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"adm12","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u00011\r","kf2":"\u00012\r","kf3":"\u00013\r","kf4":"\u00014\r","kf5":"\u00015\r","kf6":"\u00016\r","kf7":"\u00017\r","kf8":"\u00018\r","kf9":"\u00019\r","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm1a","aliases":["adm1"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;$\u003c1\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"adm2","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm20","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","sgr0":"\u001b(","cup":"\u001b=%i%p2%{31}%+%c%p1%{31}%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001","kf2":"\u0002","kf3":"\u0017","kf4":"\u0004","kf5":"\u0005","kf6":"\u0018","kf7":"\u001a"} +{"name":"adm21","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c1/\u003e","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm22","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+","sgr0":"\u001b(","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm31","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","smul":"\u001bG1","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u00011\r","kf2":"\u00012\r","kf3":"\u00013\r","kf4":"\u00014\r","kf5":"\u00015\r","kf6":"\u00016\r","kf7":"\u00017\r","kf8":"\u00018\r","kf9":"\u00019\r","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm31-old","aliases":["o31"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u00011\r","kf2":"\u00012\r","kf3":"\u00013\r","kf4":"\u00014\r","kf5":"\u00015\r","kf6":"\u00016\r","kf7":"\u00017\r","kf8":"\u00018\r","kf9":"\u00019\r","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm36","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"adm3a","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c1/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm3a+","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c1/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm42","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;","sgr0":"\u001bG0","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm42-ns","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;\u001bF \t","sgr0":"\u001bG0","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c6\u003e\u001bF \t","cub1":"\u0008","cuu1":"\u000b","pad":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"adm5","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c1/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"aepro","cols":80,"lines":24,"clear":"\u000c$\u003c300/\u003e","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cuu1":"\u001bA","pad":"\u0000"} +{"name":"aixterm","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"jjkkllmmnnqqttuuvvwwxx","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"aixterm-16color","cols":80,"lines":25,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"jjkkllmmnnqqttuuvvwwxx","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"aixterm-m","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"jjkkllmmnnqqttuuvvwwxx"} +{"name":"aixterm-m-old","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"aj510","cols":80,"lines":24,"clear":"\u000c","smcup":"\u001b\"N","rmcup":"\u001b\"N","smul":"\u001b\"U","cup":"\u001b#%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bY","pad":"","kcuu1":"\u001bY","kcud1":"\u001bZ","kcub1":"\u001bW","kcuf1":"\u001bX"} +{"name":"alto-h19","aliases":["alto-heath","altoh19","altoheath"],"cols":80,"lines":60,"bell":"\u0007","clear":"\u001bE","cnorm":"\u001by4","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"altos2","aliases":["alt2","altos-2"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[1A","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf32":"\u0001`\r","kf33":"\u0001a\r","kf34":"\u0001b\r","kf35":"\u0001c\r","kf36":"\u0001d\r","kf37":"\u0001e\r","kf38":"\u0001f\r","kf39":"\u0001g\r","kf40":"\u0001h\r","kf41":"\u0001i\r","kf42":"\u0001j\r","kf43":"\u0001k\r","kdch":"\u0001M\r","khome":"\u001b[f","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u0001K\r","kclr":"\u0001L\r"} +{"name":"altos3","aliases":["alt3","alt5","altos-3","altos-5","altos5"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[2J","sgr0":"\u001b[p","smul":"\u001b[4m","blink":"\u001b[5p","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[1A","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf32":"\u0001`\r","kf33":"\u0001a\r","kf34":"\u0001b\r","kf35":"\u0001c\r","kf36":"\u0001d\r","kf37":"\u0001e\r","kf38":"\u0001f\r","kf39":"\u0001g\r","kf40":"\u0001h\r","kf41":"\u0001i\r","kf42":"\u0001j\r","kf43":"\u0001k\r","kdch":"\u0001M\r","khome":"\u001b[f","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u0001K\r","kclr":"\u0001L\r"} +{"name":"altos4","aliases":["alt4","altos-4"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003","rev":"\u001b`6\u001b)","dim":"\u001b`7\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kHOM":"\u001b{"} +{"name":"altos7","aliases":["alt7"],"cols":80,"lines":24,"clear":"\u001b+\u001e","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bGt","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf32":"\u0001`\r","kf33":"\u0001a\r","kf34":"\u0001b\r","kf35":"\u0001c\r","kf36":"\u0001d\r","kf37":"\u0001e\r","kf38":"\u0001f\r","kf39":"\u0001g\r","kf40":"\u0001h\r","kf41":"\u0001i\r","kf42":"\u0001j\r","kf43":"\u0001k\r","kdch":"\u0001M\r","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u0001K\r","kclr":"\u0001L\r","acsc":"j5k3l2m1n8q:t4u9v=w0x6"} +{"name":"altos7pc","aliases":["alt7pc"],"cols":80,"lines":24,"clear":"\u001b+\u001e","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bGt","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf32":"\u0001`\r","kf33":"\u0001a\r","kf34":"\u0001b\r","kf35":"\u0001c\r","kf36":"\u0001d\r","kf37":"\u0001e\r","kf38":"\u0001f\r","kf39":"\u0001g\r","kf40":"\u0001h\r","kf41":"\u0001i\r","kf42":"\u0001j\r","kf43":"\u0001k\r","kdch":"\u0001M\r","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u0001K\r","kclr":"\u0001L\r","acsc":"j5k3l2m1n8q:t4u9v=w0x6"} +{"name":"amiga","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[ p","civis":"\u001b[0 p","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[7;2m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[0~","kf2":"\u001b[1~","kf3":"\u001b[2~","kf4":"\u001b[3~","kf5":"\u001b[4~","kf6":"\u001b[5~","kf7":"\u001b[6~","kf8":"\u001b[7~","kf9":"\u001b[8~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000e","rmacs":"\u000f"} +{"name":"amiga-8bit","cols":80,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l","rmcup":"\ufffd?7h","cnorm":"\ufffd p","civis":"\ufffd0 p","sgr0":"\ufffd0m","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd7;2m","rev":"\ufffd7m","dim":"\ufffd2m","cup":"\ufffd%i%p1%d;%p2%dH","cub1":"\ufffdD","cuu1":"\ufffdA","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd0~","kf2":"\ufffd1~","kf3":"\ufffd2~","kf4":"\ufffd3~","kf5":"\ufffd4~","kf6":"\ufffd5~","kf7":"\ufffd6~","kf8":"\ufffd7~","kf9":"\ufffd8~","kdch":"","khome":"\ufffd A","kend":"\ufffd @","kpp":"\ufffdT","knp":"\ufffdS","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","smacs":"\u000e","rmacs":"\u000f"} +{"name":"amiga-h","cols":80,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l","rmcup":"\ufffd?7h","cnorm":"\ufffd p","civis":"\ufffd0 p","sgr0":"\ufffd0m","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd7;2m","rev":"\ufffd7m","dim":"\ufffd2m","cup":"\ufffd%i%p1%d;%p2%dH","cub1":"\ufffdD","cuu1":"\ufffdA","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd0~","kf2":"\ufffd1~","kf3":"\ufffd2~","kf4":"\ufffd3~","kf5":"\ufffd4~","kf6":"\ufffd5~","kf7":"\ufffd6~","kf8":"\ufffd7~","kf9":"\ufffd8~","kdch":"","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","smacs":"\u000e","rmacs":"\u000f"} +{"name":"amiga-vnc","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7h","rmcup":"\u001b[?7h\u001b[r\u001b[J","cnorm":"\u001b[p\u001b[\u003e?6l","civis":"\u001b[0p","sgr0":"\u001b[0m\u000f\u001b[30;85;\u003e15m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[7;2m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1h","rmkx":"\u001b[?1l","setaf":"\u001b[%?%p1%{8}%\u003e%t%'2'%p1%+%d%e3%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003e%t%'F'%p1%+%d%e4%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[0~","kf2":"\u001b[1~","kf3":"\u001b[2~","kf4":"\u001b[3~","kf5":"\u001b[4~","kf6":"\u001b[5~","kf7":"\u001b[6~","kf8":"\u001b[7~","kf9":"\u001b[8~","kdch":"","khome":"\u001b[44~","khlp":"\u001b[?~","kpp":"\u001b[41~","knp":"\u001b[42~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\ufffdZ","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","_setfgbg":"\u001b[%?%p1%{8}%\u003e%t%'2'%p1%+%d%e3%p1%d%;;%?%p2%{8}%\u003e%t%'F'%p2%+%d%e4%p2%d%;m"} +{"name":"ampex175","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+","smcup":"\u001bN","rmcup":"\u001bF","smul":"\u001bl","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"ampex175-b","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+","smcup":"\u001bN","rmcup":"\u001bF","smul":"\u001bl","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u001f","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"ampex210","aliases":["a210"],"cols":80,"lines":24,"clear":"\u001b*","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u00011\r","kf2":"\u00012\r","kf3":"\u00013\r","kf4":"\u00014\r","kf5":"\u00015\r","kf6":"\u00016\r","kf7":"\u00017\r","kf8":"\u00018\r","kf9":"\u00019\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"ampex219","aliases":["amp219","ampex-219"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","cnorm":"\u001b[?3l","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m","dim":"\u001b[1m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kf1":"\u001b[7~","kf2":"\u001b[8~","kf3":"\u001b[9~","kf4":"\u001b[10~","kf5":"\u001b[11~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ampex219w","aliases":["amp219w","ampex-219w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","cnorm":"\u001b[?3l","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m","dim":"\u001b[1m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kf1":"\u001b[7~","kf2":"\u001b[8~","kf3":"\u001b[9~","kf4":"\u001b[10~","kf5":"\u001b[11~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ampex232","aliases":["ampex-232"],"cols":80,"lines":24,"clear":"\u001b+","cnorm":"\u001b.4","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001A\r","kf2":"\u0001B\r","kf3":"\u0001C\r","kf4":"\u0001D\r","kf5":"\u0001E\r","kf6":"\u0001F\r","kf7":"\u0001G\r","kf8":"\u0001H\r","kf9":"\u0001I\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"ampex232w","cols":132,"lines":24,"clear":"\u001b+","cnorm":"\u001b.4","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001A\r","kf2":"\u0001B\r","kf3":"\u0001C\r","kf4":"\u0001D\r","kf5":"\u0001E\r","kf6":"\u0001F\r","kf7":"\u0001G\r","kf8":"\u0001H\r","kf9":"\u0001I\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"ampex80","aliases":["a80","d80","dialogue","dialogue80"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c75\u003e","smul":"\u001bl","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"annarbor4080","aliases":["aa4080"],"cols":80,"lines":40,"bell":"\u0007","clear":"\u000c$\u003c2\u003e","cup":"\u000f%p2%{10}%/%{16}%*%p2%{10}%m%+%c%p1%?%p1%{19}%\u003e%t%{12}%+%;%'@'%+%c","cub1":"\u0008","cuu1":"\u000e","pad":"\u0000","kbs":"\u001e","khome":"\u000b","kcuu1":"\u000e","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001f"} +{"name":"ansi","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[L","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ansi-color-2-emx","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[0;37;44m\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0;37;44m","smul":"\u001b[1;36;44m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[1;37;46m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd;","kf2":"\ufffd\u003c","kf3":"\ufffd=","kf4":"\ufffd\u003e","kf5":"\ufffd?","kf6":"\ufffd@","kf7":"\ufffdA","kf8":"\ufffdB","kf9":"\ufffdC","kf10":"\ufffdD","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffdT","kf14":"\ufffdU","kf15":"\ufffdV","kf16":"\ufffdW","kf17":"\ufffdX","kf18":"\ufffdY","kf19":"\ufffdZ","kf20":"\ufffd[","kf21":"\ufffd\\","kf22":"\ufffd]","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd^","kf26":"\ufffd_","kf27":"\ufffd`","kf28":"\ufffda","kf29":"\ufffdb","kf30":"\ufffdc","kf31":"\ufffdd","kf32":"\ufffde","kf33":"\ufffdf","kf34":"\ufffdg","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffdh","kf38":"\ufffdi","kf39":"\ufffdj","kf40":"\ufffdk","kf41":"\ufffdl","kf42":"\ufffdm","kf43":"\ufffdn","kf44":"\ufffdo","kf45":"\ufffdp","kf46":"\ufffdq","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffdR","kdch":"\ufffdS","khome":"\ufffdG","kend":"\ufffdO","kpp":"\ufffdI","knp":"\ufffdQ","kcuu1":"\ufffdH","kcud1":"\ufffdP","kcub1":"\ufffdK","kcuf1":"\ufffdM","kcbt":"\ufffd\u000f","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ansi-color-3-emx","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[0;37;40m\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0;10m","smul":"\u001b[0;36;40m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[1;37;46m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd;","kf2":"\ufffd\u003c","kf3":"\ufffd=","kf4":"\ufffd\u003e","kf5":"\ufffd?","kf6":"\ufffd@","kf7":"\ufffdA","kf8":"\ufffdB","kf9":"\ufffdC","kf10":"\ufffdD","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffdT","kf14":"\ufffdU","kf15":"\ufffdV","kf16":"\ufffdW","kf17":"\ufffdX","kf18":"\ufffdY","kf19":"\ufffdZ","kf20":"\ufffd[","kf21":"\ufffd\\","kf22":"\ufffd]","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd^","kf26":"\ufffd_","kf27":"\ufffd`","kf28":"\ufffda","kf29":"\ufffdb","kf30":"\ufffdc","kf31":"\ufffdd","kf32":"\ufffde","kf33":"\ufffdf","kf34":"\ufffdg","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffdh","kf38":"\ufffdi","kf39":"\ufffdj","kf40":"\ufffdk","kf41":"\ufffdl","kf42":"\ufffdm","kf43":"\ufffdn","kf44":"\ufffdo","kf45":"\ufffdp","kf46":"\ufffdq","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffdR","kdch":"\ufffdS","khome":"\ufffdG","kend":"\ufffdO","kpp":"\ufffdI","knp":"\ufffdQ","kcuu1":"\ufffdH","kcud1":"\ufffdP","kcub1":"\ufffdK","kcuf1":"\ufffdM","kcbt":"\ufffd\u000f","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ansi-emx","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[1;33;44m\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b[1;33;44m","smul":"\u001b[1;31;44m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[5;37;41m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd;","kf2":"\ufffd\u003c","kf3":"\ufffd=","kf4":"\ufffd\u003e","kf5":"\ufffd?","kf6":"\ufffd@","kf7":"\ufffdA","kf8":"\ufffdB","kf9":"\ufffdC","kf10":"\ufffdD","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffdT","kf14":"\ufffdU","kf15":"\ufffdV","kf16":"\ufffdW","kf17":"\ufffdX","kf18":"\ufffdY","kf19":"\ufffdZ","kf20":"\ufffd[","kf21":"\ufffd\\","kf22":"\ufffd]","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd^","kf26":"\ufffd_","kf27":"\ufffd`","kf28":"\ufffda","kf29":"\ufffdb","kf30":"\ufffdc","kf31":"\ufffdd","kf32":"\ufffde","kf33":"\ufffdf","kf34":"\ufffdg","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffdh","kf38":"\ufffdi","kf39":"\ufffdj","kf40":"\ufffdk","kf41":"\ufffdl","kf42":"\ufffdm","kf43":"\ufffdn","kf44":"\ufffdo","kf45":"\ufffdp","kf46":"\ufffdq","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffdR","kdch":"\ufffdS","khome":"\ufffdG","kend":"\ufffdO","kpp":"\ufffdI","knp":"\ufffdQ","kcuu1":"\ufffdH","kcud1":"\ufffdP","kcub1":"\ufffdK","kcuf1":"\ufffdM","kcbt":"\ufffd\u000f","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ansi-generic","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ansi-m","aliases":["ansi-mono"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[L","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m"} +{"name":"ansi-mini","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cup":"\u001b[%i%p1%d;%p2%dH","pad":"\u0000"} +{"name":"ansi-mtabs","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000"} +{"name":"ansi-nt","aliases":["psx_ansi"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[0m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001b[A","kcud1":"\u001b[V","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ansi.sys","cols":80,"lines":25,"colors":8,"clear":"\u001b[2J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ansi.sys-old","cols":80,"lines":25,"colors":8,"clear":"\u001b[2J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ansi.sysk","aliases":["ansisysk"],"cols":80,"lines":25,"colors":8,"clear":"\u001b[2J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[;71;30p\u001b[;72;11p\u001b[;73;27;21p\u001b[;77;12p\u001b[;80;10p\u001b[;81;27;4p\u001b[;82;27;27;105p\u001b[;83;127p","rmkx":"\u001b[;71;0;71p\u001b[;72;0;72p\u001b[;73;0;73p\u001b[;77;0;77p\u001b[;80;0;80p\u001b[;81;0;81p\u001b[;82;0;82p\u001b[;83;0;83p","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ansi77","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"apollo","cols":88,"lines":53,"clear":"\u000c","smcup":"\u001bW","rmcup":"\u001bX","smul":"\u001bU","cup":"\u001bM%p1%' '%+%c%p2%d)","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"apollo_15P","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"apollo_19L","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"apollo_color","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"apple-80","cols":80,"lines":24,"clear":"\u000c$\u003c10*/\u003e","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000"} +{"name":"apple-ae","cols":80,"lines":24,"bell":"\u0007$\u003c500/\u003e","clear":"\u000c","sgr0":"\u000e","rev":"\u000f","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0015","kclr":"\u0018"} +{"name":"apple-soroc","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c300\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"apple-uterm","cols":80,"lines":24,"clear":"\u000c","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cuu1":"\u001f","pad":"\u0000"} +{"name":"apple-uterm-vb","cols":80,"lines":24,"clear":"\u000c","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cuu1":"\u001f","pad":"\u0000"} +{"name":"apple-videx","cols":80,"lines":24,"clear":"\u000c$\u003c300/\u003e","sgr0":"\u001a2","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","khome":"\u0019","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0015"} +{"name":"apple-videx2","cols":80,"lines":24,"bell":"\u0007$\u003c100/\u003e","clear":"\u000c$\u003c16*/\u003e","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","kbs":"\u0008","khome":"\u0019","kcuu1":"\u001f","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001c"} +{"name":"apple-videx3","aliases":["vapple"],"cols":80,"lines":24,"clear":"\u001bv","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001bQ","kf2":"\u001bR","kf3":"\u001b ","kf4":"\u001b!","kf5":"\u001b\"","kf6":"\u001b#","kf7":"\u001b$","kf8":"\u001b%%","kf9":"\u001b\u0026","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"apple-vm80","aliases":["ap-vm80"],"cols":80,"lines":24,"clear":"\u000c$\u003c300/\u003e","cup":"\u001e%p1%' '%+%c%p2%' '%+%c$\u003c100/\u003e","cuu1":"\u001f","pad":"\u0000"} +{"name":"apple2e-p","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c100/\u003e","sgr0":"\u000e","rev":"\u000f","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","kbs":"\u0008","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0015"} +{"name":"apple80p","cols":80,"lines":24,"clear":"\u0019\u000c","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cuu1":"\u001f","pad":"\u0000","kcub1":"\u0008"} +{"name":"appleII","cols":80,"lines":24,"clear":"\u000c","cnorm":"\u0014C2","sgr0":"\u000e","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","kcud1":"\n","kcuf1":"\u0015"} +{"name":"appleIIgs","aliases":["appleIIc","appleIIe"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","kbs":"\u0008","kdch":"","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0015","kclr":"\u0018"} +{"name":"arm100","aliases":["arm100-am"],"cols":80,"lines":30,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[P","kf2":"\u001b[Q","kf3":"\u001b[R","kf4":"\u001b[S","kf5":"\u001b[t","kf6":"\u001b[u","kf7":"\u001b[v","kf8":"\u001b[l","kf9":"\u001b[w","kf10":"\u001b[x","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"arm100-w","aliases":["arm100-wam"],"cols":132,"lines":50,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[P","kf2":"\u001b[Q","kf3":"\u001b[R","kf4":"\u001b[S","kf5":"\u001b[t","kf6":"\u001b[u","kf7":"\u001b[v","kf8":"\u001b[l","kf9":"\u001b[w","kf10":"\u001b[x","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"atari","cols":80,"lines":25,"clear":"\u001bH\u001bJ","sgr0":"\u001bq","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"aterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"att2300","aliases":["sv80"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[1r","kf2":"\u001b[2r","kf3":"\u001b[3r","kf4":"\u001b[4r","kf5":"\u001b[5r","kf6":"\u001b[6r","kf7":"\u001b[7r","kf8":"\u001b[8r","kf9":"\u001b[9r","kf10":"\u001b[10r","kf11":"\u001b[11r","kf12":"\u001b[12r","kf13":"\u001b[13r","kf14":"\u001b[14r","kf15":"\u001b[15r","kf16":"\u001b[16r","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"att2350","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[1r","kf2":"\u001b[2r","kf3":"\u001b[3r","kf4":"\u001b[4r","kf5":"\u001b[5r","kf6":"\u001b[6r","kf7":"\u001b[7r","kf8":"\u001b[8r","kf9":"\u001b[9r","kf10":"\u001b[10r","kf11":"\u001b[11r","kf12":"\u001b[12r","kf13":"\u001b[13r","kf14":"\u001b[14r","kf15":"\u001b[15r","kf16":"\u001b[16r","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"att4410","aliases":["att5410","tty5410"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4410v1-w","aliases":["att5410v1-w","tty5410v1-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4415","aliases":["att5420","tty5420"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[x\u001b[J","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j\u001b[21;4j\u001bent","rmkx":"\u001b[19;0j\u001b[21;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dx","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4415-nl","aliases":["att5420-nl","tty5420-nl"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[x\u001b[J","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j\u001b[21;4j\u001bent","rmkx":"\u001b[19;0j\u001b[21;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dx","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4415-rv","aliases":["att5420-rv","tty5420-rv"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[x\u001b[J","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j\u001b[21;4j\u001bent","rmkx":"\u001b[19;0j\u001b[21;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dx","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4415-rv-nl","aliases":["att5420-rv-nl","tty5420-rv-nl"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[x\u001b[J","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j\u001b[21;4j\u001bent","rmkx":"\u001b[19;0j\u001b[21;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dx","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4415-w","aliases":["att5420-w","tty5420-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[x\u001b[J","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j\u001b[21;4j\u001bent","rmkx":"\u001b[19;0j\u001b[21;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dx","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4415-w-nl","aliases":["att5420-w-nl","tty5420-w-nl"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[x\u001b[J","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j\u001b[21;4j\u001bent","rmkx":"\u001b[19;0j\u001b[21;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dx","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4415-w-rv","aliases":["att5420-w-rv","tty5420-w-rv"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[x\u001b[J","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j\u001b[21;4j\u001bent","rmkx":"\u001b[19;0j\u001b[21;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dx","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4415-w-rv-n","aliases":["att5420-w-rv-n","tty5420-w-rv-n"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[x\u001b[J","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j\u001b[21;4j\u001bent","rmkx":"\u001b[19;0j\u001b[21;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dx","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4418","aliases":["att5418"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[h","kf2":"\u001b[i","kf3":"\u001b[j","kf6":"\u001b[k","kf7":"\u001b[l","kf8":"\u001b[f","kf9":"\u001b[w","kf10":"\u001b[m","kf11":"\u001b[n","kf12":"\u001b[o","kf13":"\u001b[H","kf14":"\u001b[I","kf15":"\u001b[J","kf18":"\u001b[K","kf19":"\u001b[L","kf20":"\u001b[E","kf21":"\u001b[_","kf22":"\u001b[M","kf23":"\u001b[N","kf24":"\u001b[O","khome":"\u001bc","kcuu1":"\u001bS","kcud1":"\u001bU","kcub1":"\u001b@","kcuf1":"\u001bA","kclr":"\u001b[%%","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4418-w","aliases":["att5418-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[h","kf2":"\u001b[i","kf3":"\u001b[j","kf6":"\u001b[k","kf7":"\u001b[l","kf8":"\u001b[f","kf9":"\u001b[w","kf10":"\u001b[m","kf11":"\u001b[n","kf12":"\u001b[o","kf13":"\u001b[H","kf14":"\u001b[I","kf15":"\u001b[J","kf18":"\u001b[K","kf19":"\u001b[L","kf20":"\u001b[E","kf21":"\u001b[_","kf22":"\u001b[M","kf23":"\u001b[N","kf24":"\u001b[O","khome":"\u001bc","kcuu1":"\u001bS","kcud1":"\u001bU","kcub1":"\u001b@","kcuf1":"\u001bA","kclr":"\u001b[%%","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att4420","aliases":["tty4420"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","smul":"\u001b\\","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kf3":"\u001b@","kich":"\u001b^","kdch":"\u001bP","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u0008","kcuf1":"\u001bC","kcbt":"\u001bO","kclr":"\u001bJ"} +{"name":"att4424","aliases":["tty4424"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001bX\u001b~\u001bZ\u001b4\u001b(B","smul":"\u001b\\","bold":"\u001b3","blink":"\u001b3","rev":"\u001b}","dim":"\u001bW","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001bJ","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"att4424-1","aliases":["tty4424-1"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001bX\u001b~\u001bZ\u001b4\u001b(B","smul":"\u001b\\","bold":"\u001b3","blink":"\u001b3","rev":"\u001b}","dim":"\u001bW","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"att4424m","aliases":["tty4424m"],"cols":80,"lines":23,"bell":"\u0007","clear":"\u001b[2;H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%2d;%p2%2dH\u001b[B","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"att4426","aliases":["tty4426"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J\u001b[1U\u001b[H\u001b[2J\u001b[1V","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","khome":"\u001b[H","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bO","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"att500","aliases":["att513"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[11;0|","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1|\u001b[21;4|\u001bent","rmkx":"\u001b[19;0|\u001b[21;1|\ufffd","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001bNj","kdch":"\u001bNf","khome":"\u001b[H","kend":"\u001b0","khlp":"\u001bOm","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001bOk","kclr":"\u001b[J","kprt":"\u001bOz","kcan":"\u001bOw","acsc":"+g,h-f.e`bhrisjjkkllmmnnqqttuuvvwwxx{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)1","kRIT":"\u001bNL","kLFT":"\u001bNK","kHOM":"\u001bNM","kEND":"\u001bNN"} +{"name":"att505","aliases":["att5430","gs5430","pt505"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[\u003el","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[01s","kf2":"\u001b[02s","kf3":"\u001b[03s","kf4":"\u001b[04s","kf5":"\u001b[05s","kf6":"\u001b[06s","kf18":"\u001b[18s","kf19":"\u001b[19s","kf20":"\u001b[20s","kf21":"\u001b[21s","kf22":"\u001b[22s","kf23":"\u001b[23s","kf24":"\u001b[24s","kf26":"\u001b[26s","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"att505-24","aliases":["gs5430-24","pt505-24"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[\u003el","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[01s","kf2":"\u001b[02s","kf3":"\u001b[03s","kf4":"\u001b[04s","kf5":"\u001b[05s","kf6":"\u001b[06s","kf18":"\u001b[18s","kf19":"\u001b[19s","kf20":"\u001b[20s","kf21":"\u001b[21s","kf22":"\u001b[22s","kf23":"\u001b[23s","kf24":"\u001b[24s","kf26":"\u001b[26s","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"att510a","aliases":["bct510a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[11;3|","civis":"\u001b[11;0|","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1|","rmkx":"\u001b[19;0|","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOm","kf2":"\u001bOV","kf3":"\u001bOu","kf4":"\u001bNj","kf5":"\u001bNe","kf6":"\u001bNf","kf7":"\u001bNh","kf8":"\u001b[H","kf9":"\u001bOc","kf10":"\u001bOd","kf11":"\u001bOe","kf12":"\u001bOf","kf13":"\u001bOg","kf14":"\u001bOh","kf15":"\u001bOi","kf16":"\u001bOj","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+g,h-f.e`bhrisjjkkllmmnnqqttuuvvwwxx{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)1","kRIT":"\u001b[v","kLFT":"\u001b[u"} +{"name":"att510d","aliases":["bct510d"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[11;3|","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1|","rmkx":"\u001b[19;0|","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOm","kf2":"\u001bOV","kf3":"\u001bOu","kf4":"\u001bNj","kf5":"\u001bNe","kf6":"\u001bNf","kf7":"\u001bNh","kf8":"\u001b[H","kf9":"\u001bOc","kf10":"\u001bOd","kf11":"\u001bOe","kf12":"\u001bOf","kf13":"\u001bOg","kf14":"\u001bOh","kf15":"\u001bOi","kf16":"\u001bOj","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+g,h-f.e`bhrisjjkkllmmnnqqttuuvvwwxx{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)1","kRIT":"\u001b[v","kLFT":"\u001b[u"} +{"name":"att5410-w","aliases":["4410-w","5410-w","att4410-w","tty5410-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att5410v1","aliases":["att4410v1","tty5410v1"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","acsc":"++,,--..00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att5420_2","cols":80,"lines":24,"clear":"\u001bH\u001bJ","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j","rmkx":"\u001b[19;0j","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att5420_2-w","cols":132,"lines":24,"clear":"\u001bH\u001bJ","cnorm":"\u001b[11;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[19;1j","rmkx":"\u001b[19;0j","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"att5425","aliases":["att4425","tty5425"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[12;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[21;1j\u001b[25;4j\u001bent\u001b~","rmkx":"\u001b[21;0j\u001b[25;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"att5425-nl","aliases":["att4425-nl","tty5425-nl"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[12;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[21;1j\u001b[25;4j\u001bent","rmkx":"\u001b[21;0j\u001b[25;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"att5425-w","aliases":["att4425-w","tty5425-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[12;0j","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[2;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[21;1j\u001b[25;4j\u001bent\u001b~","rmkx":"\u001b[21;0j\u001b[25;1j\ufffd","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001bz","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"att5620","aliases":["5620","dmd","tty5620","ttydmd"],"cols":88,"lines":70,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[2m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J"} +{"name":"att5620-1","aliases":["dmd1","tty5620-1"],"cols":88,"lines":70,"bell":"\u0007","clear":"\u001b[H\u001b[J","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J"} +{"name":"att5620-24","aliases":["dmd-24","tty5620-24"],"cols":88,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[2m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J"} +{"name":"att5620-34","aliases":["dmd-34","tty5620-34"],"cols":88,"lines":34,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[2m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J"} +{"name":"att5620-s","aliases":["layer","tty5620-s","vitty"],"cols":80,"lines":72,"bell":"\u0007","clear":"\u000c","cup":"\u001bY%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J"} +{"name":"att605","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bOC","kf16":"\u001bOD","kf17":"\u001bOE","kf18":"\u001bOF","kf19":"\u001bOG","kf20":"\u001bOH","kf21":"\u001bOI","kf22":"\u001bOJ","kf23":"\u001bNO","kf24":"\u001bNP","kf25":"\u001bNQ","kf26":"\u001bNR","kf27":"\u001bNS","kf28":"\u001bNT","kf29":"\u001bOP","kf30":"\u001bOQ","kf31":"\u001bOR","kf32":"\u001bOS","kf33":"\u001bOw","kf34":"\u001bOx","kf35":"\u001bOy","kf36":"\u001bOm","kf37":"\u001bOt","kf38":"\u001bOu","kf39":"\u001bOv","kf40":"\u001bOl","kf41":"\u001bOq","kf42":"\u001bOr","kf43":"\u001bOs","kf44":"\u001bOp","kf45":"\u001bOn","kf46":"\u001bOM","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[24;1H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b)0\u000e","rmacs":"\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A"} +{"name":"att605-pc","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bOC","kf16":"\u001bOD","kf17":"\u001bOE","kf18":"\u001bOF","kf19":"\u001bOG","kf20":"\u001bOH","kf21":"\u001bOI","kf22":"\u001bOJ","kf23":"\u001bNO","kf24":"\u001bNP","kf25":"\u001bNQ","kf26":"\u001bNR","kf27":"\u001bNS","kf28":"\u001bNT","kf29":"\u001bOP","kf30":"\u001bOQ","kf31":"\u001bOR","kf32":"\u001bOS","kf33":"\u001bOw","kf34":"\u001bOx","kf35":"\u001bOy","kf36":"\u001bOm","kf37":"\u001bOt","kf38":"\u001bOu","kf39":"\u001bOv","kf40":"\u001bOl","kf41":"\u001bOq","kf42":"\u001bOr","kf43":"\u001bOs","kf44":"\u001bOp","kf45":"\u001bOn","kf46":"\u001bOM","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","smacs":"\u001b)0\u000e","rmacs":"\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A"} +{"name":"att605-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bOC","kf16":"\u001bOD","kf17":"\u001bOE","kf18":"\u001bOF","kf19":"\u001bOG","kf20":"\u001bOH","kf21":"\u001bOI","kf22":"\u001bOJ","kf23":"\u001bNO","kf24":"\u001bNP","kf25":"\u001bNQ","kf26":"\u001bNR","kf27":"\u001bNS","kf28":"\u001bNT","kf29":"\u001bOP","kf30":"\u001bOQ","kf31":"\u001bOR","kf32":"\u001bOS","kf33":"\u001bOw","kf34":"\u001bOx","kf35":"\u001bOy","kf36":"\u001bOm","kf37":"\u001bOt","kf38":"\u001bOu","kf39":"\u001bOv","kf40":"\u001bOl","kf41":"\u001bOq","kf42":"\u001bOr","kf43":"\u001bOs","kf44":"\u001bOp","kf45":"\u001bOn","kf46":"\u001bOM","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[24;1H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b)0\u000e","rmacs":"\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A"} +{"name":"att610","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[ A","kLFT":"\u001b[ @"} +{"name":"att610-103k","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001bNj","kdch":"\u001bNf","khome":"\u001b[H","kend":"\u001b0","khlp":"\u001bOm","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001bOk","kclr":"\u001b[2J","kprt":"\u001bOz","kcan":"\u001bOw","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[ A","kLFT":"\u001b[ @","kEND":"\u001bNN"} +{"name":"att610-103k-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001bNj","kdch":"\u001bNf","khome":"\u001b[H","kend":"\u001b0","khlp":"\u001bOm","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001bOk","kclr":"\u001b[2J","kprt":"\u001bOz","kcan":"\u001bOw","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[ A","kLFT":"\u001b[ @","kEND":"\u001bNN"} +{"name":"att610-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[ A","kLFT":"\u001b[ @"} +{"name":"att615","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bOC","kf16":"\u001bOD","kf17":"\u001bOE","kf18":"\u001bOF","kf19":"\u001bOG","kf20":"\u001bOH","kf21":"\u001bOI","kf22":"\u001bOJ","kf23":"\u001bNO","kf24":"\u001bNP","kf25":"\u001bNQ","kf26":"\u001bNR","kf27":"\u001bNS","kf28":"\u001bNT","kf29":"\u001bOP","kf30":"\u001bOQ","kf31":"\u001bOR","kf32":"\u001bOS","kf33":"\u001bOw","kf34":"\u001bOx","kf35":"\u001bOy","kf36":"\u001bOm","kf37":"\u001bOt","kf38":"\u001bOu","kf39":"\u001bOv","kf40":"\u001bOl","kf41":"\u001bOq","kf42":"\u001bOr","kf43":"\u001bOs","kf44":"\u001bOp","kf45":"\u001bOn","kf46":"\u001bOM","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A"} +{"name":"att615-103k","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001bNj","kdch":"\u001bNf","khome":"\u001b[H","kend":"\u001b0","khlp":"\u001bOm","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001bOk","kclr":"\u001b[2J","kprt":"\u001bOz","kcan":"\u001bOw","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A","kEND":"\u001bNN"} +{"name":"att615-103k-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001bNj","kdch":"\u001bNf","khome":"\u001b[H","kend":"\u001b0","khlp":"\u001bOm","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001bOk","kclr":"\u001b[2J","kprt":"\u001bOz","kcan":"\u001bOw","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A","kEND":"\u001bNN"} +{"name":"att615-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bOC","kf16":"\u001bOD","kf17":"\u001bOE","kf18":"\u001bOF","kf19":"\u001bOG","kf20":"\u001bOH","kf21":"\u001bOI","kf22":"\u001bOJ","kf23":"\u001bNO","kf24":"\u001bNP","kf25":"\u001bNQ","kf26":"\u001bNR","kf27":"\u001bNS","kf28":"\u001bNT","kf29":"\u001bOP","kf30":"\u001bOQ","kf31":"\u001bOR","kf32":"\u001bOS","kf33":"\u001bOw","kf34":"\u001bOx","kf35":"\u001bOy","kf36":"\u001bOm","kf37":"\u001bOt","kf38":"\u001bOu","kf39":"\u001bOv","kf40":"\u001bOl","kf41":"\u001bOq","kf42":"\u001bOr","kf43":"\u001bOs","kf44":"\u001bOp","kf45":"\u001bOn","kf46":"\u001bOM","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A"} +{"name":"att620","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bOC","kf16":"\u001bOD","kf17":"\u001bOE","kf18":"\u001bOF","kf19":"\u001bOG","kf20":"\u001bOH","kf21":"\u001bOI","kf22":"\u001bOJ","kf23":"\u001bNO","kf24":"\u001bNP","kf25":"\u001bNQ","kf26":"\u001bNR","kf27":"\u001bNS","kf28":"\u001bNT","kf29":"\u001bOP","kf30":"\u001bOQ","kf31":"\u001bOR","kf32":"\u001bOS","kf33":"\u001bOw","kf34":"\u001bOx","kf35":"\u001bOy","kf36":"\u001bOm","kf37":"\u001bOt","kf38":"\u001bOu","kf39":"\u001bOv","kf40":"\u001bOl","kf41":"\u001bOq","kf42":"\u001bOr","kf43":"\u001bOs","kf44":"\u001bOp","kf45":"\u001bOn","kf46":"\u001bOM","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b)0\u000e","rmacs":"\u001b(B\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A"} +{"name":"att620-103k","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001bNj","kdch":"\u001bNf","khome":"\u001b[H","kend":"\u001b0","khlp":"\u001bOm","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001bOk","kclr":"\u001b[2J","kprt":"\u001bOz","kcan":"\u001bOw","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b)0\u000e","rmacs":"\u001b(B\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A","kEND":"\u001bNN"} +{"name":"att620-103k-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001bNj","kdch":"\u001bNf","khome":"\u001b[H","kend":"\u001b0","khlp":"\u001bOm","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001bOk","kclr":"\u001b[2J","kprt":"\u001bOz","kcan":"\u001bOw","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b)0\u000e","rmacs":"\u001b(B\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A","kEND":"\u001bNN"} +{"name":"att620-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bOC","kf16":"\u001bOD","kf17":"\u001bOE","kf18":"\u001bOF","kf19":"\u001bOG","kf20":"\u001bOH","kf21":"\u001bOI","kf22":"\u001bOJ","kf23":"\u001bNO","kf24":"\u001bNP","kf25":"\u001bNQ","kf26":"\u001bNR","kf27":"\u001bNS","kf28":"\u001bNT","kf29":"\u001bOP","kf30":"\u001bOQ","kf31":"\u001bOR","kf32":"\u001bOS","kf33":"\u001bOw","kf34":"\u001bOx","kf35":"\u001bOy","kf36":"\u001bOm","kf37":"\u001bOt","kf38":"\u001bOu","kf39":"\u001bOv","kf40":"\u001bOl","kf41":"\u001bOq","kf42":"\u001bOr","kf43":"\u001bOs","kf44":"\u001bOp","kf45":"\u001bOn","kf46":"\u001bOM","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b)0\u000e","rmacs":"\u001b(B\u000f","kRIT":"\u001b[ @","kLFT":"\u001b[ A"} +{"name":"att630","cols":80,"lines":60,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bNu","kf16":"\u001bNv","kf17":"\u001bNw","kf18":"\u001bNx","kf19":"\u001bNy","kf20":"\u001bNz","kf21":"\u001bN{","kf22":"\u001bN|","kf23":"\u001bN}","kf24":"\u001bN~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J"} +{"name":"att630-24","aliases":["5630-24","5630DMD-24","630MTG-24"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bNu","kf16":"\u001bNv","kf17":"\u001bNw","kf18":"\u001bNx","kf19":"\u001bNy","kf20":"\u001bNz","kf21":"\u001bN{","kf22":"\u001bN|","kf23":"\u001bN}","kf24":"\u001bN~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J"} +{"name":"att6386","aliases":["386at","at386"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[=1C","civis":"\u001b[=C","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[Y","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001d","acsc":"``a1fxgqh0jYk?lZm@nEooppqDrrsstCu4vAwBx3yyzz{{||}}~~","smacs":"\u001b[12m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"att700","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bOC","kf16":"\u001bOD","kf17":"\u001bOE","kf18":"\u001bOF","kf19":"\u001bOG","kf20":"\u001bOH","kf21":"\u001bOI","kf22":"\u001bOJ","kf23":"\u001bNO","kf24":"\u001bNP","kf25":"\u001bNQ","kf26":"\u001bNR","kf27":"\u001bNS","kf28":"\u001bNT","kf29":"\u001bOq","kf30":"\u001bOr","kf31":"\u001bOs","kf32":"\u001bOt","kf33":"\u001bOu","kf34":"\u001bOv","kf35":"\u001bOw","kf36":"\u001bOx","kf37":"\u001bOy","kf38":"\u001bOu","kf39":"\u001bOv","kf40":"\u001bOl","kf41":"\u001bOq","kf42":"\u001bOr","kf43":"\u001bOs","kf44":"\u001bOp","kf45":"\u001bOn","kf46":"\u001bOM","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[24;1H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[ @","kLFT":"\u001b[ A"} +{"name":"att730","cols":80,"lines":60,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bNu","kf16":"\u001bNv","kf17":"\u001bNw","kf18":"\u001bNx","kf19":"\u001bNy","kf20":"\u001bNz","kf21":"\u001bN{","kf22":"\u001bN|","kf23":"\u001bN}","kf24":"\u001bN~","kf25":"\u001bOC","kf26":"\u001bOD","kf27":"\u001bOE","kf28":"\u001bOF","kf29":"\u001bOG","kf30":"\u001bOH","kf31":"\u001bOI","kf32":"\u001bOJ","kf33":"\u001bNO","kf34":"\u001bNP","kf35":"\u001bNQ","kf36":"\u001bNR","kf37":"\u001bNS","kf38":"\u001bNT","kf39":"\u001bOU","kf40":"\u001bOV","kf41":"\u001bOW","kf42":"\u001bOX","kf43":"\u001bOY","kf44":"\u001bOZ","kf45":"\u001bO[","kf46":"\u001bO ","kf47":"\u001bO]","kf48":"\u001bO^","kich":"\u001b[@","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[ A","kLFT":"\u001b[ @"} +{"name":"att730-24","aliases":["730MTG-24"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bNu","kf16":"\u001bNv","kf17":"\u001bNw","kf18":"\u001bNx","kf19":"\u001bNy","kf20":"\u001bNz","kf21":"\u001bN{","kf22":"\u001bN|","kf23":"\u001bN}","kf24":"\u001bN~","kf25":"\u001bOC","kf26":"\u001bOD","kf27":"\u001bOE","kf28":"\u001bOF","kf29":"\u001bOG","kf30":"\u001bOH","kf31":"\u001bOI","kf32":"\u001bOJ","kf33":"\u001bNO","kf34":"\u001bNP","kf35":"\u001bNQ","kf36":"\u001bNR","kf37":"\u001bNS","kf38":"\u001bNT","kf39":"\u001bOU","kf40":"\u001bOV","kf41":"\u001bOW","kf42":"\u001bOX","kf43":"\u001bOY","kf44":"\u001bOZ","kf45":"\u001bO[","kf46":"\u001bO ","kf47":"\u001bO]","kf48":"\u001bO^","kich":"\u001b[@","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[ A","kLFT":"\u001b[ @"} +{"name":"att730-41","aliases":["730MTG-41"],"cols":80,"lines":41,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bNu","kf16":"\u001bNv","kf17":"\u001bNw","kf18":"\u001bNx","kf19":"\u001bNy","kf20":"\u001bNz","kf21":"\u001bN{","kf22":"\u001bN|","kf23":"\u001bN}","kf24":"\u001bN~","kf25":"\u001bOC","kf26":"\u001bOD","kf27":"\u001bOE","kf28":"\u001bOF","kf29":"\u001bOG","kf30":"\u001bOH","kf31":"\u001bOI","kf32":"\u001bOJ","kf33":"\u001bNO","kf34":"\u001bNP","kf35":"\u001bNQ","kf36":"\u001bNR","kf37":"\u001bNS","kf38":"\u001bNT","kf39":"\u001bOU","kf40":"\u001bOV","kf41":"\u001bOW","kf42":"\u001bOX","kf43":"\u001bOY","kf44":"\u001bOZ","kf45":"\u001bO[","kf46":"\u001bO ","kf47":"\u001bO]","kf48":"\u001bO^","kich":"\u001b[@","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[ A","kLFT":"\u001b[ @"} +{"name":"att7300","aliases":["3b1","pc7300","s4","unixpc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[=0C","civis":"\u001b[=1C","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[9m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kich":"\u001bNj","kdch":"\u001bNf","khome":"\u001b[H","kend":"\u001b0","khlp":"\u001bOm","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001bOk","kclr":"\u001b[J","kprt":"\u001bOz","kcan":"\u001bOw","kRIT":"\u001bNL","kLFT":"\u001bNK","kHOM":"\u001bNM","kEND":"\u001bNN"} +{"name":"att730r","aliases":["730MTGr"],"cols":80,"lines":60,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bNu","kf16":"\u001bNv","kf17":"\u001bNw","kf18":"\u001bNx","kf19":"\u001bNy","kf20":"\u001bNz","kf21":"\u001bN{","kf22":"\u001bN|","kf23":"\u001bN}","kf24":"\u001bN~","kf25":"\u001bOC","kf26":"\u001bOD","kf27":"\u001bOE","kf28":"\u001bOF","kf29":"\u001bOG","kf30":"\u001bOH","kf31":"\u001bOI","kf32":"\u001bOJ","kf33":"\u001bNO","kf34":"\u001bNP","kf35":"\u001bNQ","kf36":"\u001bNR","kf37":"\u001bNS","kf38":"\u001bNT","kf39":"\u001bOU","kf40":"\u001bOV","kf41":"\u001bOW","kf42":"\u001bOX","kf43":"\u001bOY","kf44":"\u001bOZ","kf45":"\u001bO[","kf46":"\u001bO ","kf47":"\u001bO]","kf48":"\u001bO^","kich":"\u001b[@","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[ A","kLFT":"\u001b[ @"} +{"name":"att730r-24","aliases":["730MTGr-24"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bNu","kf16":"\u001bNv","kf17":"\u001bNw","kf18":"\u001bNx","kf19":"\u001bNy","kf20":"\u001bNz","kf21":"\u001bN{","kf22":"\u001bN|","kf23":"\u001bN}","kf24":"\u001bN~","kf25":"\u001bOC","kf26":"\u001bOD","kf27":"\u001bOE","kf28":"\u001bOF","kf29":"\u001bOG","kf30":"\u001bOH","kf31":"\u001bOI","kf32":"\u001bOJ","kf33":"\u001bNO","kf34":"\u001bNP","kf35":"\u001bNQ","kf36":"\u001bNR","kf37":"\u001bNS","kf38":"\u001bNT","kf39":"\u001bOU","kf40":"\u001bOV","kf41":"\u001bOW","kf42":"\u001bOX","kf43":"\u001bOY","kf44":"\u001bOZ","kf45":"\u001bO[","kf46":"\u001bO ","kf47":"\u001bO]","kf48":"\u001bO^","kich":"\u001b[@","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[ A","kLFT":"\u001b[ @"} +{"name":"att730r-41","aliases":["730MTG-41r"],"cols":80,"lines":41,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bNo","kf10":"\u001bNp","kf11":"\u001bNq","kf12":"\u001bNr","kf13":"\u001bNs","kf14":"\u001bNt","kf15":"\u001bNu","kf16":"\u001bNv","kf17":"\u001bNw","kf18":"\u001bNx","kf19":"\u001bNy","kf20":"\u001bNz","kf21":"\u001bN{","kf22":"\u001bN|","kf23":"\u001bN}","kf24":"\u001bN~","kf25":"\u001bOC","kf26":"\u001bOD","kf27":"\u001bOE","kf28":"\u001bOF","kf29":"\u001bOG","kf30":"\u001bOH","kf31":"\u001bOI","kf32":"\u001bOJ","kf33":"\u001bNO","kf34":"\u001bNP","kf35":"\u001bNQ","kf36":"\u001bNR","kf37":"\u001bNS","kf38":"\u001bNT","kf39":"\u001bOU","kf40":"\u001bOV","kf41":"\u001bOW","kf42":"\u001bOX","kf43":"\u001bOY","kf44":"\u001bOZ","kf45":"\u001bO[","kf46":"\u001bO ","kf47":"\u001bO]","kf48":"\u001bO^","kich":"\u001b[@","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[2J","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[ A","kLFT":"\u001b[ @"} +{"name":"avatar","aliases":["avatar1"],"cols":80,"lines":25,"cnorm":"\u0016'\u0001","civis":"\u0016'\u0002","sgr0":"\u0016\u0001\u0007","smul":"\u0016\u0001\u0001","bold":"\u0016\u0001\u0010","blink":"\u0016\u0002","rev":"\u0016\u0001p","cup":"\u0016\u0008%p1%c%p2%c","cub1":"\u0016\u0005","cuu1":"\u0016\u0003","pad":"\u0000","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd"} +{"name":"avatar0","cols":80,"lines":25,"sgr0":"\u0016\u0001\u0007","smul":"\u0016\u0001\u0001","bold":"\u0016\u0001\u0010","blink":"\u0016\u0002","rev":"\u0016\u0001p","cup":"\u0016\u0008%p1%c%p2%c","cub1":"\u0016\u0005","cuu1":"\u0016\u0003","pad":"\u0000","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd"} +{"name":"avatar0+","cols":80,"lines":25,"sgr0":"\u0016\u0001\u0007","smul":"\u0016\u0001\u0001","bold":"\u0016\u0001\u0010","blink":"\u0016\u0002","rev":"\u0016\u0001p","cup":"\u0016\u0008%p1%c%p2%c","cub1":"\u0016\u0005","cuu1":"\u0016\u0003","pad":"\u0000","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd"} +{"name":"avt","aliases":["avt-s","concept-avt"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c38\u003e","smcup":"\u001b[2;25w\u001b2\r","rmcup":"\u001b[2w\u001b2\r\n","cnorm":"\u001b[=119l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[1!{","smkx":"\u001b[1!z\u001b[0;3u","rmkx":"\u001b[!z\u001b[0;2u","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b\u0001\r","kdch":"\u001b\u0002\r","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000f$\u003c1\u003e","rmacs":"\u000e$\u003c1\u003e"} +{"name":"avt-ns","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c38\u003e","smcup":"\u001b[=4l\u001b[1;24w\u001b2\r","rmcup":"\u001b[w\u001b2\r\n","cnorm":"\u001b[=119l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[1!{","smkx":"\u001b[1!z\u001b[0;3u","rmkx":"\u001b[!z\u001b[0;2u","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b\u0001\r","kdch":"\u001b\u0002\r","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000f$\u003c1\u003e","rmacs":"\u000e$\u003c1\u003e"} +{"name":"avt-rv","aliases":["avt-rv-s"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c38\u003e","smcup":"\u001b[2;25w\u001b2\r","rmcup":"\u001b[2w\u001b2\r\n","cnorm":"\u001b[=119l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[1!{","smkx":"\u001b[1!z\u001b[0;3u","rmkx":"\u001b[!z\u001b[0;2u","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b\u0001\r","kdch":"\u001b\u0002\r","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000f$\u003c1\u003e","rmacs":"\u000e$\u003c1\u003e"} +{"name":"avt-rv-ns","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c38\u003e","smcup":"\u001b[=4l\u001b[1;24w\u001b2\r","rmcup":"\u001b[w\u001b2\r\n","cnorm":"\u001b[=119l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[1!{","smkx":"\u001b[1!z\u001b[0;3u","rmkx":"\u001b[!z\u001b[0;2u","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b\u0001\r","kdch":"\u001b\u0002\r","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000f$\u003c1\u003e","rmacs":"\u000e$\u003c1\u003e"} +{"name":"avt-w","aliases":["avt-w-s"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c38\u003e","smcup":"\u001b[H\u001b[1;24;1;132w","rmcup":"\u001b[2w\u001b2\r\n","cnorm":"\u001b[=119l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[1!{","smkx":"\u001b[1!z\u001b[0;3u","rmkx":"\u001b[!z\u001b[0;2u","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b\u0001\r","kdch":"\u001b\u0002\r","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000f$\u003c1\u003e","rmacs":"\u000e$\u003c1\u003e"} +{"name":"avt-w-ns","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c38\u003e","smcup":"\u001b[H\u001b[1;24;1;132w","rmcup":"\u001b[w\u001b2\r\n","cnorm":"\u001b[=119l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[1!{","smkx":"\u001b[1!z\u001b[0;3u","rmkx":"\u001b[!z\u001b[0;2u","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b\u0001\r","kdch":"\u001b\u0002\r","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000f$\u003c1\u003e","rmacs":"\u000e$\u003c1\u003e"} +{"name":"avt-w-rv","aliases":["avt-w-rv-s"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c38\u003e","smcup":"\u001b[H\u001b[1;24;1;132w","rmcup":"\u001b[2w\u001b2\r\n","cnorm":"\u001b[=119l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[1!{","smkx":"\u001b[1!z\u001b[0;3u","rmkx":"\u001b[!z\u001b[0;2u","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b\u0001\r","kdch":"\u001b\u0002\r","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000f$\u003c1\u003e","rmacs":"\u000e$\u003c1\u003e"} +{"name":"avt-w-rv-ns","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c38\u003e","smcup":"\u001b[H\u001b[1;24;1;132w","rmcup":"\u001b[w\u001b2\r\n","cnorm":"\u001b[=119l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[1!{","smkx":"\u001b[1!z\u001b[0;3u","rmkx":"\u001b[!z\u001b[0;2u","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b\u0001\r","kdch":"\u001b\u0002\r","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000f$\u003c1\u003e","rmacs":"\u000e$\u003c1\u003e"} +{"name":"aws","cols":80,"lines":28,"clear":"\u000c","smul":"\u001bAUN","cup":"\u001bC%p2%c%p1%c","cuu1":"\u0001","pad":"\u0000","kbs":"\u0008","kcuu1":"\u0001","kcud1":"\u000b","kcub1":"\u000e","kcuf1":"\u0012","smacs":"\u001bAAN","rmacs":"\u001bAAF"} +{"name":"awsc","cols":80,"lines":24,"clear":"\u000c","smul":"\u001bAC","cup":"\u001bC%p2%c%p1%c","cuu1":"\u0001","pad":"\u0000","kbs":"\u0008","kcuu1":"\u0001","kcud1":"\u000b","kcub1":"\u000e","kcuf1":"\u0012","smacs":"\u001bAAN","rmacs":"\u001bAAF"} +{"name":"bantam","aliases":["pe550","pe6100"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK$\u003c20\u003e","cup":"\u001bX%p1%' '%+%c\u001bY%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"basis","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c300/\u003e","sgr0":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"beacon","cols":80,"lines":32,"bell":"\u001bSTART\r\u001b37\r\u001bEND\r$\u003c1\u003e","clear":"\u001bZ$\u003c10\u003e","smcup":"\u001bSTART\r\u001b2,0\r\u001b12\r\u001bEND\r$\u003c10\u003e","sgr0":"\u001bSTART\r\u001b78\r\u001b70,0\r\u001bEND\r$\u003c20\u003e","smul":"\u001bSTART\r\u001b60,1\r\u001bEND\r","blink":"\u001bSTART\r\u001b61,1\r\u001bEND\r","rev":"\u001bSTART\r\u001b59,1\r\u001bEND\r","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c20\u003e","cub1":"\u0008","cuu1":"\u001bU","pad":"\u0000"} +{"name":"beehive","aliases":["bee"],"cols":80,"lines":24,"clear":"\u001bE","sgr0":"\u001bd@","smul":"\u001bd`","cup":"\u001bF%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b\u003e","kclr":"\u001bE"} +{"name":"beterm","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?4h","rmkx":"\u001b[?4l","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[16~","kf7":"\u001b[17~","kf8":"\u001b[18~","kf9":"\u001b[19~","kf10":"\u001b[20~","kf11":"\u001b[21~","kf12":"\u001b[22~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"bg1.25","cols":85,"lines":64,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c150\u003e","sgr0":"\u001b[m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bP","kf2":"\u001bQ","kf3":"\u001bR","kf4":"\u001bS","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"bg1.25nv","cols":85,"lines":64,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c150\u003e","sgr0":"\u001b[m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bP","kf2":"\u001bQ","kf3":"\u001bR","kf4":"\u001bS","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"bg1.25rv","cols":85,"lines":64,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c150\u003e","sgr0":"\u001b[m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bP","kf2":"\u001bQ","kf3":"\u001bR","kf4":"\u001bS","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"bg2.0","aliases":["bg3.10"],"cols":85,"lines":64,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c150\u003e","sgr0":"\u001b[m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"bg2.0rv","aliases":["bg3.10rv"],"cols":85,"lines":64,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c150\u003e","sgr0":"\u001b[m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"bitgraph","aliases":["bg2.0nv","bg3.10nv"],"cols":85,"lines":64,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c150\u003e","sgr0":"\u001b[m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"blit","aliases":["jerq"],"cols":87,"lines":72,"bell":"\u0007","clear":"\u000c","cup":"\u001bY%p2%' '%+%c%p1%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bx","kf2":"\u001by","kf3":"\u001bz","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"bobcat","aliases":["sbobcat"],"cols":128,"lines":47,"clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c6/\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bh","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"bq300","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7l\u001b[?1l\u001b(B","rmcup":"\u001b[?7h","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-8","cols":80,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l\ufffd?1l\u001b(B","rmcup":"\ufffd?7h","cnorm":"\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","rmkx":"\ufffd?1l\u001b\u003e","cup":"\ufffd%i%p1%d;%p2%dH","pad":"\u0000","kbs":"\u0008","kf1":"\ufffdP","kf2":"\ufffdQ","kf3":"\ufffdR","kf4":"\ufffdS","kf6":"\ufffd17~","kf7":"\ufffd18~","kf8":"\ufffd19~","kf9":"\ufffd20~","kf10":"\ufffd21~","kf11":"\ufffd23~","kf12":"\ufffd24~","kf13":"\ufffd25~","kf14":"\ufffd26~","kf15":"\ufffd28~","kf16":"\ufffd29~","kf17":"\ufffd31~","kf18":"\ufffd32~","kf19":"\ufffd33~","kf20":"\ufffd34~","kich":"\ufffd2~","kdch":"\ufffd3~","khlp":"\ufffd28~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-8-pc","aliases":["Q306-8-pc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l\ufffd?1l\u001b(B","rmcup":"\ufffd?7h","cnorm":"\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","rmkx":"\ufffd?1l\u001b\u003e","cup":"\ufffd%i%p1%d;%p2%dH","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd17~","kf2":"\ufffd18~","kf3":"\ufffd19~","kf4":"\ufffd20~","kf5":"\ufffd21~","kf6":"\ufffd23~","kf7":"\ufffd24~","kf8":"\ufffd25~","kf9":"\ufffd26~","kf10":"\ufffd28~","kf11":"\ufffd29~","kf12":"\ufffd31~","kich":"\ufffd2~","kdch":"\ufffd3~","khome":"\ufffd1~","kend":"\ufffd4~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-8-pc-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l\ufffd?1l\u001b(B","rmcup":"\ufffd?7h","cnorm":"\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","rmkx":"\ufffd?1l\u001b\u003e","cup":"\ufffd%i%p1%d;%p2%dH","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd17~","kf2":"\ufffd18~","kf3":"\ufffd19~","kf4":"\ufffd20~","kf5":"\ufffd21~","kf6":"\ufffd23~","kf7":"\ufffd24~","kf8":"\ufffd25~","kf9":"\ufffd26~","kf10":"\ufffd28~","kf11":"\ufffd29~","kf12":"\ufffd31~","kich":"\ufffd2~","kdch":"\ufffd3~","khome":"\ufffd1~","kend":"\ufffd4~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-8-pc-w","cols":132,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l\ufffd?1l\u001b(B","rmcup":"\ufffd?7h","cnorm":"\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","rmkx":"\ufffd?1l\u001b\u003e","cup":"\ufffd%i%p1%d;%p2%dH","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd17~","kf2":"\ufffd18~","kf3":"\ufffd19~","kf4":"\ufffd20~","kf5":"\ufffd21~","kf6":"\ufffd23~","kf7":"\ufffd24~","kf8":"\ufffd25~","kf9":"\ufffd26~","kf10":"\ufffd28~","kf11":"\ufffd29~","kf12":"\ufffd31~","kich":"\ufffd2~","kdch":"\ufffd3~","khome":"\ufffd1~","kend":"\ufffd4~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-8-pc-w-rv","cols":132,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l\ufffd?1l\u001b(B","rmcup":"\ufffd?7h","cnorm":"\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","rmkx":"\ufffd?1l\u001b\u003e","cup":"\ufffd%i%p1%d;%p2%dH","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd17~","kf2":"\ufffd18~","kf3":"\ufffd19~","kf4":"\ufffd20~","kf5":"\ufffd21~","kf6":"\ufffd23~","kf7":"\ufffd24~","kf8":"\ufffd25~","kf9":"\ufffd26~","kf10":"\ufffd28~","kf11":"\ufffd29~","kf12":"\ufffd31~","kich":"\ufffd2~","kdch":"\ufffd3~","khome":"\ufffd1~","kend":"\ufffd4~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-8rv","cols":80,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l\ufffd?1l\u001b(B","rmcup":"\ufffd?7h","cnorm":"\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","rmkx":"\ufffd?1l\u001b\u003e","cup":"\ufffd%i%p1%d;%p2%dH","pad":"\u0000","kbs":"\u0008","kf1":"\ufffdP","kf2":"\ufffdQ","kf3":"\ufffdR","kf4":"\ufffdS","kf6":"\ufffd17~","kf7":"\ufffd18~","kf8":"\ufffd19~","kf9":"\ufffd20~","kf10":"\ufffd21~","kf11":"\ufffd23~","kf12":"\ufffd24~","kf13":"\ufffd25~","kf14":"\ufffd26~","kf15":"\ufffd28~","kf16":"\ufffd29~","kf17":"\ufffd31~","kf18":"\ufffd32~","kf19":"\ufffd33~","kf20":"\ufffd34~","kich":"\ufffd2~","kdch":"\ufffd3~","khlp":"\ufffd28~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-8w","cols":132,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l\ufffd?1l\u001b(B","rmcup":"\ufffd?7h","cnorm":"\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","rmkx":"\ufffd?1l\u001b\u003e","cup":"\ufffd%i%p1%d;%p2%dH","pad":"\u0000","kbs":"\u0008","kf1":"\ufffdP","kf2":"\ufffdQ","kf3":"\ufffdR","kf4":"\ufffdS","kf6":"\ufffd17~","kf7":"\ufffd18~","kf8":"\ufffd19~","kf9":"\ufffd20~","kf10":"\ufffd21~","kf11":"\ufffd23~","kf12":"\ufffd24~","kf13":"\ufffd25~","kf14":"\ufffd26~","kf15":"\ufffd28~","kf16":"\ufffd29~","kf17":"\ufffd31~","kf18":"\ufffd32~","kf19":"\ufffd33~","kf20":"\ufffd34~","kich":"\ufffd2~","kdch":"\ufffd3~","khlp":"\ufffd28~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-pc","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7l\u001b[?1l\u001b(B","rmcup":"\u001b[?7h","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-pc-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7l\u001b[?1l\u001b(B","rmcup":"\u001b[?7h","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-pc-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7l\u001b[?1l\u001b(B","rmcup":"\u001b[?7h","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-pc-w-rv","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7l\u001b[?1l\u001b(B","rmcup":"\u001b[?7h","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7l\u001b[?1l\u001b(B","rmcup":"\u001b[?7h","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7l\u001b[?1l\u001b(B","rmcup":"\u001b[?7h","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-w-8rv","cols":132,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","smcup":"\ufffd?7l\ufffd?1l\u001b(B","rmcup":"\ufffd?7h","cnorm":"\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","rmkx":"\ufffd?1l\u001b\u003e","cup":"\ufffd%i%p1%d;%p2%dH","pad":"\u0000","kbs":"\u0008","kf1":"\ufffdP","kf2":"\ufffdQ","kf3":"\ufffdR","kf4":"\ufffdS","kf6":"\ufffd17~","kf7":"\ufffd18~","kf8":"\ufffd19~","kf9":"\ufffd20~","kf10":"\ufffd21~","kf11":"\ufffd23~","kf12":"\ufffd24~","kf13":"\ufffd25~","kf14":"\ufffd26~","kf15":"\ufffd28~","kf16":"\ufffd29~","kf17":"\ufffd31~","kf18":"\ufffd32~","kf19":"\ufffd33~","kf20":"\ufffd34~","kich":"\ufffd2~","kdch":"\ufffd3~","khlp":"\ufffd28~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"bq300-w-rv","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?7l\u001b[?1l\u001b(B","rmcup":"\u001b[?7h","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b(B\u001b)0"} +{"name":"bsdos-pc","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[L","khome":"\u001b[H","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"bsdos-pc-m","aliases":["bsdos-pc-mono"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[L","khome":"\u001b[H","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"bsdos-pc-nobold","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[L","khome":"\u001b[H","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"bsdos-ppc","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[L","khome":"\u001b[H","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"bsdos-sparc","cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"c100","aliases":["c100-4p","c104","concept","concept100"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b?\u001b\u0005$\u003c2*\u003e","smcup":"\u001bU\u001bv 8p\u001bp\r\u001b\u0015$\u003c16\u003e","rmcup":"\u001bv $\u003c6\u003e\u001bp\r\n","sgr0":"\u001bN@","smul":"\u001bG","blink":"\u001bC","rev":"\u001bD","dim":"\u001bE","smkx":"\u001bX","rmkx":"\u001bx","cup":"\u001ba%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001b;","pad":"\u0000","kbs":"\u0008","kf1":"\u001b5","kf2":"\u001b6","kf3":"\u001b7","kf4":"\u001b8","kf5":"\u001b9","kf6":"\u001b:a","kf7":"\u001b:b","kf8":"\u001b:c","kich":"\u001b\u0010","kdch":"\u001b\u0011","khome":"\u001b?","kpp":"\u001b.","knp":"\u001b-","kcuu1":"\u001b;","kcud1":"\u001b\u003c","kcub1":"\u001b\u003e","kcuf1":"\u001b=","kcbt":"\u001b'"} +{"name":"c100-rv","aliases":["c100-rv-4p","concept100-rv"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b?\u001b\u0005$\u003c2*\u003e","smcup":"\u001bU\u001bv 8p\u001bp\r\u001b\u0015$\u003c16\u003e","rmcup":"\u001bv $\u003c6\u003e\u001bp\r\n","sgr0":"\u001bN@","smul":"\u001bG","blink":"\u001bC","rev":"\u001bD","dim":"\u001bE","smkx":"\u001bX","rmkx":"\u001bx","cup":"\u001ba%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001b;","pad":"\u0000","kbs":"\u0008","kf1":"\u001b5","kf2":"\u001b6","kf3":"\u001b7","kf4":"\u001b8","kf5":"\u001b9","kf6":"\u001b:a","kf7":"\u001b:b","kf8":"\u001b:c","kich":"\u001b\u0010","kdch":"\u001b\u0011","khome":"\u001b?","kpp":"\u001b.","knp":"\u001b-","kcuu1":"\u001b;","kcud1":"\u001b\u003c","kcub1":"\u001b\u003e","kcuf1":"\u001b=","kcbt":"\u001b'"} +{"name":"c108","aliases":["c108-8p","concept108","concept108-8p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b?\u001b\u0005$\u003c2*\u003e","smcup":"\u001bU\u001bv 8p\u001bp\r\u001b\u0015","rmcup":"\u001bv \u0001p\u001bp\r\n","cnorm":"\u001bw","sgr0":"\u001bN@","smul":"\u001bG","blink":"\u001bC","rev":"\u001bD","dim":"\u001bE","smkx":"\u001bX","rmkx":"\u001bx","cup":"\u001ba%p1%?%p1%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c%p2%?%p2%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c","cub1":"\u0008","cuu1":"\u001b;","pad":"\u0000","kbs":"\u0008","kf1":"\u001b5","kf2":"\u001b6","kf3":"\u001b7","kf4":"\u001b8","kf5":"\u001b9","kf6":"\u001b:a","kf7":"\u001b:b","kf8":"\u001b:c","kich":"\u001b\u0010","kdch":"\u001b\u0011","khome":"\u001b?","kpp":"\u001b.","knp":"\u001b-","kcuu1":"\u001b;","kcud1":"\u001b\u003c","kcub1":"\u001b\u003e","kcuf1":"\u001b=","kcbt":"\u001b'","acsc":"jEkTl\\mMqLxU","smacs":"\u001bj!","rmacs":"\u001bj "} +{"name":"c108-4p","aliases":["concept108-4p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b?\u001b\u0005$\u003c2*\u003e","smcup":"\u001bU\u001bv 8p\u001bp\r\u001b\u0015","rmcup":"\u001bv \u0001 p\u001bp\r\n","cnorm":"\u001bw","sgr0":"\u001bN@","smul":"\u001bG","blink":"\u001bC","rev":"\u001bD","dim":"\u001bE","smkx":"\u001bX","rmkx":"\u001bx","cup":"\u001ba%p1%?%p1%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c%p2%?%p2%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c","cub1":"\u0008","cuu1":"\u001b;","pad":"\u0000","kbs":"\u0008","kf1":"\u001b5","kf2":"\u001b6","kf3":"\u001b7","kf4":"\u001b8","kf5":"\u001b9","kf6":"\u001b:a","kf7":"\u001b:b","kf8":"\u001b:c","kich":"\u001b\u0010","kdch":"\u001b\u0011","khome":"\u001b?","kpp":"\u001b.","knp":"\u001b-","kcuu1":"\u001b;","kcud1":"\u001b\u003c","kcub1":"\u001b\u003e","kcuf1":"\u001b=","kcbt":"\u001b'","acsc":"jEkTl\\mMqLxU","smacs":"\u001bj!","rmacs":"\u001bj "} +{"name":"c108-rv","aliases":["c108-rv-8p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b?\u001b\u0005$\u003c2*\u003e","smcup":"\u001bU\u001bv 8p\u001bp\r","rmcup":"\u001bv \u0002 p\u001bp\r\n","cnorm":"\u001bw","sgr0":"\u001bN@","smul":"\u001bG","blink":"\u001bC","rev":"\u001bD","dim":"\u001bE","smkx":"\u001bX","rmkx":"\u001bx","cup":"\u001ba%p1%?%p1%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c%p2%?%p2%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c","cub1":"\u0008","cuu1":"\u001b;","pad":"\u0000","kbs":"\u0008","kf1":"\u001b5","kf2":"\u001b6","kf3":"\u001b7","kf4":"\u001b8","kf5":"\u001b9","kf6":"\u001b:a","kf7":"\u001b:b","kf8":"\u001b:c","kich":"\u001b\u0010","kdch":"\u001b\u0011","khome":"\u001b?","kpp":"\u001b.","knp":"\u001b-","kcuu1":"\u001b;","kcud1":"\u001b\u003c","kcub1":"\u001b\u003e","kcuf1":"\u001b=","kcbt":"\u001b'","acsc":"jEkTl\\mMqLxU","smacs":"\u001bj!","rmacs":"\u001bj "} +{"name":"c108-rv-4p","aliases":["concept108rv4p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b?\u001b\u0005$\u003c2*\u003e","smcup":"\u001bU\u001bv 8p\u001bp\r\u001b\u0015","rmcup":"\u001bv \u0001 p\u001bp\r\n","cnorm":"\u001bw","sgr0":"\u001bN@","smul":"\u001bG","blink":"\u001bC","rev":"\u001bD","dim":"\u001bE","smkx":"\u001bX","rmkx":"\u001bx","cup":"\u001ba%p1%?%p1%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c%p2%?%p2%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c","cub1":"\u0008","cuu1":"\u001b;","pad":"\u0000","kbs":"\u0008","kf1":"\u001b5","kf2":"\u001b6","kf3":"\u001b7","kf4":"\u001b8","kf5":"\u001b9","kf6":"\u001b:a","kf7":"\u001b:b","kf8":"\u001b:c","kich":"\u001b\u0010","kdch":"\u001b\u0011","khome":"\u001b?","kpp":"\u001b.","knp":"\u001b-","kcuu1":"\u001b;","kcud1":"\u001b\u003c","kcub1":"\u001b\u003e","kcuf1":"\u001b=","kcbt":"\u001b'","acsc":"jEkTl\\mMqLxU","smacs":"\u001bj!","rmacs":"\u001bj "} +{"name":"c108-w","aliases":["c108-w-8p","concept108-w-8","concept108-w8p"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b?\u001b\u0005$\u003c2*\u003e","smcup":"\u001bU\u001bv 8\u0001D\u001bp\r","rmcup":"\u001bv \u00010\u0001D\u001bp\r\n","cnorm":"\u001bw","sgr0":"\u001bN@","smul":"\u001bG","blink":"\u001bC","rev":"\u001bD","dim":"\u001bE","smkx":"\u001bX","rmkx":"\u001bx","cup":"\u001ba%p1%?%p1%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c%p2%?%p2%'_'%\u003e%t\u0001%'`'%-%;%' '%+%c","cub1":"\u0008","cuu1":"\u001b;","pad":"\u0000","kbs":"\u0008","kf1":"\u001b5","kf2":"\u001b6","kf3":"\u001b7","kf4":"\u001b8","kf5":"\u001b9","kf6":"\u001b:a","kf7":"\u001b:b","kf8":"\u001b:c","kich":"\u001b\u0010","kdch":"\u001b\u0011","khome":"\u001b?","kpp":"\u001b.","knp":"\u001b-","kcuu1":"\u001b;","kcud1":"\u001b\u003c","kcub1":"\u001b\u003e","kcuf1":"\u001b=","kcbt":"\u001b'","acsc":"jEkTl\\mMqLxU","smacs":"\u001bj!","rmacs":"\u001bj "} +{"name":"ca22851","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c8\u003e","cup":"\u0002%i%p1%c%p2%c","cub1":"\u0015","cuu1":"\u0016","pad":"\u0000","khome":"\u001e","kcuu1":"\u0016","kcud1":"\u0017","kcub1":"\u0015"} +{"name":"cbblit","aliases":["fixterm"],"cols":88,"lines":72,"bell":"\u0007","clear":"\u000c","smul":"\u001bU\"","cup":"\u001bY%p2%' '%+%c%p1%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bx","kf2":"\u001by","kf3":"\u001bz","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"cbunix","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bL","smul":"\u001ba\u0001","cup":"\u001bG%p2%c%p1%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"cci","aliases":["cci1","z8001","zen8001"],"cols":80,"lines":24,"clear":"\u001bH\u001bJ","cnorm":"\u001bP","sgr0":"\u001bM ","smul":"\u001bM0","blink":"\u001bM\"","rev":"\u001bM$","dim":"\u001bM!","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"cdc456","cols":80,"lines":24,"bell":"\u0007","clear":"\u0019\u0018","cup":"\u001b1%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000"} +{"name":"cdc721","cols":80,"lines":24,"clear":"\u000c","cup":"\u0002%p2%' '%+%c%p1%' '%+%c","cuu1":"\u0017","pad":"\u0000","khome":"\u0019","kcuu1":"\u0017","kcud1":"\n","kcub1":"\u0008","kcuf1":"\t"} +{"name":"cdc721-esc","cols":80,"lines":30,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f\u0015\u001d\u001eE\u001e\u0012\\","smul":"\u001c","blink":"\u000e","rev":"\u001eD","dim":"\u001c","smkx":"\u001e\u0012k","rmkx":"\u001e\u0012l","cup":"\u0002%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u0017","pad":"\u0000","kbs":"\u0008","kf1":"\u001er","kf2":"\u001es","kf3":"\u001et","kf4":"\u001eu","kf5":"\u001ev","kf6":"\u001ew","kf7":"\u001ex","kf8":"\u001ey","kf9":"\u001ez","khome":"\u0019","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"cdc721ll","cols":132,"lines":24,"clear":"\u000c","cup":"\u0002%p2%' '%+%c%p1%' '%+%c","cuu1":"\u0017","pad":"\u0000","khome":"\u0019","kcuu1":"\u0017","kcud1":"\n","kcub1":"\u0008","kcuf1":"\t"} +{"name":"cdc752","cols":80,"lines":24,"bell":"\u0007","clear":"\u0018\u001b1 ","cup":"\u001b1%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000"} +{"name":"cdc756","cols":80,"lines":24,"bell":"\u0007","clear":"\u0019\u0018","cup":"\u001b1%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","kf1":"\u001bB","kf2":"\u001bC","kf3":"\u001bD","kf4":"\u001bE","kf5":"\u001bF","kf6":"\u001bG","kf7":"\u001bH","kf8":"\u001ba","kf9":"\u001bb","kich":"\u001bK","kdch":"\u001bI","khome":"\u0019","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0015"} +{"name":"cg7900","aliases":["chromatics"],"cols":80,"lines":40,"bell":"\u0007","clear":"\u000c","smcup":"\u0001P0\u0001O1\u0001R1\u0001C4,\u0001c0,\u000c\u0001M0,42,WARNING DOUBLE ENTER ESCAPE and \u0015\u0001C1,\u0001c2,\u0001W0,0,79,39,","rmcup":"\u0001W0,40,85,48,\u000c\u0001W0,0,85,48,\u0001M0,40,","cup":"\u0001M%p2%d,%p1%d,","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"cit101","aliases":["citc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[V\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"cit101e","cols":80,"lines":24,"clear":"\u001b[H\u001b[J","smul":"\u001b[4m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%2d;%p2%2dH","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOm","kf6":"\u001bOl","kf7":"\u001bOM","kf8":"\u001bOn","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000e","rmacs":"\u000f"} +{"name":"cit101e-132","cols":132,"lines":24,"clear":"\u001b[H\u001b[J","smul":"\u001b[4m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%2d;%p2%2dH","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOm","kf6":"\u001bOl","kf7":"\u001bOM","kf8":"\u001bOn","kcuu1":"\u001b[A","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001b[C","smacs":"\u000e","rmacs":"\u000f"} +{"name":"cit101e-n","cols":80,"lines":24,"clear":"\u001b[H\u001b[J","smul":"\u001b[4m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%2d;%p2%2dH","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOm","kf6":"\u001bOl","kf7":"\u001bOM","kf8":"\u001bOn","kcuu1":"\u001b[A","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001b[C","smacs":"\u000e","rmacs":"\u000f"} +{"name":"cit101e-n132","cols":132,"lines":24,"clear":"\u001b[H\u001b[J","smul":"\u001b[4m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%2d;%p2%2dH","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOm","kf6":"\u001bOl","kf7":"\u001bOM","kf8":"\u001bOn","kcuu1":"\u001b[A","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001b[C","smacs":"\u000e","rmacs":"\u000f"} +{"name":"cit101e-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[\u003e5g\u001b[?7h\u001b[?5h","cnorm":"\u001b[0;3;4v","civis":"\u001b[1v","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"cit500","cols":80,"lines":64,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOQ","kf2":"\u001bOR","kf3":"\u001bOS","kf4":"\u001bOU","kf5":"\u001bOV","kf6":"\u001bOW","kf7":"\u001bOX","kf8":"\u001bOY","kf9":"\u001bOZ","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","smacs":"\u000e","rmacs":"\u000f"} +{"name":"cit80","aliases":["cit-80"],"cols":80,"lines":24,"clear":"\u001b[H\u001bJ","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%2d;%p2%2dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"coco3","aliases":["os9LII"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c5*/\u003e","cnorm":"\u0005!","civis":"\u0005 ","sgr0":"\u001f!\u001b:\ufffd","smul":"\u001f\"","bold":"\u001b:\u0001","blink":"\u001f\"","rev":"\u001f ","cup":"\u0002%p2%' '%+%c%p1%' '%+%c$\u003c2/\u003e","cub1":"\u0008","cuu1":"\t","pad":"\u0000","kcuu1":"\u000c","kcud1":"\n","kcub1":"\u0008","kcuf1":"\t"} +{"name":"color_xterm","aliases":["cx","cx100"],"cols":80,"lines":65,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1;41s\u001b[?1;41h\u001b=","rmcup":"\u001b\u003e\u001b[?41;1r","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"commodore","aliases":["b-128"],"cols":80,"lines":24,"clear":"\u001b\u0006$\u003c10/\u003e","cup":"\u001b\u000b%p1%2d,%p2%2d,$\u003c20/\u003e","cuu1":"\u0010","pad":"\u0000","khome":"\u001b\u0005","kcuu1":"\u0010","kcud1":"\n","kcub1":"\u0002","kcuf1":"\u0006"} +{"name":"cons25","aliases":["ansi80x25","ansis"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons25-m","aliases":["ansi80x25-mono","ansis-mono"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons25l1","aliases":["cons25-iso8859"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\ufffd,\ufffd-\u0018.\u0019`\ufffda\ufffdf\ufffdg\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdp\ufffdq\ufffdr\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons25l1-m","aliases":["cons25-iso-m"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\ufffd,\ufffd-\u0018.\u0019`\ufffda\ufffdf\ufffdg\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdp\ufffdq\ufffdr\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons25r","aliases":["cons25-koi8-r","ibmpc3r","pc3r"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons25r-m","aliases":["cons25-koi8r-m","ibmpc3r-mono","pc3r-m"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons25w","aliases":["ansi80x25-raw","ansiw"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons30","aliases":["ansi80x30"],"cols":80,"lines":30,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons30-m","aliases":["ansi80x30-mono"],"cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons43","aliases":["ansi80x43"],"cols":80,"lines":43,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons43-m","aliases":["ansi80x43-mono"],"cols":80,"lines":43,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons50","aliases":["ansi80x50","ansil"],"cols":80,"lines":50,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons50-m","aliases":["ansi80x50-mono","ansil-mono"],"cols":80,"lines":50,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons50l1","aliases":["cons50-iso8859"],"cols":80,"lines":50,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\ufffd,\ufffd-\u0018.\u0019`\ufffda\ufffdf\ufffdg\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdp\ufffdq\ufffdr\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons50l1-m","aliases":["cons50-iso-m"],"cols":80,"lines":50,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\ufffd,\ufffd-\u0018.\u0019`\ufffda\ufffdf\ufffdg\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdp\ufffdq\ufffdr\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons50r","aliases":["cons50-koi8r"],"cols":80,"lines":50,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons50r-m","aliases":["cons50-koi8r-m"],"cols":80,"lines":50,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons60","aliases":["ansi80x60"],"cols":80,"lines":60,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons60-m","aliases":["ansi80x60-mono"],"cols":80,"lines":60,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons60l1","aliases":["cons60-iso"],"cols":80,"lines":60,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\ufffd,\ufffd-\u0018.\u0019`\ufffda\ufffdf\ufffdg\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdp\ufffdq\ufffdr\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons60l1-m","aliases":["cons60-iso-m"],"cols":80,"lines":60,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\ufffd,\ufffd-\u0018.\u0019`\ufffda\ufffdf\ufffdg\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdp\ufffdq\ufffdr\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"cons60r","aliases":["cons60-koi8r"],"cols":80,"lines":60,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cons60r-m","aliases":["cons60-koi8r-m"],"cols":80,"lines":60,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[=0C","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[30;1m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdh\ufffdi\u0015j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd~\ufffd"} +{"name":"contel300","aliases":["c300","contel320"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001b!\ufffd","cup":"\u001bX%p1%' '%+%c\u001bY%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bRA","kf2":"\u001bRB","kf3":"\u001bRC","kf4":"\u001bRD","kf5":"\u001bRE","kf6":"\u001bRF","kf7":"\u001bRG","kf8":"\u001bRH","kf9":"\u001bRI"} +{"name":"contel301","aliases":["c301","c321","contel321"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001b!\ufffd","cup":"\u001bX%p1%' '%+%c\u001bY%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bRA","kf2":"\u001bRB","kf3":"\u001bRC","kf4":"\u001bRD","kf5":"\u001bRE","kf6":"\u001bRF","kf7":"\u001bRG","kf8":"\u001bRH","kf9":"\u001bRI"} +{"name":"cops10","aliases":["cops","cops-10"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u0018$\u003c30/\u003e","cup":"\u0010%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u0019","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"crt","aliases":["crt-vt220"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cs10","aliases":["colorscan"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%02d;%p2%02dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"cs10-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%02d;%p2%03dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ct8500","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b\u0005","sgr0":"\u001b ","smul":"\u001b!","cup":"\u001b|%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bR","pad":"\u0000"} +{"name":"ctrm","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@%{0}%PA%{0}%PB%{0}%PH","smul":"\u001b\u0026dD","bold":"%?%gH%{0}%=%t\u001b\u0026dH%{1}%PH%;","blink":"\u001b\u0026dA%{1}%PA","rev":"%?%gB%{0}%=%t\u001b\u0026dB%{1}%PB%;","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026jA","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","khome":"\u001bp\r","kcuu1":"\u001bt\r","kcud1":"\u001bw\r","kcub1":"\u001bu\r","kcuf1":"\u001bv\r"} +{"name":"cyb110","aliases":["mdl110"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u0018$\u003c70\u003e","cup":"\u0010%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000"} +{"name":"cyb83","aliases":["xl83"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c62\u003e","cup":"\u0017%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000e","pad":"\u0000","kcuu1":"\u000e","kcud1":"\n","kcub1":"\u0008","kcuf1":"\t"} +{"name":"cygwin","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cygwinB19","cols":80,"lines":25,"colors":8,"clear":"\u001b[2J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"cygwinDBG","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"d132","aliases":["datagraphix"],"cols":80,"lines":30,"bell":"\u0007","clear":"\u000c","cnorm":"\u001bm\u001bn","cup":"\u001b8%i%p1%3d%p2%3d","cub1":"\u0008","cuu1":"\u001bK","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"d200","aliases":["d200-dg"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f\u0015\u001d\u001eE","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d210","aliases":["d214"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i"} +{"name":"d210-dg","aliases":["d214-dg"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f\u0015\u001d\u001eE","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d211","aliases":["d215"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi"} +{"name":"d211-7b","aliases":["d215-7b"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i"} +{"name":"d211-dg","aliases":["d215-dg"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f\u0015\u001d\u001eE","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d216-dg","aliases":["d216+dg","d216e+dg","d216e-dg","d217-dg"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f\u0015\u001d\u001eE","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d216-unix","aliases":["d216+","d216e+","d216e-unix"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001ePH","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d216-unix-25","aliases":["d216+25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001ePH","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d217-unix","cols":80,"lines":24,"bell":"\u0007","clear":"\u001ePH","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d217-unix-25","cols":80,"lines":25,"bell":"\u0007","clear":"\u001ePH","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d220","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","setbg":"\u001b[4%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f","_setfgbg":"\u001b[3%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;;4%p2%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m"} +{"name":"d220-7b","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","setbg":"\u001b[4%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6","_setfgbg":"\u001b[3%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;;4%p2%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m"} +{"name":"d220-dg","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%'0'%+%c","setbg":"\u001eB%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%'0'%+%c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d230c","aliases":["d230"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[50m\u001b)4\u000f","smul":"\u001b[4;50m","bold":"\u001b[4;7;50m","blink":"\u001b[5;50m","rev":"\u001b[7;50m","dim":"\u001b[2;50m","smkx":"\u001b[2;0v","rmkx":"\u001b[2;1v","setaf":"\u001b[3%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","setbg":"\u001b[4%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f","_setfgbg":"\u001b[3%p1%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;;4%p2%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m"} +{"name":"d230c-dg","aliases":["d230-dg"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%'0'%+%c","setbg":"\u001eB%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%'0'%+%c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d400","aliases":["d400-dg","d450","d450-dg"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eO","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eN","rmacs":"\u001eO","enacs":"\u001eN\u001eFS11\u001eO","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d410","aliases":["d411","d460","d461"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f"} +{"name":"d410-7b","aliases":["d411-7b","d460-7b","d461-7b"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6"} +{"name":"d410-7b-w","aliases":["d411-7b-w","d460-7b-w","d461-7b-w"],"cols":126,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6"} +{"name":"d410-dg","aliases":["d411-dg","d460-dg","d461-dg"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d410-w","aliases":["d411-w","d460-w","d461-w"],"cols":126,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f"} +{"name":"d412-dg","aliases":["d412+dg","d413-dg","d462+dg","d462-dg","d462e-dg","d463-dg"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d412-unix","aliases":["d412+","d462+","d462-unix"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d412-unix-25","aliases":["d412+25","d462+25","d462-unix-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d412-unix-s","aliases":["d412+s","d462+s","d462-unix-s"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFG\u001ePH","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d412-unix-sr","aliases":["d412+sr","d462+sr","d462-unix-sr"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d412-unix-w","aliases":["d412+w","d462+w","d462-unix-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d413-unix","aliases":["d463-unix"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d413-unix-25","aliases":["d463-unix-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d413-unix-s","aliases":["d463-unix-s"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFG\u001ePH","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d413-unix-sr","aliases":["d463-unix-sr"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d413-unix-w","aliases":["d463-unix-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d414-unix","aliases":["d464-unix"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d414-unix-25","aliases":["d464-unix-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d414-unix-s","aliases":["d464-unix-s"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFG\u001ePH","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d414-unix-sr","aliases":["d464-unix-sr"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d414-unix-w","aliases":["d464-unix-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-dg","aliases":["d430-dg"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","setbg":"\u001eB%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d430c-dg-ccc","aliases":["d430-dg-ccc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d430c-unix","aliases":["d430-unix"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","setbg":"\u001eB%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-25","aliases":["d430-unix-25"],"cols":80,"lines":25,"colors":16,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","setbg":"\u001eB%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-25-ccc","aliases":["d430-unix-25-ccc"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-ccc","aliases":["d430-unix-ccc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-s","aliases":["d430-unix-s"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001eFG\u001ePH","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","setbg":"\u001eB%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-s-ccc","aliases":["d430-unix-s-ccc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFG\u001ePH","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-sr","aliases":["d430-unix-sr"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","setbg":"\u001eB%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-sr-ccc","aliases":["d430-unix-sr-ccc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-w","aliases":["d430-unix-w"],"cols":132,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","setbg":"\u001eB%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d430c-unix-w-ccc","aliases":["d430-unix-w-ccc"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001eFE","cnorm":"\u001eFQ5","civis":"\u001eFQ0","sgr0":"\u001ePJ\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u001ePI","rev":"\u001eD","dim":"\u001c","cup":"\u001eFP%p2%2.2X%p1%2.2X","cub1":"\u001ePD","cuu1":"\u001ePA","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u001ePF","kcuu1":"\u001ePA","kcud1":"\u001ePB","kcub1":"\u001ePD","kcuf1":"\u001ePC","kclr":"\u001ePH","kprt":"\u001eP0","acsc":"aj$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001ePc","kLFT":"\u001ePd","kHOM":"\u001ePf"} +{"name":"d470c","aliases":["d470"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%e\u003c%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%e=%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%e\u003c%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;;%?%p2%{8}%\u003c%t4%p2%e=%p2%{2}%\u0026%?%p2%{1}%\u0026%t%{4}%|%;%?%p2%{4}%\u0026%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m"} +{"name":"d470c-7b","aliases":["d470-7b"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%e\u003c%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%e=%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%e\u003c%p1%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;;%?%p2%{8}%\u003c%t4%p2%e=%p2%{2}%\u0026%?%p2%{1}%\u0026%t%{4}%|%;%?%p2%{4}%\u0026%t%{1}%|%;%;%d%?%gD%t;2%;%?%gU%t;4%;%?%gB%t;5%;%?%gR%t;7%;m"} +{"name":"d470c-dg","aliases":["d470-dg"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","setaf":"\u001eA%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","setbg":"\u001eB%p1%?%p1%{8}%\u003c%t%{2}%\u0026%?%p1%{1}%\u0026%t%{4}%|%;%?%p1%{4}%\u0026%t%{1}%|%;%;%'0'%+%c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d555","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f"} +{"name":"d555-7b","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6"} +{"name":"d555-7b-w","cols":126,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6"} +{"name":"d555-dg","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d555-w","cols":126,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f"} +{"name":"d577","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f"} +{"name":"d577-7b","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6"} +{"name":"d577-7b-w","cols":126,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6"} +{"name":"d577-dg","aliases":["d578-dg"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001eFQ2","civis":"\u001eFQ0","sgr0":"\u000f\u0015\u001d\u001eE\u001eFS00","smul":"\u0014","bold":"\u001eD\u0014","blink":"\u000e","rev":"\u001eD","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001e|","kf13":"\u001e}","kf14":"\u001e~","kf15":"\u001ep","kf16":"\u001ea","kf17":"\u001eb","kf18":"\u001ec","kf19":"\u001ed","kf20":"\u001ee","kf21":"\u001ef","kf22":"\u001eg","kf23":"\u001eh","kf24":"\u001ei","kf25":"\u001ej","kf26":"\u001ek","kf27":"\u001el","kf28":"\u001em","kf29":"\u001en","kf30":"\u001e`","kf31":"\u001e1","kf32":"\u001e2","kf33":"\u001e3","kf34":"\u001e4","kf35":"\u001e5","kf36":"\u001e6","kf37":"\u001e7","kf38":"\u001e8","kf39":"\u001e9","kf40":"\u001e:","kf41":"\u001e;","kf42":"\u001e\u003c","kf43":"\u001e=","kf44":"\u001e\u003e","kf45":"\u001e0","kf46":"\u001e!","kf47":"\u001e\"","kf48":"\u001e#","kf49":"\u001e$","kf50":"\u001e%%","kf51":"\u001e\u0026","kf52":"\u001e'","kf53":"\u001e(","kf54":"\u001e)","kf55":"\u001e*","kf56":"\u001e+","kf57":"\u001e,","kf58":"\u001e-","kf59":"\u001e.","kf60":"\u001e ","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001eFS11","rmacs":"\u001eFS00","kRIT":"\u001e\u0018","kLFT":"\u001e\u0019","kHOM":"\u001e\u0008"} +{"name":"d577-w","cols":126,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f"} +{"name":"d578","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u001b)4\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\ufffd001z","kf2":"\ufffd002z","kf3":"\ufffd003z","kf4":"\ufffd004z","kf5":"\ufffd005z","kf6":"\ufffd006z","kf7":"\ufffd007z","kf8":"\ufffd008z","kf9":"\ufffd009z","kf10":"\ufffd010z","kf11":"\ufffd011z","kf12":"\ufffd012z","kf13":"\ufffd013z","kf14":"\ufffd014z","kf15":"\ufffd000z","kf16":"\ufffd101z","kf17":"\ufffd102z","kf18":"\ufffd103z","kf19":"\ufffd104z","kf20":"\ufffd105z","kf21":"\ufffd106z","kf22":"\ufffd107z","kf23":"\ufffd108z","kf24":"\ufffd109z","kf25":"\ufffd110z","kf26":"\ufffd111z","kf27":"\ufffd112z","kf28":"\ufffd113z","kf29":"\ufffd114z","kf30":"\ufffd100z","kf31":"\ufffd201z","kf32":"\ufffd202z","kf33":"\ufffd203z","kf34":"\ufffd204z","kf35":"\ufffd205z","kf36":"\ufffd206z","kf37":"\ufffd207z","kf38":"\ufffd208z","kf39":"\ufffd209z","kf40":"\ufffd210z","kf41":"\ufffd211z","kf42":"\ufffd212z","kf43":"\ufffd213z","kf44":"\ufffd214z","kf45":"\ufffd200z","kf46":"\ufffd301z","kf47":"\ufffd302z","kf48":"\ufffd303z","kf49":"\ufffd304z","kf50":"\ufffd305z","kf51":"\ufffd306z","kf52":"\ufffd307z","kf53":"\ufffd308z","kf54":"\ufffd309z","kf55":"\ufffd310z","kf56":"\ufffd311z","kf57":"\ufffd312z","kf58":"\ufffd313z","kf59":"\ufffd314z","kf60":"\ufffd300z","khome":"\ufffdH","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kclr":"\ufffd2J","kprt":"\ufffdi","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u001b)6\u000e","rmacs":"\u001b)4\u000f"} +{"name":"d578-7b","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[3;2v","civis":"\u001b[3;0v","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[4;7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[001z","kf2":"\u001b[002z","kf3":"\u001b[003z","kf4":"\u001b[004z","kf5":"\u001b[005z","kf6":"\u001b[006z","kf7":"\u001b[007z","kf8":"\u001b[008z","kf9":"\u001b[009z","kf10":"\u001b[010z","kf11":"\u001b[011z","kf12":"\u001b[012z","kf13":"\u001b[013z","kf14":"\u001b[014z","kf15":"\u001b[000z","kf16":"\u001b[101z","kf17":"\u001b[102z","kf18":"\u001b[103z","kf19":"\u001b[104z","kf20":"\u001b[105z","kf21":"\u001b[106z","kf22":"\u001b[107z","kf23":"\u001b[108z","kf24":"\u001b[109z","kf25":"\u001b[110z","kf26":"\u001b[111z","kf27":"\u001b[112z","kf28":"\u001b[113z","kf29":"\u001b[114z","kf30":"\u001b[100z","kf31":"\u001b[201z","kf32":"\u001b[202z","kf33":"\u001b[203z","kf34":"\u001b[204z","kf35":"\u001b[205z","kf36":"\u001b[206z","kf37":"\u001b[207z","kf38":"\u001b[208z","kf39":"\u001b[209z","kf40":"\u001b[210z","kf41":"\u001b[211z","kf42":"\u001b[212z","kf43":"\u001b[213z","kf44":"\u001b[214z","kf45":"\u001b[200z","kf46":"\u001b[301z","kf47":"\u001b[302z","kf48":"\u001b[303z","kf49":"\u001b[304z","kf50":"\u001b[305z","kf51":"\u001b[306z","kf52":"\u001b[307z","kf53":"\u001b[308z","kf54":"\u001b[309z","kf55":"\u001b[310z","kf56":"\u001b[311z","kf57":"\u001b[312z","kf58":"\u001b[313z","kf59":"\u001b[314z","kf60":"\u001b[300z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","kprt":"\u001b[i","acsc":"j$k\"l!m#n)q+t'u\u0026v(w%x*","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)6"} +{"name":"d800","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[1;1H\u001b[2J","cnorm":"\u001b[\u003e12h","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``a1fxgqh0jYk?lZm@nEooppqDrrsstCu4vAwBx3yyzz{{||}}~~","smacs":"\u001b[1m","rmacs":"\u001b[m"} +{"name":"ddr","aliases":["ddr3180","rebus3180"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[2J$\u003c50/\u003e","sgr0":"\u001b[m$\u003c2/\u003e","smul":"\u001b[4m$\u003c2/\u003e","bold":"\u001b[1m$\u003c2/\u003e","blink":"\u001b[5m$\u003c2/\u003e","rev":"\u001b[7m$\u003c2/\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5/\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2/\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"dec-vt100","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"dec-vt220","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"decansi","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"delta","aliases":["dd5000"],"cols":80,"lines":27,"bell":"\u0007","clear":"\u000eR","cup":"\u000f%p1%p1%{16}%m%{2}%*%-%'9'%+%c%p2%p2%{16}%m%{2}%*%-%'9'%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000"} +{"name":"dg-generic","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f\u0015\u001d","smul":"\u0014","blink":"\u000e","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001ea","kf13":"\u001eb","kf14":"\u001ec","kf15":"\u001ed","kf16":"\u001ee","kf17":"\u001ef","kf18":"\u001eg","kf19":"\u001eh","kf20":"\u001ei","kf21":"\u001ej","kf22":"\u001ek","kf23":"\u001e1","kf24":"\u001e2","kf25":"\u001e3","kf26":"\u001e4","kf27":"\u001e5","kf28":"\u001e6","kf29":"\u001e7","kf30":"\u001e8","kf31":"\u001e9","kf32":"\u001e:","kf33":"\u001e;","kf34":"\u001e!","kf35":"\u001e\"","kf36":"\u001e#","kf37":"\u001e$","kf38":"\u001e%%","kf39":"\u001e\u0026","kf40":"\u001e'","kf41":"\u001e(","kf42":"\u001e)","kf43":"\u001e*","kf44":"\u001e+","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c"} +{"name":"dg200","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","smul":"\u0014","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018"} +{"name":"dg210","aliases":["dg-ansi"],"cols":80,"lines":24,"clear":"\u001b[2J","smul":"\u001b[4;m","cup":"\u001b[%i%p1%d;%p2%dH","cuu1":"\u001b[A","pad":"\u0000","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"dg211","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","smcup":"\u000c\u0012","rmcup":"\u000c","cnorm":"\u000c","smul":"\u0014","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kbs":"\u0019","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018"} +{"name":"dg450","aliases":["dg6134"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","smul":"\u0014","cup":"\u0010%p2%c%p1%c","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018"} +{"name":"dg460-ansi","cols":80,"lines":24,"clear":"\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%2d;%p2%2dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u001b[D","kf1":"\u001b[002z","kf2":"\u001b[003z","kf3":"\u001b[004z","kf4":"\u001b[005z","kf5":"\u001b[006z","kf6":"\u001b[007z","kf7":"\u001b[008z","kf8":"\u001b[009z","kf9":"\u001b[010z","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"dg6053","aliases":["6053","6053-dg","605x","605x-dg","d2","d2-dg","dg605x"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f\u0015\u001d","smul":"\u0014","blink":"\u000e","dim":"\u001c","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kf1":"\u001eq","kf2":"\u001er","kf3":"\u001es","kf4":"\u001et","kf5":"\u001eu","kf6":"\u001ev","kf7":"\u001ew","kf8":"\u001ex","kf9":"\u001ey","kf10":"\u001ez","kf11":"\u001e{","kf12":"\u001ea","kf13":"\u001eb","kf14":"\u001ec","kf15":"\u001ed","kf16":"\u001ee","kf17":"\u001ef","kf18":"\u001eg","kf19":"\u001eh","kf20":"\u001ei","kf21":"\u001ej","kf22":"\u001ek","kf23":"\u001e1","kf24":"\u001e2","kf25":"\u001e3","kf26":"\u001e4","kf27":"\u001e5","kf28":"\u001e6","kf29":"\u001e7","kf30":"\u001e8","kf31":"\u001e9","kf32":"\u001e:","kf33":"\u001e;","kf34":"\u001e!","kf35":"\u001e\"","kf36":"\u001e#","kf37":"\u001e$","kf38":"\u001e%%","kf39":"\u001e\u0026","kf40":"\u001e'","kf41":"\u001e(","kf42":"\u001e)","kf43":"\u001e*","kf44":"\u001e+","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018","kclr":"\u000c"} +{"name":"dg6053-old","aliases":["dg100"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","smcup":"\u000c\u0012","rmcup":"\u000c","cnorm":"\u000c","smul":"\u0014","cup":"\u0010%p2%c%p1%c","cub1":"\u0019","cuu1":"\u0017","pad":"\u0000","kbs":"\u0019","kf1":"\u001er","kf2":"\u001es","kf3":"\u001et","kf4":"\u001eu","kf5":"\u001ev","kf6":"\u001ew","kf7":"\u001ex","kf8":"\u001ey","kf9":"\u001ez","khome":"\u0008","kcuu1":"\u0017","kcud1":"\u001a","kcub1":"\u0019","kcuf1":"\u0018"} +{"name":"djgpp","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[v","civis":"\u001b[1v","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"djgpp204","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[v","civis":"\u001b[1v","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"dku7003","cols":80,"lines":25,"clear":"\u001d\u001f","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[7m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0019","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u001d","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0019","kcuf1":"\u0018"} +{"name":"dku7003-dumb","cols":80,"lines":25,"clear":"\u001d\u001f","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0019","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u001d","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0019","kcuf1":"\u0018"} +{"name":"dku7202","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?\u003eh\u001bPY99:98\u001b\\","rmcup":"\u001b[0;98v\u001b[2J\u001b[v","cnorm":"\u001b[r","civis":"\u001b[1r","sgr0":"\u001b[m\u000f","smul":"\u001b[0;2m","blink":"\u001b[0;2;4m","rev":"\u001b[0;7m","dim":"\u001b[0;5m","cup":"\u001b[%i%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[1u\u0017","kf2":"\u001b[2u\u0017","kf3":"\u001b[3u\u0017","kf4":"\u001b[4u\u0017","kf5":"\u001b[5u\u0017","kf6":"\u001b[6u\u0017","kf7":"\u001b[7u\u0017","kf8":"\u001b[8u\u0017","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggj)k,l\u0026m#n/ooppq*rrsst'u-v+w.x%yyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"dm1520","aliases":["dm1521"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","khome":"\u0019","kcuu1":"\u001f","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001c"} +{"name":"dm2500","aliases":["datamedia2500"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001e\u001e","cup":"\u000c%p2%'`'%^%c%p1%'`'%^%c","cub1":"\u0008","cuu1":"\u001a","pad":"\ufffd"} +{"name":"dm3025","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bM$\u003c2\u003e","cup":"\u001bY%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"dm3045","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bM$\u003c2\u003e","cup":"\u001bY%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kf9":"\u001bx\r","khome":"\u001bH","kcuu1":"\u001bA","kcuf1":"\u001bC"} +{"name":"dm80","aliases":["dmdt80","dt80"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"dm80w","aliases":["dmdt80w","dt80w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50/\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5/\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c5/\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"dmchat","cols":80,"lines":24,"bell":"\u0007","clear":"\u001e\u001e","cup":"\u000c%p2%'`'%^%c%p1%'`'%^%c","cub1":"\u0008","cuu1":"\u001a","pad":"\ufffd"} +{"name":"dmterm","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bj","cnorm":"\u001bG6","civis":"\u001bG5","sgr0":"\u001bG0","rev":"\u001bG4","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001b2","kf2":"\u001b3","kf3":"\u001b4","kf4":"\u001b5","kf5":"\u001b6","kf6":"\u001b7","kf7":"\u001b8","kf8":"\u001b9","kf9":"\u001b0","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"dp8242","cols":80,"lines":25,"bell":"\u0007","clear":"\u0015\u001b\u0004\u0017\u0018","cnorm":"\u0018","civis":"\u0019","smul":"\u001b\u0006","cup":"\t%p2%'\ufffd'%+%c%p1%'\ufffd'%+%c","cub1":"\u0008","pad":"\u0000","kbs":"\u0008","kf1":"\u0007\u001be","kf2":"\t\u001bd","kf3":"\n\u001bc","kf4":"\n\u001bb","kf5":"\u0013\u001ba","kf6":"\u001bO\u001be","kf7":"\u001bN\u001bd","kf8":"\u001bM\u001bc","kf9":"\u001bL\u001bb","kf10":"\u001bK\u001ba","kcuu1":"\u0005","kcud1":"\u0002","kcub1":"\u0004","kcuf1":"\u0006"} +{"name":"dt100","aliases":["dt-100"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u0008\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[?3i","kf2":"\u001b[2i","kf3":"\u001b[@","kf4":"\u001b[M","kf5":"\u001b[17~","kf6":"\u001b[18~","kf7":"\u001b[19~","kf8":"\u001b[20~","kf9":"\u001b[21~","kf10":"\u001b[?5i","khome":"\u001b[H","kpp":"\u001b[28~","knp":"\u001b[29~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"jjkkllmmnnqqttuuvvwwxx","smacs":"\u000e","rmacs":"\u000f"} +{"name":"dt100w","aliases":["dt-100w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u0008\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[?3i","kf2":"\u001b[2i","kf3":"\u001b[@","kf4":"\u001b[M","kf5":"\u001b[17~","kf6":"\u001b[18~","kf7":"\u001b[19~","kf8":"\u001b[20~","kf9":"\u001b[21~","kf10":"\u001b[?5i","khome":"\u001b[H","kpp":"\u001b[28~","knp":"\u001b[29~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"jjkkllmmnnqqttuuvvwwxx","smacs":"\u000e","rmacs":"\u000f"} +{"name":"dt110","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u0008\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[0A","pad":"\u0000","kf1":"\u001b[1~","kf2":"\u001b[2~","kf3":"\u001b[3~","kf4":"\u001b[4~","kf5":"\u001b[5~","kf6":"\u001b[6~","kf7":"\u001b[7~","kf8":"\u001b[8~","kf9":"\u001b[9~","kf10":"\u001b[10~","kich":"\u001b[@","khome":"\u001b[G","kend":"\u001b[K","kpp":"\u001b[25~","knp":"\u001b[26~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"jjkkllmmnnqqttuuvvwwxx","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"dt80-sas","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u0018","rev":"\u001b$2\u0004","cup":"\u001b=%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","khome":"\u0019","kcuu1":"\u001f","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001c","kclr":"\u000c","acsc":"``a1fxgqh0jYk?lZm@nEooppqDrrsstCu4vAwBx3yyzz{{||}}~~","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"dtc382","cols":80,"lines":24,"bell":"\u0007","clear":"\u0010\u001d$\u003c20\u003e","smcup":"\u0010\u001d$\u003c20\u003e","cnorm":"\u0010b","smul":"\u0010 \u0010","cup":"\u0010\u0011%p2%c%p1%c","cub1":"\u0008","cuu1":"\u0010\u000c","pad":""} +{"name":"dtterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"dwk","aliases":["dwk-vt"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001bX","rev":"\u001bT","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"","kf1":"\u001bf1","kf2":"\u001bf2","kf3":"\u001bf3","kf4":"\u001bf4","kf5":"\u001bf5","kf6":"\u001bf6","kf7":"\u001bf7","kf8":"\u001bf8","kf9":"\u001bf9","kf10":"\u001bf0","kich":"\u001bd","kdch":"\u001be","kpp":"\u001bg","knp":"\u001bh","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"+^,Q-S.M0`+a:f'g#h#i#jXkClJmFnNo~qUs_tEuPv\\wKxW~_","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"elks","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"elks-ansi","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"elks-vt52","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"emu","cols":80,"lines":24,"colors":15,"bell":"\u0007","clear":"\u001bP\u001bE0;0;","cnorm":"\u001ba","civis":"\u001bZ","sgr0":"\u001bS","smul":"\u001bV","bold":"\u001bU","blink":"\u001bW","rev":"\u001bT","setaf":"\u001br%i%p1%d;","setbg":"\u001bs%i%p1%d;","cup":"\u001bE%p1%d;%p2%d;","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF01","kf2":"\u001bF02","kf3":"\u001bF03","kf4":"\u001bF04","kf5":"\u001bF05","kf6":"\u001bF06","kf7":"\u001bF07","kf8":"\u001bF08","kf9":"\u001bF09","kf10":"\u001bF10","kf11":"\u001bF11","kf12":"\u001bF12","kf13":"\u001bF13","kf14":"\u001bF14","kf15":"\u001bF15","kf16":"\u001bF16","kf17":"\u001bF17","kf18":"\u001bF18","kf19":"\u001bF19","kf20":"\u001bF20","kich":"\u001bins","kdch":"","kpp":"\u001bprior","knp":"\u001bnext","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bC","kcuf1":"\u001bD","acsc":"61a\ufffdf\ufffdg2j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdq\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd~\ufffd"} +{"name":"emu-220","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","smcup":"\u001b[?1l\u001b=","rmcup":"\u001b\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[0;4m","bold":"\u001b[0;1m","blink":"\u001b[0;5m","rev":"\u001b[0;7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[1D","cuu1":"\u001b[1A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOq","kf2":"\u001bOr","kf3":"\u001bOs","kf4":"\u001bOt","kf5":"\u001bOu","kf6":"\u001bOv","kf7":"\u001bOw","kf8":"\u001bOx","kf9":"\u001bOy","kf10":"\u001bOl","kf11":"\u001bOm","kf12":"\u001bOn","kf13":"\u001bOP","kf14":"\u001bOQ","kf15":"\u001bOR","kf16":"\u001bOS","kf26":"\u001b[17~","kf27":"\u001b[18~","kf28":"\u001b[19~","kf29":"\u001b[20~","kf30":"\u001b[21~","kf34":"\u001b[26~","kf37":"\u001b[31~","kf38":"\u001b[32~","kf39":"\u001b[33~","kf40":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"emx-base","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd;","kf2":"\ufffd\u003c","kf3":"\ufffd=","kf4":"\ufffd\u003e","kf5":"\ufffd?","kf6":"\ufffd@","kf7":"\ufffdA","kf8":"\ufffdB","kf9":"\ufffdC","kf10":"\ufffdD","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffdT","kf14":"\ufffdU","kf15":"\ufffdV","kf16":"\ufffdW","kf17":"\ufffdX","kf18":"\ufffdY","kf19":"\ufffdZ","kf20":"\ufffd[","kf21":"\ufffd\\","kf22":"\ufffd]","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd^","kf26":"\ufffd_","kf27":"\ufffd`","kf28":"\ufffda","kf29":"\ufffdb","kf30":"\ufffdc","kf31":"\ufffdd","kf32":"\ufffde","kf33":"\ufffdf","kf34":"\ufffdg","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffdh","kf38":"\ufffdi","kf39":"\ufffdj","kf40":"\ufffdk","kf41":"\ufffdl","kf42":"\ufffdm","kf43":"\ufffdn","kf44":"\ufffdo","kf45":"\ufffdp","kf46":"\ufffdq","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffdR","kdch":"\ufffdS","khome":"\ufffdG","kend":"\ufffdO","kpp":"\ufffdI","knp":"\ufffdQ","kcuu1":"\ufffdH","kcud1":"\ufffdP","kcub1":"\ufffdK","kcuf1":"\ufffdM","kcbt":"\ufffd\u000f","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"env230","aliases":["envision230"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"ergo4000","cols":80,"lines":66,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c80\u003e","sgr0":"\u001b[m$\u003c20\u003e","smkx":"\u001b=$\u003c4\u003e","rmkx":"\u001b=$\u003c4\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"esprit","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u001c","smkx":"\u001b\u003c","rmkx":"\u001b\u003e","cup":"\u001b\u0011%p2%c%p1%c","cub1":"\u0008","cuu1":"\u001b\u000c","pad":"\u0000","kbs":"\u0008","kf1":"\u00021\n","kf2":"\u00022\n","kf3":"\u00023\n","kf4":"\u00024\n","kf5":"\u00025\n","kf6":"\u00026\n","kf7":"\u00027\n","kf8":"\u00028\n","kf9":"\u00029\n","khome":"\u001b\u0012","kcuu1":"\u001b\u000c","kcud1":"\u001b\u000b","kcub1":"\u0008","kcuf1":"\u0010"} +{"name":"esprit-am","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u001c","smkx":"\u001b\u003c","rmkx":"\u001b\u003e","cup":"\u001b\u0011%p2%c%p1%c","cub1":"\u0008","cuu1":"\u001b\u000c","pad":"\u0000","kbs":"\u0008","kf1":"\u00021\n","kf2":"\u00022\n","kf3":"\u00023\n","kf4":"\u00024\n","kf5":"\u00025\n","kf6":"\u00026\n","kf7":"\u00027\n","kf8":"\u00028\n","kf9":"\u00029\n","khome":"\u001b\u0012","kcuu1":"\u001b\u000c","kcud1":"\u001b\u000b","kcub1":"\u0008","kcuf1":"\u0010"} +{"name":"eterm","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000"} +{"name":"ex155","cols":80,"lines":24,"clear":"\u001bX","smul":"\u001bf\u001bD","cup":"\u001bE%p1%' '%+%c%p2%' '%+%c","pad":"\u0000","kbs":"\u0008","khome":"\u001b@","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001b[","kclr":"\u001bX"} +{"name":"excel62","aliases":["excel64"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOu","kf6":"\u001bOv","kf7":"\u001bOw","kf8":"\u001bOx","kf9":"\u001bOy","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"excel62-rv","aliases":["excel64-rv"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOu","kf6":"\u001bOv","kf7":"\u001bOw","kf8":"\u001bOx","kf9":"\u001bOy","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"excel62-w","aliases":["excel64-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50/\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5/\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c5/\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOu","kf6":"\u001bOv","kf7":"\u001bOw","kf8":"\u001bOx","kf9":"\u001bOy","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"f100","aliases":["freedom","freedom100"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","smacs":"\u001b%%","rmacs":"\u001b$"} +{"name":"f100-rv","aliases":["freedom-rv"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","smacs":"\u001b%%","rmacs":"\u001b$"} +{"name":"f110","aliases":["freedom110"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.2","civis":"\u001b.1","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001e","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"f110-14","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.2","civis":"\u001b.1","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001e","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"f110-14w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.2","civis":"\u001b.1","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001e","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"f110-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.2","civis":"\u001b.1","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001e","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"f1720","aliases":["f1720a"],"cols":80,"lines":16,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kcuu1":"\u001c","kcud1":"\u001d","kcub1":"\u001f","kcuf1":"\u001e"} +{"name":"f200","aliases":["freedom200"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001e","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"f200-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001e","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"f200vi","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001e","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"f200vi-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001e","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"falco","aliases":["ts-1","ts1"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bg0","smul":"\u001bg1","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"falco-p","aliases":["ts-1p","ts1p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","smcup":"\u001b_d","rmcup":"\u001b_b","sgr0":"\u001bg0","smul":"\u001bg1","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"fos","aliases":["fortune"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001b\\","civis":"\u001b]","sgr0":"\u001bI","smul":"\u001cHP","blink":"\u001bN","rev":"\u001bH","cup":"\u001cC%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b$\u003c3\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001a\r","kf2":"\u0001b\r","kf3":"\u0001c\r","kf4":"\u0001d\r","kf5":"\u0001e\r","kf6":"\u0001f\r","kf7":"\u0001g\r","kf8":"\u0001h\r","khome":"\u0001?\r","kend":"\u0001k\r","kpp":"\u0001n\r","knp":"\u0001o\r","kcuu1":"\u0001x\r","kcud1":"\u0001y\r","kcub1":"\u0001w\r","kcuf1":"\u0001z\r","acsc":"j*k(l m\"q\u0026v%w#x-","smacs":"\u001bo","rmacs":"\u000f"} +{"name":"fox","aliases":["pe1100"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ$\u003c132\u003e","cup":"\u001bX%p1%' '%+%c\u001bY%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"gator","cols":128,"lines":47,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"gator-52","cols":128,"lines":47,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"ffgghhompoqqss.k","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"gator-52t","cols":128,"lines":94,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"ffgghhompoqqss.k","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"gator-t","cols":128,"lines":94,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"gigi","aliases":["vk100"],"cols":84,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"gnome","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO1;2P","kf14":"\u001bO1;2Q","kf15":"\u001bO1;2R","kf16":"\u001bO1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO1;5P","kf26":"\u001bO1;5Q","kf27":"\u001bO1;5R","kf28":"\u001bO1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO1;6P","kf38":"\u001bO1;6Q","kf39":"\u001bO1;6R","kf40":"\u001bO1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO1;3P","kf50":"\u001bO1;3Q","kf51":"\u001bO1;3R","kf52":"\u001bO1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO1;4P","kf62":"\u001bO1;4Q","kf63":"\u001bO1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"gnome-2007","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO3P","kf50":"\u001bO3Q","kf51":"\u001bO3R","kf52":"\u001bO3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO4P","kf62":"\u001bO4Q","kf63":"\u001bO4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"gnome-2008","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO1;2P","kf14":"\u001bO1;2Q","kf15":"\u001bO1;2R","kf16":"\u001bO1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO1;5P","kf26":"\u001bO1;5Q","kf27":"\u001bO1;5R","kf28":"\u001bO1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO1;6P","kf38":"\u001bO1;6Q","kf39":"\u001bO1;6R","kf40":"\u001bO1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO1;3P","kf50":"\u001bO1;3Q","kf51":"\u001bO1;3R","kf52":"\u001bO1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO1;4P","kf62":"\u001bO1;4Q","kf63":"\u001bO1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"gnome-256color","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO1;2P","kf14":"\u001bO1;2Q","kf15":"\u001bO1;2R","kf16":"\u001bO1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO1;5P","kf26":"\u001bO1;5Q","kf27":"\u001bO1;5R","kf28":"\u001bO1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO1;6P","kf38":"\u001bO1;6Q","kf39":"\u001bO1;6R","kf40":"\u001bO1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO1;3P","kf50":"\u001bO1;3Q","kf51":"\u001bO1;3R","kf52":"\u001bO1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO1;4P","kf62":"\u001bO1;4Q","kf63":"\u001bO1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"gnome-fc5","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO3P","kf50":"\u001bO3Q","kf51":"\u001bO3R","kf52":"\u001bO3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO4P","kf62":"\u001bO4Q","kf63":"\u001bO4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001bO2C","kLFT":"\u001bO2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"gnome-rh62","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"gnome-rh72","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"gnome-rh80","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b\t","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"gnome-rh90","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO3P","kf50":"\u001bO3Q","kf51":"\u001bO3R","kf52":"\u001bO3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO4P","kf62":"\u001bO4Q","kf63":"\u001bO4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001bO2C","kLFT":"\u001bO2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"go140","cols":80,"lines":24,"clear":"\u001b[H\u001b[2J$\u003c10/\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%2d;%p2%2dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"go140w","cols":132,"lines":24,"clear":"\u001b[H\u001b[2J$\u003c10/\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%2d;%p2%2dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"go225","aliases":["go-225"],"cols":80,"lines":25,"clear":"\u001b[H\u001b[J","smcup":"\u001b[2;0#w\u001b[1;25r","rmcup":"\u001b[!p\u001b[?7h\u001b[2;1;1#w","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"graphos","cols":80,"lines":24,"clear":"\u001b[H\u001b[2J","cnorm":"\u001bz56;2;0;0z\u001bz73z\u001bz4;1;1z","sgr0":"\u001b[m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"graphos-30","cols":80,"lines":30,"clear":"\u001b[H\u001b[2J","cnorm":"\u001bz56;2;0;0z\u001bz73z\u001bz4;1;1z","sgr0":"\u001b[m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"gs6300","aliases":["emots"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b[10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[0s","kf2":"\u001b[24s","kf3":"\u001b[1s","kf4":"\u001b[23s","kf5":"\u001b[2s","kf6":"\u001b[22s","kf7":"\u001b[3s","kf8":"\u001b[21s","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u0012\t","acsc":"++,,--..``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"guru","aliases":["guru+unk","guru-33"],"cols":80,"lines":33,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[33p","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-24","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[24p","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-44","cols":97,"lines":44,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[44p","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-44-s","cols":80,"lines":43,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[44;1p\u001b[255;1H\u001b[K","rmcup":"\u001b[255;1p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-76","cols":89,"lines":76,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[76p","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-76-lp","aliases":["guru-lp"],"cols":134,"lines":76,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[76p","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-76-s","cols":89,"lines":75,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[76;1p\u001b[255;1H\u001b[K","rmcup":"\u001b[255;1p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-76-w","cols":178,"lines":76,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[76p","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-76-w-s","cols":178,"lines":75,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[76;1p\u001b[255;1H\u001b[K","rmcup":"\u001b[255;1p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-76-wm","cols":178,"lines":76,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[76p","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-nctxt","cols":80,"lines":33,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[H\u001b[J$\u003c156\u003e\u001b[33p\u001b[255;1H\u001b[K","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-rv","aliases":["guru-33-rv"],"cols":80,"lines":33,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[33p","rmcup":"\u001b[255p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"guru-s","aliases":["guru-33-s"],"cols":80,"lines":32,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c156\u003e","smcup":"\u001b[33;1p\u001b[255;1H\u001b[K","rmcup":"\u001b[255;1p\u001b[255;1H\u001b[K","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001bP`\u003ez~[[J`8xz~[[A`4xz~[[D`6xz~[[C`2xz~[[B\u001b\\","rmkx":"\u001bP`\u003ey~[[J`8xy~[[A`4xy~[[D`6xy~[[C`2xy~[[B\u001b\\","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOA","kf2":"\u001bOB","kf3":"\u001bOC","kf4":"\u001bOD","kf5":"\u001bOE","kf6":"\u001bOF","kf7":"\u001bOG","kf8":"\u001bOH","kf9":"\u001bOI","kf10":"\u001bOJ","kf11":"\u001bOK","kf12":"\u001bOL","kf13":"\u001bOM","kf14":"\u001bON","kf15":"\u001bOO","kf16":"\u001bOP","kf17":"\u001bOQ","kf18":"\u001bOR","kf19":"\u001bOS","kf20":"\u001bOT","kf21":"\u001bOU","kf22":"\u001bOV","kf23":"\u001bOW","kf24":"\u001bOX","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[J"} +{"name":"h19","aliases":["h19-b","heath","heath-19","heathkit","z19","zenith"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE","cnorm":"\u001by4","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"h19-a","aliases":["h19a","heath-ansi","heathkit-a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","cnorm":"\u001b[\u003e4l","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[1A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOS","kf2":"\u001bOT","kf3":"\u001bOU","kf4":"\u001bOV","kf5":"\u001bOW","kf6":"\u001bOP","kf7":"\u001bOQ","kf8":"\u001bOR","khome":"\u001b[H","kcuu1":"\u001b[1A","kcud1":"\u001b[1B","kcub1":"\u001b[1D","kcuf1":"\u001b[1C","smacs":"\u001b[10m","rmacs":"\u001b[11m"} +{"name":"h19-bs","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE","cnorm":"\u001by4","smkx":"\u001bt","rmkx":"\u001bu","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"h19-g","aliases":["h19g"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE","cnorm":"\u001bx4","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"h19-u","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"h19-us","aliases":["h19-smul","h19us"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE","smkx":"\u001bt","rmkx":"\u001bu","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"h19k","aliases":["h19kermit"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"ha8675","cols":80,"lines":24,"clear":"\u001bE","sgr0":"\u001bd@","smul":"\u001bd`","cup":"\u001bF%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u0006","kf2":"\u0010","kf3":"\u000e","kf4":"\u0016","kf5":"\n","kf6":"\u0014","kf7":"\u0008","kf8":"","kf9":"\u001be","kf10":"\u001bd","kf11":"\u0017","kf12":"\u001bR","kf13":"\u001bE","kf14":"\u001bI","kf15":"\u001bi","kf16":"\u001bg","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b\u003e","kclr":"\u001bE"} +{"name":"ha8686","cols":80,"lines":24,"clear":"\u001bE","sgr0":"\u001bd@","smul":"\u001bd`","cup":"\u001bF%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u0002\u001bp\u0003","kf2":"\u0002\u001bq\u0003","kf3":"\u0002\u001br\u0003","kf4":"\u0002\u001bs\u0003","kf5":"\u001b3","kf6":"\u001bI","kf7":"\u001bR","kf8":"\u001bJ","kf9":"\u001b(","kf10":"\u001bj","kf11":"\u001bW","kf12":"\u0002\u001b{\u0003","kf13":"\u0002\u001b|\u0003","kf14":"\u0002\u001b}\u0003","kf15":"\u0002\u001b~\u0003","kf16":"\u0002\u001b\u0003","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b\u003e","kclr":"\u001bE"} +{"name":"hazel","aliases":["exec80","h80","he80"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[;H\u001b[2J$\u003c50/\u003e","sgr0":"\u001b[m$\u003c2/\u003e","smul":"\u001b[4m$\u003c2/\u003e","bold":"\u001b[1m$\u003c2/\u003e","blink":"\u001b[5m$\u003c2/\u003e","rev":"\u001b[7m$\u003c2/\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5/\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2/\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"hds200","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[+{","civis":"\u001b[6+{","sgr0":"\u001b[m\u000f","smul":"\u001b[0;4m","bold":"\u001b[0;1m","blink":"\u001b[0;5m","rev":"\u001b[0;7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001c001\r","kf2":"\u001c002\r","kf3":"\u001c003\r","kf4":"\u001c004\r","kf5":"\u001c005\r","kf6":"\u001c006\r","kf7":"\u001c007\r","kf8":"\u001c008\r","kf9":"\u001c009\r","kf10":"\u001c010\r","kf11":"\u001c011\r","kf12":"\u001c012\r","kf13":"\u001bOP","kf14":"\u001bOQ","kf15":"\u001bOR","kf16":"\u001bOS","kf17":"\u001c017\r","kf18":"\u001c018\r","kf19":"\u001c019\r","kf20":"\u001c020\r","kf21":"\u001c021\r","kf22":"\u001c022\r","kf23":"\u001c023\r","kf31":"\u001c031\r","kf32":"\u001c032\r","kf33":"\u001c033\r","kf34":"\u001c034\r","kf35":"\u001c035\r","kf36":"\u001c036\r","kf37":"\u001c037\r","kf38":"\u001c038\r","kf39":"\u001c039\r","kf40":"\u001c040\r","kf41":"\u001c041\r","kf42":"\u001c042\r","kf43":"\u001b$P","kf44":"\u001b$Q","kf45":"\u001b$R","kf46":"\u001b$S","kf47":"\u001c047\r","kf48":"\u001c048\r","kf49":"\u001c049\r","kf50":"\u001c050\r","kf51":"\u001c051\r","kf52":"\u001c052\r","kf53":"\u001c053\r","kdch":"","khome":"\u001b[H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b$I","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b$C","kLFT":"\u001b$D","kHOM":"\u001b$H"} +{"name":"hft-c","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"jjkkllmmnnqqttuuvvwwxx","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"hft-c-old","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"hft-old","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","khome":"\u001b[H","kpp":"\u001b[159q","knp":"\u001b[153q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"hirez100","cols":80,"lines":48,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOQ","kf2":"\u001bOR","kf3":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hirez100-w","cols":132,"lines":48,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOQ","kf2":"\u001bOR","kf3":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hmod1","cols":80,"lines":24,"bell":"\u0007","clear":"~\u001c","sgr0":"~\u0019","cup":"~\u0011%p2%c%p1%c","cub1":"\u0008","cuu1":"~\u000c","pad":"\u0000","khome":"~\u0012","kcuu1":"~\u000c","kcud1":"~\u000b","kcub1":"\u0008","kcuf1":"\u0010"} +{"name":"hp110","cols":80,"lines":16,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","cup":"\u001b\u0026a%p2%dc%p1%dY$\u003c6\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcbt":"\u001bi"} +{"name":"hp150","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2","aliases":["hpex2"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0y0C\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bJ"} +{"name":"hp236","cols":80,"lines":24,"clear":"\u001bF","cnorm":"\u001bDE","sgr0":"\u001bCI","cup":"\u001bE%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"hp2382a","aliases":["hp2382"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ"} +{"name":"hp2392","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","khome":"\u001bh","kpp":"\u001bv","knp":"\u001bu","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"hp2397a","aliases":["hp2397"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dr%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2621","aliases":["2621","2621-wl","2621a","hp2621-wl","hp2621a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026jA","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcbt":"\u001bi"} +{"name":"hp2621-48","cols":80,"lines":48,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026jA","cup":"\u001b\u0026a%p2%dc%p1%dR","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcbt":"\u001bi"} +{"name":"hp2621-a","aliases":["hp2621a-a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026j@","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bp\r","kcuu1":"\u001bt\r","kcud1":"\u001bw\r","kcub1":"\u001bu\r","kcuf1":"\u001bv\r","kcbt":"\u001bi"} +{"name":"hp2621-ba","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","khome":"\u001bh","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi"} +{"name":"hp2621-fl","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026j@","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcbt":"\u001bi"} +{"name":"hp2621-k45","aliases":["hp2621k45","k45"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","khome":"\u001bh","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi"} +{"name":"hp2621-nl","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcbt":"\u001bi"} +{"name":"hp2621-nt","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026jA","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcbt":"\u001bi"} +{"name":"hp2621b","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026jA","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","khome":"\u001bh","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi"} +{"name":"hp2621b-kx","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ"} +{"name":"hp2621b-kx-p","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ"} +{"name":"hp2621b-p","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026jA","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","khome":"\u001bh","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi"} +{"name":"hp2621p","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026jA","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcbt":"\u001bi"} +{"name":"hp2621p-a","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026jB","rmkx":"\u001b\u0026jA","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bp\r","kcuu1":"\u001bt\r","kcud1":"\u001bw\r","kcub1":"\u001bu\r","kcuf1":"\u001bv\r","kcbt":"\u001bi"} +{"name":"hp2622","aliases":["hp2622a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2623","aliases":["hp2623a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2624","aliases":["hp2624a","hp2624b","hp2624b-4p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2624-10p","aliases":["hp2624a-10p","hp2624b-10p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2624b-10p-p","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2624b-p","aliases":["hp2624b-4p-p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2626","aliases":["hp2626a","hp2626p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2626-12","cols":80,"lines":12,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2626-12-s","cols":80,"lines":11,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2626-12x40","cols":40,"lines":12,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2626-ns","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2626-s","cols":80,"lines":23,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2626-x40","cols":40,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp2627a","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD\u001b\u0026v1S","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcud1":"\n","kcub1":"\u0008","kcbt":"\u001bi"} +{"name":"hp2627a-rev","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD\u001b\u0026v1S","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcud1":"\n","kcub1":"\u0008","kcbt":"\u001bi"} +{"name":"hp2627c","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD\u001b\u0026v1S","cup":"\u001b\u0026a%p2%dc%p1%dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp\r","kf2":"\u001bq\r","kf3":"\u001br\r","kf4":"\u001bs\r","kf5":"\u001bt\r","kf6":"\u001bu\r","kf7":"\u001bv\r","kf8":"\u001bw\r","kcud1":"\n","kcub1":"\u0008","kcbt":"\u001bi"} +{"name":"hp2640b","aliases":["hp2644a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","cup":"\u001b\u0026a%p2%dc%p1%dY$\u003c6\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi"} +{"name":"hp2641a","aliases":["hp2645a","hp2647a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001b\u0026a%p2%2dc%p1%2dY","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"hp2645","aliases":["hp45"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p2%dc%p1%dY$\u003c6\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi"} +{"name":"hp2648","aliases":["hp2648a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ$\u003c50\u003e","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p2%dc%p1%dY$\u003c20\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi"} +{"name":"hp300h","cols":128,"lines":51,"bell":"\u0007","clear":"\u001b\u0026a0y0C\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bh","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"hp700-wy","cols":80,"lines":24,"clear":"\u001a","sgr0":"\u001bG0$\u003c10/\u003e","smul":"\u001bG8$\u003c10/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"","kich":"\u001bq","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a"} +{"name":"hp70092","aliases":["hp70092a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0y0C\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","bold":"\u001b\u0026dB","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bJ","acsc":"0cjgktlrmfn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hp9837","aliases":["hp98720","hp98721"],"cols":128,"lines":46,"bell":"\u0007","clear":"\u001b\u0026a0y0C\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"hp9845","cols":80,"lines":21,"clear":"\u001bH\u001bJ","cup":"\u001b\u0026a%p2%2dc%p1%2dY","cuu1":"\u001bA","pad":"\u0000"} +{"name":"hp98550","aliases":["hp98550a"],"cols":128,"lines":49,"bell":"\u0007","clear":"\u001bH\u001bJ","cnorm":"\u001b*dQ","civis":"\u001b*dR","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","bold":"\u001b\u0026dJ","blink":"\u001b\u0026dA","rev":"\u001b\u0026dJ","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bJ","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hpansi","aliases":["hp700"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"hpex","cols":-1,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bh","kcuu1":"\u001bA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bC"} +{"name":"hpgeneric","aliases":["hp"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","cup":"\u001b\u0026a%p2%dc%p1%dY$\u003c6\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcbt":"\u001bi"} +{"name":"hpterm","aliases":["X-hpterm"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0y0C\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","bold":"\u001b\u0026dB","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bJ","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hpterm-color","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0y0C\u001bJ","sgr0":"\u001b\u0026d@","smul":"\u001b\u0026dD","bold":"\u001b\u0026dB","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bJ","smacs":"\u000e","rmacs":"\u000f"} +{"name":"hurd","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001bc","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00ii``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"hz1420","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u001c","cup":"\u001b\u0011%p2%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001b\u000c","pad":"\u0000"} +{"name":"hz1500","cols":80,"lines":24,"bell":"\u0007","clear":"~\u001c","cup":"~\u0011%p2%p2%?%{30}%\u003e%t%' '%+%;%'`'%+%c%p1%'`'%+%c","cub1":"\u0008","cuu1":"~\u000c","pad":"\u0000","khome":"~\u0012","kcuu1":"~\u000c","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0010"} +{"name":"hz1510","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u001c","cup":"\u001b\u0011%p2%c%p1%c","cub1":"\u0008","cuu1":"\u001b\u000c","pad":"\u0000"} +{"name":"hz1520","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u001c","sgr0":"\u001b\u0019","bold":"\u001b\u001f","cup":"\u001b\u0011%p2%c%p1%c","cub1":"\u0008","cuu1":"\u001b\u000c","pad":"\u0000","kbs":"\u0008","khome":"\u001b\u0012","kcuu1":"\u001b\u000c","kcud1":"\u001b\u000b","kcub1":"\u0008","kcuf1":"\u0010","kclr":"\u001b\u001c"} +{"name":"hz1520-noesc","cols":80,"lines":24,"bell":"\u0007","clear":"~\u001c","cup":"~\u0011%p2%c%p1%c$\u003c1\u003e","cub1":"\u0008","cuu1":"~\u000c","pad":"\u0000"} +{"name":"hz1552","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bP","kf2":"\u001bQ","kf3":"\u001bR","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"ffgghhompoqqss.k","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"hz1552-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bP","kf2":"\u001bQ","kf3":"\u001bR","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"ffgghhompoqqss.k","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"hz2000","cols":74,"lines":27,"bell":"\u0007","clear":"~\u001c$\u003c6\u003e","cup":"~\u0011%p2%c%p1%c","cub1":"\u0008","pad":""} +{"name":"i100","aliases":["gt100","gt100a"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cup":"\u001bf%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"i400","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[2J","cup":"\u001b[%i%p1%3d;%p2%3dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000"} +{"name":"ibcs2","cols":-1,"lines":-1,"clear":"\u001bc","cup":"\u001b[%i%p1%d;%p2%dH","pad":"\u0000"} +{"name":"ibm-apl","aliases":["apl"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u000c","cup":"\u001e%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001f","pad":"\u0000","khome":"\u0019","kcuu1":"\u001f","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001c"} +{"name":"ibm-system1","aliases":["system1"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cup":"\u0005%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001e","pad":"\u0000"} +{"name":"ibm3101","aliases":["i3101"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ibm3151","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001b\u003eB","rmcup":"\u001b\u003eB","sgr0":"\u001b4@\u001b\u003eB","smul":"\u001b4\"a","bold":"\u001b4(a","blink":"\u001b4$a","rev":"\u001b4!a","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001ba\r","kf2":"\u001bb\r","kf3":"\u001bc\r","kf4":"\u001bd\r","kf5":"\u001be\r","kf6":"\u001bf\r","kf7":"\u001bg\r","kf8":"\u001bh\r","kf9":"\u001bi\r","kf10":"\u001bj\r","kf11":"\u001bk\r","kf12":"\u001bl\r","kf13":"\u001b!a\r","kf14":"\u001b!b\r","kf15":"\u001b!c\r","kf16":"\u001b!d\r","kf17":"\u001b!e\r","kf18":"\u001b!f\r","kf19":"\u001b!g\r","kf20":"\u001b!h\r","kf21":"\u001b!i\r","kf22":"\u001b!j\r","kf23":"\u001b!k\r","kf24":"\u001b!l\r","kich":"\u001bP \u0008","kdch":"\u001bQ","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b2","kclr":"\u001bL\r","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","smacs":"\u001b\u003eA","rmacs":"\u001b\u003eB"} +{"name":"ibm3161","aliases":["ibm3163","wy60-316X","wyse60-316X"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001b\u003eA","rmcup":"\u001b\u003eA","sgr0":"\u001b4@\u001b\u003c@","smul":"\u001b4B","bold":"\u001b4H","blink":"\u001b4D","rev":"\u001b4A","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001ba\r","kf2":"\u001bb\r","kf3":"\u001bc\r","kf4":"\u001bd\r","kf5":"\u001be\r","kf6":"\u001bf\r","kf7":"\u001bg\r","kf8":"\u001bh\r","kf9":"\u001bi\r","kf10":"\u001bj\r","kf11":"\u001bk\r","kf12":"\u001bl\r","kf13":"\u001b!a\r","kf14":"\u001b!b\r","kf15":"\u001b!c\r","kf16":"\u001b!d\r","kf17":"\u001b!e\r","kf18":"\u001b!f\r","kf19":"\u001b!g\r","kf20":"\u001b!h\r","kf21":"\u001b!i\r","kf22":"\u001b!j\r","kf23":"\u001b!k\r","kf24":"\u001b!l\r","kich":"\u001bP \u0008","kdch":"\u001bQ","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b2","kclr":"\u001bL\r","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm3161-C","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001b\u003eB","rmcup":"\u001b\u003eB","sgr0":"\u001b4@\u001b\u003c@","smul":"\u001b4B","bold":"\u001b4H","blink":"\u001b4D","rev":"\u001b4A","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001ba\r","kf2":"\u001bb\r","kf3":"\u001bc\r","kf4":"\u001bd\r","kf5":"\u001be\r","kf6":"\u001bf\r","kf7":"\u001bg\r","kf8":"\u001bh\r","kf9":"\u001bi\r","kf10":"\u001bj\r","kf11":"\u001bk\r","kf12":"\u001bl\r","kf13":"\u001b!a\r","kf14":"\u001b!b\r","kf15":"\u001b!c\r","kf16":"\u001b!d\r","kf17":"\u001b!e\r","kf18":"\u001b!f\r","kf19":"\u001b!g\r","kf20":"\u001b!h\r","kf21":"\u001b!i\r","kf22":"\u001b!j\r","kf23":"\u001b!k\r","kf24":"\u001b!l\r","kich":"\u001bP \u0008","kdch":"\u001bQ","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b2","kclr":"\u001bL\r","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm3162","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001b\u003eB","rmcup":"\u001b\u003eB","sgr0":"\u001b4@","smul":"\u001b4\"a","bold":"\u001b4(a","blink":"\u001b4$a","rev":"\u001b4!a","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001ba\r","kf2":"\u001bb\r","kf3":"\u001bc\r","kf4":"\u001bd\r","kf5":"\u001be\r","kf6":"\u001bf\r","kf7":"\u001bg\r","kf8":"\u001bh\r","kf9":"\u001bi\r","kf10":"\u001bj\r","kf11":"\u001bk\r","kf12":"\u001bl\r","kf13":"\u001b!a\r","kf14":"\u001b!b\r","kf15":"\u001b!c\r","kf16":"\u001b!d\r","kf17":"\u001b!e\r","kf18":"\u001b!f\r","kf19":"\u001b!g\r","kf20":"\u001b!h\r","kf21":"\u001b!i\r","kf22":"\u001b!j\r","kf23":"\u001b!k\r","kf24":"\u001b!l\r","kich":"\u001bP \u0008","kdch":"\u001bQ","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b2","kclr":"\u001bL\r","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm3164","aliases":["i3164"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001b!9/N\u001b\u003eB","rmcup":"\u001b!9(N\u001b\u003eB","sgr0":"\u001b4@\u001b\u003c@","smul":"\u001b4B","bold":"\u001b4H","blink":"\u001b4D","rev":"\u001b4A","setaf":"\u001b4%?%p1%t %p1%' '%+%c%e!'%;@","setbg":"\u001b4 %p1%'@'%+%c","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001ba\r","kf2":"\u001bb\r","kf3":"\u001bc\r","kf4":"\u001bd\r","kf5":"\u001be\r","kf6":"\u001bf\r","kf7":"\u001bg\r","kf8":"\u001bh\r","kf9":"\u001bi\r","kf10":"\u001bj\r","kf11":"\u001bk\r","kf12":"\u001bl\r","kf13":"\u001b!a\r","kf14":"\u001b!b\r","kf15":"\u001b!c\r","kf16":"\u001b!d\r","kf17":"\u001b!e\r","kf18":"\u001b!f\r","kf19":"\u001b!g\r","kf20":"\u001b!h\r","kf21":"\u001b!i\r","kf22":"\u001b!j\r","kf23":"\u001b!k\r","kf24":"\u001b!l\r","kich":"\u001bP \u0008","kdch":"\u001bQ","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b2","kclr":"\u001bL\r","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm5081","aliases":["hft"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"jjkkllmmnnqqttuuvvwwxx","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ibm5081-c","aliases":["ibmmpel-c"],"cols":80,"lines":33,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bF\u001bf2;","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ibm5151","aliases":["wy60-AT","wyse60-AT"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm5154","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ibm6153","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[12m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm6153-40","cols":40,"lines":12,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm6153-90","cols":90,"lines":36,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm6154","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[12m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ibm6155","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibm8503","aliases":["ibm8507","ibm8604"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"jjkkllmmnnqqttuuvvwwxx","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ibm8512","aliases":["ibm8513"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[20;4l\u001b[?7h\u001bb","rmcup":"\u001b[20h","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"jjkkllmmnnqqttuuvvwwxx","smacs":"\u000e","rmacs":"\u000f","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ibm8514","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m\u001b(B","smul":"\u001b[4m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"jjkkllmmnnqqttuuvvwwxx","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ibm8514-c","cols":80,"lines":41,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bF\u001bf2;","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bC"} +{"name":"ibmaed","cols":80,"lines":52,"clear":"\u001bH\u001bK","sgr0":"\u001b0","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ibmapa8c","aliases":["ibmapa8"],"cols":80,"lines":31,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bW","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ibmapa8c-c","aliases":["ibm6154-c"],"cols":80,"lines":31,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bF\u001bf2;","bold":"\u001bZ","rev":"\u001bp","dim":"\u001bF\u001bf7;","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ibmega","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bW","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bC"} +{"name":"ibmega-c","aliases":["ibm5154-c"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bF\u001bf2;","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ibmmono","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bW","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ibmpc","aliases":["wy60-PC","wyse60-PC"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd","kf2":"\ufffd","kf3":"\ufffd","kf4":"\ufffd","kf5":"\ufffd","kf6":"\ufffd","kf7":"\ufffd","kf8":"\ufffd","kf9":"\ufffd","kf10":"\ufffd","kich":"\u001b[\u0008","kdch":"","khome":"\u001b[H","kend":"\u001b[Y","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001d","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"ibmpc3","aliases":["pc3-bold"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[L","khome":"\u001b[H","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ibmpcx","aliases":["ibmx","xenix"],"cols":80,"lines":25,"clear":"\u000c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[K","kf2":"\u001b[L","kf3":"\u001b[M","kf4":"\u001b[N","khome":"\u001b[Y","kend":"\u001b[d","kpp":"\u001b[Z","knp":"\u001b[e","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"ibmvga","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bW","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bC"} +{"name":"ibmvga-c","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bF\u001bf2;","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bC"} +{"name":"icl6404","aliases":["icl6402","kds6402","kds7372"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","cnorm":"\u001b.3","civis":"\u001b.0","sgr0":"\u001b[0ZZ","smul":"\u001b[8ZZ","blink":"\u001b[2ZZ","rev":"\u001b[4ZZ","cup":"\u001b=%p1%' '%+%c%p2%'P'%m%' '%+%c%p2%'P'%\u003e%' '%+%c","cuu1":"\u000b","pad":"\u0000"} +{"name":"icl6404-w","aliases":["kds7372-w"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","cnorm":"\u001b.3","civis":"\u001b.0","sgr0":"\u001b[0ZZ","smul":"\u001b[8ZZ","blink":"\u001b[2ZZ","rev":"\u001b[4ZZ","cup":"\u001b=%p1%' '%+%c%p2%'P'%m%' '%+%c%p2%'P'%\u003e%' '%+%c","cuu1":"\u000b","pad":"\u0000"} +{"name":"ifmr","cols":80,"lines":24,"clear":"\u001bZ","sgr0":"\u001bK","cup":"\u001bY%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"ims-ansi","aliases":["ultima2","ultimaII"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%2d;%p2%2dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ims950","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kich":"\u001bQ","kdch":"\u001bW","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"ims950-b","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kich":"\u001bQ","kdch":"\u001bW","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"ims950-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kich":"\u001bQ","kdch":"\u001bW","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"interix","aliases":["ntconsole","ntconsole-25","opennt","opennt-25"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"interix-nti","aliases":["ntconsole-25-nti","opennt-25-nti","opennt-nti"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"intertube","aliases":["intertec"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u000c","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c$\u003c50\u003e","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000"} +{"name":"intertube2","cols":80,"lines":25,"bell":"\u0007","clear":"\u000c","cup":"\u000e%p1%c\u0010%p2%{10}%/%{16}%*%p2%{10}%m%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000"} +{"name":"intext","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c132\u003e","smkx":"\u001e:\ufffd\u0016%%","rmkx":"\u00169","cup":"\u000f%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001c","pad":"\u0000","kbs":"\u0008","kf1":"\u0016A\r","kf2":"\u0016B\r","kf3":"\u0016C\r","kf4":"\u0016D\r","kf5":"\u0016E\r","kf6":"\u0016F\r","kf7":"\u0016G\r","kf8":"\u0016H\r","kf9":"\u0016I\r","khome":"\u001a","kcuu1":"\u001c","kcud1":"\n","kcub1":"\u001f","kcuf1":"\u001e"} +{"name":"intext2","aliases":["intextii"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smul":"\u001b[18 D","cup":"\u001b[%i%p1%d;%p2%dH","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bP\r","kf2":"\u001bQ\r","kf3":"\u001bS\r","kf4":"\u001bT\r","kf5":"\u001bU\r","kf6":"\u001bV\r","kf7":"\u001bW\r","kf8":"\u001bX\r","kf9":"\u001bY\r","khome":"\u001bR\r","kcuu1":"\u001bA\r","kcud1":"\u001bB\r","kcub1":"\u001bD\r","kcuf1":"\u001bC\r"} +{"name":"iris-ansi","aliases":["iris-ansi-net"],"cols":80,"lines":40,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[9/y\u001b[12/y\u001b[=6l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kich":"\u001b[139q","kdch":"","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kprt":"\u001b[209q","kRIT":"\u001b[167q","kLFT":"\u001b[158q","kHOM":"\u001b[143q","kEND":"\u001b[147q"} +{"name":"iris-ansi-ap","cols":80,"lines":40,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[9/y\u001b[12/y\u001b[=6l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kich":"\u001b[139q","kdch":"","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kprt":"\u001b[209q","kRIT":"\u001b[167q","kLFT":"\u001b[158q","kHOM":"\u001b[143q","kEND":"\u001b[147q"} +{"name":"iris-color","aliases":["xwsh"],"cols":80,"lines":40,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[9/y\u001b[12/y\u001b[=6l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kich":"\u001b[139q","kdch":"","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kprt":"\u001b[209q","kRIT":"\u001b[167q","kLFT":"\u001b[158q","kHOM":"\u001b[143q","kEND":"\u001b[147q","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"jaixterm","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"jaixterm-m","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q"} +{"name":"kaypro","aliases":["kaypro2"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c1/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcuf1":"\u000c"} +{"name":"kermit","cols":80,"lines":24,"clear":"\u001bE","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"kermit-am","cols":80,"lines":24,"clear":"\u001bE","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"kon","aliases":["jfbterm","kon2"],"cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"konsole","cols":80,"lines":24,"colors":8,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO3P","kf50":"\u001bO3Q","kf51":"\u001bO3R","kf52":"\u001bO3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO4P","kf62":"\u001bO4Q","kf63":"\u001bO4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"konsole-16color","cols":80,"lines":24,"colors":16,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO3P","kf50":"\u001bO3Q","kf51":"\u001bO3R","kf52":"\u001bO3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO4P","kf62":"\u001bO4Q","kf63":"\u001bO4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"konsole-256color","cols":80,"lines":24,"colors":256,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO3P","kf50":"\u001bO3Q","kf51":"\u001bO3R","kf52":"\u001bO3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO4P","kf62":"\u001bO4Q","kf63":"\u001bO4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m"} +{"name":"konsole-base","cols":80,"lines":24,"colors":8,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kich":"\u001b[2~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"konsole-linux","cols":80,"lines":24,"colors":8,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"konsole-solaris","cols":80,"lines":24,"colors":8,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"konsole-vt100","cols":80,"lines":24,"colors":8,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"konsole-vt420pc","cols":80,"lines":24,"colors":8,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"konsole-xf3x","cols":80,"lines":24,"colors":8,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"konsole-xf4x","cols":80,"lines":24,"colors":8,"clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO3P","kf50":"\u001bO3Q","kf51":"\u001bO3R","kf52":"\u001bO3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO4P","kf62":"\u001bO4Q","kf63":"\u001bO4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"kt7","cols":80,"lines":24,"clear":"\u001a","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a"} +{"name":"kt7ix","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b*","cnorm":"\u001b.3","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","blink":"\u001bG2","dim":"\u001bG@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","khome":"\u001e","kend":"\u001bY","knp":"\u001bJ","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001bI","kclr":"\u001b*","acsc":"jYk?lZm@nEqDt4uCvAwBx3","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"kterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aajjkkllmmnnooppqqrrssttuuvvwwxx~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"kterm-color","aliases":["kterm-co"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aajjkkllmmnnooppqqrrssttuuvvwwxx~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"kvt","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"lft","aliases":["LFT-PC850","lft-pc850"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[001q","kf2":"\u001b[002q","kf3":"\u001b[003q","kf4":"\u001b[004q","kf5":"\u001b[005q","kf6":"\u001b[006q","kf7":"\u001b[007q","kf8":"\u001b[008q","kf9":"\u001b[009q","kf10":"\u001b[010q","kf11":"\u001b[011q","kf12":"\u001b[012q","kf13":"\u001b[013q","kf14":"\u001b[014q","kf15":"\u001b[015q","kf16":"\u001b[016q","kf17":"\u001b[017q","kf18":"\u001b[018q","kf19":"\u001b[019q","kf20":"\u001b[020q","kf21":"\u001b[021q","kf22":"\u001b[022q","kf23":"\u001b[023q","kf24":"\u001b[024q","kf25":"\u001b[025q","kf26":"\u001b[026q","kf27":"\u001b[027q","kf28":"\u001b[028q","kf29":"\u001b[029q","kf30":"\u001b[030q","kf31":"\u001b[031q","kf32":"\u001b[032q","kf33":"\u001b[033q","kf34":"\u001b[034q","kf35":"\u001b[035q","kf36":"\u001b[036q","kich":"\u001b[139q","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[146q","kpp":"\u001b[150q","knp":"\u001b[154q","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kclr":"\u001b[144q","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"linux","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?0c","civis":"\u001b[?25l\u001b[?1c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux-basic","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux-c","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux-c-nc","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux-koi8","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?0c","civis":"\u001b[?25l\u001b[?1c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux-koi8r","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?0c","civis":"\u001b[?25l\u001b[?1c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux-lat","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?0c","civis":"\u001b[?25l\u001b[?1c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\u000bf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux-m","cols":-1,"lines":-1,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?0c","civis":"\u001b[?25l\u001b[?1c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"linux-nic","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?0c","civis":"\u001b[?25l\u001b[?1c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux-vt","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?0c","civis":"\u001b[?25l\u001b[?1c","sgr0":"\u001b[0m\u001b(K\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(K","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"linux2.6.26","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h\u001b[?0c","civis":"\u001b[?25l\u001b[?1c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"lisa","cols":88,"lines":32,"clear":"\u000c","cnorm":"\u001b[5l","civis":"\u001b[5h","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"jdkclfmenbqattuvvuwsx`","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"lisaterm","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOQ","kf2":"\u001bOR","kf3":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"lisaterm-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOQ","kf2":"\u001bOR","kf3":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u001bOC"} +{"name":"liswb","cols":88,"lines":32,"clear":"\u000c","cnorm":"\u001b[5l","civis":"\u001b[5h","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"jdkclfmenbqattuvvuwsx`","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"luna","aliases":["luna68k"],"cols":88,"lines":46,"bell":"\u0007","clear":"\u001b[H\u001b[J","cup":"\u001b[%i%p1%d;%p2%dH","pad":"\u0000"} +{"name":"m2-nam","aliases":["minitel","minitel-2","minitel-2-nam"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[\u003c1l","civis":"\u001b[\u003c1h","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOq","kf2":"\u001bOr","kf3":"\u001bOs","kf4":"\u001bOt","kf5":"\u001bOu","kf6":"\u001bOv","kf7":"\u001bOw","kf8":"\u001bOx","kf9":"\u001bOy","kf10":"\u001bOp","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kpp":"\u001bOR","knp":"\u001bOn","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","acsc":"aaffggjjkkllmmnnooqqssttuuvvwwxx","smacs":"\u000e","rmacs":"\u000f"} +{"name":"mac","aliases":["macintosh"],"cols":88,"lines":32,"clear":"\u000c","cnorm":"\u001b[5l","civis":"\u001b[5h","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"jdkclfmenbqattuvvuwsx`","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"mac-w","aliases":["macterminal-w"],"cols":132,"lines":32,"clear":"\u000c","cnorm":"\u001b[5l","civis":"\u001b[5h","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"jdkclfmenbqattuvvuwsx`","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"mach","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kich":"\u001b[@","kdch":"\u001b[9","khome":"\u001b[H","kend":"\u001b[Y","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"mach-bold","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0m","smul":"\u001b[1m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kich":"\u001b[@","kdch":"\u001b[9","khome":"\u001b[H","kend":"\u001b[Y","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"mach-color","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kich":"\u001b[@","kdch":"\u001b[9","khome":"\u001b[H","kend":"\u001b[Y","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"mai","aliases":["basic4"],"cols":82,"lines":25,"bell":"\u0007","clear":"\u001d\u001f","cnorm":"\u001b[?7h","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"masscomp","cols":80,"lines":24,"clear":"\u001b[2J","smul":"\u001bGu","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"masscomp1","cols":104,"lines":36,"clear":"\u001b[2J","smul":"\u001bGu","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"masscomp2","cols":64,"lines":21,"clear":"\u001b[2J","smul":"\u001bGu","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"memhp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dr%p2%dC","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"mgr","cols":-1,"lines":-1,"bell":"\u0007","clear":"\u000c","cnorm":"\u001bh","civis":"\u001b9h","sgr0":"\u001b0n","smul":"\u001b4n","bold":"\u001b2n","rev":"\u001b1n","cup":"\u001b%p2%d;%p1%dM","cub1":"\u0008","cuu1":"\u001bu","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"mgr-linux","cols":-1,"lines":-1,"bell":"\u0007","clear":"\u000c","cnorm":"\u001bh","civis":"\u001b9h","sgr0":"\u001b0n","smul":"\u001b4n","bold":"\u001b2n","rev":"\u001b1n","cup":"\u001b%p2%d;%p1%dM","cub1":"\u0008","cuu1":"\u001bu","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[[A","kf2":"\u001b[[B","kf3":"\u001b[[C","kf4":"\u001b[[D","kf5":"\u001b[[E","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"mgr-sun","cols":-1,"lines":-1,"bell":"\u0007","clear":"\u000c","cnorm":"\u001bh","civis":"\u001b9h","sgr0":"\u001b0n","smul":"\u001b4n","bold":"\u001b2n","rev":"\u001b1n","cup":"\u001b%p2%d;%p1%dM","cub1":"\u0008","cuu1":"\u001bu","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","khome":"\u001b[214z","kend":"\u001b[220z","khlp":"\u001b[207z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"mgt","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1048h\u001b[?1047h","rmcup":"\u001b[?1047l\u001b[?1048l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"microb","aliases":["microbee"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE","sgr0":"\u001bd@","smul":"\u001bd`","cup":"\u001bF%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kf9":"\u001bx","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"mime","aliases":["mime1","mime2","mimei","mimeii"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001d\u0003","cup":"\u0014%p1%{24}%+%c%p2%p2%?%' '%\u003e%t%'0'%+%;%'P'%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"mime-fb","cols":80,"lines":24,"bell":"\u0007","clear":"\u001d\u0003","cup":"\u0014%p1%{24}%+%c%p2%p2%?%' '%\u003e%t%'0'%+%;%'P'%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"mime-hb","cols":80,"lines":24,"bell":"\u0007","clear":"\u001d\u0003","cup":"\u0014%p1%{24}%+%c%p2%p2%?%' '%\u003e%t%'0'%+%;%'P'%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"mime2a","aliases":["mime2a-v"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bL","smul":"\u001b4","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"mime2a-s","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bL","smul":"\u001b6","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bI","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"mime314","aliases":["mm314"],"cols":80,"lines":24,"clear":"\u000c","cup":"\u0014%p1%c%p2%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"mime3a","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c1/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"mime3ax","aliases":["mime-3ax"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c1/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u001a","kcud1":"\u000b","kcub1":"\u0008","kcuf1":"\u0018"} +{"name":"minitel1","cols":40,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u0011","civis":"\u0014","sgr0":"\u001bI\u001b\\","blink":"\u001bH","rev":"\u001b]","cup":"\u001f%p1%'A'%+%c%p2%'A'%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","acsc":"+.,,./f0g1","enacs":"\u0019"} +{"name":"minitel1b","cols":40,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u0011","civis":"\u0014","sgr0":"\u001bI\u001b\\","blink":"\u001bH","rev":"\u001b]","smkx":"\u001b;iYA\u001b;jYC","cup":"\u001f%p1%'A'%+%c%p2%'A'%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","acsc":"+.,,./f0g1","enacs":"\u0019"} +{"name":"minitel1b-80","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001f@A\u0011\n","civis":"\u001f@A\u0014\n","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOq","kf2":"\u001bOr","kf3":"\u001bOs","kf4":"\u001bOt","kf5":"\u001bOu","kf6":"\u001bOv","kf7":"\u001bOw","kf8":"\u001bOx","kf9":"\u001bOy","kich":"\u001b[4h","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[2J","acsc":"+.,,./f0g1","enacs":"\u0019"} +{"name":"minix","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[0J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[V","kf2":"\u001b[U","kf3":"\u001b[T","kf4":"\u001b[S","kf5":"\u001b[G","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"minix-old","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[0J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[V","kf2":"\u001b[U","kf3":"\u001b[T","kf4":"\u001b[S","kf5":"\u001b[G","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"minix-old-am","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[0J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[V","kf2":"\u001b[U","kf3":"\u001b[T","kf4":"\u001b[S","kf5":"\u001b[G","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"mlterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[11;2~","kf14":"\u001b[12;2~","kf15":"\u001b[13;2~","kf16":"\u001b[14;2~","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[11;5~","kf26":"\u001b[12;5~","kf27":"\u001b[13;5~","kf28":"\u001b[14;5~","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[11;6~","kf38":"\u001b[12;6~","kf39":"\u001b[13;6~","kf40":"\u001b[14;6~","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[11;3~","kf50":"\u001b[12;3~","kf51":"\u001b[13;3~","kf52":"\u001b[14;3~","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[11;4~","kf62":"\u001b[12;4~","kf63":"\u001b[13;4~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001bO1;2C","kLFT":"\u001bO1;2D","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"mm340","aliases":["mime340"],"cols":80,"lines":24,"clear":"\u001a$\u003c12/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008"} +{"name":"modgraph","aliases":["mod24"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"modgraph2","cols":80,"lines":24,"clear":"\u001bH\u001bJ$\u003c50/\u003e","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c$\u003c5/\u003e","cub1":"\u0008","cuu1":"\u001bA$\u003c2/\u003e","pad":"\u0000"} +{"name":"modgraph48","aliases":["mod"],"cols":80,"lines":48,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"mono-emx","cols":80,"lines":24,"clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[0m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd;","kf2":"\ufffd\u003c","kf3":"\ufffd=","kf4":"\ufffd\u003e","kf5":"\ufffd?","kf6":"\ufffd@","kf7":"\ufffdA","kf8":"\ufffdB","kf9":"\ufffdC","kich":"\ufffdR","khome":"\ufffdG","kpp":"\ufffdI","knp":"\ufffdQ","kcuu1":"\ufffdH","kcud1":"\ufffdP","kcub1":"\ufffdK","kcuf1":"\ufffdM"} +{"name":"mrxvt","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[11;2~","kf14":"\u001b[12;2~","kf15":"\u001b[13;2~","kf16":"\u001b[14;2~","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[11;5~","kf26":"\u001b[12;5~","kf27":"\u001b[13;5~","kf28":"\u001b[14;5~","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[11;6~","kf38":"\u001b[12;6~","kf39":"\u001b[13;6~","kf40":"\u001b[14;6~","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[11;3~","kf50":"\u001b[12;3~","kf51":"\u001b[13;3~","kf52":"\u001b[14;3~","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[11;4~","kf62":"\u001b[12;4~","kf63":"\u001b[13;4~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[7^","_kcend":"\u001b[8^","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C"} +{"name":"ms-vt-utf8","aliases":["vt-utf8"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001b1","kf2":"\u001b2","kf3":"\u001b3","kf4":"\u001b4","kf5":"\u001b5","kf6":"\u001b6","kf7":"\u001b7","kf8":"\u001b8","kf9":"\u001b9","kf10":"\u001b0","kf11":"\u001b!","kf12":"\u001b@","kf13":"\u001b\u0013\u001b1","kf14":"\u001b\u0013\u001b2","kf15":"\u001b\u0013\u001b3","kf16":"\u001b\u0013\u001b4","kf17":"\u001b\u0013\u001b5","kf18":"\u001b\u0013\u001b6","kf19":"\u001b\u0013\u001b7","kf20":"\u001b\u0013\u001b8","kf21":"\u001b\u0013\u001b9","kf22":"\u001b\u0013\u001b0","kf23":"\u001b\u0013\u001b!","kf24":"\u001b\u0013\u001b@","kf25":"\u001b\u0003\u001b1","kf26":"\u001b\u0003\u001b2","kf27":"\u001b\u0003\u001b3","kf28":"\u001b\u0003\u001b4","kf29":"\u001b\u0003\u001b5","kf30":"\u001b\u0003\u001b6","kf31":"\u001b\u0003\u001b7","kf32":"\u001b\u0003\u001b8","kf33":"\u001b\u0003\u001b9","kf34":"\u001b\u0003\u001b0","kf35":"\u001b\u0003\u001b!","kf36":"\u001b\u0003\u001b@","kf37":"\u001b\u0001\u001b1","kf38":"\u001b\u0001\u001b2","kf39":"\u001b\u0001\u001b3","kf40":"\u001b\u0001\u001b4","kf41":"\u001b\u0001\u001b5","kf42":"\u001b\u0001\u001b6","kf43":"\u001b\u0001\u001b7","kf44":"\u001b\u0001\u001b8","kf45":"\u001b\u0001\u001b9","kf46":"\u001b\u0001\u001b0","kf47":"\u001b\u0001\u001b!","kf48":"\u001b\u0001\u001b@","kich":"\u001b+","kdch":"\u001b-","khome":"\u001bh","kend":"\u001bk","kpp":"\u001b?","knp":"\u001b/","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ms-vt100","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"ms-vt100+","aliases":["vt100+"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001b1","kf2":"\u001b2","kf3":"\u001b3","kf4":"\u001b4","kf5":"\u001b5","kf6":"\u001b6","kf7":"\u001b7","kf8":"\u001b8","kf9":"\u001b9","kf10":"\u001b0","kf11":"\u001b!","kf12":"\u001b@","kf13":"\u001b\u0013\u001b1","kf14":"\u001b\u0013\u001b2","kf15":"\u001b\u0013\u001b3","kf16":"\u001b\u0013\u001b4","kf17":"\u001b\u0013\u001b5","kf18":"\u001b\u0013\u001b6","kf19":"\u001b\u0013\u001b7","kf20":"\u001b\u0013\u001b8","kf21":"\u001b\u0013\u001b9","kf22":"\u001b\u0013\u001b0","kf23":"\u001b\u0013\u001b!","kf24":"\u001b\u0013\u001b@","kf25":"\u001b\u0003\u001b1","kf26":"\u001b\u0003\u001b2","kf27":"\u001b\u0003\u001b3","kf28":"\u001b\u0003\u001b4","kf29":"\u001b\u0003\u001b5","kf30":"\u001b\u0003\u001b6","kf31":"\u001b\u0003\u001b7","kf32":"\u001b\u0003\u001b8","kf33":"\u001b\u0003\u001b9","kf34":"\u001b\u0003\u001b0","kf35":"\u001b\u0003\u001b!","kf36":"\u001b\u0003\u001b@","kf37":"\u001b\u0001\u001b1","kf38":"\u001b\u0001\u001b2","kf39":"\u001b\u0001\u001b3","kf40":"\u001b\u0001\u001b4","kf41":"\u001b\u0001\u001b5","kf42":"\u001b\u0001\u001b6","kf43":"\u001b\u0001\u001b7","kf44":"\u001b\u0001\u001b8","kf45":"\u001b\u0001\u001b9","kf46":"\u001b\u0001\u001b0","kf47":"\u001b\u0001\u001b!","kf48":"\u001b\u0001\u001b@","kich":"\u001b+","kdch":"\u001b-","khome":"\u001bh","kend":"\u001bk","kpp":"\u001b?","knp":"\u001b/","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ms-vt100-color","aliases":["vtnt"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"msk227","aliases":["mskermit227"],"cols":80,"lines":24,"clear":"\u001bE","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"msk22714","aliases":["mskermit22714"],"cols":80,"lines":24,"clear":"\u001bE","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001b1","kf2":"\u001b2","kf3":"\u001b3","kf4":"\u001b4","kf5":"\u001b5","kf6":"\u001b6","kf7":"\u001b7","kf8":"\u001b8","kf9":"\u001b9","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"msk227am","aliases":["mskermit227am"],"cols":80,"lines":24,"clear":"\u001bE","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"mt4520-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[0V\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"mt70","aliases":["mt-70"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","smcup":"\u001b\"2\u001bG0\u001b]","cnorm":"\u001b\"2","civis":"\u001b\"0","sgr0":"\u001bG0","smul":"\u001bG1","rev":"\u001bG4","dim":"\u001bG2","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c1\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001`\r","kf12":"\u0001a\r","kf13":"\u0001b\r","kf14":"\u0001c\r","kf15":"\u0001d\r","kf16":"\u0001e\r","kf17":"\u0001f\r","kf18":"\u0001g\r","kf19":"\u0001h\r","kf20":"\u0001i\r","kdch":"","khome":"\u0001N\r","khlp":"\u0001O\r","kcuu1":"\u0001J\r","kcud1":"\u0001K\r","kcub1":"\u0001L\r","kcuf1":"\u0001M\r","kcbt":"\u0001\u001a\r","kclr":"\u0001n\r","acsc":"+z,{-x.yOi`|jGkFlEmDnHqJtLuKvNwMxI","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"mterm","aliases":["mouse-sun"],"cols":-1,"lines":-1,"bell":"\u0007","clear":"\u000c","cup":"\u0006%p1%d.%p2%d.","cub1":"\u0008","cuu1":"\u0018","pad":"\u0000","kbs":"\u0008"} +{"name":"mterm-ansi","cols":-1,"lines":-1,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"mvterm","aliases":["vv100"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"nansi.sys","aliases":["nansisys"],"cols":80,"lines":25,"colors":8,"clear":"\u001b[2J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"nansi.sysk","aliases":["nansisysk"],"cols":80,"lines":25,"colors":8,"clear":"\u001b[2J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[;71;30p\u001b[;72;11p\u001b[;73;27;21p\u001b[;77;12p\u001b[;80;10p\u001b[;81;27;4p\u001b[;82;27;27;105p\u001b[;83;127p","rmkx":"\u001b[;71;0;71p\u001b[;72;0;72p\u001b[;73;0;73p\u001b[;77;0;77p\u001b[;80;0;80p\u001b[;81;0;81p\u001b[;82;0;82p\u001b[;83;0;83p","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ncr160vppp","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c40\u003e","cnorm":"\u001b`5","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c$\u003c5\u003e","cub1":"\u0008$\u003c2\u003e","cuu1":"\u001a$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u00021\r","kf2":"\u00022\r","kf3":"\u00023\r","kf4":"\u00024\r","kf5":"\u00025\r","kf6":"\u00026\r","kf7":"\u00027\r","kf8":"\u00028\r","kf9":"\u00029\r","kf10":"\u0002:\r","kf11":"\u0002;\r","kf12":"\u0002\u003c\r","kf13":"\u0002=\r","kf14":"\u0002\u003e\r","kf15":"\u0002?\r","kf16":"\u0002@\r","kf17":"\u0002!\r","kf18":"\u0002\"\r","kf19":"\u0002#\r","kf20":"\u0002$\r","kf21":"\u0002%^M","kf22":"\u0002\u0026\r","kf23":"\u0002'\r","kf24":"\u0002(\r","kf25":"\u0002)\r","kf26":"\u0002*\r","kf27":"\u0002+\r","kf28":"\u0002,\r","kf29":"\u0002-\r","kf30":"\u0002.\r","kf31":"\u0002/\r","kf32":"\u00020\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u0001","kend":"\u001bK","kpp":"\u001bJ","knp":"\u001bJ","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bcB1\u001bH\u0002","rmacs":"\u001bcB0\u001bH\u0003","kRIT":"\u0006","kHOM":"\u0001","kEND":"\u001bk"} +{"name":"ncr160vpwpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c40\u003e","cnorm":"\u001b`5","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c30\u003e","cub1":"\u0008$\u003c2\u003e","cuu1":"\u001a$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u00021\r","kf2":"\u00022\r","kf3":"\u00023\r","kf4":"\u00024\r","kf5":"\u00025\r","kf6":"\u00026\r","kf7":"\u00027\r","kf8":"\u00028\r","kf9":"\u00029\r","kf10":"\u0002:\r","kf11":"\u0002;\r","kf12":"\u0002\u003c\r","kf13":"\u0002=\r","kf14":"\u0002\u003e\r","kf15":"\u0002?\r","kf16":"\u0002@\r","kf17":"\u0002!\r","kf18":"\u0002\"\r","kf19":"\u0002#\r","kf20":"\u0002$\r","kf21":"\u0002%^M","kf22":"\u0002\u0026\r","kf23":"\u0002'\r","kf24":"\u0002(\r","kf25":"\u0002)\r","kf26":"\u0002*\r","kf27":"\u0002+\r","kf28":"\u0002,\r","kf29":"\u0002-\r","kf30":"\u0002.\r","kf31":"\u0002/\r","kf32":"\u00020\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u0001","kend":"\u001bK","kpp":"\u001bJ","knp":"\u001bJ","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bcB1\u001bH\u0002","rmacs":"\u001bcB0\u001bH\u0003","kRIT":"\u0006","kHOM":"\u0001","kEND":"\u001bk"} +{"name":"ncr160vt100an","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"ncr160vt100pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b[1~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[28~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"ncr160vt100wan","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"ncr160vt100wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b[1~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[28~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"ncr160vt200an","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr160vt200pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr160vt200wan","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr160vt200wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr160vt300an","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr160vt300pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr160vt300wan","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr160vt300wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr160wy50+pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c30\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr160wy50+wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c30\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr160wy60pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c100\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bcB0\u001bcD$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c10\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI$\u003c15\u003e","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr160wy60wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c100\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bcB0\u001bcD$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001ba%i%p1%dR%p2%dC$\u003c30\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI$\u003c15\u003e","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr260intan","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ncr260intpp","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ncr260intwan","cols":132,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ncr260intwpp","cols":132,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ncr260vppp","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c40\u003e","cnorm":"\u001b`5","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c$\u003c5\u003e","cub1":"\u0008$\u003c2\u003e","cuu1":"\u001a$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u00021\r","kf2":"\u00022\r","kf3":"\u00023\r","kf4":"\u00024\r","kf5":"\u00025\r","kf6":"\u00026\r","kf7":"\u00027\r","kf8":"\u00028\r","kf9":"\u00029\r","kf10":"\u0002:\r","kf11":"\u0002;\r","kf12":"\u0002\u003c\r","kf13":"\u0002=\r","kf14":"\u0002\u003e\r","kf15":"\u0002?\r","kf16":"\u0002@\r","kf17":"\u0002!\r","kf18":"\u0002\"\r","kf19":"\u0002#\r","kf20":"\u0002$\r","kf21":"\u0002%^M","kf22":"\u0002\u0026\r","kf23":"\u0002'\r","kf24":"\u0002(\r","kf25":"\u0002)\r","kf26":"\u0002*\r","kf27":"\u0002+\r","kf28":"\u0002,\r","kf29":"\u0002-\r","kf30":"\u0002.\r","kf31":"\u0002/\r","kf32":"\u00020\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u0001","kend":"\u001bK","kpp":"\u001bJ","knp":"\u001bJ","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bcB1\u001bH\u0002","rmacs":"\u001bcB0\u001bH\u0003","kRIT":"\u0006","kHOM":"\u0001","kEND":"\u001bk"} +{"name":"ncr260vpwpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c40\u003e","cnorm":"\u001b`5","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c30\u003e","cub1":"\u0008$\u003c2\u003e","cuu1":"\u001a$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u00021\r","kf2":"\u00022\r","kf3":"\u00023\r","kf4":"\u00024\r","kf5":"\u00025\r","kf6":"\u00026\r","kf7":"\u00027\r","kf8":"\u00028\r","kf9":"\u00029\r","kf10":"\u0002:\r","kf11":"\u0002;\r","kf12":"\u0002\u003c\r","kf13":"\u0002=\r","kf14":"\u0002\u003e\r","kf15":"\u0002?\r","kf16":"\u0002@\r","kf17":"\u0002!\r","kf18":"\u0002\"\r","kf19":"\u0002#\r","kf20":"\u0002$\r","kf21":"\u0002%^M","kf22":"\u0002\u0026\r","kf23":"\u0002'\r","kf24":"\u0002(\r","kf25":"\u0002)\r","kf26":"\u0002*\r","kf27":"\u0002+\r","kf28":"\u0002,\r","kf29":"\u0002-\r","kf30":"\u0002.\r","kf31":"\u0002/\r","kf32":"\u00020\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u0001","kend":"\u001bK","kpp":"\u001bJ","knp":"\u001bJ","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bcB1\u001bH\u0002","rmacs":"\u001bcB0\u001bH\u0003","kRIT":"\u0006","kHOM":"\u0001","kEND":"\u001bk"} +{"name":"ncr260vt100an","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"ncr260vt100pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b[1~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[28~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"ncr260vt100wan","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"ncr260vt100wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kich":"\u001b[1~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[28~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"ncr260vt200an","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr260vt200pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr260vt200wan","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr260vt200wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr260vt300an","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr260vt300pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[4~","khome":"\u001b[H","kend":"\u001b[1~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr260vt300wan","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c20\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f$\u003c20\u003e","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c30\u003e","cub1":"\u001b[D$\u003c5\u003e","cuu1":"\u001b[A$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[31~","kf22":"\u001b[32~","kf23":"\u001b[33~","kf24":"\u001b[34~","kf25":"\u001b[35~","kf26":"\u001b[1~","kf27":"\u001b[2~","kf28":"\u001b[3~","kf29":"\u001b[4~","kf30":"\u001b[5~","kf31":"\u001b[6~","kf32":"\u001b[7~","kf33":"\u001b[8~","kf34":"\u001b[9~","kf35":"\u001b[10~","kich":"\u001b[2~","kdch":"\u001b[3~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u000e$\u003c20\u003e","rmacs":"\u000f$\u003c20\u003e"} +{"name":"ncr260wy325pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c10\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bcB0\u001bcD$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c10\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bH\u0002\u001bcB1","rmacs":"\u001bH\u0003\u001bcB0","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr260wy325wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c10\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bcB0\u001bcD$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001ba%i%p1%dR%p2%dC$\u003c30\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bH\u0002\u001bcB1","rmacs":"\u001bH\u0003\u001bcB0","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr260wy350pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c40\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bH\u0002\u001bcB1","rmacs":"\u001bH\u0003\u001bcB0","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr260wy350wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c30\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bH\u0002\u001bcB1","rmacs":"\u001bH\u0003\u001bcB0","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr260wy50+pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c30\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr260wy50+wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bH\u0003$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c30\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr260wy60pp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c100\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bcB0\u001bcD$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c10\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI$\u003c15\u003e","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr260wy60wpp","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c100\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001bcB0\u001bcD$\u003c15\u003e","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001ba%i%p1%dR%p2%dC$\u003c30\u003e","cub1":"\u0008$\u003c5\u003e","cuu1":"\u000b$\u003c5\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kf17":"\u0001`\r","kf18":"\u0001a\r","kf19":"\u0001b\r","kf20":"\u0001c\r","kf21":"\u0001d\r","kf22":"\u0001e\r","kf23":"\u0001f\r","kf24":"\u0001g\r","kf25":"\u0001h\r","kf26":"\u0001i\r","kf27":"\u0001j\r","kf28":"\u0001k\r","kf29":"\u0001l\r","kf30":"\u0001m\r","kf31":"\u0001n\r","kf32":"\u0001o\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kend":"\u001bT","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI$\u003c15\u003e","kprt":"\u001bP","acsc":"07a?h;j5k3l2m1n8q:t4u9v=w0x6","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kRIT":"\u000c","kHOM":"\u001b{","kEND":"\u001bY"} +{"name":"ncr7900i","aliases":["ncr7900"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b0@","smul":"\u001b0`","blink":"\u001b0B","rev":"\u001b0P","dim":"\u001b0A","cup":"\u001b1%p2%c%p1%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"ncr7900iv","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cup":"\u000b%p1%'@'%+%c\u001b\u0005%p2%02d","cub1":"\u0008","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ncr7901","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u0018","civis":"\u0017","sgr0":"\u000f","smul":"\u001b0`\u000e","blink":"\u001b0B","rev":"\u001b0P","dim":"\u001b0A","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","khome":"\u0008","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006","kclr":"\u000c"} +{"name":"ncrvt100an","aliases":["ncrvt100pp"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c300\u003e","sgr0":"\u000f\u001b[0m$\u003c120\u003e","smul":"\u001b[4m$\u003c30\u003e","bold":"\u001b[1m$\u003c30\u003e","blink":"\u001b[5m$\u003c30\u003e","rev":"\u001b[7m$\u003c30\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c100\u003e","cub1":"\u001b[D$\u003c2\u003e","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffgghhiijjkkllmmnnqqttuuvvwwxxyyzz~~","smacs":"\u000e$\u003c90\u003e","rmacs":"\u000f$\u003c90\u003e","enacs":"\u001b(B\u001b)0$\u003c40\u003e","kRIT":"\u001b[C","kLFT":"\u001b[D"} +{"name":"ncrvt100wan","aliases":["NCRVT100WPP","ncrvt100wpp"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[1;1H$\u003c300\u003e","sgr0":"\u000f\u001b[0m$\u003c120\u003e","smul":"\u001b[4m$\u003c30\u003e","bold":"\u001b[1m$\u003c30\u003e","blink":"\u001b[5m$\u003c30\u003e","rev":"\u001b[7m$\u003c30\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c100\u003e","cub1":"\u001b[D$\u003c2\u003e","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffgghhiijjkkllmmnnqqttuuvvwwxxyyzz~~","smacs":"\u000e$\u003c90\u003e","rmacs":"\u000f$\u003c90\u003e","enacs":"\u001b(B\u001b)0$\u003c40\u003e","kRIT":"\u001b[C","kLFT":"\u001b[D"} +{"name":"ncsa","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7","rmcup":"\u001b[2J\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kf13":"\u001b[32~","kf14":"\u001b[33~","kf15":"\u001b[34~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[1~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ncsa-m","aliases":["ncsa-vt220-8"],"cols":-1,"lines":-1,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7","rmcup":"\u001b[2J\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kf13":"\u001b[32~","kf14":"\u001b[33~","kf15":"\u001b[34~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[1~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b)0"} +{"name":"ncsa-m-ns","cols":-1,"lines":-1,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7","rmcup":"\u001b[2J\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kf13":"\u001b[32~","kf14":"\u001b[33~","kf15":"\u001b[34~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[1~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b)0"} +{"name":"ncsa-ns","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7","rmcup":"\u001b[2J\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kf13":"\u001b[32~","kf14":"\u001b[33~","kf15":"\u001b[34~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[1~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ncsa-vt220","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7","rmcup":"\u001b[2J\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[21~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kdch":"\u001b[4~","khome":"\u001b[2~","kend":"\u001b[5~","khlp":"\u001b[1~","kpp":"\u001b[3~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ndr9500","aliases":["nd9500"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0\u001b%%\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a","kprt":"\u001bP","acsc":"qKnImAjDwNuLtMvOlBkCxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"ndr9500-25","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b;","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0\u001b%%\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a","kprt":"\u001bP","acsc":"qKnImAjDwNuLtMvOlBkCxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"ndr9500-25-mc","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b;","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0\u001b%%\u001b(","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a","kprt":"\u001bP","acsc":"qKnImAjDwNuLtMvOlBkCxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"ndr9500-25-mc-nl","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b;","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0\u001b%%\u001b(","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a","kprt":"\u001bP","acsc":"qKnImAjDwNuLtMvOlBkCxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"ndr9500-25-nl","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b;","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0\u001b%%\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a","kprt":"\u001bP","acsc":"qKnImAjDwNuLtMvOlBkCxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"ndr9500-mc","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0\u001b%%\u001b(","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a","kprt":"\u001bP","acsc":"qKnImAjDwNuLtMvOlBkCxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"ndr9500-mc-nl","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0\u001b%%\u001b(","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a","kprt":"\u001bP","acsc":"qKnImAjDwNuLtMvOlBkCxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"ndr9500-nl","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;","cnorm":"\u001b.1","civis":"\u001b.0","sgr0":"\u001bG0\u001b%%\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001a","kprt":"\u001bP","acsc":"qKnImAjDwNuLtMvOlBkCxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"news-old-unk","cols":80,"lines":-1,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"news-unk","cols":80,"lines":-1,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"news28","cols":80,"lines":28,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"news29","aliases":["news28-a"],"cols":80,"lines":29,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"next","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"northstar","cols":80,"lines":24,"clear":"\u0004$\u003c200/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c1/\u003e","pad":"\u0000"} +{"name":"nsterm","aliases":["Apple_Terminal"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"0#`\ufffda:f\ufffdg\ufffdh#i\ufffdjjkkllmmnno\ufffdp\ufffdq\ufffdrrssttuuvvwwxxy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd+\ufffd-\ufffd,\ufffd.\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"nsterm+7","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nsterm+acs","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"nsterm+mac","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"0#`\ufffda:f\ufffdg\ufffdh#i\ufffdjjkkllmmnno\ufffdp\ufffdq\ufffdrrssttuuvvwwxxy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd+\ufffd-\ufffd,\ufffd.\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"nsterm-16color","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"nsterm-7","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"nsterm-7-c","aliases":["nsterm-c-7"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"nsterm-acs","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"nsterm-c","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"0#`\ufffda:f\ufffdg\ufffdh#i\ufffdjjkkllmmnno\ufffdp\ufffdq\ufffdrrssttuuvvwwxxy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd+\ufffd-\ufffd,\ufffd.\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"nsterm-c-acs","aliases":["nsterm-acs-c"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"nsterm-c-s","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"0#`\ufffda:f\ufffdg\ufffdh#i\ufffdjjkkllmmnno\ufffdp\ufffdq\ufffdrrssttuuvvwwxxy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd+\ufffd-\ufffd,\ufffd.\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"nsterm-c-s-7","aliases":["nsterm-7-c-s"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"nsterm-c-s-acs","aliases":["nsterm-acs-c-s"],"cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"nsterm-m","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"0#`\ufffda:f\ufffdg\ufffdh#i\ufffdjjkkllmmnno\ufffdp\ufffdq\ufffdrrssttuuvvwwxxy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd+\ufffd-\ufffd,\ufffd.\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"nsterm-m-7","aliases":["nsterm-7-m"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nsterm-m-acs","aliases":["nsterm-acs-m"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"nsterm-m-s","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"0#`\ufffda:f\ufffdg\ufffdh#i\ufffdjjkkllmmnno\ufffdp\ufffdq\ufffdrrssttuuvvwwxxy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd+\ufffd-\ufffd,\ufffd.\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"nsterm-m-s-7","aliases":["nsterm-7-m-s"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nsterm-m-s-acs","aliases":["nsterm-acs-m-s"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"nsterm-s","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"0#`\ufffda:f\ufffdg\ufffdh#i\ufffdjjkkllmmnno\ufffdp\ufffdq\ufffdrrssttuuvvwwxxy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd+\ufffd-\ufffd,\ufffd.\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"nsterm-s-7","aliases":["nsterm-7-s"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"nsterm-s-acs","aliases":["nsterm-acs-s"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"nwp511","aliases":["nwp-511"],"cols":80,"lines":24,"clear":"\u001b[;H\u001b[2J$\u003c20/\u003e","smul":"\u001b[4m$\u003c2/\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cuu1":"\u001b[A$\u003c2/\u003e","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001b#W","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"nwp512","aliases":["news","news40","nwp514","vt100-bm"],"cols":80,"lines":40,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nwp512-a","aliases":["news-a","news40-a","news42","nwp514-a"],"cols":80,"lines":42,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nwp512-o","aliases":["news-o","news40-o","nwp514-o","vt100-bm-o"],"cols":80,"lines":40,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nwp513","aliases":["news31","newscbm","nwe501","nwp518"],"cols":80,"lines":31,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nwp513-a","aliases":["news31-a","news33","newscbm-a","newscbm33","nwe501-a","nwp251-a","nwp518-a"],"cols":80,"lines":33,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nwp513-o","aliases":["news31-o","newscbm-o","nwe501-o","nwp251-o","nwp518-o"],"cols":80,"lines":31,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"nwp517","aliases":["nwp-517"],"cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"nwp517-w","aliases":["nwp-517-w"],"cols":132,"lines":50,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"oblit","aliases":["ojerq"],"cols":88,"lines":72,"bell":"\u0007","clear":"\u000c","cup":"\u001bY%p2%' '%+%c%p1%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008"} +{"name":"oc100","aliases":["c100-1p","oconcept"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b?\u001b\u0005$\u003c2*\u003e","smcup":"\u001bU\u001bv 8p\u001bp\r\u001b\u0015$\u003c16\u003e","rmcup":"\u001bv $\u003c6\u003e\u001bp\r\n","sgr0":"\u001bN@","smul":"\u001bG","blink":"\u001bC","rev":"\u001bD","dim":"\u001bE","smkx":"\u001bX","rmkx":"\u001bx","cup":"\u001ba%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001b;","pad":"\u0000","kbs":"\u0008","kf1":"\u001b5","kf2":"\u001b6","kf3":"\u001b7","kf4":"\u001b8","kf5":"\u001b9","kf6":"\u001b:a","kf7":"\u001b:b","kf8":"\u001b:c","kich":"\u001b\u0010","kdch":"\u001b\u0011","khome":"\u001b?","kpp":"\u001b.","knp":"\u001b-","kcuu1":"\u001b;","kcud1":"\u001b\u003c","kcub1":"\u001b\u003e","kcuf1":"\u001b=","kcbt":"\u001b'"} +{"name":"ofcons","cols":80,"lines":30,"bell":"\u0007","clear":"\u000c","sgr0":"\ufffd0m","bold":"\ufffd1m","blink":"\ufffd7;2m","rev":"\ufffd7m","dim":"\ufffd2m","cup":"\ufffd%i%p1%d;%p2%dH","cub1":"\ufffdD","cuu1":"\ufffdA","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd0P","kf2":"\ufffd0Q","kf3":"\ufffd0W","kf4":"\ufffd0x","kf5":"\ufffd0t","kf6":"\ufffd0u","kf7":"\ufffd0q","kf8":"\ufffd0r","kf9":"\ufffd0p","kf10":"\ufffd0M","kdch":"\ufffdP","kpp":"\ufffd?","knp":"\ufffd/","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC"} +{"name":"oldsun","cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"opennt-100","aliases":["ntconsole-100"],"cols":80,"lines":100,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-100-nti","aliases":["ntconsole-100-nti"],"cols":80,"lines":100,"colors":8,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-35","aliases":["ntconsole-35"],"cols":80,"lines":35,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-35-nti","aliases":["ntconsole-35-nti"],"cols":80,"lines":35,"colors":8,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-35-w","aliases":["ntconsole-35-w"],"cols":125,"lines":35,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-50","aliases":["ntconsole-50"],"cols":80,"lines":50,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-50-nti","aliases":["ntconsole-50-nti"],"cols":80,"lines":50,"colors":8,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-50-w","aliases":["ntconsole-50-w"],"cols":125,"lines":50,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-60","aliases":["ntconsole-60"],"cols":80,"lines":60,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-60-nti","aliases":["ntconsole-60-nti"],"cols":80,"lines":60,"colors":8,"bell":"\u0007","clear":"\u001b[2J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-60-w","aliases":["ntconsole-60-w"],"cols":125,"lines":60,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-w","aliases":["ntconsole-25-w","ntconsole-w","opennt-25-w"],"cols":125,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opennt-w-vt","aliases":["ntconsole-25-w-vt","ntconsole-w-vt","opennt-25-w-vt"],"cols":132,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[s\u001b[1b","rmcup":"\u001b[2b\u001b[u\r\u001b[K","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bF1","kf2":"\u001bF2","kf3":"\u001bF3","kf4":"\u001bF4","kf5":"\u001bF5","kf6":"\u001bF6","kf7":"\u001bF7","kf8":"\u001bF8","kf9":"\u001bF9","kf10":"\u001bFA","kf11":"\u001bFB","kf12":"\u001bFC","kf13":"\u001bFD","kf14":"\u001bFE","kf15":"\u001bFF","kf16":"\u001bFG","kf17":"\u001bFH","kf18":"\u001bFI","kf19":"\u001bFJ","kf20":"\u001bFK","kf21":"\u001bFL","kf22":"\u001bFM","kf23":"\u001bFN","kf24":"\u001bFO","kf25":"\u001bFP","kf26":"\u001bFQ","kf27":"\u001bFR","kf28":"\u001bFS","kf29":"\u001bFT","kf30":"\u001bFU","kf31":"\u001bFV","kf32":"\u001bFW","kf33":"\u001bFX","kf34":"\u001bFY","kf35":"\u001bFZ","kf36":"\u001bFa","kf37":"\u001bFb","kf38":"\u001bFc","kf39":"\u001bFd","kf40":"\u001bFe","kf41":"\u001bFf","kf42":"\u001bFg","kf43":"\u001bFh","kf44":"\u001bFi","kf45":"\u001bFj","kf46":"\u001bFk","kf47":"\u001bFm","kf48":"\u001bFn","kf49":"\u001bFo","kf50":"\u001bFp","kf51":"\u001bFq","kf52":"\u001bFr","kf53":"\u001bFs","kf54":"\u001bFt","kf55":"\u001bFu","kf56":"\u001bFv","kf57":"\u001bFw","kf58":"\u001bFx","kf59":"\u001bFy","kf60":"\u001bFz","kf61":"\u001bF+","kf62":"\u001bF-","kf63":"\u001bF\u000c kf64=\u001bF$","kich":"\u001b[L","kdch":"\u001b[M","kend":"\u001b[U","kpp":"\u001b[S","knp":"\u001b[T","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~q\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd.\u0019-\u0018,\u0011+\u00100\ufffdp\ufffdr\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"opus3n1+","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c100\u003e","smcup":"\u001bzz\u0026\u001b[A\u001bzz'\u001b[B\u001bzz(\u001b[D\u001bzz)\u001b[C\u001bzz\u003c\u001b[Q","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kend":"\u001b[F","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kHOM":"\u001b{"} +{"name":"origpc3","aliases":["origibmpc3"],"cols":80,"lines":25,"clear":"\u001bc","sgr0":"\u001b[m\u001b[1;0x\u001b[2;7x","smul":"\u001b[1;7x\u001b[2;0x","bold":"\u001b[7m","cup":"\u001b[%i%p1%2d;%p2%2dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","khome":"\u001b[Y","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"j\ufffdk\ufffdl\ufffdm\ufffdn\ufffdq\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd"} +{"name":"osborne","aliases":["osborne1"],"cols":80,"lines":24,"clear":"\u001a","smul":"\u001bl","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008$\u003c4\u003e","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"osborne-w","aliases":["osborne1-w"],"cols":104,"lines":24,"bell":"\u0007","clear":"\u001a","smul":"\u001bl","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"osexec","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","smul":"\u001bl","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001A\r","kf2":"\u0001B\r","kf3":"\u0001C\r","kf4":"\u0001D\r","kf5":"\u0001E\r","kf6":"\u0001F\r","kf7":"\u0001G\r","kf8":"\u0001H\r","kf9":"\u0001I\r","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"otek4115","cols":80,"lines":34,"clear":"\u001b[H\u001b[2J","smcup":"\u001b%!0\u001bLBB2\u001b%!1","rmcup":"\u001b%!0\u001bLBG8\u001b%!1\u001b[34;1H\u001b[J","cnorm":"\u001b%!0\u001bLBG8\u001b%!1\u001b[34;1H","sgr0":"\u001b[m","smul":"\u001b[4m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008"} +{"name":"owl","aliases":["pe1200"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ$\u003c132\u003e","sgr0":"\u001b!\ufffd","cup":"\u001bX%p1%' '%+%c\u001bY%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bRA","kf2":"\u001bRB","kf3":"\u001bRC","kf4":"\u001bRD","kf5":"\u001bRE","kf6":"\u001bRF","kf7":"\u001bRG","kf8":"\u001bRH","kf9":"\u001bRI"} +{"name":"p19","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE","cnorm":"\u001by4","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"p8gl","aliases":["prism8gl"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u0003 ","smul":"\u00030","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0015","cuu1":"\u001a","pad":"\ufffd","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf12":"\u0001J\r","kf13":"\u0001K\r","kf14":"\u0001L\r","kf15":"\u0001M\r","kf16":"\u0001N\r","kf17":"\u0001O\r","kdch":" \u0008","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"pc-coherent","aliases":["coherent","pcz19"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001bE","sgr0":"\u001bq","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"pc-minix","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[0J","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[V","kf2":"\u001b[U","kf3":"\u001b[T","kf4":"\u001b[S","kf5":"\u001b[G","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"pc-venix","aliases":["venix"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bG","kcuu1":"\u001bH","kcud1":"\u001bP","kcub1":"\u001bK","kcuf1":"\u001bM"} +{"name":"pc3","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001bc","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kich":"\u001b[L","khome":"\u001b[H","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"pc6300plus","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[=1C","civis":"\u001b[=C","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%2d;%p2%2dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOc","kf2":"\u001bOd","kf3":"\u001bOe","kf4":"\u001bOf","kf5":"\u001bOg","kf6":"\u001bOh","kf7":"\u001bOi","kf8":"\u001bOj","kf9":"\u001bOk","kf10":"\u001bOu","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"pcansi","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"pcansi-25","aliases":["pcansi25"],"cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"pcansi-25-m","aliases":["pcansi25m"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m"} +{"name":"pcansi-33","aliases":["pcansi33"],"cols":80,"lines":33,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"pcansi-33-m","aliases":["pcansi33m"],"cols":80,"lines":33,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m"} +{"name":"pcansi-43","aliases":["pcansi43"],"cols":80,"lines":43,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"pcansi-43-m","aliases":["ansi43m"],"cols":80,"lines":43,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m"} +{"name":"pcansi-m","aliases":["pcansi-mono"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m"} +{"name":"pccons","aliases":["pcconsole"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"pcix","cols":80,"lines":24,"clear":"\u001bc","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%2d;%p2%2dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000"} +{"name":"pckermit","aliases":["pckermit12"],"cols":80,"lines":25,"clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"pckermit120","cols":80,"lines":24,"clear":"\u001bE","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"pcmw","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[;H\u001b[2J$\u003c50/\u003e","sgr0":"\u001b[m$\u003c2/\u003e","smul":"\u001b[4m$\u003c2/\u003e","bold":"\u001b[1m$\u003c2/\u003e","blink":"\u001b[5m$\u003c2/\u003e","rev":"\u001b[7m$\u003c2/\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5/\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2/\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"pcplot","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"pcvt25","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt25-color","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[17~","kf6":"\u001b[18~","kf7":"\u001b[19~","kf8":"\u001b[20~","kf9":"\u001b[21~","kf10":"\u001b[29~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"pcvt25w","cols":132,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt28","cols":80,"lines":28,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt28w","cols":132,"lines":28,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt35","cols":80,"lines":35,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt35w","cols":132,"lines":35,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt40","cols":80,"lines":40,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt40w","cols":132,"lines":40,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt43","cols":80,"lines":43,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt43w","cols":132,"lines":43,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt50","cols":80,"lines":50,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvt50w","cols":132,"lines":50,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pcvtXX","cols":-1,"lines":-1,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"pe1251","aliases":["pe6300","pe6312"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK$\u003c332\u003e","cup":"\u001bX%p1%' '%+%c\u001bY%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001bRB","kf2":"\u001bRC","kf3":"\u001bRD","kf4":"\u001bRE","kf5":"\u001bRF","kf6":"\u001bRG","kf7":"\u001bRH","kf8":"\u001bRI","kf9":"\u001bRJ","kf10":"\u001bRK"} +{"name":"pe7000c","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","smul":"\u001b! ","cup":"\u001bS%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b!\u0001","kf2":"\u001b!\u0002","kf3":"\u001b!\u0003","kf4":"\u001b!\u0004","kf5":"\u001b!\u0005","kf6":"\u001b!\u0006","kf7":"\u001b!\u0007","kf8":"\u001b!\u0008","kf9":"\u001b!\t","kf10":"\u001b!\n","khome":"\u001b!S","kcuu1":"\u001b!T","kcud1":"\u001b!U","kcub1":"\u001b!V","kcuf1":"\u001b!W"} +{"name":"pe7000m","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bK","cup":"\u001bS%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b!\u0001","kf2":"\u001b!\u0002","kf3":"\u001b!\u0003","kf4":"\u001b!\u0004","kf5":"\u001b!\u0005","kf6":"\u001b!\u0006","kf7":"\u001b!\u0007","kf8":"\u001b!\u0008","kf9":"\u001b!\t","kf10":"\u001b!\n","khome":"\u001b!S","kcuu1":"\u001b!T","kcud1":"\u001b!U","kcub1":"\u001b!V","kcuf1":"\u001b!W"} +{"name":"pilot","aliases":["tgtelnet"],"cols":39,"lines":16,"bell":"\u0007","clear":"\u001bc","cup":"\u001bm%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","pad":"\u0000","kbs":"\u0008","kpp":"\u000b","knp":"\u000c","kcud1":"\n","kcub1":"\u0008"} +{"name":"prism12","aliases":["P12","p12"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[\u003c4h","civis":"\u001b[\u003c4l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u000c"} +{"name":"prism12-m","aliases":["P12-M","p12-m"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism12-m-w","aliases":["P12-M-W","p12-m-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism12-w","aliases":["P12-W","p12-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[\u003c4h","civis":"\u001b[\u003c4l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u000c"} +{"name":"prism14","aliases":["P14","p14"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[\u003c4h","civis":"\u001b[\u003c4l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u000c"} +{"name":"prism14-m","aliases":["P14-M","p14-m"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism14-m-w","aliases":["P14-M-W","p14-m-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism14-w","aliases":["P14-W","p14-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[\u003c4h","civis":"\u001b[\u003c4l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u000c"} +{"name":"prism2","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cup":"\u000b%p1%' '%+%c\u0010%p2%{10}%/%{16}%*%p2%{10}%m%+%Pc%?%{17}%gc%=%{19}%gc%=%|%gc%!%|%t%{1}%gc%+%c%{8}%e%gc%;%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism4","aliases":["P4","p4"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u000b%p1%' '%+%c\u0010%p2%{10}%/%{16}%*%p2%{10}%m%+%Pc%?%{17}%gc%=%{19}%gc%=%|%gc%!%|%t%{1}%gc%+%c%{8}%e%gc%;%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism5","aliases":["P5","p5"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u000b%p1%' '%+%c\u0010%p2%{10}%/%{16}%*%p2%{10}%m%+%Pc%?%{17}%gc%=%{19}%gc%=%|%gc%!%|%t%{1}%gc%+%c%{8}%e%gc%;%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism7","aliases":["P7","p7"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism8","aliases":["P8","p8"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism8-w","aliases":["P8-W","p8-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism9","aliases":["P9","p9"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[\u003c4h","civis":"\u001b[\u003c4l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u000c"} +{"name":"prism9-8","aliases":["P9-8","p9-8"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism9-8-w","aliases":["P9-8-W","p9-8-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c20\u003e","cnorm":"\u001d\ufffd","civis":"\u001d\ufffd","sgr0":"\u0003 ","smul":"\u0003P","blink":"\u0003B","rev":"\u0003D","dim":"\u0003A","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001"} +{"name":"prism9-w","aliases":["P9-W","p9-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[\u003c4h","civis":"\u001b[\u003c4l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u000c"} +{"name":"pro350","aliases":["decpro"],"cols":80,"lines":24,"clear":"\u001bH\u001bJ","smul":"\u001b\u0004","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001bF","kf2":"\u001bG","kf3":"\u001bH","kf4":"\u001bI","kf5":"\u001bJ","kf6":"\u001bi","kf7":"\u001bj","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"ps300","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"psterm","aliases":["psterm-basic"],"cols":80,"lines":34,"clear":"\u000c","smcup":"\u001bOt","rmcup":"\u001bNt","sgr0":"\u001bN*","smul":"\u001bOu","bold":"\u001bOd","blink":"\u001bOb","rev":"\u001bOr","cup":"\u001b%p1%d;%p2%d;","cub1":"\u001bT","cuu1":"\u001bY","pad":"\u0000","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"psterm-80x24","cols":80,"lines":24,"clear":"\u000c","smcup":"\u001bOt","rmcup":"\u001bNt","sgr0":"\u001bN*","smul":"\u001bOu","bold":"\u001bOd","blink":"\u001bOb","rev":"\u001bOr","cup":"\u001b%p1%d;%p2%d;","cub1":"\u001bT","cuu1":"\u001bY","pad":"\u0000","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"psterm-90x28","cols":90,"lines":28,"clear":"\u000c","smcup":"\u001bOt","rmcup":"\u001bNt","sgr0":"\u001bN*","smul":"\u001bOu","bold":"\u001bOd","blink":"\u001bOb","rev":"\u001bOr","cup":"\u001b%p1%d;%p2%d;","cub1":"\u001bT","cuu1":"\u001bY","pad":"\u0000","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"psterm-96x48","cols":96,"lines":48,"clear":"\u000c","smcup":"\u001bOt","rmcup":"\u001bNt","sgr0":"\u001bN*","smul":"\u001bOu","bold":"\u001bOd","blink":"\u001bOb","rev":"\u001bOr","cup":"\u001b%p1%d;%p2%d;","cub1":"\u001bT","cuu1":"\u001bY","pad":"\u0000","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"psterm-fast","cols":80,"lines":34,"clear":"\u000c","smcup":"\u000ft","rmcup":"\u000et","sgr0":"\u000e*","smul":"\u000fu","bold":"\u000fd","blink":"\u000fb","rev":"\u000fr","cup":"\u0004%p1%d;%p2%d;","cub1":"\u0014","cuu1":"\u0019","pad":"\u0000","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"pt100","aliases":["fenix","pt200","wren"],"cols":80,"lines":24,"clear":"\u001b?","smcup":"\u001b[\u003e1l\u001b[\u003e2l\u001b[\u003e16l\u001b[4l\u001b[\u003e9l\u001b[20l\u001b[\u003e3l\u001b[\u003e7h\u001b[\u003e12l\u001b[1Q","sgr0":"\u001b[m","smul":"\u001b[4m","dim":"\u001b[2m","smkx":"\u001b[\u003e13h","rmkx":"\u001b[\u003e13l","cup":"\u001b0%p1%'!'%+%c%p2%'!'%+%c","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","khome":"\u001b$A","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"pt100w","aliases":["fenixw","pt200w","wrenw"],"cols":132,"lines":24,"clear":"\u001b?","smcup":"\u001b[\u003e1l\u001b[\u003e2l\u001b[\u003e16l\u001b[4l\u001b[\u003e9l\u001b[20l\u001b[\u003e3l\u001b[\u003e7h\u001b[\u003e12l\u001b[1Q","sgr0":"\u001b[m","smul":"\u001b[4m","dim":"\u001b[2m","smkx":"\u001b[\u003e13h","rmkx":"\u001b[\u003e13l","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","khome":"\u001b$A","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"pt250","cols":80,"lines":24,"clear":"\u001b?","smcup":"\u001b[\u003e1l\u001b[\u003e2l\u001b[\u003e16l\u001b[4l\u001b[\u003e9l\u001b[20l\u001b[\u003e3l\u001b[\u003e7h\u001b[\u003e12l\u001b[1Q","sgr0":"\u001b[m","smul":"\u001b[4m","dim":"\u001b[2m","smkx":"\u001b[\u003e13h","rmkx":"\u001b[\u003e13l","cup":"\u001b0%p1%'!'%+%c%p2%'!'%+%c","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","khome":"\u001b$A","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"pt250w","cols":132,"lines":24,"clear":"\u001b?","smcup":"\u001b[\u003e1l\u001b[\u003e2l\u001b[\u003e16l\u001b[4l\u001b[\u003e9l\u001b[20l\u001b[\u003e3l\u001b[\u003e7h\u001b[\u003e12l\u001b[1Q","sgr0":"\u001b[m","smul":"\u001b[4m","dim":"\u001b[2m","smkx":"\u001b[\u003e13h","rmkx":"\u001b[\u003e13l","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","khome":"\u001b$A","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"pty","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bL","smul":"\u001ba!","cup":"\u001bG%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"putty","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kcan":"\u0003","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"putty-256color","cols":-1,"lines":-1,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kcan":"\u0003","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m"} +{"name":"putty-vt100","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bO[","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kcan":"\u0003","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"qansi","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","kf13":"\u001bOp","kf14":"\u001bOq","kf15":"\u001bOr","kf16":"\u001bOs","kf17":"\u001bOt","kf18":"\u001bOu","kf19":"\u001bOv","kf20":"\u001bOw","kf21":"\u001bOx","kf22":"\u001bOy","kf23":"\u001bOz","kf24":"\u001bOa","kf25":"\u001b[1~","kf26":"\u001b[2~","kf27":"\u001b[3~","kf28":"\u001b[4~","kf29":"\u001b[5~","kf30":"\u001b[6~","kf31":"\u001b[7~","kf32":"\u001b[8~","kf33":"\u001b[9~","kf34":"\u001b[10~","kf35":"\u001b[11~","kf36":"\u001b[12~","kf37":"\u001b[17~","kf38":"\u001b[18~","kf39":"\u001b[19~","kf40":"\u001b[20~","kf41":"\u001b[21~","kf42":"\u001b[22~","kf43":"\u001b[23~","kf44":"\u001b[24~","kf45":"\u001b[25~","kf46":"\u001b[26~","kf47":"\u001b[27~","kf48":"\u001b[28~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[Y","khlp":"\u001bNh","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001b[y","kclr":"\u001bNa","kcan":"\u001b[S","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~Oa","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[h","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od"} +{"name":"qansi-g","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","kf13":"\u001bOp","kf14":"\u001bOq","kf15":"\u001bOr","kf16":"\u001bOs","kf17":"\u001bOt","kf18":"\u001bOu","kf19":"\u001bOv","kf20":"\u001bOw","kf21":"\u001bOx","kf22":"\u001bOy","kf23":"\u001bOz","kf24":"\u001bOa","kf25":"\u001b[1~","kf26":"\u001b[2~","kf27":"\u001b[3~","kf28":"\u001b[4~","kf29":"\u001b[5~","kf30":"\u001b[6~","kf31":"\u001b[7~","kf32":"\u001b[8~","kf33":"\u001b[9~","kf34":"\u001b[10~","kf35":"\u001b[11~","kf36":"\u001b[12~","kf37":"\u001b[17~","kf38":"\u001b[18~","kf39":"\u001b[19~","kf40":"\u001b[20~","kf41":"\u001b[21~","kf42":"\u001b[22~","kf43":"\u001b[23~","kf44":"\u001b[24~","kf45":"\u001b[25~","kf46":"\u001b[26~","kf47":"\u001b[27~","kf48":"\u001b[28~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[Y","khlp":"\u001bNh","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001b[y","kclr":"\u001bNa","kcan":"\u001b[S","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~Oa","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[h","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od"} +{"name":"qansi-m","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","kf13":"\u001bOp","kf14":"\u001bOq","kf15":"\u001bOr","kf16":"\u001bOs","kf17":"\u001bOt","kf18":"\u001bOu","kf19":"\u001bOv","kf20":"\u001bOw","kf21":"\u001bOx","kf22":"\u001bOy","kf23":"\u001bOz","kf24":"\u001bOa","kf25":"\u001b[1~","kf26":"\u001b[2~","kf27":"\u001b[3~","kf28":"\u001b[4~","kf29":"\u001b[5~","kf30":"\u001b[6~","kf31":"\u001b[7~","kf32":"\u001b[8~","kf33":"\u001b[9~","kf34":"\u001b[10~","kf35":"\u001b[11~","kf36":"\u001b[12~","kf37":"\u001b[17~","kf38":"\u001b[18~","kf39":"\u001b[19~","kf40":"\u001b[20~","kf41":"\u001b[21~","kf42":"\u001b[22~","kf43":"\u001b[23~","kf44":"\u001b[24~","kf45":"\u001b[25~","kf46":"\u001b[26~","kf47":"\u001b[27~","kf48":"\u001b[28~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[Y","khlp":"\u001bNh","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001b[y","kclr":"\u001bNa","kcan":"\u001b[S","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~Oa","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[h","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od"} +{"name":"qansi-t","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","kf13":"\u001bOp","kf14":"\u001bOq","kf15":"\u001bOr","kf16":"\u001bOs","kf17":"\u001bOt","kf18":"\u001bOu","kf19":"\u001bOv","kf20":"\u001bOw","kf21":"\u001bOx","kf22":"\u001bOy","kf23":"\u001bOz","kf24":"\u001bOa","kf25":"\u001b[1~","kf26":"\u001b[2~","kf27":"\u001b[3~","kf28":"\u001b[4~","kf29":"\u001b[5~","kf30":"\u001b[6~","kf31":"\u001b[7~","kf32":"\u001b[8~","kf33":"\u001b[9~","kf34":"\u001b[10~","kf35":"\u001b[11~","kf36":"\u001b[12~","kf37":"\u001b[17~","kf38":"\u001b[18~","kf39":"\u001b[19~","kf40":"\u001b[20~","kf41":"\u001b[21~","kf42":"\u001b[22~","kf43":"\u001b[23~","kf44":"\u001b[24~","kf45":"\u001b[25~","kf46":"\u001b[26~","kf47":"\u001b[27~","kf48":"\u001b[28~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[Y","khlp":"\u001bNh","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001b[y","kclr":"\u001bNa","kcan":"\u001b[S","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~Oa","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[h","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od"} +{"name":"qansi-w","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h\u001b[?12l","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","kf13":"\u001bOp","kf14":"\u001bOq","kf15":"\u001bOr","kf16":"\u001bOs","kf17":"\u001bOt","kf18":"\u001bOu","kf19":"\u001bOv","kf20":"\u001bOw","kf21":"\u001bOx","kf22":"\u001bOy","kf23":"\u001bOz","kf24":"\u001bOa","kf25":"\u001b[1~","kf26":"\u001b[2~","kf27":"\u001b[3~","kf28":"\u001b[4~","kf29":"\u001b[5~","kf30":"\u001b[6~","kf31":"\u001b[7~","kf32":"\u001b[8~","kf33":"\u001b[9~","kf34":"\u001b[10~","kf35":"\u001b[11~","kf36":"\u001b[12~","kf37":"\u001b[17~","kf38":"\u001b[18~","kf39":"\u001b[19~","kf40":"\u001b[20~","kf41":"\u001b[21~","kf42":"\u001b[22~","kf43":"\u001b[23~","kf44":"\u001b[24~","kf45":"\u001b[25~","kf46":"\u001b[26~","kf47":"\u001b[27~","kf48":"\u001b[28~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b[Y","khlp":"\u001bNh","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kext":"\u001b[y","kclr":"\u001bNa","kcan":"\u001b[S","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~Oa","smacs":"\u000e","rmacs":"\u000f","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[h","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od"} +{"name":"qdss","aliases":["qdcons"],"cols":128,"lines":57,"clear":"\u001a$\u003c1/\u003e","cup":"\u001b=%p1%c%p2%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"qnx","aliases":["qnx4"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001bi","rmcup":"\u001bh\u001bR","cnorm":"\u001by1","civis":"\u001by0","sgr0":"\u001b}\u001b]\u001b\u003e\u001b)","smul":"\u001b[","bold":"\u001b\u003c","blink":"\u001b{","rev":"\u001b(","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\ufffd\ufffd","kf2":"\ufffd\ufffd","kf3":"\ufffd\ufffd","kf4":"\ufffd\ufffd","kf5":"\ufffd\ufffd","kf6":"\ufffd\ufffd","kf7":"\ufffd\ufffd","kf8":"\ufffd\ufffd","kf9":"\ufffd\ufffd","kf10":"\ufffd\ufffd","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffd\ufffd","kf14":"\ufffd\ufffd","kf15":"\ufffd\ufffd","kf16":"\ufffd\ufffd","kf17":"\ufffd\ufffd","kf18":"\ufffd\ufffd","kf19":"\ufffd\ufffd","kf20":"\ufffd\ufffd","kf21":"\ufffd\ufffd","kf22":"\ufffd\ufffd","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd\ufffd","kf26":"\ufffd\ufffd","kf27":"\ufffd\ufffd","kf28":"\ufffd\ufffd","kf29":"\ufffd\ufffd","kf30":"\ufffd\ufffd","kf31":"\ufffd\ufffd","kf32":"\ufffd\ufffd","kf33":"\ufffd\ufffd","kf34":"\ufffd\ufffd","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffd\ufffd","kf38":"\ufffd\ufffd","kf39":"\ufffd\ufffd","kf40":"\ufffd\ufffd","kf41":"\ufffd\ufffd","kf42":"\ufffd\ufffd","kf43":"\ufffd\ufffd","kf44":"\ufffd\ufffd","kf45":"\ufffd\ufffd","kf46":"\ufffd\ufffd","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffd\ufffd","kdch":"\ufffd\ufffd","khome":"\ufffd\ufffd","kend":"\ufffd\ufffd","khlp":"\ufffd\ufffd","kpp":"\ufffd\ufffd","knp":"\ufffd\ufffd","kcuu1":"\ufffd\ufffd","kcud1":"\ufffd\ufffd","kcub1":"\ufffd\ufffd","kcuf1":"\ufffd\ufffd","kcbt":"\ufffd\ufffd","kext":"\ufffd\ufffd","kclr":"\ufffd\ufffd","kprt":"\ufffd\ufffd","kcan":"\ufffd\ufffd","acsc":"O\ufffda\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdq\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","kRIT":"\ufffd\ufffd","kLFT":"\ufffd\ufffd","kHOM":"\ufffd\ufffd","kEND":"\ufffd\ufffd"} +{"name":"qnxm","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001bi","rmcup":"\u001bh\u001bR","cnorm":"\u001by1","civis":"\u001by0","sgr0":"\u001b}\u001b]\u001b\u003e\u001b)","smul":"\u001b[","bold":"\u001b\u003c","blink":"\u001b{","rev":"\u001b(","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\ufffd\ufffd","kf2":"\ufffd\ufffd","kf3":"\ufffd\ufffd","kf4":"\ufffd\ufffd","kf5":"\ufffd\ufffd","kf6":"\ufffd\ufffd","kf7":"\ufffd\ufffd","kf8":"\ufffd\ufffd","kf9":"\ufffd\ufffd","kf10":"\ufffd\ufffd","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffd\ufffd","kf14":"\ufffd\ufffd","kf15":"\ufffd\ufffd","kf16":"\ufffd\ufffd","kf17":"\ufffd\ufffd","kf18":"\ufffd\ufffd","kf19":"\ufffd\ufffd","kf20":"\ufffd\ufffd","kf21":"\ufffd\ufffd","kf22":"\ufffd\ufffd","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd\ufffd","kf26":"\ufffd\ufffd","kf27":"\ufffd\ufffd","kf28":"\ufffd\ufffd","kf29":"\ufffd\ufffd","kf30":"\ufffd\ufffd","kf31":"\ufffd\ufffd","kf32":"\ufffd\ufffd","kf33":"\ufffd\ufffd","kf34":"\ufffd\ufffd","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffd\ufffd","kf38":"\ufffd\ufffd","kf39":"\ufffd\ufffd","kf40":"\ufffd\ufffd","kf41":"\ufffd\ufffd","kf42":"\ufffd\ufffd","kf43":"\ufffd\ufffd","kf44":"\ufffd\ufffd","kf45":"\ufffd\ufffd","kf46":"\ufffd\ufffd","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffd\ufffd","kdch":"\ufffd\ufffd","khome":"\ufffd\ufffd","kend":"\ufffd\ufffd","khlp":"\ufffd\ufffd","kpp":"\ufffd\ufffd","knp":"\ufffd\ufffd","kcuu1":"\ufffd\ufffd","kcud1":"\ufffd\ufffd","kcub1":"\ufffd\ufffd","kcuf1":"\ufffd\ufffd","kcbt":"\ufffd\ufffd","kext":"\ufffd\ufffd","kclr":"\ufffd\ufffd","kprt":"\ufffd\ufffd","kcan":"\ufffd\ufffd","acsc":"O\ufffda\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdq\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","kRIT":"\ufffd\ufffd","kLFT":"\ufffd\ufffd","kHOM":"\ufffd\ufffd","kEND":"\ufffd\ufffd"} +{"name":"qnxt","aliases":["qnxt4"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001bi","rmcup":"\u001bh\u001bR","cnorm":"\u001by1","civis":"\u001by0","sgr0":"\u001b}\u001b]\u001b\u003e\u001b)","smul":"\u001b[","bold":"\u001b\u003c","blink":"\u001b{","rev":"\u001b(","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\ufffd\ufffd","kf2":"\ufffd\ufffd","kf3":"\ufffd\ufffd","kf4":"\ufffd\ufffd","kf5":"\ufffd\ufffd","kf6":"\ufffd\ufffd","kf7":"\ufffd\ufffd","kf8":"\ufffd\ufffd","kf9":"\ufffd\ufffd","kf10":"\ufffd\ufffd","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffd\ufffd","kf14":"\ufffd\ufffd","kf15":"\ufffd\ufffd","kf16":"\ufffd\ufffd","kf17":"\ufffd\ufffd","kf18":"\ufffd\ufffd","kf19":"\ufffd\ufffd","kf20":"\ufffd\ufffd","kf21":"\ufffd\ufffd","kf22":"\ufffd\ufffd","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd\ufffd","kf26":"\ufffd\ufffd","kf27":"\ufffd\ufffd","kf28":"\ufffd\ufffd","kf29":"\ufffd\ufffd","kf30":"\ufffd\ufffd","kf31":"\ufffd\ufffd","kf32":"\ufffd\ufffd","kf33":"\ufffd\ufffd","kf34":"\ufffd\ufffd","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffd\ufffd","kf38":"\ufffd\ufffd","kf39":"\ufffd\ufffd","kf40":"\ufffd\ufffd","kf41":"\ufffd\ufffd","kf42":"\ufffd\ufffd","kf43":"\ufffd\ufffd","kf44":"\ufffd\ufffd","kf45":"\ufffd\ufffd","kf46":"\ufffd\ufffd","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffd\ufffd","kdch":"\ufffd\ufffd","khome":"\ufffd\ufffd","kend":"\ufffd\ufffd","khlp":"\ufffd\ufffd","kpp":"\ufffd\ufffd","knp":"\ufffd\ufffd","kcuu1":"\ufffd\ufffd","kcud1":"\ufffd\ufffd","kcub1":"\ufffd\ufffd","kcuf1":"\ufffd\ufffd","kcbt":"\ufffd\ufffd","kext":"\ufffd\ufffd","kclr":"\ufffd\ufffd","kprt":"\ufffd\ufffd","kcan":"\ufffd\ufffd","acsc":"O\ufffda\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdq\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","kRIT":"\ufffd\ufffd","kLFT":"\ufffd\ufffd","kHOM":"\ufffd\ufffd","kEND":"\ufffd\ufffd"} +{"name":"qnxt2","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","sgr0":"\u001b}\u001b]\u001b\u003e\u001b)","smul":"\u001b[","bold":"\u001b\u003c","blink":"\u001b{","rev":"\u001b(","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\ufffd\ufffd","kf2":"\ufffd\ufffd","kf3":"\ufffd\ufffd","kf4":"\ufffd\ufffd","kf5":"\ufffd\ufffd","kf6":"\ufffd\ufffd","kf7":"\ufffd\ufffd","kf8":"\ufffd\ufffd","kf9":"\ufffd\ufffd","kf10":"\ufffd\ufffd","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffd\ufffd","kf14":"\ufffd\ufffd","kf15":"\ufffd\ufffd","kf16":"\ufffd\ufffd","kf17":"\ufffd\ufffd","kf18":"\ufffd\ufffd","kf19":"\ufffd\ufffd","kf20":"\ufffd\ufffd","kf21":"\ufffd\ufffd","kf22":"\ufffd\ufffd","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd\ufffd","kf26":"\ufffd\ufffd","kf27":"\ufffd\ufffd","kf28":"\ufffd\ufffd","kf29":"\ufffd\ufffd","kf30":"\ufffd\ufffd","kf31":"\ufffd\ufffd","kf32":"\ufffd\ufffd","kf33":"\ufffd\ufffd","kf34":"\ufffd\ufffd","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffd\ufffd","kf38":"\ufffd\ufffd","kf39":"\ufffd\ufffd","kf40":"\ufffd\ufffd","kf41":"\ufffd\ufffd","kf42":"\ufffd\ufffd","kf43":"\ufffd\ufffd","kf44":"\ufffd\ufffd","kf45":"\ufffd\ufffd","kf46":"\ufffd\ufffd","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffd\ufffd","kdch":"\ufffd\ufffd","khome":"\ufffd\ufffd","kend":"\ufffd\ufffd","khlp":"\ufffd\ufffd","kpp":"\ufffd\ufffd","knp":"\ufffd\ufffd","kcuu1":"\ufffd\ufffd","kcud1":"\ufffd\ufffd","kcub1":"\ufffd\ufffd","kcuf1":"\ufffd\ufffd","kcbt":"\ufffd\ufffd","kext":"\ufffd\ufffd","kclr":"\ufffd\ufffd","kprt":"\ufffd\ufffd","kcan":"\ufffd\ufffd","acsc":"O\ufffda\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdq\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","kRIT":"\ufffd\ufffd","kLFT":"\ufffd\ufffd","kHOM":"\ufffd\ufffd","kEND":"\ufffd\ufffd"} +{"name":"qnxtmono","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001bi","rmcup":"\u001bh\u001bR","cnorm":"\u001by1","civis":"\u001by0","sgr0":"\u001b}\u001b]\u001b\u003e\u001b)","smul":"\u001b[","bold":"\u001b\u003c","blink":"\u001b{","rev":"\u001b(","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\ufffd\ufffd","kf2":"\ufffd\ufffd","kf3":"\ufffd\ufffd","kf4":"\ufffd\ufffd","kf5":"\ufffd\ufffd","kf6":"\ufffd\ufffd","kf7":"\ufffd\ufffd","kf8":"\ufffd\ufffd","kf9":"\ufffd\ufffd","kf10":"\ufffd\ufffd","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffd\ufffd","kf14":"\ufffd\ufffd","kf15":"\ufffd\ufffd","kf16":"\ufffd\ufffd","kf17":"\ufffd\ufffd","kf18":"\ufffd\ufffd","kf19":"\ufffd\ufffd","kf20":"\ufffd\ufffd","kf21":"\ufffd\ufffd","kf22":"\ufffd\ufffd","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd\ufffd","kf26":"\ufffd\ufffd","kf27":"\ufffd\ufffd","kf28":"\ufffd\ufffd","kf29":"\ufffd\ufffd","kf30":"\ufffd\ufffd","kf31":"\ufffd\ufffd","kf32":"\ufffd\ufffd","kf33":"\ufffd\ufffd","kf34":"\ufffd\ufffd","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffd\ufffd","kf38":"\ufffd\ufffd","kf39":"\ufffd\ufffd","kf40":"\ufffd\ufffd","kf41":"\ufffd\ufffd","kf42":"\ufffd\ufffd","kf43":"\ufffd\ufffd","kf44":"\ufffd\ufffd","kf45":"\ufffd\ufffd","kf46":"\ufffd\ufffd","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffd\ufffd","kdch":"\ufffd\ufffd","khome":"\ufffd\ufffd","kend":"\ufffd\ufffd","khlp":"\ufffd\ufffd","kpp":"\ufffd\ufffd","knp":"\ufffd\ufffd","kcuu1":"\ufffd\ufffd","kcud1":"\ufffd\ufffd","kcub1":"\ufffd\ufffd","kcuf1":"\ufffd\ufffd","kcbt":"\ufffd\ufffd","kext":"\ufffd\ufffd","kclr":"\ufffd\ufffd","kprt":"\ufffd\ufffd","kcan":"\ufffd\ufffd","acsc":"O\ufffda\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdq\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","kRIT":"\ufffd\ufffd","kLFT":"\ufffd\ufffd","kHOM":"\ufffd\ufffd","kEND":"\ufffd\ufffd"} +{"name":"qnxw","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001bi","rmcup":"\u001bh\u001bR","cnorm":"\u001by1","civis":"\u001by0","sgr0":"\u001b}\u001b]\u001b\u003e\u001b)","smul":"\u001b[","bold":"\u001b\u003c","blink":"\u001b{","rev":"\u001b(","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\ufffd\ufffd","kf2":"\ufffd\ufffd","kf3":"\ufffd\ufffd","kf4":"\ufffd\ufffd","kf5":"\ufffd\ufffd","kf6":"\ufffd\ufffd","kf7":"\ufffd\ufffd","kf8":"\ufffd\ufffd","kf9":"\ufffd\ufffd","kf10":"\ufffd\ufffd","kf11":"\ufffd\ufffd","kf12":"\ufffd\ufffd","kf13":"\ufffd\ufffd","kf14":"\ufffd\ufffd","kf15":"\ufffd\ufffd","kf16":"\ufffd\ufffd","kf17":"\ufffd\ufffd","kf18":"\ufffd\ufffd","kf19":"\ufffd\ufffd","kf20":"\ufffd\ufffd","kf21":"\ufffd\ufffd","kf22":"\ufffd\ufffd","kf23":"\ufffd\ufffd","kf24":"\ufffd\ufffd","kf25":"\ufffd\ufffd","kf26":"\ufffd\ufffd","kf27":"\ufffd\ufffd","kf28":"\ufffd\ufffd","kf29":"\ufffd\ufffd","kf30":"\ufffd\ufffd","kf31":"\ufffd\ufffd","kf32":"\ufffd\ufffd","kf33":"\ufffd\ufffd","kf34":"\ufffd\ufffd","kf35":"\ufffd\ufffd","kf36":"\ufffd\ufffd","kf37":"\ufffd\ufffd","kf38":"\ufffd\ufffd","kf39":"\ufffd\ufffd","kf40":"\ufffd\ufffd","kf41":"\ufffd\ufffd","kf42":"\ufffd\ufffd","kf43":"\ufffd\ufffd","kf44":"\ufffd\ufffd","kf45":"\ufffd\ufffd","kf46":"\ufffd\ufffd","kf47":"\ufffd\ufffd","kf48":"\ufffd\ufffd","kich":"\ufffd\ufffd","kdch":"\ufffd\ufffd","khome":"\ufffd\ufffd","kend":"\ufffd\ufffd","khlp":"\ufffd\ufffd","kpp":"\ufffd\ufffd","knp":"\ufffd\ufffd","kcuu1":"\ufffd\ufffd","kcud1":"\ufffd\ufffd","kcub1":"\ufffd\ufffd","kcuf1":"\ufffd\ufffd","kcbt":"\ufffd\ufffd","kext":"\ufffd\ufffd","kclr":"\ufffd\ufffd","kprt":"\ufffd\ufffd","kcan":"\ufffd\ufffd","acsc":"O\ufffda\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo\ufffdq\ufffds\ufffdt\ufffdu\ufffdv\ufffdw\ufffdx\ufffd","kRIT":"\ufffd\ufffd","kLFT":"\ufffd\ufffd","kHOM":"\ufffd\ufffd","kEND":"\ufffd\ufffd"} +{"name":"qvt101","aliases":["qvt108"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.4","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kich":"\u001bQ","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI"} +{"name":"qvt101+","aliases":["qvt101p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.4","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kich":"\u001bQ","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI"} +{"name":"qvt102","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kich":"\u001bQ","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI"} +{"name":"qvt103","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"qvt103-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"qvt119+","aliases":["qvt119","qvt119p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*1","cnorm":"\u001b.4","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"qvt119+-25","aliases":["qvt119p-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b*1","cnorm":"\u001b.4","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"qvt119+-25-w","aliases":["qvt119-25-w","qvt119p-25-w"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b*1","cnorm":"\u001b.4","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"qvt119+-w","aliases":["qvt119-w","qvt119p-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b*1","cnorm":"\u001b.4","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"qvt203","aliases":["qvt203+"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[28~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"qvt203-25","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[28~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"qvt203-25-w","cols":132,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[28~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"qvt203-w","aliases":["qvt203-w-am"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[28~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"rbcomm","cols":80,"lines":25,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u0014","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u0012","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001f%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001e","pad":"\u0000","kbs":"\u0008","khome":"\u0001","kcuu1":"\u0010","kcud1":"\u000e","kcub1":"\u0002","kcuf1":"\u0006"} +{"name":"rbcomm-nam","cols":80,"lines":25,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u0014","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u0012","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001f%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001e","pad":"\u0000","kbs":"\u0008","khome":"\u0001","kcuu1":"\u0010","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0006"} +{"name":"rbcomm-w","cols":132,"lines":25,"bell":"\u0007","clear":"\u000c","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u0014","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u0012","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001f%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","cuu1":"\u001e","pad":"\u0000","kbs":"\u0008","khome":"\u0001","kcuu1":"\u0010","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0006"} +{"name":"rca","cols":40,"lines":24,"clear":"\u000c","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cuu1":"\u000b","pad":"\u0000"} +{"name":"rcons","cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"rcons-color","cols":80,"lines":34,"colors":8,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"regent100","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b0@","smul":"\u001b0`","cup":"\u000b%p1%' '%+%c\u0010%p2%{10}%/%{16}%*%p2%{10}%m%+%c","cub1":"\u0015","cuu1":"\u001a","pad":"\u0000","kf1":"\u00022\r","kf2":"\u00023\r","kf3":"\u00024\r","kf4":"\u00025\r","kf5":"\u00026\r","kf6":"\u00027\r","kf7":"\u00028\r"} +{"name":"regent20","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0015","cuu1":"\u001a","pad":"\u0000"} +{"name":"regent25","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0015","cuu1":"\u001a","pad":"\u0000","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"regent40","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b0@","smul":"\u001b0`","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0015","cuu1":"\u001a","pad":"\u0000","kf1":"\u00022\r","kf2":"\u00023\r","kf3":"\u00024\r","kf4":"\u00025\r","kf5":"\u00026\r","kf6":"\u00027\r","kf7":"\u00028\r","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"regent40+","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b0@","smul":"\u001b0`","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0015","cuu1":"\u001a","pad":"\u0000","kf1":"\u00022\r","kf2":"\u00023\r","kf3":"\u00024\r","kf4":"\u00025\r","kf5":"\u00026\r","kf6":"\u00027\r","kf7":"\u00028\r","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"regent60","aliases":["regent200"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b0@","smul":"\u001b0`","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0015","cuu1":"\u001a","pad":"\u0000","kf1":"\u00022\r","kf2":"\u00023\r","kf3":"\u00024\r","kf4":"\u00025\r","kf5":"\u00026\r","kf6":"\u00027\r","kf7":"\u00028\r","kich":"\u001bF","kdch":"\u001bE","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"rt6221","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[1;1H\u001b[J","cnorm":"\u001b[\u003e5h\u001b[\u003e9h","civis":"\u001b[\u003e5l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOQ","kf2":"\u001bOR","kf3":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000e","rmacs":"\u000f"} +{"name":"rt6221-w","cols":160,"lines":48,"bell":"\u0007","clear":"\u001b[1;1H\u001b[J","cnorm":"\u001b[\u003e5h\u001b[\u003e9h","civis":"\u001b[\u003e5l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOQ","kf2":"\u001bOR","kf3":"\u001bOS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u000e","rmacs":"\u000f"} +{"name":"rtpc","aliases":["ibmapa16"],"cols":80,"lines":32,"bell":"\u0007","clear":"\u001bK","sgr0":"\u001bw\u001bq\u001bz\u001bB","smul":"\u001bW","bold":"\u001bZ","rev":"\u001bp","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bY","kich":"\ufffd","khome":"\u001bH","kpp":"\u001bg","knp":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"rxvt","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-16color","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-256color","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-88color","cols":80,"lines":24,"colors":88,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-basic","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-color","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-cygwin","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"0\ufffd+\ufffd,\ufffd-^`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-cygwin-native","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"0\ufffd+\ufffd,\ufffd-^`\u0004a\ufffdf\ufffdg\ufffdh\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd~\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"rxvt-xpm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[7~","kend":"\u001b[8~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"sb1","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH$\u003c1\u003e\u001bJ$\u003c3\u003e","smcup":"\u001bO","sgr0":"\u001b_3","smul":"\u001b_0","cup":"\u001bF%p2%03d%p1%03d","cub1":"\u0008","cuu1":"\u001bA$\u003c3\u003e","pad":"\u0000","kbs":"\u001f","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kf9":"\u001b1","kich":"\u001bQ\u001bO","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"sb2","aliases":["sb3"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH$\u003c1\u003e\u001bJ$\u003c3\u003e","smcup":"\u001bO","sgr0":"\u001b_3","smul":"\u001b_0","cup":"\u001bF%p2%03d%p1%03d","cub1":"\u0008","cuu1":"\u001bA$\u003c3\u003e","pad":"\u0000","kbs":"\u001f","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kf9":"\u001b1","kich":"\u001bQ\u001bO","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"sbi","aliases":["superbee"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH$\u003c1\u003e\u001bJ$\u003c3\u003e","smcup":"\u001bO","sgr0":"\u001b_3","smul":"\u001b_0","cup":"\u001bF%p2%03d%p1%03d","cub1":"\u0008","cuu1":"\u001bA$\u003c3\u003e","pad":"\u0000","kbs":"\u001f","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kf9":"\u001b1","kich":"\u001bQ\u001bO","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"scanset","aliases":["sc410","sc415"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"j%k4l\u003cm-q,x5","smacs":"\u000e","rmacs":"\u000f"} +{"name":"scoansi","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[=10;12C","civis":"\u001b[=14;12C","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\ufffd.\ufffd,.+/0[5566778899::;;\u003c\u003c==\u003e\u003eFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX`\ufffda0fxgqh2jYk?lZm@nEqDtCu4vAwBx3yszr{c}\u001c~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"scoansi-new","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[=1c","civis":"\u001b[=0c","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\ufffd.\ufffd,.+/0[5566778899::;;\u003c\u003c==\u003e\u003eFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX`\ufffda0fxgqh2jYk?lZm@nEqDtCu4vAwBx3yszr{c}\u001c~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"scoansi-old","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[=10;12C","civis":"\u001b[=14;12C","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"-\ufffd.\ufffd,.+/0[5566778899::;;\u003c\u003c==\u003e\u003eFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX`\ufffda0fxgqh2jYk?lZm@nEqDtCu4vAwBx3yszr{c}\u001c~\ufffd","smacs":"\u001b[12m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"screen","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"screen-16color","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"screen-16color-bce","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"screen-16color-bce-s","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"screen-16color-s","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm"} +{"name":"screen-256color","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m"} +{"name":"screen-256color-bce","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m"} +{"name":"screen-256color-bce-s","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m"} +{"name":"screen-256color-s","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m"} +{"name":"screen-bce","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"screen-s","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"screen-w","cols":132,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"screen.linux","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"screen.mlterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[11;2~","kf14":"\u001b[12;2~","kf15":"\u001b[13;2~","kf16":"\u001b[14;2~","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[11;5~","kf26":"\u001b[12;5~","kf27":"\u001b[13;5~","kf28":"\u001b[14;5~","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[11;6~","kf38":"\u001b[12;6~","kf39":"\u001b[13;6~","kf40":"\u001b[14;6~","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[11;3~","kf50":"\u001b[12;3~","kf51":"\u001b[13;3~","kf52":"\u001b[14;3~","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[11;4~","kf62":"\u001b[12;4~","kf63":"\u001b[13;4~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"00``aaffgghhjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001bO1;2C","kLFT":"\u001bO1;2D","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"screen.rxvt","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[23$","kf22":"\u001b[24$","kf23":"\u001b[11^","kf24":"\u001b[12^","kf25":"\u001b[13^","kf26":"\u001b[14^","kf27":"\u001b[15^","kf28":"\u001b[17^","kf29":"\u001b[18^","kf30":"\u001b[19^","kf31":"\u001b[20^","kf32":"\u001b[21^","kf33":"\u001b[23^","kf34":"\u001b[24^","kf35":"\u001b[25^","kf36":"\u001b[26^","kf37":"\u001b[28^","kf38":"\u001b[29^","kf39":"\u001b[31^","kf40":"\u001b[32^","kf41":"\u001b[33^","kf42":"\u001b[34^","kf43":"\u001b[23@","kf44":"\u001b[24@","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[c","kLFT":"\u001b[d","kHOM":"\u001b[7$","kEND":"\u001b[8$","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[a","_kscud1":"\u001b[b","_kccu1":"\u001b[Oa","_kccud1":"\u001b[Ob","_kccuf1":"\u001b[Oc","_kccub1":"\u001b[Od","_kchome":"\u001b[7^","_kcend":"\u001b[8^"} +{"name":"screen.teraterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"screen.xterm-r6","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"screen.xterm-xfree86","aliases":["screen.xterm-new"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"screen2","cols":80,"lines":24,"clear":"\u001b[2J\u001b[H","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001b0I","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"screen3","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"screwpoint","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u000f\u001b0`","sgr0":"\u000f","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kf2":"\u00022","kf3":"\u0002!","kf4":"\u0002\"","kf5":"\u0002#","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"scrhp","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u0026a0c0Y\u001bJ$\u003c40\u003e","sgr0":"\u001b\u0026d@\u000f","smul":"\u001b\u0026dD","bold":"\u001b\u0026dF","blink":"\u001b\u0026dA","rev":"\u001b\u0026dB","dim":"\u001b\u0026dH","smkx":"\u001b\u0026s1A","rmkx":"\u001b\u0026s0A","cup":"\u001b\u0026a%p1%dy%p2%dC$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kpp":"\u001bV","knp":"\u001bU","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001bi","kclr":"\u001bJ","acsc":"2[3@4\u003e5I9(:'JSKWLQMAO#P$Q;R!S\"T1U2V4W3X:Y+Z*dHjGkTlRmFn/q,t5u6v8w7x.","smacs":"\u000e","rmacs":"\u000f"} +{"name":"sibo","cols":61,"lines":20,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"simterm","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001bVS","rmcup":"\u001bVE","sgr0":"\u001b\u0026d@","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"soroc120","aliases":["iq120","soroc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c2\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"soroc140","aliases":["iq140"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+","smul":"\u001b\u0001","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","khome":"\u001e","kcuu1":"\u000b","kcuf1":"\u000c"} +{"name":"st52","cols":80,"lines":25,"bell":"\u0007","clear":"\u001bH\u001bJ","smcup":"\u001be","cnorm":"\u001be","civis":"\u001bf","sgr0":"\u001bq","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b#;","kf2":"\u001b#\u003c","kf3":"\u001b#=","kf4":"\u001b#\u003e","kf5":"\u001b#?","kf6":"\u001b#@","kf7":"\u001b#A","kf8":"\u001b#B","kf9":"\u001b#C","khome":"\u001b#G","kcuu1":"\u001b#H","kcud1":"\u001b#P","kcub1":"\u001b#K","kcuf1":"\u001b#M","kclr":"\u001b#7"} +{"name":"sun","aliases":["sun1","sun2"],"cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-1","cols":80,"lines":1,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-12","cols":80,"lines":12,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-17","cols":80,"lines":17,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-24","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-34","cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-48","cols":80,"lines":48,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-c","aliases":["sun-cmd"],"cols":80,"lines":35,"bell":"\u0007","clear":"\u000c","smcup":"\u001b[\u003e4l","rmcup":"\u001b[\u003e4h","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-cgsix","aliases":["sun-ss5"],"cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-color","cols":80,"lines":34,"colors":8,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"sun-e","aliases":["sun-nic","sune"],"cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-e-s","aliases":["sun-s-e"],"cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-il","cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-s","cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"sun-type4","cols":80,"lines":34,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b[m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[234z","kf12":"\u001b[235z","kdch":"","khome":"\u001b[214z","kend":"\u001b[220z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001b[215z","kcud1":"\u001b[221z","kcub1":"\u001b[217z","kcuf1":"\u001b[219z"} +{"name":"superbee-xsb","cols":80,"lines":25,"clear":"\u001bH\u001bJ$\u003c3\u003e","cnorm":"\n","sgr0":"\u001b_3","cup":"\u001bF%p2%3d%p1%3d","cub1":"\u0008","cuu1":"\u001bA$\u003c3\u003e","pad":"\u0000","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"superbeeic","cols":80,"lines":25,"clear":"\u001bH\u001bJ$\u003c3\u003e","cnorm":"\n","sgr0":"\u001b_3","cup":"\u001bF%p2%3d%p1%3d","cub1":"\u0008","cuu1":"\u001bA$\u003c3\u003e","pad":"\u0000","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"superbrain","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c5*\u003e","smcup":"\u000c","rmcup":"\u000c","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c$\u003c20\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"swtp","aliases":["ct82"],"cols":82,"lines":20,"bell":"\u0007","clear":"\u000c","cup":"\u000b%p2%c%p1%c","cub1":"\u0004","cuu1":"\u0001","pad":"\u0000"} +{"name":"synertek","aliases":["ktm","synertek380"],"cols":80,"lines":24,"clear":"\u001a","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"t10","cols":80,"lines":24,"clear":"\u001bj$\u003c30/\u003e","smul":"\u001bRH","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\ufffd"} +{"name":"t1061","aliases":["teleray"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c1\u003e","smul":"\u001bRH","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001a1","kf2":"\u001a2","kf3":"\u001a3","kf4":"\u001a4","kf5":"\u001a5","kf6":"\u001a6","kf7":"\u001a7","kf8":"\u001a8"} +{"name":"t1061f","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c$\u003c1\u003e","smul":"\u001bRH","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001a1","kf2":"\u001a2","kf3":"\u001a3","kf4":"\u001a4","kf5":"\u001a5","kf6":"\u001a6","kf7":"\u001a7","kf8":"\u001a8"} +{"name":"t16","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[U\u001b[?38l","rmcup":"\u001b[V\u001b[24;1f\u001b[?38h","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"%i\u001b[%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001a1","kf2":"\u001a2","kf3":"\u001a3","kf4":"\u001a4","kf5":"\u001a5","kf6":"\u001a6","kf7":"\u001a7","kf8":"\u001a8","kf9":"\u001a9","kf10":"\u001a0"} +{"name":"t3800","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"tab132","aliases":["tab","tab132-15"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"tab132-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"tab132-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"tab132-w-rv","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"tandem6510","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c1/\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tandem653","aliases":["t653x"],"cols":80,"lines":24,"clear":"\u001bI","sgr0":"\u001b6 ","smul":"\u001b60","cup":"\u0013%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"tek4023","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b\u000c$\u003c4/\u003e","cup":"\u001c%p2%' '%+%c%p1%' '%+%c","cub1":"\u0008","pad":"\u0000","kbs":"\u0008"} +{"name":"tek4025-cr","cols":80,"lines":33,"clear":"\u001fera;","smcup":"\u001fwor 33h","rmcup":"\u001fwor 0","cup":"\u001fjum%i%p1%d,%p2%d;","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"tek4105","cols":79,"lines":29,"bell":"\u0007","clear":"\u001b[2J\u001b[H","smcup":"\u001b%!1\u001b[?6l\u001b[2J","sgr0":"\u001b[=0;\u003c1m","smul":"\u001b[=5;\u003c2m","bold":"\u001b[=7;\u003c4m","blink":"\u001b[=3;\u003c7m","rev":"\u001b[=1;\u003c3m","dim":"\u001b[=1;\u003c6m","cup":"\u001b[%i%p1%2d;%p2%2dH","cuu1":"\u001b[1A","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001b[1A","kcud1":"\u001b[1B","kcub1":"\u001b[1D","kcuf1":"\u001b[1C","smacs":"\u001b[1m","rmacs":"\u001b[m"} +{"name":"tek4105-30","cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"tek4105a","cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?6l","rmcup":"\u001b%!0\u001bLBH=\u001b%!1","cnorm":"\u001b%!0\u001bTD10\u001b%!1","civis":"\u001b%!0\u001bTD00\u001b%!1","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOB","kf2":"\u001bOC","kf3":"\u001bOD","kf4":"\u001bOP","kf5":"\u001bOQ","kf6":"\u001bOR","kf7":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","smacs":"\u000e","rmacs":"\u000f"} +{"name":"tek4106brl","aliases":["tek4107brl","tek4109brl"],"cols":80,"lines":32,"bell":"\u0007","clear":"\u001b[H\u001b[J","smcup":"\u001b[?6l","rmcup":"\u001b%!0\u001bLBH=\u001b%!1","cnorm":"\u001b%!0\u001bTD10\u001b%!1","civis":"\u001b%!0\u001bTD00\u001b%!1","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOB","kf2":"\u001bOC","kf3":"\u001bOD","kf4":"\u001bOP","kf5":"\u001bOQ","kf6":"\u001bOR","kf7":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","smacs":"\u000e","rmacs":"\u000f"} +{"name":"tek4107","aliases":["tek4109"],"cols":79,"lines":29,"bell":"\u0007","clear":"\u001bLZ","cnorm":"\u001b%!0","sgr0":"\u001b%!1\u001b[m$\u003c2\u003e\u001b%!0","smul":"\u001b%!1\u001b[4m$\u003c2\u003e\u001b%!0","bold":"\u001b%!1\u001b[1m$\u003c2\u003e\u001b%!0","blink":"\u001b%!1\u001b[5m$\u003c2\u003e\u001b%!0","rev":"\u001b%!1\u001b[7m$\u003c2\u003e\u001b%0","dim":"\u001b%!1\u001b[\u003c0m$\u003c2\u003e\u001b%!0","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"tek4112","aliases":["tek4114"],"cols":80,"lines":34,"clear":"\u001b[2J\u001b[0;0H","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000"} +{"name":"tek4112-5","cols":80,"lines":5,"clear":"\u001b[2J\u001b[0;0H","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000"} +{"name":"tek4112-nd","cols":80,"lines":34,"clear":"\u001b[2J\u001b[0;0H","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"tek4115","cols":80,"lines":34,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"tek4125","cols":80,"lines":34,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"tek4205","cols":80,"lines":30,"bell":"\u0007","clear":"\u001b[2J\u001b[H","smcup":"\u001b%%!1\u001b[?6l\u001b[2J","sgr0":"\u001b[=0;\u003c1m\u001b[24;25;27m\u000f","smul":"\u001b[4m","bold":"\u001b[=7;\u003c4m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[=1;\u003c6m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOB","kf2":"\u001bOC","kf3":"\u001bOD","kf4":"\u001bP","kf5":"\u001bQ","kf6":"\u001bR","kf7":"\u001bS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"tek4207","cols":80,"lines":32,"clear":"\u001b[H\u001b[J$\u003c156/\u003e","smcup":"\u001b[?6l\u001b[H\u001b[J","rmcup":"\u001b[?6h\u001b%!0\u001bLBP0\u001b%!1\u001b[32;1f","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","khome":"\u001b[H","kcuu1":"\u001bM","kcud1":"\u001bD","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"tek4207-s","cols":79,"lines":29,"bell":"\u0007","clear":"\u001bLZ","cnorm":"\u001b%!0","sgr0":"\u001b%!1\u001b[m$\u003c2\u003e\u001b%!0","smul":"\u001b%!1\u001b[4m$\u003c2\u003e\u001b%!0","bold":"\u001b%!1\u001b[1m$\u003c2\u003e\u001b%!0","blink":"\u001b%!1\u001b[5m$\u003c2\u003e\u001b%!0","rev":"\u001b%!1\u001b[7m$\u003c2\u003e\u001b%0","dim":"\u001b%!1\u001b[\u003c0m$\u003c2\u003e\u001b%!0","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"tek4404","cols":80,"lines":32,"clear":"\u001b[H\u001b[2J","smcup":"\u001b%\u001b!1\u001b[1;32r\u001b[?6l\u001b\u003e","rmcup":"\u001b[1;1H\u001b[0J\u001b[?6h\u001b[?1l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","smkx":"\u001b[?1l","rmkx":"\u001b[?1h","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"teraterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"teraterm2.3","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"teraterm4.59","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ti916","aliases":["ti916-220-7"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c6\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%p1%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","khlp":"\u001b[28~","kpp":"\u001b[T","knp":"\u001b[S","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\u0018","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e$\u003c2\u003e","rmacs":"\u000f$\u003c2\u003e","enacs":"\u001b(B\u001b)0"} +{"name":"ti916-132","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c6\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%p1%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","khlp":"\u001b[28~","kpp":"\u001b[T","knp":"\u001b[S","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\u0018","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e$\u003c2\u003e","rmacs":"\u000f$\u003c2\u003e","enacs":"\u001b(B\u001b)0"} +{"name":"ti916-8","aliases":["ti916-220-8"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c6\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%p1%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd17~","kf2":"\ufffd18~","kf3":"\ufffd19~","kf4":"\ufffd20~","kf5":"\ufffd21~","kf6":"\ufffd23~","kf7":"\ufffd24~","kf8":"\ufffd25~","kf9":"\ufffd26~","kf10":"\ufffd28~","kf11":"\ufffd29~","kf12":"\ufffd31~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\ufffd@","kdch":"\ufffdP","khome":"\ufffdH","khlp":"\u001b[28~","kpp":"\ufffdT","knp":"\ufffdS","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kprt":"\u0018","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e$\u003c2\u003e","rmacs":"\u000f$\u003c2\u003e","enacs":"\u001b(B\u001b)0"} +{"name":"ti916-8-132","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c6\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%p1%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd17~","kf2":"\ufffd18~","kf3":"\ufffd19~","kf4":"\ufffd20~","kf5":"\ufffd21~","kf6":"\ufffd23~","kf7":"\ufffd24~","kf8":"\ufffd25~","kf9":"\ufffd26~","kf10":"\ufffd28~","kf11":"\ufffd29~","kf12":"\ufffd31~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\ufffd@","kdch":"\ufffdP","khome":"\ufffdH","khlp":"\u001b[28~","kpp":"\ufffdT","knp":"\ufffdS","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kprt":"\u0018","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e$\u003c2\u003e","rmacs":"\u000f$\u003c2\u003e","enacs":"\u001b(B\u001b)0"} +{"name":"ti924","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[16~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kich":"\u001b[@","kdch":"\u001b[P","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ti924-8","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"P$\u003c\ufffd\u003e","kf2":"Q$\u003c\ufffd\u003e","kf3":"R$\u003c\ufffd\u003e","kf4":"S$\u003c\ufffd\u003e","kf5":"~$\u003c\ufffd16\u003e","kf6":"~$\u003c\ufffd17\u003e","kf7":"~$\u003c\ufffd18\u003e","kf8":"~$\u003c\ufffd19\u003e","kf9":"~$\u003c\ufffd20\u003e","kich":"@$\u003c\ufffd\u003e","kdch":"P$\u003c\ufffd\u003e","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ti924-8w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"P$\u003c\ufffd\u003e","kf2":"Q$\u003c\ufffd\u003e","kf3":"R$\u003c\ufffd\u003e","kf4":"S$\u003c\ufffd\u003e","kf5":"~$\u003c\ufffd16\u003e","kf6":"~$\u003c\ufffd17\u003e","kf7":"~$\u003c\ufffd18\u003e","kf8":"~$\u003c\ufffd19\u003e","kf9":"~$\u003c\ufffd20\u003e","kich":"@$\u003c\ufffd\u003e","kdch":"P$\u003c\ufffd\u003e","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ti924w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[16~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kich":"\u001b[@","kdch":"\u001b[P","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ti926","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[16~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kich":"\u001b[@","kdch":"\u001b[P","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ti926-8","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"%i\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"P$\u003c\ufffd\u003e","kf2":"Q$\u003c\ufffd\u003e","kf3":"R$\u003c\ufffd\u003e","kf4":"S$\u003c\ufffd\u003e","kf5":"~$\u003c\ufffd16\u003e","kf6":"~$\u003c\ufffd17\u003e","kf7":"~$\u003c\ufffd18\u003e","kf8":"~$\u003c\ufffd19\u003e","kf9":"~$\u003c\ufffd20\u003e","kich":"@$\u003c\ufffd\u003e","kdch":"P$\u003c\ufffd\u003e","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"ti928","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J\u001b[H","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[17~","kf2":"\u001b[18~","kf3":"\u001b[19~","kf4":"\u001b[20~","kf5":"\u001b[21~","kf6":"\u001b[23~","kf7":"\u001b[24~","kf8":"\u001b[25~","kf9":"\u001b[26~","kf10":"\u001b[28~","kf11":"\u001b[29~","kf12":"\u001b[31~","kf13":"\u001b[32~","kf15":"\u001b[34~","kich":"\u001b[@","kdch":"\u001b[P","khome":"\u001b[H","kend":"\u001b_1\u001b\\","kpp":"\u001b[T","knp":"\u001b[S","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\u001b[35~","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ti928-8","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J\u001b[H","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\ufffd17~","kf2":"\ufffd18~","kf3":"\ufffd19~","kf4":"\ufffd20~","kf5":"\ufffd21~","kf6":"\ufffd23~","kf7":"\ufffd24~","kf8":"\ufffd25~","kf9":"\ufffd26~","kf10":"\ufffd28~","kf11":"\ufffd29~","kf12":"\ufffd31~","kf13":"\ufffd32~","kf15":"\ufffd34~","kich":"\ufffd@","kdch":"\ufffdP","khome":"\ufffdH","kend":"\ufffd1\ufffd","kpp":"\ufffdT","knp":"\ufffdS","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\ufffd35~","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"ti931","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bL","cnorm":"\u001b4@","sgr0":"\u001b4@","smul":"\u001b4D","blink":"\u001b4P","rev":"\u001b4B","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001bi1","kf2":"\u001bi2","kf3":"\u001bi3","kf4":"\u001bi4","kf5":"\u001bi5","kf6":"\u001bi6","kf7":"\u001bi7","kf8":"\u001bi8","kf9":"\u001bi9","kich":"\u001bP","kdch":"\u001bQ","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"ti_ansi","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[2J\u001b[H","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"trs16","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001bRC","civis":"\u001bRc","sgr0":"\u001bR@","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u0002","kf2":"\u0004","kf3":"\u000c","kf4":"\u0015","kf5":"\u0010","kf6":"\u000e","kf7":"\u0013","khome":"\u0017","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"jak`l_mbquvewcxs","smacs":"\u001bRG","rmacs":"\u001bRg"} +{"name":"trs2","aliases":["trs80II","trsII"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001e","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001e","kcud1":"\u001f","kcub1":"\u001c","kcuf1":"\u001d"} +{"name":"ts100","aliases":["ts100-sp"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"ts100-ctxt","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","smcup":"\u001b~_d\u001b[2J","rmcup":"\u001b~_b","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"tt","aliases":["tkterm"],"cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","cup":"\u001b[%p1%d;%p2%dH","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX"} +{"name":"tt505-22","aliases":["gs5430-22","pt505-22"],"cols":80,"lines":22,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[\u003el","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[01s","kf2":"\u001b[02s","kf3":"\u001b[03s","kf4":"\u001b[04s","kf5":"\u001b[05s","kf6":"\u001b[06s","kf18":"\u001b[18s","kf19":"\u001b[19s","kf20":"\u001b[20s","kf21":"\u001b[21s","kf22":"\u001b[22s","kf23":"\u001b[23s","kf24":"\u001b[24s","kf26":"\u001b[26s","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b[11m","rmacs":"\u001b[10m"} +{"name":"tvi803","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*$\u003c10\u003e","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"tvi9065","cols":80,"lines":25,"bell":"\u0007","clear":"\u001a","smcup":"\u001b.2","rmcup":"\u001b.3\u001br\u001b[1;25r\u001b[25;0H","cnorm":"\u001b.3","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","bold":"\u001bG,","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","acsc":"'r0_jhkglfmeniopqksqtmulvownxj","smacs":"\u001b$","rmacs":"\u001b%%","kHOM":"\u001b "} +{"name":"tvi910","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi910+","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001A\r","kf2":"\u0001B\r","kf3":"\u0001C\r","kf4":"\u0001D\r","kf5":"\u0001E\r","kf6":"\u0001F\r","kf7":"\u0001G\r","kf8":"\u0001H\r","kf9":"\u0001I\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912","aliases":["tvi914","tvi920"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","smul":"\u001bl","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b","aliases":["tvi912c"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","sgr0":"\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-2p","aliases":["tvi912c-2p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","sgr0":"\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-2p-mc","aliases":["tvi912b-mc-2p","tvi912c-2p-mc","tvi912c-mc-2p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","sgr0":"\u001b(\u001bk\u0008\u001bm\u0008\u001bq","smul":"\u001bl","blink":"\u001b^","rev":"\u001bj","dim":"\u001b) ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-2p-p","aliases":["tvi912b-p-2p","tvi912c-2p-p","tvi912c-p-2p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-2p-unk","aliases":["tvi912b-unk-2p","tvi912c-2p-unk","tvi912c-unk-2p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-mc","aliases":["tvi912c-mc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","sgr0":"\u001b(\u001bk\u0008\u001bm\u0008\u001bq","smul":"\u001bl","blink":"\u001b^","rev":"\u001bj","dim":"\u001b) ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-p","aliases":["tvi912c-p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-unk","aliases":["tvi912c-unk"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-vb","aliases":["tvi912c-vb"],"cols":80,"lines":24,"bell":"\u001bK$\u003c100\u003e\u001bK","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","sgr0":"\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-vb-mc","aliases":["tvi912b-mc-vb","tvi912c-mc-vb","tvi912c-vb-mc"],"cols":80,"lines":24,"bell":"\u001bK$\u003c100\u003e\u001bK","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","sgr0":"\u001b(\u001bk\u0008\u001bm\u0008\u001bq","smul":"\u001bl","blink":"\u001b^","rev":"\u001bj","dim":"\u001b) ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-vb-p","aliases":["tvi912b-p-vb","tvi912c-p-vb","tvi912c-vb-p"],"cols":80,"lines":24,"bell":"\u001bK$\u003c100\u003e\u001bK","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi912b-vb-unk","aliases":["tvi912b-unk-vb","tvi912c-unk-vb","tvi912c-vb-unk"],"cols":80,"lines":24,"bell":"\u001bK$\u003c100\u003e\u001bK","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b","aliases":["tvi920c"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","sgr0":"\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-2p","aliases":["tvi920c-2p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","sgr0":"\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-2p-mc","aliases":["tvi920b-mc-2p","tvi920c-2p-mc","tvi920c-mc-2p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","sgr0":"\u001b(\u001bk\u0008\u001bm\u0008\u001bq","smul":"\u001bl","blink":"\u001b^","rev":"\u001bj","dim":"\u001b) ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-2p-p","aliases":["tvi920b-p-2p","tvi920c-2p-p","tvi920c-p-2p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-2p-unk","aliases":["tvi920b-unk-2p","tvi920c-2p-unk","tvi920c-unk-2p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-mc","aliases":["tvi920c-mc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","sgr0":"\u001b(\u001bk\u0008\u001bm\u0008\u001bq","smul":"\u001bl","blink":"\u001b^","rev":"\u001bj","dim":"\u001b) ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-p","aliases":["tvi920c-p"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-unk","aliases":["tvi920c-unk"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001a$\u003c50\u003e","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-vb","aliases":["tvi920c-vb"],"cols":80,"lines":24,"bell":"\u001bK$\u003c100\u003e\u001bK","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","sgr0":"\u001b(","dim":"\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-vb-mc","aliases":["tvi920b-mc-vb","tvi920c-mc-vb","tvi920c-vb-mc"],"cols":80,"lines":24,"bell":"\u001bK$\u003c100\u003e\u001bK","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","sgr0":"\u001b(\u001bk\u0008\u001bm\u0008\u001bq","smul":"\u001bl","blink":"\u001b^","rev":"\u001bj","dim":"\u001b) ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-vb-p","aliases":["tvi920b-p-vb","tvi920c-p-vb","tvi920c-vb-p"],"cols":80,"lines":24,"bell":"\u001bK$\u003c100\u003e\u001bK","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi920b-vb-unk","aliases":["tvi920b-unk-vb","tvi920c-unk-vb","tvi920c-vb-unk"],"cols":80,"lines":24,"bell":"\u001bK$\u003c100\u003e\u001bK","clear":"\u001a$\u003c50\u003e","smcup":"\u001bK\u001a$\u003c50\u003e\u001b(\u001bk\u0008\u001bm\u0008\u001bq\u001a$\u003c50\u003e","rmcup":"\u001a$\u003c50\u003e\u001bK\u001b=7 ","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001`\r","kf13":"\u0001a\r","kf14":"\u0001b\r","kf15":"\u0001c\r","kf16":"\u0001d\r","kf17":"\u0001e\r","kf18":"\u0001f\r","kf19":"\u0001g\r","kf20":"\u0001h\r","kf21":"\u0001i\r","kf22":"\u0001j\r","kdch":"","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tvi921","cols":80,"lines":24,"clear":"\u001a","cnorm":"\u001b.3","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c3/\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kich":"\u001bQ","kdch":"\u001bW","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001a","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"tvi924","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*0","cnorm":"\u001b.3","civis":"\u001b.0","sgr0":"\u001bG0","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001A\r","kf2":"\u0001B\r","kf3":"\u0001C\r","kf4":"\u0001D\r","kf5":"\u0001E\r","kf6":"\u0001F\r","kf7":"\u0001G\r","kf8":"\u0001H\r","kf9":"\u0001I\r","kf10":"\u0001J\r","kf11":"\u0001K\r","kf12":"\u0001L\r","kf13":"\u0001M\r","kf14":"\u0001N\r","kf15":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001b*0"} +{"name":"tvi925","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.4","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001a"} +{"name":"tvi925-hi","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cnorm":"\u001b.4","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001a"} +{"name":"tvi92B","cols":80,"lines":24,"clear":"\u001a","cnorm":"\u001b.3","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c3/\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kich":"\u001bQ","kdch":"\u001bW","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001a","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"tvi92D","cols":80,"lines":24,"clear":"\u001a","cnorm":"\u001b.3","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c3/\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kich":"\u001bQ","kdch":"\u001bW","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kclr":"\u001a","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"tvi950","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"tvi950-2p","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","smcup":"\u001b\\1\u001b-07 ","rmcup":"\u001b\\2\u001b-07 ","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","smkx":"\u001bl","rmkx":"\u001bk","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"tvi950-4p","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","smcup":"\u001b\\1\u001b-07 ","rmcup":"\u001b\\3\u001b-07 ","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","smkx":"\u001bl","rmkx":"\u001bk","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"tvi950-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"tvi950-rv-2p","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","smcup":"\u001b\\1\u001b-07 ","rmcup":"\u001b\\2\u001b-07 ","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","smkx":"\u001bl","rmkx":"\u001bk","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"tvi950-rv-4p","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","smcup":"\u001b\\1\u001b-07 ","rmcup":"\u001b\\3\u001b-07 ","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","smkx":"\u001bl","rmkx":"\u001bk","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"b\tc\u000cd\re\ni\u000b","smacs":"\u0015","rmacs":"\u0018"} +{"name":"tvi955","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","cnorm":"\u001b.2","civis":"\u001b.0","sgr0":"\u001bG0\u001b[=5l","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001b[=5h","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"0_`RjHkGlFmEnIoPqKsQtMuLvOwNxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"tvi955-hb","aliases":["955-hb"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","cnorm":"\u001b.2","civis":"\u001b.0","sgr0":"\u001bG0\u001b[=5h","smul":"\u001bG8","bold":"\u001b[=5l","blink":"\u001bG2","rev":"\u001bG4","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"0_`RjHkGlFmEnIoPqKsQtMuLvOwNxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"tvi955-w","aliases":["955-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b*","cnorm":"\u001b.2","civis":"\u001b.0","sgr0":"\u001bG0\u001b[=5l","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001b[=5h","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\u0016","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kclr":"\u001b*","acsc":"0_`RjHkGlFmEnIoPqKsQtMuLvOwNxJ","smacs":"\u001b$","rmacs":"\u001b%%"} +{"name":"tvi970","cols":80,"lines":24,"clear":"\u001b[H\u001b[2J","smcup":"\u001b[?20l\u001b[?7h\u001b[1Q","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001b?a","kf2":"\u001b?b","kf3":"\u001b?c","kf4":"\u001b?d","kf5":"\u001b?e","kf6":"\u001b?f","kf7":"\u001b?g","kf8":"\u001b?h","kf9":"\u001b?i","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u001b(B","rmacs":"\u001b(B"} +{"name":"tvi970-2p","cols":80,"lines":24,"clear":"\u001b[H\u001b[2J","smcup":"\u001b[U\u001b[?20l\u001b[?7h\u001b[1Q","rmcup":"\u001b[H\u001b[J\u001b[V","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001b?a","kf2":"\u001b?b","kf3":"\u001b?c","kf4":"\u001b?d","kf5":"\u001b?e","kf6":"\u001b?f","kf7":"\u001b?g","kf8":"\u001b?h","kf9":"\u001b?i","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u001b(B","rmacs":"\u001b(B"} +{"name":"tvi970-vb","cols":80,"lines":24,"clear":"\u001b[H\u001b[2J","smcup":"\u001b[?20l\u001b[?7h\u001b[1Q","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001b?a","kf2":"\u001b?b","kf3":"\u001b?c","kf4":"\u001b?d","kf5":"\u001b?e","kf6":"\u001b?f","kf7":"\u001b?g","kf8":"\u001b?h","kf9":"\u001b?i","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","smacs":"\u001b(B","rmacs":"\u001b(B"} +{"name":"tvipt","cols":80,"lines":24,"clear":"\u001a","smul":"\u001bG1B@\u001bH","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0002","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"tws-generic","aliases":["dku7102"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?\u003eh\u001bPY99:98\u001b\\","rmcup":"\u001b[0;98v\u001b[2J\u001b[v","cnorm":"\u001b[r","civis":"\u001b[1r","sgr0":"\u001b[m\u000f","smul":"\u001b[0;4m","blink":"\u001b[0;5m","rev":"\u001b[0;7m","dim":"\u001b[0;2m","cup":"\u001b[%i%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[1u\u0017","kf2":"\u001b[2u\u0017","kf3":"\u001b[3u\u0017","kf4":"\u001b[4u\u0017","kf5":"\u001b[5u\u0017","kf6":"\u001b[6u\u0017","kf7":"\u001b[7u\u0017","kf8":"\u001b[8u\u0017","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggj)k,l\u0026m#n/ooppq*rrsst'u-v+w.x%yyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"tws2102-sna","aliases":["dku7102-sna"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?\u003eh\u001bPY99:98\u001b\\","rmcup":"\u001b[0;98v\u001b[2J\u001b[v","cnorm":"\u001b[r","civis":"\u001b[1r","sgr0":"\u001b[m\u000f","smul":"\u001b[0;4m","blink":"\u001b[0;5m","rev":"\u001b[0;7m","dim":"\u001b[0;2m","cup":"\u001b[%i%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[1u\u0017","kf2":"\u001b[2u\u0017","kf3":"\u001b[3u\u0017","kf4":"\u001b[4u\u0017","kf5":"\u001b[5u\u0017","kf6":"\u001b[6u\u0017","kf7":"\u001b[7u\u0017","kf8":"\u001b[8u\u0017","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggj)k,l\u0026m#n/ooppq*rrsst'u-v+w.x%yyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"tws2103","aliases":["xdku"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?\u003eh\u001bPY99:98\u001b\\","rmcup":"\u001b[0;98v\u001b[2J\u001b[v","cnorm":"\u001b[r","civis":"\u001b[1r","sgr0":"\u001b[m\u000f","smul":"\u001b[0;4m","blink":"\u001b[0;5m","rev":"\u001b[0;7m","dim":"\u001b[0;2m","cup":"\u001b[%i%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[1u\u0017","kf2":"\u001b[2u\u0017","kf3":"\u001b[3u\u0017","kf4":"\u001b[4u\u0017","kf5":"\u001b[5u\u0017","kf6":"\u001b[6u\u0017","kf7":"\u001b[7u\u0017","kf8":"\u001b[8u\u0017","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggj)k,l\u0026m#n/ooppq*rrsst'u-v+w.x%yyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"tws2103-sna","aliases":["dku7103-sna"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?\u003eh\u001bPY99:98\u001b\\","rmcup":"\u001b[0;98v\u001b[2J\u001b[v","cnorm":"\u001b[r","civis":"\u001b[1r","sgr0":"\u001b[m\u000f","smul":"\u001b[0;4m","blink":"\u001b[0;5m","rev":"\u001b[0;7m","dim":"\u001b[0;2m","cup":"\u001b[%i%p1%d;%p2%df","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[1u\u0017","kf2":"\u001b[2u\u0017","kf3":"\u001b[3u\u0017","kf4":"\u001b[4u\u0017","kf5":"\u001b[5u\u0017","kf6":"\u001b[6u\u0017","kf7":"\u001b[7u\u0017","kf8":"\u001b[8u\u0017","kdch":"\u001b[P","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggj)k,l\u0026m#n/ooppq*rrsst'u-v+w.x%yyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"uniterm","aliases":["uniterm49"],"cols":80,"lines":49,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"uts30","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u001bS","civis":"\u001bR","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001bF","rmacs":"\u001bd"} +{"name":"uwin","cols":-1,"lines":-1,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0;10m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","kich":"\u001b[@","kdch":"","khome":"\u001b[H","kend":"\u001b[Y","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"+\u0010,\u0011-\u0018.\u00190\ufffd`\u0004a\ufffdf\ufffdg\ufffdh\ufffdi\ufffdj\ufffdk\ufffdl\ufffdm\ufffdn\ufffdo~p\ufffdq\ufffdr\ufffds_t\ufffdu\ufffdv\ufffdw\ufffdx\ufffdy\ufffdz\ufffd{\ufffd|\ufffd}\ufffd~\ufffd","smacs":"\u001b[11m","rmacs":"\u001b[10m","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"v3220","cols":80,"lines":24,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b[2~","kf2":"\u001b[3~","kf3":"\u001b[4~","kf4":"\u001b[5~","kf5":"\u001b[6~","kf6":"\u001b[OP","kf7":"\u001b[OQ","kf8":"\u001b[OR","kf9":"\u001b[OS","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"v5410","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vc404","cols":80,"lines":24,"bell":"\u0007","clear":"\u0018$\u003c40\u003e","cup":"\u0010%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0015"} +{"name":"vc404-s","cols":80,"lines":24,"bell":"\u0007","clear":"\u0018$\u003c40\u003e","cup":"\u0010%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0015"} +{"name":"vc414","aliases":["vc414h"],"cols":80,"lines":24,"clear":"\u001b\u001c$\u003c40\u003e","cup":"\u001b\u0011%p2%c%p1%c$\u003c40\u003e","cuu1":"\u001b\u000c","pad":"\u0000","kf1":"\u001bB","kf2":"\u001bC","kf3":"\u001bD","kf4":"\u001bE","kf5":"\u001bF","kf6":"\u001bG","kf7":"\u001bH","khome":"\u001b\u0012","kcuu1":"\u001b\u000c","kcud1":"\u001b\u000b","kcub1":"\u0008","kcuf1":"\u0010"} +{"name":"vc415","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cup":"\u0010%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u0015"} +{"name":"versaterm","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[;H\u001b[2J$\u003c50/\u003e","sgr0":"\u001b[m$\u003c2/\u003e","smul":"\u001b[4m$\u003c2/\u003e","bold":"\u001b[1m$\u003c2/\u003e","blink":"\u001b[5m$\u003c2/\u003e","rev":"\u001b[7m$\u003c2/\u003e","smkx":"\u001b=\u001b[?1h","rmkx":"\u001b\u003e\u001b[?1l","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5/\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2/\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"vi200","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bv","cnorm":"\u001bc","sgr0":"\u001b3\u001bb","dim":"\u001b4","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b?q","kf2":"\u001b?r","kf3":"\u001b?s","kf4":"\u001b?t","kf5":"\u001b?u","kf6":"\u001b?v","kf7":"\u001b?w","kf8":"\u001b?x","kf9":"\u001b?y","kich":"\u001bi","kdch":"\u001bO","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bv","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"vi200-f","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bv","cnorm":"\u001bc","sgr0":"\u001b3\u001bb","dim":"\u001b4","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b?q","kf2":"\u001b?r","kf3":"\u001b?s","kf4":"\u001b?t","kf5":"\u001b?u","kf6":"\u001b?v","kf7":"\u001b?w","kf8":"\u001b?x","kf9":"\u001b?y","kich":"\u001bi","kdch":"\u001bO","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bv","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"vi200-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bv","sgr0":"\u001b3\u001bb","dim":"\u001b4","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b?q","kf2":"\u001b?r","kf3":"\u001b?s","kf4":"\u001b?t","kf5":"\u001b?u","kf6":"\u001b?v","kf7":"\u001b?w","kf8":"\u001b?x","kf9":"\u001b?y","kich":"\u001bi","kdch":"\u001bO","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bv","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"vi300","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b_A\u001b\\","kf2":"\u001b_B\u001b\\","kf3":"\u001b_C\u001b\\","kf4":"\u001b_D\u001b\\","kf5":"\u001b_E\u001b\\","kf6":"\u001b_F\u001b\\","kf7":"\u001b_G\u001b\\","kf8":"\u001b_H\u001b\\","kf9":"\u001b_I\u001b\\","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"vi300-old","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b_A\u001b\\","kf2":"\u001b_B\u001b\\","kf3":"\u001b_C\u001b\\","kf4":"\u001b_D\u001b\\","kf5":"\u001b_E\u001b\\","kf6":"\u001b_F\u001b\\","kf7":"\u001b_G\u001b\\","kf8":"\u001b_H\u001b\\","kf9":"\u001b_I\u001b\\","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"vi50","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","smul":"\u001bS","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bP","kf2":"\u001bQ","kf3":"\u001bR","kf4":"\u001bV","kf5":"\u001bE","kf6":"\u001b]","kf7":"\u001bL","kf8":"\u001bv","kf9":"\u001bM","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"vi500","cols":80,"lines":33,"clear":"\u001bv$\u003c6*/\u003e","smul":"\u001b\u0004","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","smacs":"\u000e","rmacs":"\u000f"} +{"name":"vi50adm","cols":80,"lines":24,"bell":"\u0007","clear":"\u001a","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"vi55","cols":80,"lines":24,"clear":"\u001bv","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"vi550","cols":80,"lines":33,"bell":"\u0007","clear":"\u0018\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kf1":"\u001b_A\u001b\\","kf2":"\u001b_B\u001b\\","kf3":"\u001b_C\u001b\\","kf4":"\u001b_D\u001b\\","kf5":"\u001b_E\u001b\\","kf6":"\u001b_F\u001b\\","kf7":"\u001b_G\u001b\\","kf8":"\u001b_H\u001b\\","kf9":"\u001b_I\u001b\\","khome":"\u001b[H","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C"} +{"name":"vi603","aliases":["visual603"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"viewpoint","aliases":["addsviewpoint"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","cnorm":"\u000f\u001b0`","sgr0":"\u000f","smul":"\u000e","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kf2":"\u00022","kf3":"\u0002!","kf4":"\u0002\"","kf5":"\u0002#","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"vip","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b`","sgr0":"\u001bsR\u001bsU\u001bF","smul":"\u001bs_","blink":"\u001bsB","rev":"\u001bsI","dim":"\u001bsL","cup":"\u001b[%i%p1%03d%p2%03df","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b0","kf2":"\u001b2","kf3":"\u001b6","kf4":"\u001b8","kf5":"\u001b:","kf6":"\u001b\u003c","kf7":"\u001b\u003e","kf8":"\u001bP","kf9":"\u001bR","kf10":"\u001bT","kf11":"\u001b\\","kf12":"\u001b^","kf21":"\u001b1","kf22":"\u001b5","kf23":"\u001b7","kf24":"\u001b9","kf25":"\u001b;","kf26":"\u001b=","kf27":"\u001b?","kf28":"\u001bQ","kf29":"\u001bS","kf30":"\u001bV","kf31":"\u001b]","kf32":"\u001b_","kich":"\u001b[I","kdch":"\u001b[P","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b[Z","kclr":"\u001b`","acsc":"0pjdkblamcnkqitgufvhwexj","smacs":"\u001bG","rmacs":"\u001bF","kRIT":"\u001bu","kLFT":"\u001bo","kHOM":"\u001bH"} +{"name":"vip-H","aliases":["Q310-vip-H","Q310-vip-H-am","vip7800-H"],"cols":80,"lines":72,"bell":"\u0007","clear":"\u001b`","sgr0":"\u001bsR\u001bsU\u001bF","smul":"\u001bs_","blink":"\u001bsB","rev":"\u001bsI","dim":"\u001bsL","cup":"\u001b[%i%p1%03d%p2%03df","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b0","kf2":"\u001b2","kf3":"\u001b6","kf4":"\u001b8","kf5":"\u001b:","kf6":"\u001b\u003c","kf7":"\u001b\u003e","kf8":"\u001bP","kf9":"\u001bR","kf10":"\u001bT","kf11":"\u001b\\","kf12":"\u001b^","kf21":"\u001b1","kf22":"\u001b5","kf23":"\u001b7","kf24":"\u001b9","kf25":"\u001b;","kf26":"\u001b=","kf27":"\u001b?","kf28":"\u001bQ","kf29":"\u001bS","kf30":"\u001bV","kf31":"\u001b]","kf32":"\u001b_","kich":"\u001b[I","kdch":"\u001b[P","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b[Z","kclr":"\u001b`","acsc":"0pjdkblamcnkqitgufvhwexj","smacs":"\u001bG","rmacs":"\u001bF","kRIT":"\u001bu","kLFT":"\u001bo","kHOM":"\u001bH"} +{"name":"vip-Hw","aliases":["Q310-vip-Hw","vip7800-Hw"],"cols":132,"lines":72,"bell":"\u0007","clear":"\u001b`","sgr0":"\u001bsR\u001bsU\u001bF","smul":"\u001bs_","blink":"\u001bsB","rev":"\u001bsI","dim":"\u001bsL","cup":"\u001b[%i%p1%03d%p2%03df","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b0","kf2":"\u001b2","kf3":"\u001b6","kf4":"\u001b8","kf5":"\u001b:","kf6":"\u001b\u003c","kf7":"\u001b\u003e","kf8":"\u001bP","kf9":"\u001bR","kf10":"\u001bT","kf11":"\u001b\\","kf12":"\u001b^","kf21":"\u001b1","kf22":"\u001b5","kf23":"\u001b7","kf24":"\u001b9","kf25":"\u001b;","kf26":"\u001b=","kf27":"\u001b?","kf28":"\u001bQ","kf29":"\u001bS","kf30":"\u001bV","kf31":"\u001b]","kf32":"\u001b_","kich":"\u001b[I","kdch":"\u001b[P","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b[Z","kclr":"\u001b`","acsc":"0pjdkblamcnkqitgufvhwexj","smacs":"\u001bG","rmacs":"\u001bF","kRIT":"\u001bu","kLFT":"\u001bo","kHOM":"\u001bH"} +{"name":"vip-w","aliases":["Q310-vip-w","Q310-vip-w-am","vip7800-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b`","sgr0":"\u001bsR\u001bsU\u001bF","smul":"\u001bs_","blink":"\u001bsB","rev":"\u001bsI","dim":"\u001bsL","cup":"\u001b[%i%p1%03d%p2%03df","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001b0","kf2":"\u001b2","kf3":"\u001b6","kf4":"\u001b8","kf5":"\u001b:","kf6":"\u001b\u003c","kf7":"\u001b\u003e","kf8":"\u001bP","kf9":"\u001bR","kf10":"\u001bT","kf11":"\u001b\\","kf12":"\u001b^","kf21":"\u001b1","kf22":"\u001b5","kf23":"\u001b7","kf24":"\u001b9","kf25":"\u001b;","kf26":"\u001b=","kf27":"\u001b?","kf28":"\u001bQ","kf29":"\u001bS","kf30":"\u001bV","kf31":"\u001b]","kf32":"\u001b_","kich":"\u001b[I","kdch":"\u001b[P","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kcbt":"\u001b[Z","kclr":"\u001b`","acsc":"0pjdkblamcnkqitgufvhwexj","smacs":"\u001bG","rmacs":"\u001bF","kRIT":"\u001bu","kLFT":"\u001bo","kHOM":"\u001bH"} +{"name":"visa50","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[0;2m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b001","kf2":"\u001b002","kf3":"\u001b003","kf4":"\u001b004","kf5":"\u001b005","kf6":"\u001b006","kf7":"\u001b007","kf8":"\u001b008","kf9":"\u001b009","kf10":"\u001b011","kdch":"","khome":"\u001b[f","kcuu1":"\u001b[A","kcud1":"\u001b[A","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"0_aaffggh jjkkllmmnnooqqssttuuvvwwxx","smacs":"\u001b3h","rmacs":"\u001b[3l"} +{"name":"vp3a+","aliases":["viewpoint3a+"],"cols":80,"lines":24,"clear":"\u001b*$\u003c80\u003e","cnorm":"\u0018","civis":"\u0017","sgr0":"\u001b(","smul":"\u001b0`\u001b)","blink":"\u001b0B\u001b)","rev":"\u001b0P\u001b)","dim":"\u001b0A\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"vp60","aliases":["addsvp60","viewpoint60"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u001b0@","smul":"\u001b0`","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0015","cuu1":"\u001a","pad":"\u0000","kf1":"\u00022\r","kf2":"\u00023\r","kf3":"\u00024\r","kf4":"\u00025\r","kf5":"\u00026\r","kf6":"\u00027\r","kf7":"\u00028\r","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"vp90","aliases":["viewpoint90"],"cols":80,"lines":24,"clear":"\u001bG\u001bk","sgr0":"\u001bR\u001b0@\u001bV","smul":"\u001bR\u001b0`\u001bV","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","kf1":"\u00022\r","kf2":"\u00023\r","kf3":"\u00024\r","kf4":"\u00025\r","kf5":"\u00026\r","kf6":"\u00027\r","kf7":"\u00028\r","kf8":"\u00029\r","kf9":"\u0002:\r","kf10":"\u0002;\r","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"vremote","cols":79,"lines":24,"bell":"\u0007","clear":"\u001bL","smul":"\u001ba\u0001","cup":"\u001bG%p2%c%p1%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","khome":"\u001bE","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"vsc","cols":80,"lines":26,"clear":"\u001b[;H\u001b[2J$\u003c50/\u003e","sgr0":"\u001f!","smul":"\u001f\"","rev":"\u001f ","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kcud1":"\n","kcub1":"\u0008"} +{"name":"vt100","aliases":["vt100-am"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100-nav","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100-nav-w","aliases":["vt100-w-nav"],"cols":132,"lines":14,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100-putty","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100-s","aliases":["vt100-s-top","vt100-top-s"],"cols":80,"lines":23,"bell":"\u0007","clear":"\u001b[2;1H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%{1}%+%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100-s-bot","aliases":["vt100-bot-s"],"cols":80,"lines":23,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100-vb","cols":80,"lines":24,"clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100-w","aliases":["vt100-w-am"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100-w-nam","aliases":["vt100-nam-w"],"cols":132,"lines":14,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt100nam","aliases":["vt100-nam"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt102","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt102-nsgr","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt102-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt125","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J\u001bPpS(E)\u001b\\$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt131","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[;H\u001b[2J$\u003c50/\u003e","sgr0":"\u001b[m$\u003c2/\u003e","smul":"\u001b[4m$\u003c2/\u003e","bold":"\u001b[1m$\u003c2/\u003e","blink":"\u001b[5m$\u003c2/\u003e","rev":"\u001b[7m$\u003c2/\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5/\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2/\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"vt132","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m\u000f$\u003c2\u003e","smul":"\u001b[4m$\u003c2\u003e","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"vt200-js","aliases":["vt220-js"],"cols":80,"lines":-1,"bell":"\u0007","clear":"\u001b[H\u001b[J","smul":"\u001b[4m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"vt220","aliases":["vt200"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"vt220-8bit","aliases":["vt200-8","vt200-8bit","vt220-8"],"cols":80,"lines":24,"bell":"\u0007","clear":"\ufffdH\ufffdJ","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","cup":"\ufffd%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\ufffdA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\ufffd17~","kf7":"\ufffd18~","kf8":"\ufffd19~","kf9":"\ufffd20~","kf10":"\ufffd21~","kf11":"\ufffd23~","kf12":"\ufffd24~","kf13":"\ufffd25~","kf14":"\ufffd26~","kf17":"\ufffd31~","kf18":"\ufffd32~","kf19":"\ufffd33~","kf20":"\ufffd34~","kich":"\ufffd2~","khome":"\ufffdH","khlp":"\ufffd28~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b)0"} +{"name":"vt220-nam","aliases":["v200-nam"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"vt220-old","aliases":["vt200-old"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[17~","kf6":"\u001b[18~","kf7":"\u001b[19~","kf8":"\u001b[20~","kf9":"\u001b[21~","kf10":"\u001b[29~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt220-w","aliases":["vt200-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"vt220d","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt320","aliases":["vt300"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"vt320-k3","cols":80,"lines":49,"bell":"\u0007","clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kich":"\u001b[2~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"vt320-k311","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[;H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f"} +{"name":"vt320-nam","aliases":["vt300-nam"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"vt320-w","aliases":["vt300-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"vt320-w-nam","aliases":["vt300-w-nam"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"vt320nam","aliases":["v320n"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"vt340","aliases":["dec-vt330","dec-vt340","vt330"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"vt400","aliases":["dec-vt400","vt400-24"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[J$\u003c10/\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"vt420","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[17~","kf6":"\u001b[18~","kf7":"\u001b[19~","kf8":"\u001b[20~","kf9":"\u001b[21~","kf10":"\u001b[29~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt420f","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt420pc","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[11;2~","kf14":"\u001b[12;2~","kf15":"\u001b[13;2~","kf16":"\u001b[14;2~","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[23~","kf26":"\u001b[24~","kf27":"\u001b[25~","kf28":"\u001b[26~","kf29":"\u001b[28~","kf30":"\u001b[29~","kf31":"\u001b[31~","kf32":"\u001b[32~","kf33":"\u001b[33~","kf34":"\u001b[34~","kf35":"\u001b[35~","kf36":"\u001b[36~","kf37":"\u001b[23;2~","kf38":"\u001b[24;2~","kf39":"\u001b[25;2~","kf40":"\u001b[26;2~","kf41":"\u001b[28;2~","kf42":"\u001b[29;2~","kf43":"\u001b[31;2~","kf44":"\u001b[32;2~","kf45":"\u001b[33;2~","kf46":"\u001b[34;2~","kf47":"\u001b[35;2~","kf48":"\u001b[36;2~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt420pcdos","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[11;2~","kf14":"\u001b[12;2~","kf15":"\u001b[13;2~","kf16":"\u001b[14;2~","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[23~","kf26":"\u001b[24~","kf27":"\u001b[25~","kf28":"\u001b[26~","kf29":"\u001b[28~","kf30":"\u001b[29~","kf31":"\u001b[31~","kf32":"\u001b[32~","kf33":"\u001b[33~","kf34":"\u001b[34~","kf35":"\u001b[35~","kf36":"\u001b[36~","kf37":"\u001b[23;2~","kf38":"\u001b[24;2~","kf39":"\u001b[25;2~","kf40":"\u001b[26;2~","kf41":"\u001b[28;2~","kf42":"\u001b[29;2~","kf43":"\u001b[31;2~","kf44":"\u001b[32;2~","kf45":"\u001b[33;2~","kf46":"\u001b[34;2~","kf47":"\u001b[35;2~","kf48":"\u001b[36;2~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt50h","cols":80,"lines":12,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000"} +{"name":"vt510","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[17~","kf6":"\u001b[18~","kf7":"\u001b[19~","kf8":"\u001b[20~","kf9":"\u001b[21~","kf10":"\u001b[29~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt510pc","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[11;2~","kf14":"\u001b[12;2~","kf15":"\u001b[13;2~","kf16":"\u001b[14;2~","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[23~","kf26":"\u001b[24~","kf27":"\u001b[25~","kf28":"\u001b[26~","kf29":"\u001b[28~","kf30":"\u001b[29~","kf31":"\u001b[31~","kf32":"\u001b[32~","kf33":"\u001b[33~","kf34":"\u001b[34~","kf35":"\u001b[35~","kf36":"\u001b[36~","kf37":"\u001b[23;2~","kf38":"\u001b[24;2~","kf39":"\u001b[25;2~","kf40":"\u001b[26;2~","kf41":"\u001b[28;2~","kf42":"\u001b[29;2~","kf43":"\u001b[31;2~","kf44":"\u001b[32;2~","kf45":"\u001b[33;2~","kf46":"\u001b[34;2~","kf47":"\u001b[35;2~","kf48":"\u001b[36;2~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt510pcdos","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","smkx":"\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[11;2~","kf14":"\u001b[12;2~","kf15":"\u001b[13;2~","kf16":"\u001b[14;2~","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[23~","kf26":"\u001b[24~","kf27":"\u001b[25~","kf28":"\u001b[26~","kf29":"\u001b[28~","kf30":"\u001b[29~","kf31":"\u001b[31~","kf32":"\u001b[32~","kf33":"\u001b[33~","kf34":"\u001b[34~","kf35":"\u001b[35~","kf36":"\u001b[36~","kf37":"\u001b[23;2~","kf38":"\u001b[24;2~","kf39":"\u001b[25;2~","kf40":"\u001b[26;2~","kf41":"\u001b[28;2~","kf42":"\u001b[29;2~","kf43":"\u001b[31;2~","kf44":"\u001b[32;2~","kf45":"\u001b[33;2~","kf46":"\u001b[34;2~","kf47":"\u001b[35;2~","kf48":"\u001b[36;2~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt52","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"ffgghhompoqqss.k","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"vt520","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[17~","kf6":"\u001b[18~","kf7":"\u001b[19~","kf8":"\u001b[20~","kf9":"\u001b[21~","kf10":"\u001b[29~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt525","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J$\u003c50\u003e","sgr0":"\u001b[m$\u003c2\u003e","smul":"\u001b[4m","bold":"\u001b[1m$\u003c2\u003e","blink":"\u001b[5m$\u003c2\u003e","rev":"\u001b[7m$\u003c2\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c10\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[17~","kf6":"\u001b[18~","kf7":"\u001b[19~","kf8":"\u001b[20~","kf9":"\u001b[21~","kf10":"\u001b[29~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e"} +{"name":"vt61","aliases":["vt-61","vt61.5"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ$\u003c120\u003e","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c$\u003c20\u003e","cub1":"\u0008","cuu1":"\u001bA$\u003c20\u003e","pad":"\u0000","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"wsiris","aliases":["iris40"],"cols":80,"lines":40,"bell":"\u0007","clear":"\u001bv","cnorm":"\u001b\u003e","sgr0":"\u001b7F7","smul":"\u001b7R2\u001b9P","dim":"\u001b7F2","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kf1":"\u001b1","kf2":"\u001b2","kf3":"\u001b3","kf4":"\u001b4","kf5":"\u001b5","kf6":"\u001b6","kf7":"\u001b7","kf8":"\u001b8","kf9":"\u001b9","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} +{"name":"wsvt25","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khome":"\u001b[7~","kend":"\u001b[8~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"wsvt25m","cols":80,"lines":25,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khome":"\u001b[7~","kend":"\u001b[8~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"wy100","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b;","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","khome":"\u001b{","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"wy100q","cols":80,"lines":24,"clear":"\u001a","sgr0":"\u001bG0","smul":"\u001bG8","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"wy120","aliases":["wy150","wyse120","wyse150"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy120-25","aliases":["wy150-25","wyse120-25","wyse150-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy120-25-w","aliases":["wy150-25-w","wyse120-25-w","wyse150-25-w"],"cols":132,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy120-vb","aliases":["wy150-vb","wyse120-vb","wyse150-vb"],"cols":80,"lines":24,"clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy120-w","aliases":["wy150-w","wyse120-w","wyse150-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy120-w-vb","aliases":["wy120-wvb","wy150-w-vb","wyse120-wvb","wyse150-w-vb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160","aliases":["wyse160"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c30\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-25","aliases":["wyse160-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c30\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-25-w","aliases":["wyse160-25-w"],"cols":132,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c30\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-42","aliases":["wyse160-42"],"cols":80,"lines":42,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-42-w","aliases":["wyse160-42-w"],"cols":132,"lines":42,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-43","aliases":["wyse160-43"],"cols":80,"lines":43,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-43-w","aliases":["wyse160-43-w"],"cols":132,"lines":43,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-tek","cols":74,"lines":35,"bell":"\u0007","clear":"\u001b\u000c","cup":"\u001d%{3103}%'['%p1%*%-%Py%p2%'7'%*%Px%gy%{128}%/%{31}%\u0026%' '%+%c%gy%{3}%\u0026%{4}%*%gx%{3}%\u0026%+%'`'%+%c%gy%{004}%/%{31}%\u0026%'`'%+%c%gx%{128}%/%{31}%\u0026%' '%+%c%gx%{004}%/%{31}%\u0026%'@'%+%c\u001f","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"wy160-vb","aliases":["wyse160-vb"],"cols":80,"lines":24,"clear":"\u001b+$\u003c30\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-w","aliases":["wyse160-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c30\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy160-w-vb","aliases":["wy160-wvb","wyse160-wvb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c30\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy185","aliases":["wyse185"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy185-24","aliases":["wyse185-24"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy185-vb","aliases":["wyse185-vb"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy185-w","aliases":["wyse185-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy185-wvb","aliases":["wyse185-wvb"],"cols":132,"lines":24,"clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy30","aliases":["wyse30"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c80\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003","dim":"\u001b`7\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy30-mc","aliases":["wyse30-mc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c80\u003e","rmcup":"\u001bG0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001b(\u001bH\u0003","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bG0\u001bH\u0002","rmacs":"\u001bG0\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy30-vb","aliases":["wyse30-vb"],"cols":80,"lines":24,"clear":"\u001b+$\u003c80\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003","dim":"\u001b`7\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy325","aliases":["wyse325"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-25","aliases":["wy325-80","wyse-325","wyse325-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-25w","aliases":["wyse325-25w"],"cols":132,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-42","aliases":["wyse325-42"],"cols":80,"lines":42,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-42w","aliases":["wyse325-42w"],"cols":132,"lines":42,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-42w-vb","aliases":["wy325-42wvb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-43","aliases":["wyse325-43"],"cols":80,"lines":43,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-43w","aliases":["wyse325-43w"],"cols":132,"lines":43,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-43w-vb","aliases":["wy325-43wvb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-vb","aliases":["wyse325-vb"],"cols":80,"lines":24,"clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-w","aliases":["wy325w-24","wyse325-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy325-w-vb","aliases":["wy325-wvb","wyse325-wvb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c50\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bq","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy350","aliases":["wyse350"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001b(\u001bH\u0003%{0}%PA%{0}%PC","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bG0\u001bH\u0002","rmacs":"\u001bG0\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy350-vb","aliases":["wyse350-vb"],"cols":80,"lines":24,"clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001b(\u001bH\u0003%{0}%PA%{0}%PC","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bG0\u001bH\u0002","rmacs":"\u001bG0\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy350-w","aliases":["wyse350-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001b(\u001bH\u0003%{0}%PA%{0}%PC","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bG0\u001bH\u0002","rmacs":"\u001bG0\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy350-wvb","aliases":["wyse350-wvb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001b(\u001bH\u0003%{0}%PA%{0}%PC","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bG0\u001bH\u0002","rmacs":"\u001bG0\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy370","aliases":["wy370-101k","wyse370"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?4i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kich":"\u001bOP","kdch":"\u001bOQ","khome":"\u001b[H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy370-105k","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy370-EPC","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","khome":"\u001b[H","kend":"\u001b[1~","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy370-nk","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy370-rv","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?4i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kich":"\u001bOP","kdch":"\u001bOQ","khome":"\u001b[H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy370-tek","cols":80,"lines":36,"bell":"\u0007","clear":"\u001b\u000c","cup":"\u001d%{775}%'l'%p1%*%{5}%/%-%Py%p2%'@'%*%{4}%+%{5}%/%Px%gy%' '%/%{31}%\u0026%' '%+%c%gy%{31}%\u0026%'`'%+%c%gx%' '%/%{31}%\u0026%' '%+%c%gx%{31}%\u0026%'@'%+%c\u001f","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\t"} +{"name":"wy370-vb","cols":80,"lines":24,"clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?4i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kich":"\u001bOP","kdch":"\u001bOQ","khome":"\u001b[H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy370-w","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?4i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kich":"\u001bOP","kdch":"\u001bOQ","khome":"\u001b[H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy370-wvb","cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?4i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kich":"\u001bOP","kdch":"\u001bOQ","khome":"\u001b[H","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy50","aliases":["wyse50"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003","rev":"\u001b`6\u001b)","dim":"\u001b`7\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy50-mc","aliases":["wyse50-mc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","rmcup":"\u001bG0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001bG0\u001b(\u001bH\u0003","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bG0\u001bH\u0002","rmacs":"\u001bG0\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy50-vb","aliases":["wyse50-vb"],"cols":80,"lines":24,"clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003","rev":"\u001b`6\u001b)","dim":"\u001b`7\u001b)","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy50-w","aliases":["wyse50-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003","rev":"\u001b`6\u001b)","dim":"\u001b`7\u001b)","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy50-wvb","aliases":["wyse50-wvb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c20\u003e","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003","rev":"\u001b`6\u001b)","dim":"\u001b`7\u001b)","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"0wa_h[jukslrmqnxqzttuyv]wpxv","smacs":"\u001bH\u0002","rmacs":"\u001bH\u0003","kHOM":"\u001b{"} +{"name":"wy520","aliases":["wyse520"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-24","aliases":["wyse520-24"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-36","aliases":["wyse520-36"],"cols":80,"lines":36,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-36pc","aliases":["wyse520-36pc"],"cols":80,"lines":36,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-36w","aliases":["wyse520-36w"],"cols":132,"lines":36,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-36wpc","aliases":["wyse520-36wpc"],"cols":132,"lines":36,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-48","aliases":["wyse520-48"],"cols":80,"lines":48,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-48pc","aliases":["wyse520-48pc"],"cols":80,"lines":48,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-48w","aliases":["wyse520-48w"],"cols":132,"lines":48,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-48wpc","aliases":["wyse520-48wpc"],"cols":132,"lines":48,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-epc","aliases":["wyse520-epc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-epc-24","aliases":["wyse520-pc-24"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-epc-vb","aliases":["wyse520-pc-vb"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-epc-w","aliases":["wyse520-epc-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-epc-wvb","aliases":["wyse520-p-wvb"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001b[H","kend":"\u001b[4~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-vb","aliases":["wyse520-vb"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-w","aliases":["wyse520-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy520-wvb","aliases":["wyse520-wvb"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c40\u003e","smcup":"\u001b[ Q\u001b[?67;8h","rmcup":"\u001b[ R","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy60","aliases":["wyse60"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c100\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-25","aliases":["wyse60-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c100\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-25-w","aliases":["wyse60-25-w"],"cols":132,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c100\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-42","aliases":["wyse60-42"],"cols":80,"lines":42,"bell":"\u0007","clear":"\u001b+$\u003c260\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c2\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-42-w","aliases":["wyse60-42-w"],"cols":132,"lines":42,"bell":"\u0007","clear":"\u001b+$\u003c260\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c2\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-43","aliases":["wyse60-43"],"cols":80,"lines":43,"bell":"\u0007","clear":"\u001b+$\u003c260\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c$\u003c2\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-43-w","aliases":["wyse60-43-w"],"cols":132,"lines":43,"bell":"\u0007","clear":"\u001b+$\u003c260\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c2\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-vb","aliases":["wyse60-vb"],"cols":80,"lines":24,"clear":"\u001b+$\u003c100\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-w","aliases":["wyse60-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c100\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy60-w-vb","aliases":["wy60-wvb","wyse60-wvb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c100\u003e","smcup":"\u001bw0","rmcup":"\u001bw1","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy75","aliases":["wyse75"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c30\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[2t\u001b[4m","rev":"\u001b[1t\u001b[7m","dim":"\u001b[0t\u001b[2m","smkx":"\u001b[?1l\u001b[?7h\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?5i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[35~","kich":"\u001b[@","khome":"\u001b[H","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\u001b[?5i","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy75-mc","aliases":["wyse75-mc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c30\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0p\u000f","smul":"\u001b[8p","blink":"\u001b[2p","rev":"\u001b[16p","dim":"\u001b[1p","smkx":"\u001b[?1l\u001b[?7h\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?5i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[35~","kich":"\u001b[@","khome":"\u001b[H","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\u001b[?5i","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b[0p\u000e","rmacs":"\u001b[0p\u000f","enacs":"\u001b)0"} +{"name":"wy75-vb","aliases":["wyse75-vb"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[J$\u003c30\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[2t\u001b[4m","rev":"\u001b[1t\u001b[7m","dim":"\u001b[0t\u001b[2m","smkx":"\u001b[?1l\u001b[?7h\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?5i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[35~","kich":"\u001b[@","khome":"\u001b[H","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\u001b[?5i","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy75-w","aliases":["wyse75-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c30\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[2t\u001b[4m","rev":"\u001b[1t\u001b[7m","dim":"\u001b[0t\u001b[2m","smkx":"\u001b[?1l\u001b[?7h\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?5i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[35~","kich":"\u001b[@","khome":"\u001b[H","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\u001b[?5i","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy75-wvb","aliases":["wyse75-wvb"],"cols":132,"lines":24,"clear":"\u001b[H\u001b[J$\u003c30\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[2t\u001b[4m","rev":"\u001b[1t\u001b[7m","dim":"\u001b[0t\u001b[2m","smkx":"\u001b[?1l\u001b[?7h\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?5i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[35~","kich":"\u001b[@","khome":"\u001b[H","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kprt":"\u001b[?5i","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy75ap","aliases":["wy-75ap","wyse-75ap","wyse75ap"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c30\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[2t\u001b[4m","rev":"\u001b[1t\u001b[7m","dim":"\u001b[0t\u001b[2m","smkx":"\u001b[?1h\u001b=$\u003c10/\u003e","rmkx":"\u001b[?1l\u001b\u003e$\u003c10/\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[?5i","kf2":"\u001b[?3i","kf3":"\u001b[2i","kf4":"\u001b[@","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kf21":"\u001b[35~","kich":"\u001b[@","khome":"\u001bOH","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kprt":"\u001b[?5i","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy85","aliases":["wyse85"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c110\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy85-8bit","aliases":["wyse85-8bit"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c110\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\ufffd17~","kf7":"\ufffd18~","kf8":"\ufffd19~","kf9":"\ufffd20~","kf10":"\ufffd21~","kf11":"\ufffd23~","kf12":"\ufffd24~","kf13":"\ufffd25~","kf14":"\ufffd26~","kf15":"\ufffd28~","kf16":"\ufffd29~","kf17":"\ufffd31~","kf18":"\ufffd32~","kf19":"\ufffd33~","kf20":"\ufffd34~","kich":"\ufffd2~","kdch":"\ufffd3~","khome":"\ufffd26~","khlp":"\ufffd28~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy85-vb","aliases":["wyse85-vb"],"cols":80,"lines":24,"clear":"\u001b[H\u001b[J$\u003c110\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy85-w","aliases":["wyse85-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c110\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy85-wvb","aliases":["wyse85-wvb"],"cols":132,"lines":24,"clear":"\u001b[H\u001b[J$\u003c110\u003e","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1l\u001b=","rmkx":"\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c1\u003e","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[26~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy99-ansi","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c200\u003e","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f\u001b[\"q","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1h","rmkx":"\u001b[?1l","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008$\u003c1\u003e","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf17":"\u001b[K","kf18":"\u001b[31~","kf19":"\u001b[32~","kf20":"\u001b[33~","kf21":"\u001b[34~","kf22":"\u001b[35~","kf23":"\u001b[1~","kf24":"\u001b[2~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[z","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy99a-ansi","cols":80,"lines":25,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c200\u003e","cnorm":"\u001b[34h\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f\u001b[\"q","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[?1h","rmkx":"\u001b[?1l","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008$\u003c1\u003e","cuu1":"\u001bM","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[M","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf17":"\u001b[K","kf18":"\u001b[31~","kf19":"\u001b[32~","kf20":"\u001b[33~","kf21":"\u001b[34~","kf22":"\u001b[35~","kf23":"\u001b[1~","kf24":"\u001b[2~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[z","acsc":"``aaffggjjkkllmmnnooqqssttuuvvwwxx{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"wy99f","aliases":["wy-99fgt","wy99fgt"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b'\u001b(\u001a","smcup":"\u001bc20\u001bc30","rmcup":"\u001bc21\u001bc31","cnorm":"\u001b`4\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001`\r","kf14":"\u0001a\r","kf15":"\u0001b\r","kf16":"\u0001c\r","kf17":"\u0001d\r","kf18":"\u0001e\r","kf19":"\u0001f\r","kf20":"\u0001g\r","kf21":"\u0001h\r","kf22":"\u0001i\r","kf23":"\u0001j\r","kf24":"\u0001k\r","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"'x+y.wi~_vj(k'l\u0026m%n)o9q*s8t-u.v,w+x=","smacs":"\u001bcE","rmacs":"\u001bcD","enacs":"\u001bc@1J$\u003c2000\u003e"} +{"name":"wy99fa","aliases":["wy-99fgta","wy99fgta"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b'\u001b(\u001a","smcup":"\u001bc20\u001bc30","rmcup":"\u001bc21\u001bc31","cnorm":"\u001b`4\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bG0","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001`\r","kf14":"\u0001a\r","kf15":"\u0001b\r","kf16":"\u0001c\r","kf17":"\u0001d\r","kf18":"\u0001e\r","kf19":"\u0001f\r","kf20":"\u0001g\r","kf21":"\u0001h\r","kf22":"\u0001i\r","kf23":"\u0001j\r","kf24":"\u0001k\r","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"'x+y.wi~_vj(k'l\u0026m%n)o9q*s8t-u.v,w+x=","smacs":"\u001bcE","rmacs":"\u001bcD","enacs":"\u001bc@1J$\u003c2000\u003e"} +{"name":"wy99gt","aliases":["wyse99gt"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c130\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy99gt-25","aliases":["wyse99gt-25"],"cols":80,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c130\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy99gt-25-w","aliases":["wyse99gt-25-w"],"cols":132,"lines":25,"bell":"\u0007","clear":"\u001b+$\u003c160\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c2\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy99gt-tek","cols":74,"lines":35,"bell":"\u0007","clear":"\u001b\u000c","cup":"\u001d%{3040}%'Y'%p1%*%-%Py%p2%'7'%*%Px%gy%{128}%/%{31}%\u0026%' '%+%c%gy%{3}%\u0026%{4}%*%gx%{3}%\u0026%+%'`'%+%c%gy%{004}%/%{31}%\u0026%'`'%+%c%gx%{128}%/%{31}%\u0026%' '%+%c%gx%{004}%/%{31}%\u0026%'@'%+%c\u001f","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"wy99gt-vb","aliases":["wyse99gt-vb"],"cols":80,"lines":24,"clear":"\u001b+$\u003c130\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy99gt-w","aliases":["wyse99gt-w"],"cols":132,"lines":24,"bell":"\u0007","clear":"\u001b+$\u003c160\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c2\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wy99gt-w-vb","aliases":["wy99gt-wvb","wyse99gt-wvb"],"cols":132,"lines":24,"clear":"\u001b+$\u003c160\u003e","smcup":"\u001bw1","rmcup":"\u001bw0","cnorm":"\u001b`1","civis":"\u001b`0","sgr0":"\u001b(\u001bH\u0003\u001bG0\u001bcD","smul":"\u001bG8","blink":"\u001bG2","rev":"\u001bG4","dim":"\u001bGp","cup":"\u001ba%i%p1%dR%p2%dC$\u003c2\u003e","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","kbs":"\u0008","kf1":"\u0001@\r","kf2":"\u0001A\r","kf3":"\u0001B\r","kf4":"\u0001C\r","kf5":"\u0001D\r","kf6":"\u0001E\r","kf7":"\u0001F\r","kf8":"\u0001G\r","kf9":"\u0001H\r","kf10":"\u0001I\r","kf11":"\u0001J\r","kf12":"\u0001K\r","kf13":"\u0001L\r","kf14":"\u0001M\r","kf15":"\u0001N\r","kf16":"\u0001O\r","kich":"\u001bQ","kdch":"\u001bW","khome":"\u001e","kpp":"\u001bJ","knp":"\u001bK","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c","kcbt":"\u001bI","kprt":"\u001bP","acsc":"+/,.0[iha2fxgqh1jYk?lZm@nEqDtCu4vAwBx3yszr{c~~","smacs":"\u001bcE","rmacs":"\u001bcD","kHOM":"\u001b{"} +{"name":"wyse-vp","cols":80,"lines":24,"bell":"\u0007","clear":"\u000c","sgr0":"\u000f","smul":"\u000e","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001a","pad":"\u0000","kbs":"\u0008","khome":"\u0001","kcuu1":"\u001a","kcud1":"\n","kcub1":"\u0015","kcuf1":"\u0006"} +{"name":"x10term","aliases":["vs100-x10"],"cols":80,"lines":65,"clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"x68k","aliases":["x68k-ite"],"cols":96,"lines":32,"bell":"\u0007","clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","khlp":"\u001b[28~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kclr":"\u001b[9~","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0$\u003c2\u003e","rmacs":"\u001b(B$\u003c4\u003e","enacs":"\u001b)0"} +{"name":"xerox820","aliases":["x820"],"cols":80,"lines":24,"bell":"\u0007","clear":"1\u001a","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"xfce","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[0m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO1;2P","kf14":"\u001bO1;2Q","kf15":"\u001bO1;2R","kf16":"\u001bO1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO1;5P","kf26":"\u001bO1;5Q","kf27":"\u001bO1;5R","kf28":"\u001bO1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO1;6P","kf38":"\u001bO1;6Q","kf39":"\u001bO1;6R","kf40":"\u001bO1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001bO1;3P","kf50":"\u001bO1;3Q","kf51":"\u001bO1;3R","kf52":"\u001bO1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001bO1;4P","kf62":"\u001bO1;4Q","kf63":"\u001bO1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xiterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc","aliases":["darwin"],"cols":-1,"lines":-1,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc+b","cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[35m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc+basic","cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc+f","cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[36;4m","bold":"\u001b[35m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc+f2","cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[34m","bold":"\u001b[33m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-100x37","aliases":["darwin-100x37"],"cols":100,"lines":37,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-100x37-m","aliases":["darwin-100x37-m"],"cols":100,"lines":37,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-112x37","aliases":["darwin-112x37"],"cols":112,"lines":37,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-112x37-m","aliases":["darwin-112x37-m"],"cols":112,"lines":37,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-128x40","aliases":["darwin-128x40"],"cols":128,"lines":40,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-128x40-m","aliases":["darwin-128x40-m"],"cols":128,"lines":40,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-128x48","aliases":["darwin-128x48"],"cols":128,"lines":48,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-128x48-m","aliases":["darwin-128x48-m"],"cols":128,"lines":48,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-144x48","aliases":["darwin-144x48"],"cols":144,"lines":48,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-144x48-m","aliases":["darwin-144x48-m"],"cols":144,"lines":48,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-160x64","aliases":["darwin-160x64"],"cols":160,"lines":64,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-160x64-m","aliases":["darwin-160x64-m"],"cols":160,"lines":64,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-200x64","aliases":["darwin-200x64"],"cols":200,"lines":64,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-200x64-m","aliases":["darwin-200x64-m"],"cols":200,"lines":64,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-200x75","aliases":["darwin-200x75"],"cols":200,"lines":75,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-200x75-m","aliases":["darwin-200x75-m"],"cols":200,"lines":75,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-256x96","aliases":["darwin-256x96"],"cols":256,"lines":96,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-256x96-m","aliases":["darwin-256x96-m"],"cols":256,"lines":96,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-80x25","aliases":["darwin-80x25"],"cols":80,"lines":25,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-80x25-m","aliases":["darwin-80x25-m"],"cols":80,"lines":25,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-80x30","aliases":["darwin-80x30"],"cols":80,"lines":30,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-80x30-m","aliases":["darwin-80x30-m"],"cols":80,"lines":30,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-90x30","aliases":["darwin-90x30"],"cols":90,"lines":30,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-90x30-m","aliases":["darwin-90x30-m"],"cols":90,"lines":30,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-b","aliases":["darwin-b"],"cols":-1,"lines":-1,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[35m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-f","aliases":["darwin-f"],"cols":-1,"lines":-1,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[36;4m","bold":"\u001b[35m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-f2","aliases":["darwin-f2"],"cols":-1,"lines":-1,"colors":8,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[34m","bold":"\u001b[33m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xnuppc-m","aliases":["darwin-m"],"cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-m-b","aliases":["darwin-m-b"],"cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[35m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-m-f","aliases":["darwin-m-f"],"cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[36;4m","bold":"\u001b[35m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xnuppc-m-f2","aliases":["darwin-m-f2"],"cols":-1,"lines":-1,"clear":"\u001b[H\u001b[J","sgr0":"\u001b[m\u000f","smul":"\u001b[34m","bold":"\u001b[33m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[D","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC"} +{"name":"xtalk","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[J$\u003c50\u003e","sgr0":"\u001b[m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH$\u003c5\u003e","cub1":"\u0008","cuu1":"\u001b[A$\u003c2\u003e","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOt","kf6":"\u001bOu","kf7":"\u001bOv","kf8":"\u001bOl","kf9":"\u001bOw","kf10":"\u001bOx","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"xterm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm+sl","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm+sl-twm","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-1002","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"\u001b[?1002%?%p1%{1}%=%th%el%;","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-1003","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"\u001b[?1003%?%p1%{1}%=%th%el%;","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-16color","cols":80,"lines":24,"colors":16,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%dm","setbg":"\u001b[%?%p1%{8}%\u003c%t%p1%'('%+%e%p1%{92}%+%;%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t%p1%{30}%+%e%p1%'R'%+%;%d;%?%p2%{8}%\u003c%t%p2%'('%+%e%p2%{92}%+%;%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-24","aliases":["vs100","xterms"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"xterm-256color","cols":80,"lines":24,"colors":256,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-88color","cols":80,"lines":24,"colors":88,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;m","setbg":"\u001b[%?%p1%{8}%\u003c%t4%p1%d%e%p1%{16}%\u003c%t10%p1%{8}%-%d%e48;5;%p1%d%;m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[%?%p1%{8}%\u003c%t3%p1%d%e%p1%{16}%\u003c%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%\u003c%t4%p2%d%e%p2%{16}%\u003c%t10%p2%{8}%-%d%e48;5;%p2%d%;m","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-8bit","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\ufffdH\ufffd2J","smcup":"\ufffd?1049h","rmcup":"\ufffd?1049l","cnorm":"\ufffd?25l\ufffd?25h","civis":"\ufffd?25l","sgr0":"\ufffd0m\u001b(B","smul":"\ufffd4m","bold":"\ufffd1m","blink":"\ufffd5m","rev":"\ufffd7m","smkx":"\ufffd?1h\u001b=","rmkx":"\ufffd?1l\u001b\u003e","setaf":"\ufffd3%p1%dm","setbg":"\ufffd4%p1%dm","cup":"\ufffd%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\ufffdA","kbs":"\u0008","kf1":"\ufffd11~","kf2":"\ufffd12~","kf3":"\ufffd13~","kf4":"\ufffd14~","kf5":"\ufffd15~","kf6":"\ufffd17~","kf7":"\ufffd18~","kf8":"\ufffd19~","kf9":"\ufffd20~","kf10":"\ufffd21~","kf11":"\ufffd23~","kf12":"\ufffd24~","kf13":"\ufffd25~","kf14":"\ufffd26~","kf15":"\ufffd28~","kf16":"\ufffd29~","kf17":"\ufffd31~","kf18":"\ufffd32~","kf19":"\ufffd33~","kf20":"\ufffd34~","kich":"\ufffd2~","kdch":"\ufffd3~","khome":"\ufffd1~","kend":"\ufffd4~","kpp":"\ufffd5~","knp":"\ufffd6~","kcuu1":"\ufffdA","kcud1":"\ufffdB","kcub1":"\ufffdD","kcuf1":"\ufffdC","kcbt":"\ufffdZ","kmous":"\ufffdM","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"xterm-basic","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-bold","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[1m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"xterm-color","aliases":["nxterm"],"cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-hp","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bp","kf2":"\u001bq","kf3":"\u001br","kf4":"\u001bs","kf5":"\u001bt","kf6":"\u001bu","kf7":"\u001bv","kf8":"\u001bw","kich":"\u001bQ","kdch":"\u001bP","khome":"\u001bh","kend":"\u001bF","kpp":"\u001bT","knp":"\u001bS","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","kclr":"\u001bJ","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-new","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-nic","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-noapp","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b=","rmkx":"\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-pcolor","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m\u001b[42m","bold":"\u001b[1m\u001b[43m","blink":"\u001b[5m","rev":"\u001b[7m\u001b[34m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","enacs":"\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-r5","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c"} +{"name":"xterm-r6","aliases":["xterm-old"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b)0"} +{"name":"xterm-sco","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[M","kf2":"\u001b[N","kf3":"\u001b[O","kf4":"\u001b[P","kf5":"\u001b[Q","kf6":"\u001b[R","kf7":"\u001b[S","kf8":"\u001b[T","kf9":"\u001b[U","kf10":"\u001b[V","kf11":"\u001b[W","kf12":"\u001b[X","kf13":"\u001b[Y","kf14":"\u001b[Z","kf15":"\u001b[a","kf16":"\u001b[b","kf17":"\u001b[c","kf18":"\u001b[d","kf19":"\u001b[e","kf20":"\u001b[f","kf21":"\u001b[g","kf22":"\u001b[h","kf23":"\u001b[i","kf24":"\u001b[j","kf25":"\u001b[k","kf26":"\u001b[l","kf27":"\u001b[m","kf28":"\u001b[n","kf29":"\u001b[o","kf30":"\u001b[p","kf31":"\u001b[q","kf32":"\u001b[r","kf33":"\u001b[s","kf34":"\u001b[t","kf35":"\u001b[u","kf36":"\u001b[v","kf37":"\u001b[w","kf38":"\u001b[x","kf39":"\u001b[y","kf40":"\u001b[z","kf41":"\u001b[@","kf42":"\u001b[[","kf43":"\u001b[\\","kf44":"\u001b[]","kf45":"\u001b[^","kf46":"\u001b[_","kf47":"\u001b[`","kf48":"\u001b[{","kich":"\u001b[L","kdch":"","khome":"\u001b[H","kend":"\u001b[F","kpp":"\u001b[I","knp":"\u001b[G","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","kmous":"\u001b[\u003eM","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-sun","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[192z","kf12":"\u001b[193z","kf13":"\u001b[194z","kf14":"\u001b[195z","kf15":"\u001b[196z","kf17":"\u001b[198z","kf18":"\u001b[199z","kf19":"\u001b[200z","kf20":"\u001b[201z","kf31":"\u001b[208z","kf32":"\u001b[209z","kf33":"\u001b[210z","kf34":"\u001b[211z","kf35":"\u001b[212z","kf36":"\u001b[213z","kf38":"\u001b[215z","kf40":"\u001b[217z","kf42":"\u001b[219z","kf44":"\u001b[221z","kf45":"\u001b[222z","kf46":"\u001b[234z","kf47":"\u001b[235z","kich":"\u001b[2z","kdch":"\u001b[3z","khome":"\u001b[214z","kend":"\u001b[220z","khlp":"\u001b[196z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-vt220","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kend":"\u001b[4~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-vt52","cols":80,"lines":24,"bell":"\u0007","clear":"\u001bH\u001bJ","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u001bD","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"xterm-xf86-v32","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[11~","kf2":"\u001b[12~","kf3":"\u001b[13~","kf4":"\u001b[14~","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-xf86-v33","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-xf86-v333","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1048h\u001b[?1047h","rmcup":"\u001b[?1047l\u001b[?1048l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-xf86-v40","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001bO5C","kLFT":"\u001bO5D","kHOM":"\u001bO5H","kEND":"\u001bO5F","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm-xf86-v43","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-xf86-v44","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-xfree86","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001bO2P","kf14":"\u001bO2Q","kf15":"\u001bO2R","kf16":"\u001bO2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001bO5P","kf26":"\u001bO5Q","kf27":"\u001bO5R","kf28":"\u001bO5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001bO6P","kf38":"\u001bO6Q","kf39":"\u001bO6R","kf40":"\u001bO6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xterm-xi","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b7\u001b[?47h","rmcup":"\u001b[2J\u001b[?47l\u001b8","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u000f","smul":"\u001b[4m","bold":"\u001b[1m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xterm1","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001b[15~","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[1;2P","kf14":"\u001b[1;2Q","kf15":"\u001b[1;2R","kf16":"\u001b[1;2S","kf17":"\u001b[15;2~","kf18":"\u001b[17;2~","kf19":"\u001b[18;2~","kf20":"\u001b[19;2~","kf21":"\u001b[20;2~","kf22":"\u001b[21;2~","kf23":"\u001b[23;2~","kf24":"\u001b[24;2~","kf25":"\u001b[1;5P","kf26":"\u001b[1;5Q","kf27":"\u001b[1;5R","kf28":"\u001b[1;5S","kf29":"\u001b[15;5~","kf30":"\u001b[17;5~","kf31":"\u001b[18;5~","kf32":"\u001b[19;5~","kf33":"\u001b[20;5~","kf34":"\u001b[21;5~","kf35":"\u001b[23;5~","kf36":"\u001b[24;5~","kf37":"\u001b[1;6P","kf38":"\u001b[1;6Q","kf39":"\u001b[1;6R","kf40":"\u001b[1;6S","kf41":"\u001b[15;6~","kf42":"\u001b[17;6~","kf43":"\u001b[18;6~","kf44":"\u001b[19;6~","kf45":"\u001b[20;6~","kf46":"\u001b[21;6~","kf47":"\u001b[23;6~","kf48":"\u001b[24;6~","kf49":"\u001b[1;3P","kf50":"\u001b[1;3Q","kf51":"\u001b[1;3R","kf52":"\u001b[1;3S","kf53":"\u001b[15;3~","kf54":"\u001b[17;3~","kf55":"\u001b[18;3~","kf56":"\u001b[19;3~","kf57":"\u001b[20;3~","kf58":"\u001b[21;3~","kf59":"\u001b[23;3~","kf60":"\u001b[24;3~","kf61":"\u001b[1;4P","kf62":"\u001b[1;4Q","kf63":"\u001b[1;4R","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001bOH","kend":"\u001bOF","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kcbt":"\u001b[Z","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","kRIT":"\u001b[1;2C","kLFT":"\u001b[1;2D","kHOM":"\u001b[1;2H","kEND":"\u001b[1;2F","_setfgbg":"\u001b[3%p1%d;4%p2%dm","_kscu1":"\u001b[1;2A","_kscud1":"\u001b[1;2B","_kccu1":"\u001b[1;5A","_kccud1":"\u001b[1;5B","_kccuf1":"\u001b[1;5C","_kccub1":"\u001b[1;5D","_kmcu1":"\u001b[1;9A","_kmcud1":"\u001b[1;9B","_kmcuf1":"\u001b[1;9C","_kmcub1":"\u001b[1;9D","_kacu1":"\u001b[1;3A","_kacud1":"\u001b[1;3B","_kacuf1":"\u001b[1;3C","_kacub1":"\u001b[1;3D","_kchome":"\u001b[1;5H","_kcend":"\u001b[1;5F","_kahome":"\u001b[1;9H","_kaend":"\u001b[1;9F","_kascu1":"\u001b[1;4A","_kascud1":"\u001b[1;4B","_kascub1":"\u001b[1;4D","_kascuf1":"\u001b[1;4C","_kmscu1":"\u001b[1;10A","_kmscud1":"\u001b[1;10B","_kmscub1":"\u001b[1;10D","_kmscuf1":"\u001b[1;10C","_kcscu1":"\u001b[1;6A","_kcscud1":"\u001b[1;6B","_kcscub1":"\u001b[1;6D","_kcscuf1":"\u001b[1;6C","_kcHOME":"\u001b[1;6H","_kcEND":"\u001b[1;6F","_kaHOME":"\u001b[1;4H","_kaEND":"\u001b[1;4F","_kmHOME":"\u001b[1;10H","_kmEND":"\u001b[1;10F"} +{"name":"xtermc","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b@0\u001b[?4s\u001b[?4h\u001b@1","rmcup":"\u001b@0\u001b[?4r","sgr0":"\u001b[m\u000f","bold":"\u001b[1m","rev":"\u001b[7m","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[1D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","khome":"\u001b[H","kend":"\u001b[Y","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[\u001f","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"xtermm","cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b@0\u001b[?4s\u001b[?4h\u001b@1","rmcup":"\u001b@0\u001b[?4r","sgr0":"\u001b[m\u000f","bold":"\u001b[1m","rev":"\u001b[7m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u001b[1D","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf5":"\u001bOT","kf6":"\u001bOU","kf7":"\u001bOV","kf8":"\u001bOW","kf9":"\u001bOX","kf10":"\u001bOY","kf11":"\u001bOZ","kf12":"\u001bOA","khome":"\u001b[H","kend":"\u001b[Y","kpp":"\u001b[V","knp":"\u001b[U","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[\u001f","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u000e","rmacs":"\u000f","enacs":"\u001b(B\u001b)0"} +{"name":"xterms-sun","cols":80,"lines":24,"colors":8,"bell":"\u0007","clear":"\u001b[H\u001b[2J","smcup":"\u001b[?1049h","rmcup":"\u001b[?1049l","cnorm":"\u001b[?12l\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b(B\u001b[m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","setaf":"\u001b[3%p1%dm","setbg":"\u001b[4%p1%dm","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001b[224z","kf2":"\u001b[225z","kf3":"\u001b[226z","kf4":"\u001b[227z","kf5":"\u001b[228z","kf6":"\u001b[229z","kf7":"\u001b[230z","kf8":"\u001b[231z","kf9":"\u001b[232z","kf10":"\u001b[233z","kf11":"\u001b[192z","kf12":"\u001b[193z","kf13":"\u001b[194z","kf14":"\u001b[195z","kf15":"\u001b[196z","kf17":"\u001b[198z","kf18":"\u001b[199z","kf19":"\u001b[200z","kf20":"\u001b[201z","kf31":"\u001b[208z","kf32":"\u001b[209z","kf33":"\u001b[210z","kf34":"\u001b[211z","kf35":"\u001b[212z","kf36":"\u001b[213z","kf38":"\u001b[215z","kf40":"\u001b[217z","kf42":"\u001b[219z","kf44":"\u001b[221z","kf45":"\u001b[222z","kf46":"\u001b[234z","kf47":"\u001b[235z","kich":"\u001b[2z","kdch":"\u001b[3z","khome":"\u001b[214z","kend":"\u001b[220z","khlp":"\u001b[196z","kpp":"\u001b[216z","knp":"\u001b[222z","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kmous":"\u001b[M","XM":"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\u001b[?1000%ga%c\u001b[?1002%ga%c\u001b[?1003%ga%c\u001b[?1006%ga%c","acsc":"``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B","_setfgbg":"\u001b[3%p1%d;4%p2%dm"} +{"name":"z100","aliases":["h-100","h100","z-100","z110"],"cols":80,"lines":24,"clear":"\u001bE$\u003c5*/\u003e","cnorm":"\u001by4\u001bm70","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c$\u003c1*/\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bOI","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"z100bw","aliases":["h-100bw","h100bw","z-100bw","z110bw"],"cols":80,"lines":24,"clear":"\u001bE$\u003c5*/\u003e","cnorm":"\u001by4","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c$\u003c1*/\u003e","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001bOI","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","acsc":"~^x`qanbkcjdmelfgg+hai.kwsutvutvozs{","smacs":"\u001bF","rmacs":"\u001bG"} +{"name":"z29","aliases":["z29b","zenith29"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001bE$\u003c14\u003e","cnorm":"\u001by4","smul":"\u001bs8","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001b$\u003c1\u003eA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bS","kf2":"\u001bT","kf3":"\u001bU","kf4":"\u001bV","kf5":"\u001bW","kf6":"\u001bP","kf7":"\u001bQ","kf8":"\u001bR","kf9":"\u001b0I","khome":"\u001bH","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC","smacs":"\u001bG","rmacs":"\u001bF"} +{"name":"z29a","aliases":["h29a-kc-bc","z29a-kc-bc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?7l","rmcup":"\u001b[?7h","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[2m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOS","kf2":"\u001bOT","kf3":"\u001bOU","kf4":"\u001bOV","kf5":"\u001bOW","kf6":"\u001bOP","kf7":"\u001bOQ","kf8":"\u001bOR","kf9":"\u001bOX","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kclr":"\u001b[J"} +{"name":"z29a-kc-uc","aliases":["h29a-kc-uc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?7l","rmcup":"\u001b[?7h","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[2m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOS","kf2":"\u001bOT","kf3":"\u001bOU","kf4":"\u001bOV","kf5":"\u001bOW","kf6":"\u001bOP","kf7":"\u001bOQ","kf8":"\u001bOR","kf9":"\u001bOX","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kclr":"\u001b[J"} +{"name":"z29a-nkc-bc","aliases":["h29a-nkc-bc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?7l","rmcup":"\u001b[?7h","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[2m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOS","kf2":"\u001bOT","kf3":"\u001bOU","kf4":"\u001bOV","kf5":"\u001bOW","kf6":"\u001bOP","kf7":"\u001bOQ","kf8":"\u001bOR","kf9":"\u001bOX","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kclr":"\u001b[J"} +{"name":"z29a-nkc-uc","aliases":["h29a-nkc-uc"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J","smcup":"\u001b[?7l","rmcup":"\u001b[?7h","sgr0":"\u001b[m","smul":"\u001b[4m","bold":"\u001b[2m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOS","kf2":"\u001bOT","kf3":"\u001bOU","kf4":"\u001bOV","kf5":"\u001bOW","kf6":"\u001bOP","kf7":"\u001bOQ","kf8":"\u001bOR","kf9":"\u001bOX","khome":"\u001b[H","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","kclr":"\u001b[J"} +{"name":"z340","cols":132,"lines":42,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"z340-nam","cols":132,"lines":42,"bell":"\u0007","clear":"\u001b[H\u001b[2J","cnorm":"\u001b[?25h","civis":"\u001b[?25l","sgr0":"\u001b[m\u001b(B","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","smkx":"\u001b[?1h\u001b=","rmkx":"\u001b[?1l\u001b\u003e","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"","kf1":"\u001bOP","kf2":"\u001bOQ","kf3":"\u001bOR","kf4":"\u001bOS","kf6":"\u001b[17~","kf7":"\u001b[18~","kf8":"\u001b[19~","kf9":"\u001b[20~","kf10":"\u001b[21~","kf11":"\u001b[23~","kf12":"\u001b[24~","kf13":"\u001b[25~","kf14":"\u001b[26~","kf15":"\u001b[28~","kf16":"\u001b[29~","kf17":"\u001b[31~","kf18":"\u001b[32~","kf19":"\u001b[33~","kf20":"\u001b[34~","kich":"\u001b[2~","kdch":"\u001b[3~","khome":"\u001b[1~","kpp":"\u001b[5~","knp":"\u001b[6~","kcuu1":"\u001bOA","kcud1":"\u001bOB","kcub1":"\u001bOD","kcuf1":"\u001bOC","acsc":"``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"z39-a","aliases":["z39a","zenith39-a","zenith39-ansi"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b[2J\u001b[H","cnorm":"\u001b[\u003e5l","civis":"\u001b[\u003e5h","sgr0":"\u001b[0m","smul":"\u001b[4m","bold":"\u001b[1m","blink":"\u001b[5m","rev":"\u001b[7m","dim":"\u001b[2m","smkx":"\u001b[\u003e7h","rmkx":"\u001b[\u003e7l","cup":"\u001b[%i%p1%d;%p2%dH","cub1":"\u0008","cuu1":"\u001b[A","pad":"\u0000","kbs":"\u0008","kf1":"\u001bOS","kf2":"\u001bOT","kf3":"\u001bOU","kf4":"\u001bOV","kf5":"\u001bOW","kf6":"\u001bOP","kf7":"\u001bOQ","kf8":"\u001bOR","kf9":"\u001bOX","khome":"\u001b[H","khlp":"\u001b[~","kcuu1":"\u001b[A","kcud1":"\u001b[B","kcub1":"\u001b[D","kcuf1":"\u001b[C","acsc":"0a``aaffggjjkkllmmnnooqqssttuuvvwwxx~~","smacs":"\u001b(0","rmacs":"\u001b(B"} +{"name":"zen30","aliases":["z30"],"cols":80,"lines":24,"bell":"\u0007","clear":"\u001b*","sgr0":"\u001bG0","rev":"\u001bG4","dim":"\u001bG2","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000"} +{"name":"zen50","aliases":["z50"],"cols":80,"lines":24,"clear":"\u001b+","sgr0":"\u001bG0","rev":"\u001bG4","cup":"\u001b=%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u000b","pad":"\u0000","khome":"\u001e","kcuu1":"\u000b","kcud1":"\n","kcub1":"\u0008","kcuf1":"\u000c"} +{"name":"ztx","aliases":["htx11","zt-1","ztx-1-a","ztx11"],"cols":80,"lines":24,"clear":"\u001bE","smul":"\u001bs2","cup":"\u001bY%p1%' '%+%c%p2%' '%+%c","cub1":"\u0008","cuu1":"\u001bA","pad":"\u0000","kbs":"\u0008","kf1":"\u001bB","kf2":"\u001bU","kf3":"\u001bV","kf4":"\u001bW","kf5":"\u001bP","kf6":"\u001bQ","kf7":"\u001bR","kcuu1":"\u001bA","kcud1":"\u001bB","kcub1":"\u001bD","kcuf1":"\u001bC"} diff --git a/vendor/github.com/gdamore/tcell/doc.go b/vendor/github.com/gdamore/tcell/doc.go new file mode 100644 index 00000000..93ebecfd --- /dev/null +++ b/vendor/github.com/gdamore/tcell/doc.go @@ -0,0 +1,40 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package tcell provides a lower-level, portable API for building +// programs that interact with terminals or consoles. It works with +// both common (and many uncommon!) terminals or terminal emulators, +// and Windows console implementations. +// +// It provides support for up to 256 colors, text attributes, and box drawing +// elements. A database of terminals built from a real terminfo database +// is provided, along with code to generate new database entries. +// +// Tcell offers very rich support for mice, dependent upon the terminal +// of course. (Windows, XTerm, and iTerm 2 are known to work very well.) +// +// If the environment is not Unicode by default, such as an ISO8859 based +// locale or GB18030, Tcell can convert input and outupt, so that your +// terminal can operate in whatever locale is most convenient, while the +// application program can just assume "everything is UTF-8". Reasonable +// defaults are used for updating characters to something suitable for +// display. Unicode box drawing characters will be converted to use the +// alternate character set of your terminal, if native conversions are +// not available. If no ACS is available, then some ASCII fallbacks will +// be used. +// +// A rich set of keycodes is supported, with support for up to 65 function +// keys, and various other special keys. +// +package tcell diff --git a/vendor/github.com/gdamore/tcell/encoding.go b/vendor/github.com/gdamore/tcell/encoding.go new file mode 100644 index 00000000..596a6e80 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/encoding.go @@ -0,0 +1,139 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "strings" + "sync" + + "golang.org/x/text/encoding" + + gencoding "github.com/gdamore/encoding" +) + +var encodings map[string]encoding.Encoding +var encodingLk sync.Mutex +var encodingFallback EncodingFallback = EncodingFallbackFail + +// RegisterEncoding may be called by the application to register an encoding. +// The presence of additional encodings will facilitate application usage with +// terminal environments where the I/O subsystem does not support Unicode. +// +// Windows systems use Unicode natively, and do not need any of the encoding +// subsystem when using Windows Console screens. +// +// Please see the Go documentation for golang.org/x/text/encoding -- most of +// the common ones exist already as stock variables. For example, ISO8859-15 +// can be registered using the following code: +// +// import "golang.org/x/text/encoding/charmap" +// +// ... +// RegisterEncoding("ISO8859-15", charmap.ISO8859_15) +// +// Aliases can be registered as well, for example "8859-15" could be an alias +// for "ISO8859-15". +// +// For POSIX systems, the tcell package will check the environment variables +// LC_ALL, LC_CTYPE, and LANG (in that order) to determine the character set. +// These are expected to have the following pattern: +// +// $language[.$codeset[@$variant] +// +// We extract only the $codeset part, which will usually be something like +// UTF-8 or ISO8859-15 or KOI8-R. Note that if the locale is either "POSIX" +// or "C", then we assume US-ASCII (the POSIX 'portable character set' +// and assume all other characters are somehow invalid.) +// +// Modern POSIX systems and terminal emulators may use UTF-8, and for those +// systems, this API is also unnecessary. For example, Darwin (MacOS X) and +// modern Linux running modern xterm generally will out of the box without +// any of this. Use of UTF-8 is recommended when possible, as it saves +// quite a lot processing overhead. +// +// Note that some encodings are quite large (for example GB18030 which is a +// superset of Unicode) and so the application size can be expected ot +// increase quite a bit as each encoding is added. The East Asian encodings +// have been seen to add 100-200K per encoding to the application size. +// +func RegisterEncoding(charset string, enc encoding.Encoding) { + encodingLk.Lock() + charset = strings.ToLower(charset) + encodings[charset] = enc + encodingLk.Unlock() +} + +// EncodingFallback describes how the system behavees when the locale +// requires a character set that we do not support. The system always +// supports UTF-8 and US-ASCII. On Windows consoles, UTF-16LE is also +// supported automatically. Other character sets must be added using the +// RegisterEncoding API. (A large group of nearly all of them can be +// added using the RegisterAll function in the encoding sub package.) +type EncodingFallback int + +const ( + // EncodingFallbackFail behavior causes GetEncoding to fail + // when it cannot find an encoding. + EncodingFallbackFail = iota + + // EncodingFallbackASCII behaviore causes GetEncoding to fall back + // to a 7-bit ASCII encoding, if no other encoding can be found. + EncodingFallbackASCII + + // EncodingFallbackUTF8 behavior causes GetEncoding to assume + // UTF8 can pass unmodified upon failure. Note that this behavior + // is not recommended, unless you are sure your terminal can cope + // with real UTF8 sequences. + EncodingFallbackUTF8 +) + +// SetEncodingFallback changes the behavior of GetEncoding when a suitable +// encoding is not found. The default is EncodingFallbackFail, which +// causes GetEncoding to simply return nil. +func SetEncodingFallback(fb EncodingFallback) { + encodingLk.Lock() + encodingFallback = fb + encodingLk.Unlock() +} + +// GetEncoding is used by Screen implementors who want to locate an encoding +// for the given character set name. Note that this will return nil for +// either the Unicode (UTF-8) or ASCII encodings, since we don't use +// encodings for them but instead have our own native methods. +func GetEncoding(charset string) encoding.Encoding { + charset = strings.ToLower(charset) + encodingLk.Lock() + defer encodingLk.Unlock() + if enc, ok := encodings[charset]; ok { + return enc + } + switch encodingFallback { + case EncodingFallbackASCII: + return gencoding.ASCII + case EncodingFallbackUTF8: + return encoding.Nop + } + return nil +} + +func init() { + // We always support UTF-8 and ASCII. + encodings = make(map[string]encoding.Encoding) + encodings["utf-8"] = gencoding.UTF8 + encodings["utf8"] = gencoding.UTF8 + encodings["us-ascii"] = gencoding.ASCII + encodings["ascii"] = gencoding.ASCII + encodings["iso646"] = gencoding.ASCII +} diff --git a/vendor/github.com/gdamore/tcell/errors.go b/vendor/github.com/gdamore/tcell/errors.go new file mode 100644 index 00000000..920b64b2 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/errors.go @@ -0,0 +1,73 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "errors" + "time" + + "github.com/gdamore/tcell/terminfo" +) + +var ( + // ErrTermNotFound indicates that a suitable terminal entry could + // not be found. This can result from either not having TERM set, + // or from the TERM failing to support certain minimal functionality, + // in particular absolute cursor addressability (the cup capability) + // is required. For example, legacy "adm3" lacks this capability, + // whereas the slightly newer "adm3a" supports it. This failure + // occurs most often with "dumb". + ErrTermNotFound = terminfo.ErrTermNotFound + + // ErrNoScreen indicates that no suitable screen could be found. + // This may result from attempting to run on a platform where there + // is no support for either termios or console I/O (such as nacl), + // or from running in an environment where there is no access to + // a suitable console/terminal device. (For example, running on + // without a controlling TTY or with no /dev/tty on POSIX platforms.) + ErrNoScreen = errors.New("no suitable screen available") + + // ErrNoCharset indicates that the locale environment the + // program is not supported by the program, because no suitable + // encoding was found for it. This problem never occurs if + // the environment is UTF-8 or UTF-16. + ErrNoCharset = errors.New("character set not supported") + + // ErrEventQFull indicates that the event queue is full, and + // cannot accept more events. + ErrEventQFull = errors.New("event queue full") +) + +// An EventError is an event representing some sort of error, and carries +// an error payload. +type EventError struct { + t time.Time + err error +} + +// When returns the time when the event was created. +func (ev *EventError) When() time.Time { + return ev.t +} + +// Error implements the error. +func (ev *EventError) Error() string { + return ev.err.Error() +} + +// NewEventError creates an ErrorEvent with the given error payload. +func NewEventError(err error) *EventError { + return &EventError{t: time.Now(), err: err} +} diff --git a/vendor/github.com/gdamore/tcell/event.go b/vendor/github.com/gdamore/tcell/event.go new file mode 100644 index 00000000..a3b77006 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/event.go @@ -0,0 +1,53 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "time" +) + +// Event is a generic interface used for passing around Events. +// Concrete types follow. +type Event interface { + // When reports the time when the event was generated. + When() time.Time +} + +// EventTime is a simple base event class, suitable for easy reuse. +// It can be used to deliver actual timer events as well. +type EventTime struct { + when time.Time +} + +// When returns the time stamp when the event occurred. +func (e *EventTime) When() time.Time { + return e.when +} + +// SetEventTime sets the time of occurrence for the event. +func (e *EventTime) SetEventTime(t time.Time) { + e.when = t +} + +// SetEventNow sets the time of occurrence for the event to the current time. +func (e *EventTime) SetEventNow() { + e.SetEventTime(time.Now()) +} + +// EventHandler is anything that handles events. If the handler has +// consumed the event, it should return true. False otherwise. +type EventHandler interface { + HandleEvent(Event) bool +} diff --git a/vendor/github.com/gdamore/tcell/interrupt.go b/vendor/github.com/gdamore/tcell/interrupt.go new file mode 100644 index 00000000..70dddfce --- /dev/null +++ b/vendor/github.com/gdamore/tcell/interrupt.go @@ -0,0 +1,41 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "time" +) + +// EventInterrupt is a generic wakeup event. Its can be used to +// to request a redraw. It can carry an arbitrary payload, as well. +type EventInterrupt struct { + t time.Time + v interface{} +} + +// When returns the time when this event was created. +func (ev *EventInterrupt) When() time.Time { + return ev.t +} + +// Data is used to obtain the opaque event payload. +func (ev *EventInterrupt) Data() interface{} { + return ev.v +} + +// NewEventInterrupt creates an EventInterrupt with the given payload. +func NewEventInterrupt(data interface{}) *EventInterrupt { + return &EventInterrupt{t: time.Now(), v: data} +} diff --git a/vendor/github.com/gdamore/tcell/key.go b/vendor/github.com/gdamore/tcell/key.go new file mode 100644 index 00000000..3545215a --- /dev/null +++ b/vendor/github.com/gdamore/tcell/key.go @@ -0,0 +1,464 @@ +// Copyright 2016 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "fmt" + "strings" + "time" +) + +// EventKey represents a key press. Usually this is a key press followed +// by a key release, but since terminal programs don't have a way to report +// key release events, we usually get just one event. If a key is held down +// then the terminal may synthesize repeated key presses at some predefined +// rate. We have no control over that, nor visibility into it. +// +// In some cases, we can have a modifier key, such as ModAlt, that can be +// generated with a key press. (This usually is represented by having the +// high bit set, or in some cases, by sending an ESC prior to the rune.) +// +// If the value of Key() is KeyRune, then the actual key value will be +// available with the Rune() method. This will be the case for most keys. +// In most situations, the modifiers will not be set. For example, if the +// rune is 'A', this will be reported without the ModShift bit set, since +// really can't tell if the Shift key was pressed (it might have been CAPSLOCK, +// or a terminal that only can send capitals, or keyboard with separate +// capital letters from lower case letters). +// +// Generally, terminal applications have far less visibility into keyboard +// activity than graphical applications. Hence, they should avoid depending +// overly much on availability of modifiers, or the availability of any +// specific keys. +type EventKey struct { + t time.Time + mod ModMask + key Key + ch rune +} + +// When returns the time when this Event was created, which should closely +// match the time when the key was pressed. +func (ev *EventKey) When() time.Time { + return ev.t +} + +// Rune returns the rune corresponding to the key press, if it makes sense. +// The result is only defined if the value of Key() is KeyRune. +func (ev *EventKey) Rune() rune { + return ev.ch +} + +// Key returns a virtual key code. We use this to identify specific key +// codes, such as KeyEnter, etc. Most control and function keys are reported +// with unique Key values. Normal alphanumeric and punctuation keys will +// generally return KeyRune here; the specific key can be further decoded +// using the Rune() function. +func (ev *EventKey) Key() Key { + return ev.key +} + +// Modifiers returns the modifiers that were present with the key press. Note +// that not all platforms and terminals support this equally well, and some +// cases we will not not know for sure. Hence, applications should avoid +// using this in most circumstances. +func (ev *EventKey) Modifiers() ModMask { + return ev.mod +} + +// KeyNames holds the written names of special keys. Useful to echo back a key +// name, or to look up a key from a string value. +var KeyNames = map[Key]string{ + KeyEnter: "Enter", + KeyBackspace: "Backspace", + KeyTab: "Tab", + KeyBacktab: "Backtab", + KeyEsc: "Esc", + KeyBackspace2: "Backspace2", + KeyDelete: "Delete", + KeyInsert: "Insert", + KeyUp: "Up", + KeyDown: "Down", + KeyLeft: "Left", + KeyRight: "Right", + KeyHome: "Home", + KeyEnd: "End", + KeyUpLeft: "UpLeft", + KeyUpRight: "UpRight", + KeyDownLeft: "DownLeft", + KeyDownRight: "DownRight", + KeyCenter: "Center", + KeyPgDn: "PgDn", + KeyPgUp: "PgUp", + KeyClear: "Clear", + KeyExit: "Exit", + KeyCancel: "Cancel", + KeyPause: "Pause", + KeyPrint: "Print", + KeyF1: "F1", + KeyF2: "F2", + KeyF3: "F3", + KeyF4: "F4", + KeyF5: "F5", + KeyF6: "F6", + KeyF7: "F7", + KeyF8: "F8", + KeyF9: "F9", + KeyF10: "F10", + KeyF11: "F11", + KeyF12: "F12", + KeyF13: "F13", + KeyF14: "F14", + KeyF15: "F15", + KeyF16: "F16", + KeyF17: "F17", + KeyF18: "F18", + KeyF19: "F19", + KeyF20: "F20", + KeyF21: "F21", + KeyF22: "F22", + KeyF23: "F23", + KeyF24: "F24", + KeyF25: "F25", + KeyF26: "F26", + KeyF27: "F27", + KeyF28: "F28", + KeyF29: "F29", + KeyF30: "F30", + KeyF31: "F31", + KeyF32: "F32", + KeyF33: "F33", + KeyF34: "F34", + KeyF35: "F35", + KeyF36: "F36", + KeyF37: "F37", + KeyF38: "F38", + KeyF39: "F39", + KeyF40: "F40", + KeyF41: "F41", + KeyF42: "F42", + KeyF43: "F43", + KeyF44: "F44", + KeyF45: "F45", + KeyF46: "F46", + KeyF47: "F47", + KeyF48: "F48", + KeyF49: "F49", + KeyF50: "F50", + KeyF51: "F51", + KeyF52: "F52", + KeyF53: "F53", + KeyF54: "F54", + KeyF55: "F55", + KeyF56: "F56", + KeyF57: "F57", + KeyF58: "F58", + KeyF59: "F59", + KeyF60: "F60", + KeyF61: "F61", + KeyF62: "F62", + KeyF63: "F63", + KeyF64: "F64", + KeyCtrlA: "Ctrl-A", + KeyCtrlB: "Ctrl-B", + KeyCtrlC: "Ctrl-C", + KeyCtrlD: "Ctrl-D", + KeyCtrlE: "Ctrl-E", + KeyCtrlF: "Ctrl-F", + KeyCtrlG: "Ctrl-G", + KeyCtrlJ: "Ctrl-J", + KeyCtrlK: "Ctrl-K", + KeyCtrlL: "Ctrl-L", + KeyCtrlN: "Ctrl-N", + KeyCtrlO: "Ctrl-O", + KeyCtrlP: "Ctrl-P", + KeyCtrlQ: "Ctrl-Q", + KeyCtrlR: "Ctrl-R", + KeyCtrlS: "Ctrl-S", + KeyCtrlT: "Ctrl-T", + KeyCtrlU: "Ctrl-U", + KeyCtrlV: "Ctrl-V", + KeyCtrlW: "Ctrl-W", + KeyCtrlX: "Ctrl-X", + KeyCtrlY: "Ctrl-Y", + KeyCtrlZ: "Ctrl-Z", + KeyCtrlSpace: "Ctrl-Space", + KeyCtrlUnderscore: "Ctrl-_", + KeyCtrlRightSq: "Ctrl-]", + KeyCtrlBackslash: "Ctrl-\\", + KeyCtrlCarat: "Ctrl-^", +} + +// Name returns a printable value or the key stroke. This can be used +// when printing the event, for example. +func (ev *EventKey) Name() string { + s := "" + m := []string{} + if ev.mod&ModShift != 0 { + m = append(m, "Shift") + } + if ev.mod&ModAlt != 0 { + m = append(m, "Alt") + } + if ev.mod&ModMeta != 0 { + m = append(m, "Meta") + } + if ev.mod&ModCtrl != 0 { + m = append(m, "Ctrl") + } + + ok := false + if s, ok = KeyNames[ev.key]; !ok { + if ev.key == KeyRune { + s = "Rune[" + string(ev.ch) + "]" + } else { + s = fmt.Sprintf("Key[%d,%d]", ev.key, int(ev.ch)) + } + } + if len(m) != 0 { + if ev.mod&ModCtrl != 0 && strings.HasPrefix(s, "Ctrl-") { + s = s[5:] + } + return fmt.Sprintf("%s+%s", strings.Join(m, "+"), s) + } + return s +} + +// NewEventKey attempts to create a suitable event. It parses the various +// ASCII control sequences if KeyRune is passed for Key, but if the caller +// has more precise information it should set that specifically. Callers +// that aren't sure about modifier state (most) should just pass ModNone. +func NewEventKey(k Key, ch rune, mod ModMask) *EventKey { + if k == KeyRune && (ch < ' ' || ch == 0x7f) { + // Turn specials into proper key codes. This is for + // control characters and the DEL. + k = Key(ch) + if mod == ModNone && ch < ' ' { + switch Key(ch) { + case KeyBackspace, KeyTab, KeyEsc, KeyEnter: + // these keys are directly typeable without CTRL + default: + // most likely entered with a CTRL keypress + mod = ModCtrl + } + } + } + return &EventKey{t: time.Now(), key: k, ch: ch, mod: mod} +} + +// ModMask is a mask of modifier keys. Note that it will not always be +// possible to report modifier keys. +type ModMask int16 + +// These are the modifiers keys that can be sent either with a key press, +// or a mouse event. Note that as of now, due to the confusion associated +// with Meta, and the lack of support for it on many/most platforms, the +// current implementations never use it. Instead, they use ModAlt, even for +// events that could possibly have been distinguished from ModAlt. +const ( + ModShift ModMask = 1 << iota + ModCtrl + ModAlt + ModMeta + ModNone ModMask = 0 +) + +// Key is a generic value for representing keys, and especially special +// keys (function keys, cursor movement keys, etc.) For normal keys, like +// ASCII letters, we use KeyRune, and then expect the application to +// inspect the Rune() member of the EventKey. +type Key int16 + +// This is the list of named keys. KeyRune is special however, in that it is +// a place holder key indicating that a printable character was sent. The +// actual value of the rune will be transported in the Rune of the associated +// EventKey. +const ( + KeyRune Key = iota + 256 + KeyUp + KeyDown + KeyRight + KeyLeft + KeyUpLeft + KeyUpRight + KeyDownLeft + KeyDownRight + KeyCenter + KeyPgUp + KeyPgDn + KeyHome + KeyEnd + KeyInsert + KeyDelete + KeyHelp + KeyExit + KeyClear + KeyCancel + KeyPrint + KeyPause + KeyBacktab + KeyF1 + KeyF2 + KeyF3 + KeyF4 + KeyF5 + KeyF6 + KeyF7 + KeyF8 + KeyF9 + KeyF10 + KeyF11 + KeyF12 + KeyF13 + KeyF14 + KeyF15 + KeyF16 + KeyF17 + KeyF18 + KeyF19 + KeyF20 + KeyF21 + KeyF22 + KeyF23 + KeyF24 + KeyF25 + KeyF26 + KeyF27 + KeyF28 + KeyF29 + KeyF30 + KeyF31 + KeyF32 + KeyF33 + KeyF34 + KeyF35 + KeyF36 + KeyF37 + KeyF38 + KeyF39 + KeyF40 + KeyF41 + KeyF42 + KeyF43 + KeyF44 + KeyF45 + KeyF46 + KeyF47 + KeyF48 + KeyF49 + KeyF50 + KeyF51 + KeyF52 + KeyF53 + KeyF54 + KeyF55 + KeyF56 + KeyF57 + KeyF58 + KeyF59 + KeyF60 + KeyF61 + KeyF62 + KeyF63 + KeyF64 +) + +// These are the control keys. Note that they overlap with other keys, +// perhaps. For example, KeyCtrlH is the same as KeyBackspace. +const ( + KeyCtrlSpace Key = iota + KeyCtrlA + KeyCtrlB + KeyCtrlC + KeyCtrlD + KeyCtrlE + KeyCtrlF + KeyCtrlG + KeyCtrlH + KeyCtrlI + KeyCtrlJ + KeyCtrlK + KeyCtrlL + KeyCtrlM + KeyCtrlN + KeyCtrlO + KeyCtrlP + KeyCtrlQ + KeyCtrlR + KeyCtrlS + KeyCtrlT + KeyCtrlU + KeyCtrlV + KeyCtrlW + KeyCtrlX + KeyCtrlY + KeyCtrlZ + KeyCtrlLeftSq // Escape + KeyCtrlBackslash + KeyCtrlRightSq + KeyCtrlCarat + KeyCtrlUnderscore +) + +// Special values - these are fixed in an attempt to make it more likely +// that aliases will encode the same way. + +// These are the defined ASCII values for key codes. They generally match +// with KeyCtrl values. +const ( + KeyNUL Key = iota + KeySOH + KeySTX + KeyETX + KeyEOT + KeyENQ + KeyACK + KeyBEL + KeyBS + KeyTAB + KeyLF + KeyVT + KeyFF + KeyCR + KeySO + KeySI + KeyDLE + KeyDC1 + KeyDC2 + KeyDC3 + KeyDC4 + KeyNAK + KeySYN + KeyETB + KeyCAN + KeyEM + KeySUB + KeyESC + KeyFS + KeyGS + KeyRS + KeyUS + KeyDEL Key = 0x7F +) + +// These keys are aliases for other names. +const ( + KeyBackspace = KeyBS + KeyTab = KeyTAB + KeyEsc = KeyESC + KeyEscape = KeyESC + KeyEnter = KeyCR + KeyBackspace2 = KeyDEL +) diff --git a/vendor/github.com/gdamore/tcell/mouse.go b/vendor/github.com/gdamore/tcell/mouse.go new file mode 100644 index 00000000..8c51c98e --- /dev/null +++ b/vendor/github.com/gdamore/tcell/mouse.go @@ -0,0 +1,97 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "time" +) + +// EventMouse is a mouse event. It is sent on either mouse up or mouse down +// events. It is also sent on mouse motion events - if the terminal supports +// it. We make every effort to ensure that mouse release events are delivered. +// Hence, click drag can be identified by a motion event with the mouse down, +// without any intervening button release. On some terminals only the initiating +// press and terminating release event will be delivered. +// +// Mouse wheel events, when reported, may appear on their own as individual +// impulses; that is, there will normally not be a release event delivered +// for mouse wheel movements. +// +// Most terminals cannot report the state of more than one button at a time -- +// and some cannot report motion events unless a button is pressed. +// +// Applications can inspect the time between events to resolve double or +// triple clicks. +type EventMouse struct { + t time.Time + btn ButtonMask + mod ModMask + x int + y int +} + +// When returns the time when this EventMouse was created. +func (ev *EventMouse) When() time.Time { + return ev.t +} + +// Buttons returns the list of buttons that were pressed or wheel motions. +func (ev *EventMouse) Buttons() ButtonMask { + return ev.btn +} + +// Modifiers returns a list of keyboard modifiers that were pressed +// with the mouse button(s). +func (ev *EventMouse) Modifiers() ModMask { + return ev.mod +} + +// Position returns the mouse position in character cells. The origin +// 0, 0 is at the upper left corner. +func (ev *EventMouse) Position() (int, int) { + return ev.x, ev.y +} + +// NewEventMouse is used to create a new mouse event. Applications +// shouldn't need to use this; its mostly for screen implementors. +func NewEventMouse(x, y int, btn ButtonMask, mod ModMask) *EventMouse { + return &EventMouse{t: time.Now(), x: x, y: y, btn: btn, mod: mod} +} + +// ButtonMask is a mask of mouse buttons and wheel events. Mouse button presses +// are normally delivered as both press and release events. Mouse wheel events +// are normally just single impulse events. Windows supports up to eight +// separate buttons plus all four wheel directions, but XTerm can only support +// mouse buttons 1-3 and wheel up/down. Its not unheard of for terminals +// to support only one or two buttons (think Macs). Old terminals, and true +// emulations (such as vt100) won't support mice at all, of course. +type ButtonMask int16 + +// These are the actual button values. +const ( + Button1 ButtonMask = 1 << iota // Usually left mouse button. + Button2 // Usually the middle mouse button. + Button3 // Usually the right mouse button. + Button4 // Often a side button (thumb/next). + Button5 // Often a side button (thumb/prev). + Button6 + Button7 + Button8 + WheelUp // Wheel motion up/away from user. + WheelDown // Wheel motion down/towards user. + WheelLeft // Wheel motion to left. + WheelRight // Wheel motion to right. + ButtonNone ButtonMask = 0 // No button or wheel events. +) diff --git a/vendor/github.com/gdamore/tcell/resize.go b/vendor/github.com/gdamore/tcell/resize.go new file mode 100644 index 00000000..0385673c --- /dev/null +++ b/vendor/github.com/gdamore/tcell/resize.go @@ -0,0 +1,42 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "time" +) + +// EventResize is sent when the window size changes. +type EventResize struct { + t time.Time + w int + h int +} + +// NewEventResize creates an EventResize with the new updated window size, +// which is given in character cells. +func NewEventResize(width, height int) *EventResize { + return &EventResize{t: time.Now(), w: width, h: height} +} + +// When returns the time when the Event was created. +func (ev *EventResize) When() time.Time { + return ev.t +} + +// Size returns the new window size as width, height in character cells. +func (ev *EventResize) Size() (int, int) { + return ev.w, ev.h +} diff --git a/vendor/github.com/gdamore/tcell/runes.go b/vendor/github.com/gdamore/tcell/runes.go new file mode 100644 index 00000000..ed9c63b5 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/runes.go @@ -0,0 +1,111 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +// The names of these constants are chosen to match Terminfo names, +// modulo case, and changing the prefix from ACS_ to Rune. These are +// the runes we provide extra special handling for, with ASCII fallbacks +// for terminals that lack them. +const ( + RuneSterling = '£' + RuneDArrow = '↓' + RuneLArrow = '←' + RuneRArrow = '→' + RuneUArrow = '↑' + RuneBullet = '·' + RuneBoard = '░' + RuneCkBoard = '▒' + RuneDegree = '°' + RuneDiamond = '◆' + RuneGEqual = '≥' + RunePi = 'π' + RuneHLine = '─' + RuneLantern = '§' + RunePlus = '┼' + RuneLEqual = '≤' + RuneLLCorner = '└' + RuneLRCorner = '┘' + RuneNEqual = '≠' + RunePlMinus = '±' + RuneS1 = '⎺' + RuneS3 = '⎻' + RuneS7 = '⎼' + RuneS9 = '⎽' + RuneBlock = '█' + RuneTTee = '┬' + RuneRTee = '┤' + RuneLTee = '├' + RuneBTee = '┴' + RuneULCorner = '┌' + RuneURCorner = '┐' + RuneVLine = '│' +) + +// RuneFallbacks is the default map of fallback strings that will be +// used to replace a rune when no other more appropriate transformation +// is available, and the rune cannot be displayed directly. +// +// New entries may be added to this map over time, as it becomes clear +// that such is desirable. Characters that represent either letters or +// numbers should not be added to this list unless it is certain that +// the meaning will still convey unambiguously. +// +// As an example, it would be appropriate to add an ASCII mapping for +// the full width form of the letter 'A', but it would not be appropriate +// to do so a glyph representing the country China. +// +// Programs that desire richer fallbacks may register additional ones, +// or change or even remove these mappings with Screen.RegisterRuneFallback +// Screen.UnregisterRuneFallback methods. +// +// Note that Unicode is presumed to be able to display all glyphs. +// This is a pretty poor assumption, but there is no easy way to +// figure out which glyphs are supported in a given font. Hence, +// some care in selecting the characters you support in your application +// is still appropriate. +var RuneFallbacks = map[rune]string{ + RuneSterling: "f", + RuneDArrow: "v", + RuneLArrow: "<", + RuneRArrow: ">", + RuneUArrow: "^", + RuneBullet: "o", + RuneBoard: "#", + RuneCkBoard: ":", + RuneDegree: "\\", + RuneDiamond: "+", + RuneGEqual: ">", + RunePi: "*", + RuneHLine: "-", + RuneLantern: "#", + RunePlus: "+", + RuneLEqual: "<", + RuneLLCorner: "+", + RuneLRCorner: "+", + RuneNEqual: "!", + RunePlMinus: "#", + RuneS1: "~", + RuneS3: "-", + RuneS7: "-", + RuneS9: "_", + RuneBlock: "#", + RuneTTee: "+", + RuneRTee: "+", + RuneLTee: "+", + RuneBTee: "+", + RuneULCorner: "+", + RuneURCorner: "+", + RuneVLine: "|", +} diff --git a/vendor/github.com/gdamore/tcell/screen.go b/vendor/github.com/gdamore/tcell/screen.go new file mode 100644 index 00000000..9551af6d --- /dev/null +++ b/vendor/github.com/gdamore/tcell/screen.go @@ -0,0 +1,212 @@ +// Copyright 2016 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +// Screen represents the physical (or emulated) screen. +// This can be a terminal window or a physical console. Platforms implement +// this differerently. +type Screen interface { + // Init initializes the screen for use. + Init() error + + // Fini finalizes the screen also releasing resources. + Fini() + + // Clear erases the screen. The contents of any screen buffers + // will also be cleared. This has the logical effect of + // filling the screen with spaces, using the global default style. + Clear() + + // Fill fills the screen with the given character and style. + Fill(rune, Style) + + // SetCell is an older API, and will be removed. Please use + // SetContent instead; SetCell is implemented in terms of SetContent. + SetCell(x int, y int, style Style, ch ...rune) + + // GetContent returns the contents at the given location. If the + // coordinates are out of range, then the values will be 0, nil, + // StyleDefault. Note that the contents returned are logical contents + // and may not actually be what is displayed, but rather are what will + // be displayed if Show() or Sync() is called. The width is the width + // in screen cells; most often this will be 1, but some East Asian + // characters require two cells. + GetContent(x, y int) (mainc rune, combc []rune, style Style, width int) + + // SetContent sets the contents of the given cell location. If + // the coordinates are out of range, then the operation is ignored. + // + // The first rune is the primary non-zero width rune. The array + // that follows is a possible list of combining characters to append, + // and will usually be nil (no combining characters.) + // + // The results are not displayd until Show() or Sync() is called. + // + // Note that wide (East Asian full width) runes occupy two cells, + // and attempts to place character at next cell to the right will have + // undefined effects. Wide runes that are printed in the + // last column will be replaced with a single width space on output. + SetContent(x int, y int, mainc rune, combc []rune, style Style) + + // SetStyle sets the default style to use when clearing the screen + // or when StyleDefault is specified. If it is also StyleDefault, + // then whatever system/terminal default is relevant will be used. + SetStyle(style Style) + + // ShowCursor is used to display the cursor at a given location. + // If the coordinates -1, -1 are given or are otherwise outside the + // dimensions of the screen, the cursor will be hidden. + ShowCursor(x int, y int) + + // HideCursor is used to hide the cursor. Its an alias for + // ShowCursor(-1, -1). + HideCursor() + + // Size returns the screen size as width, height. This changes in + // response to a call to Clear or Flush. + Size() (int, int) + + // PollEvent waits for events to arrive. Main application loops + // must spin on this to prevent the application from stalling. + // Furthermore, this will return nil if the Screen is finalized. + PollEvent() Event + + // PostEvent tries to post an event into the event stream. This + // can fail if the event queue is full. In that case, the event + // is dropped, and ErrEventQFull is returned. + PostEvent(ev Event) error + + // PostEventWait is like PostEvent, but if the queue is full, it + // blocks until there is space in the queue, making delivery + // reliable. However, it is VERY important that this function + // never be called from within whatever event loop is polling + // with PollEvent(), otherwise a deadlock may arise. + // + // For this reason, when using this function, the use of a + // Goroutine is recommended to ensure no deadlock can occur. + PostEventWait(ev Event) + + // EnableMouse enables the mouse. (If your terminal supports it.) + EnableMouse() + + // DisableMouse disables the mouse. + DisableMouse() + + // HasMouse returns true if the terminal (apparently) supports a + // mouse. Note that the a return value of true doesn't guarantee that + // a mouse/pointing device is present; a false return definitely + // indicates no mouse support is available. + HasMouse() bool + + // Colors returns the number of colors. All colors are assumed to + // use the ANSI color map. If a terminal is monochrome, it will + // return 0. + Colors() int + + // Show makes all the content changes made using SetContent() visible + // on the display. + // + // It does so in the most efficient and least visually disruptive + // manner possible. + Show() + + // Sync works like Show(), but it updates every visible cell on the + // physical display, assuming that it is not synchronized with any + // internal model. This may be both expensive and visually jarring, + // so it should only be used when believed to actually be necessary. + // + // Typically this is called as a result of a user-requested redraw + // (e.g. to clear up on screen corruption caused by some other program), + // or during a resize event. + Sync() + + // CharacterSet returns information about the character set. + // This isn't the full locale, but it does give us the input/output + // character set. Note that this is just for diagnostic purposes, + // we normally translate input/output to/from UTF-8, regardless of + // what the user's environment is. + CharacterSet() string + + // RegisterRuneFallback adds a fallback for runes that are not + // part of the character set -- for example one coudld register + // o as a fallback for ø. This should be done cautiously for + // characters that might be displayed ordinarily in language + // specific text -- characters that could change the meaning of + // of written text would be dangerous. The intention here is to + // facilitate fallback characters in pseudo-graphical applications. + // + // If the terminal has fallbacks already in place via an alternate + // character set, those are used in preference. Also, standard + // fallbacks for graphical characters in the ACSC terminfo string + // are registered implicitly. + + // The display string should be the same width as original rune. + // This makes it possible to register two character replacements + // for full width East Asian characters, for example. + // + // It is recommended that replacement strings consist only of + // 7-bit ASCII, since other characters may not display everywhere. + RegisterRuneFallback(r rune, subst string) + + // UnregisterRuneFallback unmaps a replacement. It will unmap + // the implicit ASCII replacements for alternate characters as well. + // When an unmapped char needs to be displayed, but no suitable + // glyph is available, '?' is emitted instead. It is not possible + // to "disable" the use of alternate characters that are supported + // by your terminal except by changing the terminal database. + UnregisterRuneFallback(r rune) + + // CanDisplay returns true if the given rune can be displayed on + // this screen. Note that this is a best guess effort -- whether + // your fonts support the character or not may be questionable. + // Mostly this is for folks who work outside of Unicode. + // + // If checkFallbacks is true, then if any (possibly imperfect) + // fallbacks are registered, this will return true. This will + // also return true if the terminal can replace the glyph with + // one that is visually indistinguishable from the one requested. + CanDisplay(r rune, checkFallbacks bool) bool + + // Resize does nothing, since its generally not possible to + // ask a screen to resize, but it allows the Screen to implement + // the View interface. + Resize(int, int, int, int) + + // HasKey returns true if the keyboard is believed to have the + // key. In some cases a keyboard may have keys with this name + // but no support for them, while in others a key may be reported + // as supported but not actually be usable (such as some emulators + // that hijack certain keys). Its best not to depend to strictly + // on this function, but it can be used for hinting when building + // menus, displayed hot-keys, etc. Note that KeyRune (literal + // runes) is always true. + HasKey(Key) bool +} + +// NewScreen returns a default Screen suitable for the user's terminal +// environment. +func NewScreen() (Screen, error) { + // First we attempt to obtain a terminfo screen. This should work + // in most places if $TERM is set. + if s, e := NewTerminfoScreen(); s != nil { + return s, nil + + } else if s, _ := NewConsoleScreen(); s != nil { + return s, nil + + } else { + return nil, e + } +} diff --git a/vendor/github.com/gdamore/tcell/simulation.go b/vendor/github.com/gdamore/tcell/simulation.go new file mode 100644 index 00000000..73980239 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/simulation.go @@ -0,0 +1,505 @@ +// Copyright 2016 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "sync" + "unicode/utf8" + + "golang.org/x/text/transform" +) + +// NewSimulationScreen returns a SimulationScreen. Note that +// SimulationScreen is also a Screen. +func NewSimulationScreen(charset string) SimulationScreen { + if charset == "" { + charset = "UTF-8" + } + s := &simscreen{charset: charset} + return s +} + +// SimulationScreen represents a screen simulation. This is intended to +// be a superset of normal Screens, but also adds some important interfaces +// for testing. +type SimulationScreen interface { + // InjectKeyBytes injects a stream of bytes corresponding to + // the native encoding (see charset). It turns true if the entire + // set of bytes were processed and delivered as KeyEvents, false + // if any bytes were not fully understood. Any bytes that are not + // fully converted are discarded. + InjectKeyBytes(buf []byte) bool + + // InjectKey injects a key event. The rune is a UTF-8 rune, post + // any translation. + InjectKey(key Key, r rune, mod ModMask) + + // InjectMouse injects a mouse event. + InjectMouse(x, y int, buttons ButtonMask, mod ModMask) + + // SetSize resizes the underlying physical screen. It also causes + // a resize event to be injected during the next Show() or Sync(). + // A new physical contents array will be allocated (with data from + // the old copied), so any prior value obtained with GetContents + // won't be used anymore + SetSize(width, height int) + + // GetContents returns screen contents as an array of + // cells, along with the physical width & height. Note that the + // physical contents will be used until the next time SetSize() + // is called. + GetContents() (cells []SimCell, width int, height int) + + // GetCursor returns the cursor details. + GetCursor() (x int, y int, visible bool) + + Screen +} + +// SimCell represents a simulated screen cell. The purpose of this +// is to track on screen content. +type SimCell struct { + // Bytes is the actual character bytes. Normally this is + // rune data, but it could be be data in another encoding system. + Bytes []byte + + // Style is the style used to display the data. + Style Style + + // Runes is the list of runes, unadulterated, in UTF-8. + Runes []rune +} + +type simscreen struct { + physw int + physh int + fini bool + style Style + evch chan Event + quit chan struct{} + + front []SimCell + back CellBuffer + clear bool + cursorx int + cursory int + cursorvis bool + mouse bool + charset string + encoder transform.Transformer + decoder transform.Transformer + fillchar rune + fillstyle Style + fallback map[rune]string + + sync.Mutex +} + +func (s *simscreen) Init() error { + s.evch = make(chan Event, 10) + s.fillchar = 'X' + s.fillstyle = StyleDefault + s.mouse = false + s.physw = 80 + s.physh = 25 + s.cursorx = -1 + s.cursory = -1 + s.style = StyleDefault + + if enc := GetEncoding(s.charset); enc != nil { + s.encoder = enc.NewEncoder() + s.decoder = enc.NewDecoder() + } else { + return ErrNoCharset + } + + s.front = make([]SimCell, s.physw*s.physh) + s.back.Resize(80, 25) + + // default fallbacks + s.fallback = make(map[rune]string) + for k, v := range RuneFallbacks { + s.fallback[k] = v + } + return nil +} + +func (s *simscreen) Fini() { + s.Lock() + s.fini = true + s.back.Resize(0, 0) + s.Unlock() + if s.quit != nil { + close(s.quit) + } + s.physw = 0 + s.physh = 0 + s.front = nil +} + +func (s *simscreen) SetStyle(style Style) { + s.Lock() + s.style = style + s.Unlock() +} + +func (s *simscreen) Clear() { + s.Fill(' ', s.style) +} + +func (s *simscreen) Fill(r rune, style Style) { + s.Lock() + s.back.Fill(r, style) + s.Unlock() +} + +func (s *simscreen) SetCell(x, y int, style Style, ch ...rune) { + + if len(ch) > 0 { + s.SetContent(x, y, ch[0], ch[1:], style) + } else { + s.SetContent(x, y, ' ', nil, style) + } +} + +func (s *simscreen) SetContent(x, y int, mainc rune, combc []rune, st Style) { + + s.Lock() + s.back.SetContent(x, y, mainc, combc, st) + s.Unlock() +} + +func (s *simscreen) GetContent(x, y int) (rune, []rune, Style, int) { + var mainc rune + var combc []rune + var style Style + var width int + s.Lock() + mainc, combc, style, width = s.back.GetContent(x, y) + s.Unlock() + return mainc, combc, style, width +} + +func (s *simscreen) drawCell(x, y int) int { + + mainc, combc, style, width := s.back.GetContent(x, y) + if !s.back.Dirty(x, y) { + return width + } + if x >= s.physw || y >= s.physh || x < 0 || y < 0 { + return width + } + simc := &s.front[(y*s.physw)+x] + + if style == StyleDefault { + style = s.style + } + simc.Style = style + simc.Runes = append([]rune{mainc}, combc...) + + // now emit runes - taking care to not overrun width with a + // wide character, and to ensure that we emit exactly one regular + // character followed up by any residual combing characters + + simc.Bytes = nil + + if x > s.physw-width { + simc.Runes = []rune{' '} + simc.Bytes = []byte{' '} + return width + } + + lbuf := make([]byte, 12) + ubuf := make([]byte, 12) + nout := 0 + + for _, r := range simc.Runes { + + l := utf8.EncodeRune(ubuf, r) + + nout, _, _ = s.encoder.Transform(lbuf, ubuf[:l], true) + + if nout == 0 || lbuf[0] == '\x1a' { + + // skip combining + + if subst, ok := s.fallback[r]; ok { + simc.Bytes = append(simc.Bytes, + []byte(subst)...) + + } else if r >= ' ' && r <= '~' { + simc.Bytes = append(simc.Bytes, byte(r)) + + } else if simc.Bytes == nil { + simc.Bytes = append(simc.Bytes, '?') + } + } else { + simc.Bytes = append(simc.Bytes, lbuf[:nout]...) + } + } + s.back.SetDirty(x, y, false) + return width +} + +func (s *simscreen) ShowCursor(x, y int) { + s.Lock() + s.cursorx, s.cursory = x, y + s.showCursor() + s.Unlock() +} + +func (s *simscreen) HideCursor() { + s.ShowCursor(-1, -1) +} + +func (s *simscreen) showCursor() { + + x, y := s.cursorx, s.cursory + if x < 0 || y < 0 || x >= s.physw || y >= s.physh { + s.cursorvis = false + } else { + s.cursorvis = true + } +} + +func (s *simscreen) hideCursor() { + // does not update cursor position + s.cursorvis = false +} + +func (s *simscreen) Show() { + s.Lock() + s.resize() + s.draw() + s.Unlock() +} + +func (s *simscreen) clearScreen() { + // We emulate a hardware clear by filling with a specific pattern + for i := range s.front { + s.front[i].Style = s.fillstyle + s.front[i].Runes = []rune{s.fillchar} + s.front[i].Bytes = []byte{byte(s.fillchar)} + } + s.clear = false +} + +func (s *simscreen) draw() { + s.hideCursor() + if s.clear { + s.clearScreen() + } + + w, h := s.back.Size() + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + width := s.drawCell(x, y) + x += width - 1 + } + } + s.showCursor() +} + +func (s *simscreen) EnableMouse() { + s.mouse = true +} + +func (s *simscreen) DisableMouse() { + s.mouse = false +} + +func (s *simscreen) Size() (int, int) { + s.Lock() + w, h := s.back.Size() + s.Unlock() + return w, h +} + +func (s *simscreen) resize() { + w, h := s.physw, s.physh + ow, oh := s.back.Size() + if w != ow || h != oh { + s.back.Resize(w, h) + ev := NewEventResize(w, h) + s.PostEvent(ev) + } +} + +func (s *simscreen) Colors() int { + return 256 +} + +func (s *simscreen) PollEvent() Event { + select { + case <-s.quit: + return nil + case ev := <-s.evch: + return ev + } +} + +func (s *simscreen) PostEventWait(ev Event) { + s.evch <- ev +} + +func (s *simscreen) PostEvent(ev Event) error { + select { + case s.evch <- ev: + return nil + default: + return ErrEventQFull + } +} + +func (s *simscreen) InjectMouse(x, y int, buttons ButtonMask, mod ModMask) { + ev := NewEventMouse(x, y, buttons, mod) + s.PostEvent(ev) +} + +func (s *simscreen) InjectKey(key Key, r rune, mod ModMask) { + ev := NewEventKey(KeyRune, r, ModNone) + s.PostEvent(ev) +} + +func (s *simscreen) InjectKeyBytes(b []byte) bool { + failed := false + +outer: + for len(b) > 0 { + if b[0] >= ' ' && b[0] <= 0x7F { + // printable ASCII easy to deal with -- no encodings + ev := NewEventKey(KeyRune, rune(b[0]), ModNone) + s.PostEvent(ev) + b = b[1:] + continue + } + + if b[0] < 0x80 { + mod := ModNone + // No encodings start with low numbered values + if Key(b[0]) >= KeyCtrlA && Key(b[0]) <= KeyCtrlZ { + mod = ModCtrl + } + ev := NewEventKey(Key(b[0]), 0, mod) + s.PostEvent(ev) + continue + } + + utfb := make([]byte, len(b)*4) // worst case + for l := 1; l < len(b); l++ { + s.decoder.Reset() + nout, nin, _ := s.decoder.Transform(utfb, b[:l], true) + + if nout != 0 { + r, _ := utf8.DecodeRune(utfb[:nout]) + if r != utf8.RuneError { + ev := NewEventKey(KeyRune, r, ModNone) + s.PostEvent(ev) + } + b = b[nin:] + continue outer + } + } + failed = true + b = b[1:] + continue + } + + return !failed +} + +func (s *simscreen) Sync() { + s.Lock() + s.clear = true + s.resize() + s.back.Invalidate() + s.draw() + s.Unlock() +} + +func (s *simscreen) CharacterSet() string { + return s.charset +} + +func (s *simscreen) SetSize(w, h int) { + s.Lock() + newc := make([]SimCell, w*h) + for row := 0; row < h && row < s.physh; row++ { + for col := 0; col < w && col < s.physw; col++ { + newc[(row*w)+col] = s.front[(row*s.physw)+col] + } + } + s.physw = w + s.physh = h + s.Unlock() +} + +func (s *simscreen) GetContents() ([]SimCell, int, int) { + s.Lock() + cells, w, h := s.front, s.physw, s.physh + s.Unlock() + return cells, w, h +} + +func (s *simscreen) GetCursor() (int, int, bool) { + s.Lock() + x, y, vis := s.cursorx, s.cursory, s.cursorvis + s.Unlock() + return x, y, vis +} + +func (s *simscreen) RegisterRuneFallback(r rune, subst string) { + s.Lock() + s.fallback[r] = subst + s.Unlock() +} + +func (s *simscreen) UnregisterRuneFallback(r rune) { + s.Lock() + delete(s.fallback, r) + s.Unlock() +} + +func (s *simscreen) CanDisplay(r rune, checkFallbacks bool) bool { + + if enc := s.encoder; enc != nil { + nb := make([]byte, 6) + ob := make([]byte, 6) + num := utf8.EncodeRune(ob, r) + + enc.Reset() + dst, _, err := enc.Transform(nb, ob[:num], true) + if dst != 0 && err == nil && nb[0] != '\x1A' { + return true + } + } + if !checkFallbacks { + return false + } + if _, ok := s.fallback[r]; ok { + return true + } + return false +} + +func (s *simscreen) HasMouse() bool { + return false +} + +func (s *simscreen) Resize(int, int, int, int) {} + +func (s *simscreen) HasKey(Key) bool { + return true +} diff --git a/vendor/github.com/gdamore/tcell/style.go b/vendor/github.com/gdamore/tcell/style.go new file mode 100644 index 00000000..c4ee9351 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/style.go @@ -0,0 +1,126 @@ +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +// Style represents a complete text style, including both foreground +// and background color. We encode it in a 64-bit int for efficiency. +// The coding is (MSB): <7b flags><1b><24b fgcolor><7b attr><1b><24b bgcolor>. +// The <1b> is set true to indicate that the color is an RGB color, rather +// than a named index. +// +// This gives 24bit color options, if it ever becomes truly necessary. +// However, applications must not rely on this encoding. +// +// Note that not all terminals can display all colors or attributes, and +// many might have specific incompatibilities between specific attributes +// and color combinations. +// +// The intention is to extend styles to support paletting, in which case +// some flag bit(s) would be set, and the foreground and background colors +// would be replaced with a palette number and palette index. +// +// To use Style, just declare a variable of its type. +type Style int64 + +// StyleDefault represents a default style, based upon the context. +// It is the zero value. +const StyleDefault Style = 0 + +// styleFlags -- used internally for now. +const ( + styleBgSet = 1 << (iota + 57) + styleFgSet + stylePalette +) + +// Foreground returns a new style based on s, with the foreground color set +// as requested. ColorDefault can be used to select the global default. +func (s Style) Foreground(c Color) Style { + if c == ColorDefault { + return (s &^ (0x1ffffff00000000 | styleFgSet)) + } + return (s &^ Style(0x1ffffff00000000)) | + ((Style(c) & 0x1ffffff) << 32) | styleFgSet +} + +// Background returns a new style based on s, with the background color set +// as requested. ColorDefault can be used to select the global default. +func (s Style) Background(c Color) Style { + if c == ColorDefault { + return (s &^ (0x1ffffff | styleBgSet)) + } + return (s &^ (0x1ffffff)) | (Style(c) & 0x1ffffff) | styleBgSet +} + +// Decompose breaks a style up, returning the foreground, background, +// and other attributes. +func (s Style) Decompose() (fg Color, bg Color, attr AttrMask) { + if s&styleFgSet != 0 { + fg = Color(s>>32) & 0x1ffffff + } else { + fg = ColorDefault + } + if s&styleBgSet != 0 { + bg = Color(s & 0x1ffffff) + } else { + bg = ColorDefault + } + attr = AttrMask(s) & attrAll + + return fg, bg, attr +} + +func (s Style) setAttrs(attrs Style, on bool) Style { + if on { + return s | attrs + } + return s &^ attrs +} + +// Normal returns the style with all attributes disabled. +func (s Style) Normal() Style { + return s &^ Style(attrAll) +} + +// Bold returns a new style based on s, with the bold attribute set +// as requested. +func (s Style) Bold(on bool) Style { + return s.setAttrs(Style(AttrBold), on) +} + +// Blink returns a new style based on s, with the blink attribute set +// as requested. +func (s Style) Blink(on bool) Style { + return s.setAttrs(Style(AttrBlink), on) +} + +// Dim returns a new style based on s, with the dim attribute set +// as requested. +func (s Style) Dim(on bool) Style { + return s.setAttrs(Style(AttrDim), on) +} + +// Reverse returns a new style based on s, with the reverse attribute set +// as requested. (Reverse usually changes the foreground and background +// colors.) +func (s Style) Reverse(on bool) Style { + return s.setAttrs(Style(AttrReverse), on) +} + +// Underline returns a new style based on s, with the underline attribute set +// as requested. +func (s Style) Underline(on bool) Style { + return s.setAttrs(Style(AttrUnderline), on) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/.gitignore b/vendor/github.com/gdamore/tcell/terminfo/.gitignore new file mode 100644 index 00000000..74f3c04f --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/.gitignore @@ -0,0 +1 @@ +mkinfo diff --git a/vendor/github.com/gdamore/tcell/terminfo/TERMINALS.md b/vendor/github.com/gdamore/tcell/terminfo/TERMINALS.md new file mode 100644 index 00000000..85c1e61c --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/TERMINALS.md @@ -0,0 +1,7 @@ +TERMINALS +========= + +The best way to populate terminals on Debian is to install ncurses, +ncurses-term, screen, tmux, rxvt-unicode, and dvtm. This populates the +the terminfo database so that we can have a reasonable set of starting +terminals. diff --git a/vendor/github.com/gdamore/tcell/terminfo/mkdatabase.sh b/vendor/github.com/gdamore/tcell/terminfo/mkdatabase.sh new file mode 100755 index 00000000..fd968bdc --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/mkdatabase.sh @@ -0,0 +1,189 @@ +#!/bin/bash + +# Copyright 2017 The TCell Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use file except in compliance with the License. +# You may obtain a copy of the license at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# When called with no arguments, this shell script builds the Go database, +# which is somewhat minimal for size reasons (it only contains the most +# commonly used entries), and then builds the complete JSON database. +# +# To limit the action to only building one or more terminals, specify them +# on the command line: +# +# ./mkdatabase xterm +# +# The script will also find and update or add any terminal "aliases". +# It does not remove any old entries. +# +# To add to the set of terminals that we compile into the Go database, +# add their names to the models.txt file. +# + +# This script is not very efficient, but there isn't really a better way +# without writing code to decode the terminfo binary format directly. +# Its not worth worrying about. + +# This script also requires bash, although ksh93 should work as well, because +# we use arrays, which are not specified in POSIX. + +export LANG=C +export LC_CTYPE=C + +progress() +{ + typeset -i num=$1 + typeset -i tot=$2 + typeset -i x + typeset back + typeset s + + if (( tot < 1 )) + then + s=$(printf "[ %d ]" $num) + back="\b\b\b\b\b" + x=$num + while (( x >= 10 )) + do + back="${back}\b" + x=$(( x / 10 )) + done + + else + x=$(( num * 100 / tot )) + s=$(printf "<%3d%%>" $x) + back="\b\b\b\b\b\b" + fi + printf "%s${back}" "$s" +} + +ord() +{ + printf "%02x" "'$1'" +} + +goterms=( $(cat models.txt) ) +args=( $* ) +if (( ${#args[@]} == 0 )) +then + args=( $(toe -a | cut -f1) ) +fi + +printf "Scanning terminal definitions: " +i=0 +aliases=() +models=() +for term in ${args[@]} +do + case "${term}" in + *-truecolor) + line="${term}|24-bit color" + ;; + *) + line=$(infocmp $term | head -2 | tail -1) + if [[ -z "$line" ]] + then + echo "Cannot find terminfo for $term" + exit 1 + fi + # take off the trailing comma + line=${line%,} + esac + + # grab primary name + term=${line%%|*} + all+=( ${term} ) + + # should this be in our go terminals? + for model in ${goterms[@]} + do + if [[ "${model}" == "${term}" ]] + then + models+=( ${term} ) + fi + done + + # chop off primary name + line=${line#${term}} + line=${line#|} + # chop off description + line=${line%|*} + while [[ "$line" != "" ]] + do + a=${line%%|*} + aliases+=( ${a}=${term} ) + line=${line#$a} + line=${line#|} + done + i=$(( i + 1 )) + progress $i ${#args[@]} +done +echo +# make sure we have mkinfo +printf "Building mkinfo: " +go build mkinfo.go +echo "done." + +# Build all the go database files for the "interesting" terminals". +printf "Building Go database: " +i=0 +for model in ${models[@]} +do + safe=$(echo $model | tr - _) + file=term_${safe}.go + ./mkinfo -go $file $model + go fmt ${file} >/dev/null + i=$(( i + 1 )) + progress $i ${#models[@]} +done +echo + +printf "Building JSON database: " + +# The JSON files are located for each terminal in a file with the +# terminal name, in the following fashion "database/x/xterm.json + +i=0 +for model in ${all[@]} +do + letter=$(ord ${model:0:1}) + dir=database/${letter} + file=${dir}/${model}.gz + mkdir -p ${dir} + ./mkinfo -nofatal -quiet -gzip -json ${file} ${model} + i=$(( i + 1 )) + progress $i ${#all[@]} +done +echo + +printf "Building JSON aliases: " +i=0 +for model in ${aliases[@]} +do + canon=${model#*=} + model=${model%=*} + letter=$(ord ${model:0:1}) + cletter=$(ord ${canon:0:1}) + dir=database/${letter} + file=${dir}/${model} + if [[ -f database/${cletter}/${canon}.gz ]] + then + [[ -d ${dir} ]] || mkdir -p ${dir} + # Generally speaking the aliases are better uncompressed + ./mkinfo -nofatal -quiet -json ${file} ${model} + fi + i=$(( i + 1 )) + progress $i ${#aliases[@]} +done +echo diff --git a/vendor/github.com/gdamore/tcell/terminfo/mkinfo.go b/vendor/github.com/gdamore/tcell/terminfo/mkinfo.go new file mode 100644 index 00000000..ba85330c --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/mkinfo.go @@ -0,0 +1,769 @@ +// +build ignore + +// Copyright 2017 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This command is used to generate suitable configuration files in either +// go syntax or in JSON. It defaults to JSON output on stdout. If no +// term values are specified on the command line, then $TERM is used. +// +// Usage is like this: +// +// mkinfo [-init] [-go file.go] [-json file.json] [-quiet] [-nofatal] [...] +// +// -gzip specifies output should be compressed (json only) +// -go specifies Go output into the named file. Use - for stdout. +// -json specifies JSON output in the named file. Use - for stdout +// -nofatal indicates that errors loading definitions should not be fatal +// + +package main + +import ( + "bytes" + "compress/gzip" + "encoding/json" + "errors" + "flag" + "fmt" + "io" + "os" + "os/exec" + "regexp" + "strconv" + "strings" + + "github.com/gdamore/tcell/terminfo" +) + +type termcap struct { + name string + desc string + aliases []string + bools map[string]bool + nums map[string]int + strs map[string]string +} + +func (tc *termcap) getnum(s string) int { + return (tc.nums[s]) +} + +func (tc *termcap) getflag(s string) bool { + return (tc.bools[s]) +} + +func (tc *termcap) getstr(s string) string { + return (tc.strs[s]) +} + +const ( + NONE = iota + CTRL + ESC +) + +func unescape(s string) string { + // Various escapes are in \x format. Control codes are + // encoded as ^M (carat followed by ASCII equivalent). + // Escapes are: \e, \E - escape + // \0 NULL, \n \l \r \t \b \f \s for equivalent C escape. + buf := &bytes.Buffer{} + esc := NONE + + for i := 0; i < len(s); i++ { + c := s[i] + switch esc { + case NONE: + switch c { + case '\\': + esc = ESC + case '^': + esc = CTRL + default: + buf.WriteByte(c) + } + case CTRL: + buf.WriteByte(c - 0x40) + esc = NONE + case ESC: + switch c { + case 'E', 'e': + buf.WriteByte(0x1b) + case '0': + buf.WriteByte(0) + case 'n': + buf.WriteByte('\n') + case 'r': + buf.WriteByte('\r') + case 't': + buf.WriteByte('\t') + case 'b': + buf.WriteByte('\b') + case 'f': + buf.WriteByte('\f') + case 's': + buf.WriteByte(' ') + case 'l': + panic("WTF: weird format: " + s) + default: + buf.WriteByte(c) + } + esc = NONE + } + } + return (buf.String()) +} + +func (tc *termcap) setupterm(name string) error { + cmd := exec.Command("infocmp", "-1", name) + output := &bytes.Buffer{} + cmd.Stdout = output + + tc.strs = make(map[string]string) + tc.bools = make(map[string]bool) + tc.nums = make(map[string]int) + + err := cmd.Run() + if err != nil { + return err + } + + // Now parse the output. + // We get comment lines (starting with "#"), followed by + // a header line that looks like "||...|" + // then capabilities, one per line, starting with a tab and ending + // with a comma and newline. + lines := strings.Split(output.String(), "\n") + for len(lines) > 0 && strings.HasPrefix(lines[0], "#") { + lines = lines[1:] + } + + // Ditch trailing empty last line + if lines[len(lines)-1] == "" { + lines = lines[:len(lines)-1] + } + header := lines[0] + if strings.HasSuffix(header, ",") { + header = header[:len(header)-1] + } + names := strings.Split(header, "|") + tc.name = names[0] + names = names[1:] + if len(names) > 0 { + tc.desc = names[len(names)-1] + names = names[:len(names)-1] + } + tc.aliases = names + for _, val := range lines[1:] { + if (!strings.HasPrefix(val, "\t")) || + (!strings.HasSuffix(val, ",")) { + return (errors.New("malformed infocmp: " + val)) + } + + val = val[1:] + val = val[:len(val)-1] + + if k := strings.SplitN(val, "=", 2); len(k) == 2 { + tc.strs[k[0]] = unescape(k[1]) + } else if k := strings.SplitN(val, "#", 2); len(k) == 2 { + if u, err := strconv.ParseUint(k[1], 10, 0); err != nil { + return (err) + } else { + tc.nums[k[0]] = int(u) + } + } else { + tc.bools[val] = true + } + } + return nil +} + +// This program is used to collect data from the system's terminfo library, +// and write it into Go source code. That is, we maintain our terminfo +// capabilities encoded in the program. It should never need to be run by +// an end user, but developers can use this to add codes for additional +// terminal types. +// +// If a terminal name ending with -truecolor is given, and we cannot find +// one, we will try to fabricate one from either the -256color (if present) +// or the unadorned base name, adding the XTerm specific 24-bit color +// escapes. We believe that all 24-bit capable terminals use the same +// escape sequences, and terminfo has yet to evolve to support this. +func getinfo(name string) (*terminfo.Terminfo, string, error) { + var tc termcap + addTrueColor := false + if err := tc.setupterm(name); err != nil { + if strings.HasSuffix(name, "-truecolor") { + base := name[:len(name)-len("-truecolor")] + // Probably -256color is closest to what we want + if err = tc.setupterm(base + "-256color"); err != nil { + err = tc.setupterm(base) + } + if err == nil { + addTrueColor = true + } + tc.name = name + } + if err != nil { + return nil, "", err + } + } + t := &terminfo.Terminfo{} + // If this is an alias record, then just emit the alias + t.Name = tc.name + if t.Name != name { + return t, "", nil + } + t.Aliases = tc.aliases + t.Colors = tc.getnum("colors") + t.Columns = tc.getnum("cols") + t.Lines = tc.getnum("lines") + t.Bell = tc.getstr("bel") + t.Clear = tc.getstr("clear") + t.EnterCA = tc.getstr("smcup") + t.ExitCA = tc.getstr("rmcup") + t.ShowCursor = tc.getstr("cnorm") + t.HideCursor = tc.getstr("civis") + t.AttrOff = tc.getstr("sgr0") + t.Underline = tc.getstr("smul") + t.Bold = tc.getstr("bold") + t.Blink = tc.getstr("blink") + t.Dim = tc.getstr("dim") + t.Reverse = tc.getstr("rev") + t.EnterKeypad = tc.getstr("smkx") + t.ExitKeypad = tc.getstr("rmkx") + t.SetFg = tc.getstr("setaf") + t.SetBg = tc.getstr("setab") + t.SetCursor = tc.getstr("cup") + t.CursorBack1 = tc.getstr("cub1") + t.CursorUp1 = tc.getstr("cuu1") + t.KeyF1 = tc.getstr("kf1") + t.KeyF2 = tc.getstr("kf2") + t.KeyF3 = tc.getstr("kf3") + t.KeyF4 = tc.getstr("kf4") + t.KeyF5 = tc.getstr("kf5") + t.KeyF6 = tc.getstr("kf6") + t.KeyF7 = tc.getstr("kf7") + t.KeyF8 = tc.getstr("kf8") + t.KeyF9 = tc.getstr("kf9") + t.KeyF10 = tc.getstr("kf10") + t.KeyF11 = tc.getstr("kf11") + t.KeyF12 = tc.getstr("kf12") + t.KeyF13 = tc.getstr("kf13") + t.KeyF14 = tc.getstr("kf14") + t.KeyF15 = tc.getstr("kf15") + t.KeyF16 = tc.getstr("kf16") + t.KeyF17 = tc.getstr("kf17") + t.KeyF18 = tc.getstr("kf18") + t.KeyF19 = tc.getstr("kf19") + t.KeyF20 = tc.getstr("kf20") + t.KeyF21 = tc.getstr("kf21") + t.KeyF22 = tc.getstr("kf22") + t.KeyF23 = tc.getstr("kf23") + t.KeyF24 = tc.getstr("kf24") + t.KeyF25 = tc.getstr("kf25") + t.KeyF26 = tc.getstr("kf26") + t.KeyF27 = tc.getstr("kf27") + t.KeyF28 = tc.getstr("kf28") + t.KeyF29 = tc.getstr("kf29") + t.KeyF30 = tc.getstr("kf30") + t.KeyF31 = tc.getstr("kf31") + t.KeyF32 = tc.getstr("kf32") + t.KeyF33 = tc.getstr("kf33") + t.KeyF34 = tc.getstr("kf34") + t.KeyF35 = tc.getstr("kf35") + t.KeyF36 = tc.getstr("kf36") + t.KeyF37 = tc.getstr("kf37") + t.KeyF38 = tc.getstr("kf38") + t.KeyF39 = tc.getstr("kf39") + t.KeyF40 = tc.getstr("kf40") + t.KeyF41 = tc.getstr("kf41") + t.KeyF42 = tc.getstr("kf42") + t.KeyF43 = tc.getstr("kf43") + t.KeyF44 = tc.getstr("kf44") + t.KeyF45 = tc.getstr("kf45") + t.KeyF46 = tc.getstr("kf46") + t.KeyF47 = tc.getstr("kf47") + t.KeyF48 = tc.getstr("kf48") + t.KeyF49 = tc.getstr("kf49") + t.KeyF50 = tc.getstr("kf50") + t.KeyF51 = tc.getstr("kf51") + t.KeyF52 = tc.getstr("kf52") + t.KeyF53 = tc.getstr("kf53") + t.KeyF54 = tc.getstr("kf54") + t.KeyF55 = tc.getstr("kf55") + t.KeyF56 = tc.getstr("kf56") + t.KeyF57 = tc.getstr("kf57") + t.KeyF58 = tc.getstr("kf58") + t.KeyF59 = tc.getstr("kf59") + t.KeyF60 = tc.getstr("kf60") + t.KeyF61 = tc.getstr("kf61") + t.KeyF62 = tc.getstr("kf62") + t.KeyF63 = tc.getstr("kf63") + t.KeyF64 = tc.getstr("kf64") + t.KeyInsert = tc.getstr("kich1") + t.KeyDelete = tc.getstr("kdch1") + t.KeyBackspace = tc.getstr("kbs") + t.KeyHome = tc.getstr("khome") + t.KeyEnd = tc.getstr("kend") + t.KeyUp = tc.getstr("kcuu1") + t.KeyDown = tc.getstr("kcud1") + t.KeyRight = tc.getstr("kcuf1") + t.KeyLeft = tc.getstr("kcub1") + t.KeyPgDn = tc.getstr("knp") + t.KeyPgUp = tc.getstr("kpp") + t.KeyBacktab = tc.getstr("kcbt") + t.KeyExit = tc.getstr("kext") + t.KeyCancel = tc.getstr("kcan") + t.KeyPrint = tc.getstr("kprt") + t.KeyHelp = tc.getstr("khlp") + t.KeyClear = tc.getstr("kclr") + t.AltChars = tc.getstr("acsc") + t.EnterAcs = tc.getstr("smacs") + t.ExitAcs = tc.getstr("rmacs") + t.EnableAcs = tc.getstr("enacs") + t.Mouse = tc.getstr("kmous") + t.KeyShfRight = tc.getstr("kRIT") + t.KeyShfLeft = tc.getstr("kLFT") + t.KeyShfHome = tc.getstr("kHOM") + t.KeyShfEnd = tc.getstr("kEND") + + // Terminfo lacks descriptions for a bunch of modified keys, + // but modern XTerm and emulators often have them. Let's add them, + // if the shifted right and left arrows are defined. + if t.KeyShfRight == "\x1b[1;2C" && t.KeyShfLeft == "\x1b[1;2D" { + t.KeyShfUp = "\x1b[1;2A" + t.KeyShfDown = "\x1b[1;2B" + t.KeyMetaUp = "\x1b[1;9A" + t.KeyMetaDown = "\x1b[1;9B" + t.KeyMetaRight = "\x1b[1;9C" + t.KeyMetaLeft = "\x1b[1;9D" + t.KeyAltUp = "\x1b[1;3A" + t.KeyAltDown = "\x1b[1;3B" + t.KeyAltRight = "\x1b[1;3C" + t.KeyAltLeft = "\x1b[1;3D" + t.KeyCtrlUp = "\x1b[1;5A" + t.KeyCtrlDown = "\x1b[1;5B" + t.KeyCtrlRight = "\x1b[1;5C" + t.KeyCtrlLeft = "\x1b[1;5D" + t.KeyAltShfUp = "\x1b[1;4A" + t.KeyAltShfDown = "\x1b[1;4B" + t.KeyAltShfRight = "\x1b[1;4C" + t.KeyAltShfLeft = "\x1b[1;4D" + + t.KeyMetaShfUp = "\x1b[1;10A" + t.KeyMetaShfDown = "\x1b[1;10B" + t.KeyMetaShfRight = "\x1b[1;10C" + t.KeyMetaShfLeft = "\x1b[1;10D" + + t.KeyCtrlShfUp = "\x1b[1;6A" + t.KeyCtrlShfDown = "\x1b[1;6B" + t.KeyCtrlShfRight = "\x1b[1;6C" + t.KeyCtrlShfLeft = "\x1b[1;6D" + } + // And also for Home and End + if t.KeyShfHome == "\x1b[1;2H" && t.KeyShfEnd == "\x1b[1;2F" { + t.KeyCtrlHome = "\x1b[1;5H" + t.KeyCtrlEnd = "\x1b[1;5F" + t.KeyAltHome = "\x1b[1;9H" + t.KeyAltEnd = "\x1b[1;9F" + t.KeyCtrlShfHome = "\x1b[1;6H" + t.KeyCtrlShfEnd = "\x1b[1;6F" + t.KeyAltShfHome = "\x1b[1;4H" + t.KeyAltShfEnd = "\x1b[1;4F" + t.KeyMetaShfHome = "\x1b[1;10H" + t.KeyMetaShfEnd = "\x1b[1;10F" + } + + // And the same thing for rxvt and workalikes (Eterm, aterm, etc.) + // It seems that urxvt at least send ESC as ALT prefix for these, + // although some places seem to indicate a separate ALT key sesquence. + if t.KeyShfRight == "\x1b[c" && t.KeyShfLeft == "\x1b[d" { + t.KeyShfUp = "\x1b[a" + t.KeyShfDown = "\x1b[b" + t.KeyCtrlUp = "\x1b[Oa" + t.KeyCtrlDown = "\x1b[Ob" + t.KeyCtrlRight = "\x1b[Oc" + t.KeyCtrlLeft = "\x1b[Od" + } + if t.KeyShfHome == "\x1b[7$" && t.KeyShfEnd == "\x1b[8$" { + t.KeyCtrlHome = "\x1b[7^" + t.KeyCtrlEnd = "\x1b[8^" + } + + // If the kmous entry is present, then we need to record the + // the codes to enter and exit mouse mode. Sadly, this is not + // part of the terminfo databases anywhere that I've found, but + // is an extension. The escape codes are documented in the XTerm + // manual, and all terminals that have kmous are expected to + // use these same codes, unless explicitly configured otherwise + // vi XM. Note that in any event, we only known how to parse either + // x11 or SGR mouse events -- if your terminal doesn't support one + // of these two forms, you maybe out of luck. + t.MouseMode = tc.getstr("XM") + if t.Mouse != "" && t.MouseMode == "" { + // we anticipate that all xterm mouse tracking compatible + // terminals understand mouse tracking (1000), but we hope + // that those that don't understand any-event tracking (1003) + // will at least ignore it. Likewise we hope that terminals + // that don't understand SGR reporting (1006) just ignore it. + t.MouseMode = "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;" + + "\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c" + } + + // We only support colors in ANSI 8 or 256 color mode. + if t.Colors < 8 || t.SetFg == "" { + t.Colors = 0 + } + if t.SetCursor == "" { + return nil, "", errors.New("terminal not cursor addressable") + } + + // For padding, we lookup the pad char. If that isn't present, + // and npc is *not* set, then we assume a null byte. + t.PadChar = tc.getstr("pad") + if t.PadChar == "" { + if !tc.getflag("npc") { + t.PadChar = "\u0000" + } + } + + // For some terminals we fabricate a -truecolor entry, that may + // not exist in terminfo. + if addTrueColor { + t.SetFgRGB = "\x1b[38;2;%p1%d;%p2%d;%p3%dm" + t.SetBgRGB = "\x1b[48;2;%p1%d;%p2%d;%p3%dm" + t.SetFgBgRGB = "\x1b[38;2;%p1%d;%p2%d;%p3%d;" + + "48;2;%p4%d;%p5%d;%p6%dm" + } + + // For terminals that use "standard" SGR sequences, lets combine the + // foreground and background together. + if strings.HasPrefix(t.SetFg, "\x1b[") && + strings.HasPrefix(t.SetBg, "\x1b[") && + strings.HasSuffix(t.SetFg, "m") && + strings.HasSuffix(t.SetBg, "m") { + fg := t.SetFg[:len(t.SetFg)-1] + r := regexp.MustCompile("%p1") + bg := r.ReplaceAllString(t.SetBg[2:], "%p2") + t.SetFgBg = fg + ";" + bg + } + + return t, tc.desc, nil +} + +func dotGoAddInt(w io.Writer, n string, i int) { + if i == 0 { + // initialized to 0, ignore + return + } + fmt.Fprintf(w, "\t\t%-13s %d,\n", n+":", i) +} +func dotGoAddStr(w io.Writer, n string, s string) { + if s == "" { + return + } + fmt.Fprintf(w, "\t\t%-13s %q,\n", n+":", s) +} + +func dotGoAddArr(w io.Writer, n string, a []string) { + if len(a) == 0 { + return + } + fmt.Fprintf(w, "\t\t%-13s []string{", n+":") + did := false + for _, b := range a { + if did { + fmt.Fprint(w, ", ") + } + did = true + fmt.Fprintf(w, "%q", b) + } + fmt.Fprintln(w, "},") +} + +func dotGoHeader(w io.Writer, packname string) { + fmt.Fprintln(w, "// Generated automatically. DO NOT HAND-EDIT.") + fmt.Fprintln(w, "") + fmt.Fprintf(w, "package %s\n", packname) + fmt.Fprintln(w, "") +} + +func dotGoTrailer(w io.Writer) { +} + +func dotGoInfo(w io.Writer, t *terminfo.Terminfo, desc string) { + + fmt.Fprintln(w, "") + fmt.Fprintln(w, "func init() {") + fmt.Fprintf(w, "\t// %s\n", desc) + fmt.Fprintln(w, "\tAddTerminfo(&Terminfo{") + dotGoAddStr(w, "Name", t.Name) + dotGoAddArr(w, "Aliases", t.Aliases) + dotGoAddInt(w, "Columns", t.Columns) + dotGoAddInt(w, "Lines", t.Lines) + dotGoAddInt(w, "Colors", t.Colors) + dotGoAddStr(w, "Bell", t.Bell) + dotGoAddStr(w, "Clear", t.Clear) + dotGoAddStr(w, "EnterCA", t.EnterCA) + dotGoAddStr(w, "ExitCA", t.ExitCA) + dotGoAddStr(w, "ShowCursor", t.ShowCursor) + dotGoAddStr(w, "HideCursor", t.HideCursor) + dotGoAddStr(w, "AttrOff", t.AttrOff) + dotGoAddStr(w, "Underline", t.Underline) + dotGoAddStr(w, "Bold", t.Bold) + dotGoAddStr(w, "Dim", t.Dim) + dotGoAddStr(w, "Blink", t.Blink) + dotGoAddStr(w, "Reverse", t.Reverse) + dotGoAddStr(w, "EnterKeypad", t.EnterKeypad) + dotGoAddStr(w, "ExitKeypad", t.ExitKeypad) + dotGoAddStr(w, "SetFg", t.SetFg) + dotGoAddStr(w, "SetBg", t.SetBg) + dotGoAddStr(w, "SetFgBg", t.SetFgBg) + dotGoAddStr(w, "PadChar", t.PadChar) + dotGoAddStr(w, "AltChars", t.AltChars) + dotGoAddStr(w, "EnterAcs", t.EnterAcs) + dotGoAddStr(w, "ExitAcs", t.ExitAcs) + dotGoAddStr(w, "EnableAcs", t.EnableAcs) + dotGoAddStr(w, "SetFgRGB", t.SetFgRGB) + dotGoAddStr(w, "SetBgRGB", t.SetBgRGB) + dotGoAddStr(w, "SetFgBgRGB", t.SetFgBgRGB) + dotGoAddStr(w, "Mouse", t.Mouse) + dotGoAddStr(w, "MouseMode", t.MouseMode) + dotGoAddStr(w, "SetCursor", t.SetCursor) + dotGoAddStr(w, "CursorBack1", t.CursorBack1) + dotGoAddStr(w, "CursorUp1", t.CursorUp1) + dotGoAddStr(w, "KeyUp", t.KeyUp) + dotGoAddStr(w, "KeyDown", t.KeyDown) + dotGoAddStr(w, "KeyRight", t.KeyRight) + dotGoAddStr(w, "KeyLeft", t.KeyLeft) + dotGoAddStr(w, "KeyInsert", t.KeyInsert) + dotGoAddStr(w, "KeyDelete", t.KeyDelete) + dotGoAddStr(w, "KeyBackspace", t.KeyBackspace) + dotGoAddStr(w, "KeyHome", t.KeyHome) + dotGoAddStr(w, "KeyEnd", t.KeyEnd) + dotGoAddStr(w, "KeyPgUp", t.KeyPgUp) + dotGoAddStr(w, "KeyPgDn", t.KeyPgDn) + dotGoAddStr(w, "KeyF1", t.KeyF1) + dotGoAddStr(w, "KeyF2", t.KeyF2) + dotGoAddStr(w, "KeyF3", t.KeyF3) + dotGoAddStr(w, "KeyF4", t.KeyF4) + dotGoAddStr(w, "KeyF5", t.KeyF5) + dotGoAddStr(w, "KeyF6", t.KeyF6) + dotGoAddStr(w, "KeyF7", t.KeyF7) + dotGoAddStr(w, "KeyF8", t.KeyF8) + dotGoAddStr(w, "KeyF9", t.KeyF9) + dotGoAddStr(w, "KeyF10", t.KeyF10) + dotGoAddStr(w, "KeyF11", t.KeyF11) + dotGoAddStr(w, "KeyF12", t.KeyF12) + dotGoAddStr(w, "KeyF13", t.KeyF13) + dotGoAddStr(w, "KeyF14", t.KeyF14) + dotGoAddStr(w, "KeyF15", t.KeyF15) + dotGoAddStr(w, "KeyF16", t.KeyF16) + dotGoAddStr(w, "KeyF17", t.KeyF17) + dotGoAddStr(w, "KeyF18", t.KeyF18) + dotGoAddStr(w, "KeyF19", t.KeyF19) + dotGoAddStr(w, "KeyF20", t.KeyF20) + dotGoAddStr(w, "KeyF21", t.KeyF21) + dotGoAddStr(w, "KeyF22", t.KeyF22) + dotGoAddStr(w, "KeyF23", t.KeyF23) + dotGoAddStr(w, "KeyF24", t.KeyF24) + dotGoAddStr(w, "KeyF25", t.KeyF25) + dotGoAddStr(w, "KeyF26", t.KeyF26) + dotGoAddStr(w, "KeyF27", t.KeyF27) + dotGoAddStr(w, "KeyF28", t.KeyF28) + dotGoAddStr(w, "KeyF29", t.KeyF29) + dotGoAddStr(w, "KeyF30", t.KeyF30) + dotGoAddStr(w, "KeyF31", t.KeyF31) + dotGoAddStr(w, "KeyF32", t.KeyF32) + dotGoAddStr(w, "KeyF33", t.KeyF33) + dotGoAddStr(w, "KeyF34", t.KeyF34) + dotGoAddStr(w, "KeyF35", t.KeyF35) + dotGoAddStr(w, "KeyF36", t.KeyF36) + dotGoAddStr(w, "KeyF37", t.KeyF37) + dotGoAddStr(w, "KeyF38", t.KeyF38) + dotGoAddStr(w, "KeyF39", t.KeyF39) + dotGoAddStr(w, "KeyF40", t.KeyF40) + dotGoAddStr(w, "KeyF41", t.KeyF41) + dotGoAddStr(w, "KeyF42", t.KeyF42) + dotGoAddStr(w, "KeyF43", t.KeyF43) + dotGoAddStr(w, "KeyF44", t.KeyF44) + dotGoAddStr(w, "KeyF45", t.KeyF45) + dotGoAddStr(w, "KeyF46", t.KeyF46) + dotGoAddStr(w, "KeyF47", t.KeyF47) + dotGoAddStr(w, "KeyF48", t.KeyF48) + dotGoAddStr(w, "KeyF49", t.KeyF49) + dotGoAddStr(w, "KeyF50", t.KeyF50) + dotGoAddStr(w, "KeyF51", t.KeyF51) + dotGoAddStr(w, "KeyF52", t.KeyF52) + dotGoAddStr(w, "KeyF53", t.KeyF53) + dotGoAddStr(w, "KeyF54", t.KeyF54) + dotGoAddStr(w, "KeyF55", t.KeyF55) + dotGoAddStr(w, "KeyF56", t.KeyF56) + dotGoAddStr(w, "KeyF57", t.KeyF57) + dotGoAddStr(w, "KeyF58", t.KeyF58) + dotGoAddStr(w, "KeyF59", t.KeyF59) + dotGoAddStr(w, "KeyF60", t.KeyF60) + dotGoAddStr(w, "KeyF61", t.KeyF61) + dotGoAddStr(w, "KeyF62", t.KeyF62) + dotGoAddStr(w, "KeyF63", t.KeyF63) + dotGoAddStr(w, "KeyF64", t.KeyF64) + dotGoAddStr(w, "KeyCancel", t.KeyCancel) + dotGoAddStr(w, "KeyPrint", t.KeyPrint) + dotGoAddStr(w, "KeyExit", t.KeyExit) + dotGoAddStr(w, "KeyHelp", t.KeyHelp) + dotGoAddStr(w, "KeyClear", t.KeyClear) + dotGoAddStr(w, "KeyBacktab", t.KeyBacktab) + dotGoAddStr(w, "KeyShfLeft", t.KeyShfLeft) + dotGoAddStr(w, "KeyShfRight", t.KeyShfRight) + dotGoAddStr(w, "KeyShfUp", t.KeyShfUp) + dotGoAddStr(w, "KeyShfDown", t.KeyShfDown) + dotGoAddStr(w, "KeyCtrlLeft", t.KeyCtrlLeft) + dotGoAddStr(w, "KeyCtrlRight", t.KeyCtrlRight) + dotGoAddStr(w, "KeyCtrlUp", t.KeyCtrlUp) + dotGoAddStr(w, "KeyCtrlDown", t.KeyCtrlDown) + dotGoAddStr(w, "KeyMetaLeft", t.KeyMetaLeft) + dotGoAddStr(w, "KeyMetaRight", t.KeyMetaRight) + dotGoAddStr(w, "KeyMetaUp", t.KeyMetaUp) + dotGoAddStr(w, "KeyMetaDown", t.KeyMetaDown) + dotGoAddStr(w, "KeyAltLeft", t.KeyAltLeft) + dotGoAddStr(w, "KeyAltRight", t.KeyAltRight) + dotGoAddStr(w, "KeyAltUp", t.KeyAltUp) + dotGoAddStr(w, "KeyAltDown", t.KeyAltDown) + dotGoAddStr(w, "KeyAltShfLeft", t.KeyAltShfLeft) + dotGoAddStr(w, "KeyAltShfRight", t.KeyAltShfRight) + dotGoAddStr(w, "KeyAltShfUp", t.KeyAltShfUp) + dotGoAddStr(w, "KeyAltShfDown", t.KeyAltShfDown) + dotGoAddStr(w, "KeyMetaShfLeft", t.KeyMetaShfLeft) + dotGoAddStr(w, "KeyMetaShfRight", t.KeyMetaShfRight) + dotGoAddStr(w, "KeyMetaShfUp", t.KeyMetaShfUp) + dotGoAddStr(w, "KeyMetaShfDown", t.KeyMetaShfDown) + dotGoAddStr(w, "KeyCtrlShfLeft", t.KeyCtrlShfLeft) + dotGoAddStr(w, "KeyCtrlShfRight", t.KeyCtrlShfRight) + dotGoAddStr(w, "KeyCtrlShfUp", t.KeyCtrlShfUp) + dotGoAddStr(w, "KeyCtrlShfDown", t.KeyCtrlShfDown) + dotGoAddStr(w, "KeyShfHome", t.KeyShfHome) + dotGoAddStr(w, "KeyShfEnd", t.KeyShfEnd) + dotGoAddStr(w, "KeyCtrlHome", t.KeyCtrlHome) + dotGoAddStr(w, "KeyCtrlEnd", t.KeyCtrlEnd) + dotGoAddStr(w, "KeyMetaHome", t.KeyMetaHome) + dotGoAddStr(w, "KeyMetaEnd", t.KeyMetaEnd) + dotGoAddStr(w, "KeyAltHome", t.KeyAltHome) + dotGoAddStr(w, "KeyAltEnd", t.KeyAltEnd) + dotGoAddStr(w, "KeyCtrlShfHome", t.KeyCtrlShfHome) + dotGoAddStr(w, "KeyCtrlShfEnd", t.KeyCtrlShfEnd) + dotGoAddStr(w, "KeyMetaShfHome", t.KeyMetaShfHome) + dotGoAddStr(w, "KeyMetaShfEnd", t.KeyMetaShfEnd) + dotGoAddStr(w, "KeyAltShfHome", t.KeyAltShfHome) + dotGoAddStr(w, "KeyAltShfEnd", t.KeyAltShfEnd) + fmt.Fprintln(w, "\t})") + fmt.Fprintln(w, "}") +} + +func main() { + gofile := "" + jsonfile := "" + packname := "terminfo" + nofatal := false + quiet := false + dogzip := false + + flag.StringVar(&gofile, "go", "", "generate go source in named file") + flag.StringVar(&jsonfile, "json", "", "generate json in named file") + flag.StringVar(&packname, "P", packname, "package name (go source)") + flag.BoolVar(&nofatal, "nofatal", false, "errors are not fatal") + flag.BoolVar(&quiet, "quiet", false, "suppress error messages") + flag.BoolVar(&dogzip, "gzip", false, "compress json output") + flag.Parse() + var e error + js := []byte{} + + args := flag.Args() + if len(args) == 0 { + args = []string{os.Getenv("TERM")} + } + + tdata := make(map[string]*terminfo.Terminfo) + descs := make(map[string]string) + + for _, term := range args { + if t, desc, e := getinfo(term); e != nil { + if !quiet { + fmt.Fprintf(os.Stderr, + "Failed loading %s: %v\n", term, e) + } + if !nofatal { + os.Exit(1) + } + } else { + tdata[term] = t + descs[term] = desc + } + } + + if len(tdata) == 0 { + // No data. + os.Exit(0) + } + if gofile != "" { + w := os.Stdout + if gofile != "-" { + if w, e = os.Create(gofile); e != nil { + fmt.Fprintf(os.Stderr, "Failed: %v", e) + os.Exit(1) + } + } + dotGoHeader(w, packname) + for term, t := range tdata { + if t.Name == term { + dotGoInfo(w, t, descs[term]) + } + } + dotGoTrailer(w) + if w != os.Stdout { + w.Close() + } + } else { + o := os.Stdout + if jsonfile != "-" && jsonfile != "" { + if o, e = os.Create(jsonfile); e != nil { + fmt.Fprintf(os.Stderr, "Failed: %v", e) + } + } + var w io.WriteCloser + w = o + if dogzip { + w = gzip.NewWriter(o) + } + for _, term := range args { + if t := tdata[term]; t != nil { + js, e = json.Marshal(t) + fmt.Fprintln(w, string(js)) + } + // arguably if there is more than one term, this + // should be a javascript array, but that's not how + // we load it. We marshal objects one at a time from + // the file. + } + if e != nil { + fmt.Fprintf(os.Stderr, "Failed: %v", e) + os.Exit(1) + } + w.Close() + if w != o { + o.Close() + } + } +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/models.txt b/vendor/github.com/gdamore/tcell/terminfo/models.txt new file mode 100644 index 00000000..ac0676d6 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/models.txt @@ -0,0 +1,59 @@ +adm3a +aixterm +ansi +aterm +beterm +bsdos-pc +cygwin +d200 +d210 +dtterm +Eterm +Eterm-256color +eterm +gnome +gnome-256color +hpterm +hz1500 +konsole +konsole-256color +kterm +linux +pcansi +rxvt +rxvt-256color +rxvt-unicode +rxvt-unicode-256color +screen +screen-256color +st +st-256color +st-truecolor +st-meta +st-meta-256color +st-meta-truecolor +sun +sun-color +tvi910 +tvi912 +tvi921 +tvi925 +tvi950 +tvi970 +vt52 +vt100 +vt102 +vt220 +vt320 +vt400 +vt420 +wy50 +wy60 +wy99-ansi +wy99a-ansi +xfce +xnuppc +xterm +xterm +xterm-256color +xterm-truecolor diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_Eterm.go b/vendor/github.com/gdamore/tcell/terminfo/term_Eterm.go new file mode 100644 index 00000000..9290e32b --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_Eterm.go @@ -0,0 +1,24 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // gnu emacs term.el terminal emulation + AddTerminfo(&Terminfo{ + Name: "eterm", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + AttrOff: "\x1b[m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + PadChar: "\x00", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_Eterm_256color.go b/vendor/github.com/gdamore/tcell/terminfo/term_Eterm_256color.go new file mode 100644 index 00000000..af2f5ff1 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_Eterm_256color.go @@ -0,0 +1,105 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Eterm with xterm 256-colors + AddTerminfo(&Terminfo{ + Name: "Eterm-256color", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1b[7~", + KeyEnd: "\x1b[8~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[11~", + KeyF2: "\x1b[12~", + KeyF3: "\x1b[13~", + KeyF4: "\x1b[14~", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyF21: "\x1b[23$", + KeyF22: "\x1b[24$", + KeyF23: "\x1b[11^", + KeyF24: "\x1b[12^", + KeyF25: "\x1b[13^", + KeyF26: "\x1b[14^", + KeyF27: "\x1b[15^", + KeyF28: "\x1b[17^", + KeyF29: "\x1b[18^", + KeyF30: "\x1b[19^", + KeyF31: "\x1b[20^", + KeyF32: "\x1b[21^", + KeyF33: "\x1b[23^", + KeyF34: "\x1b[24^", + KeyF35: "\x1b[25^", + KeyF36: "\x1b[26^", + KeyF37: "\x1b[28^", + KeyF38: "\x1b[29^", + KeyF39: "\x1b[31^", + KeyF40: "\x1b[32^", + KeyF41: "\x1b[33^", + KeyF42: "\x1b[34^", + KeyF43: "\x1b[23@", + KeyF44: "\x1b[24@", + KeyHelp: "\x1b[28~", + KeyShfLeft: "\x1b[d", + KeyShfRight: "\x1b[c", + KeyShfUp: "\x1b[a", + KeyShfDown: "\x1b[b", + KeyCtrlLeft: "\x1b[Od", + KeyCtrlRight: "\x1b[Oc", + KeyCtrlUp: "\x1b[Oa", + KeyCtrlDown: "\x1b[Ob", + KeyShfHome: "\x1b[7$", + KeyShfEnd: "\x1b[8$", + KeyCtrlHome: "\x1b[7^", + KeyCtrlEnd: "\x1b[8^", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_adm3a.go b/vendor/github.com/gdamore/tcell/terminfo/term_adm3a.go new file mode 100644 index 00000000..dc57809e --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_adm3a.go @@ -0,0 +1,22 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // lsi adm3a + AddTerminfo(&Terminfo{ + Name: "adm3a", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x0032$<1/>", + PadChar: "\x00", + SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", + CursorBack1: "\b", + CursorUp1: "\v", + KeyUp: "\v", + KeyDown: "\n", + KeyRight: "\f", + KeyLeft: "\b", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_aixterm.go b/vendor/github.com/gdamore/tcell/terminfo/term_aixterm.go new file mode 100644 index 00000000..e1d2146a --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_aixterm.go @@ -0,0 +1,76 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // IBM Aixterm Terminal Emulator + AddTerminfo(&Terminfo{ + Name: "aixterm", + Columns: 80, + Lines: 25, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + AttrOff: "\x1b[0;10m\x1b(B", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "jjkkllmmnnqqttuuvvwwxx", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[139q", + KeyDelete: "\x1b[P", + KeyBackspace: "\b", + KeyHome: "\x1b[H", + KeyEnd: "\x1b[146q", + KeyPgUp: "\x1b[150q", + KeyPgDn: "\x1b[154q", + KeyF1: "\x1b[001q", + KeyF2: "\x1b[002q", + KeyF3: "\x1b[003q", + KeyF4: "\x1b[004q", + KeyF5: "\x1b[005q", + KeyF6: "\x1b[006q", + KeyF7: "\x1b[007q", + KeyF8: "\x1b[008q", + KeyF9: "\x1b[009q", + KeyF10: "\x1b[010q", + KeyF11: "\x1b[011q", + KeyF12: "\x1b[012q", + KeyF13: "\x1b[013q", + KeyF14: "\x1b[014q", + KeyF15: "\x1b[015q", + KeyF16: "\x1b[016q", + KeyF17: "\x1b[017q", + KeyF18: "\x1b[018q", + KeyF19: "\x1b[019q", + KeyF20: "\x1b[020q", + KeyF21: "\x1b[021q", + KeyF22: "\x1b[022q", + KeyF23: "\x1b[023q", + KeyF24: "\x1b[024q", + KeyF25: "\x1b[025q", + KeyF26: "\x1b[026q", + KeyF27: "\x1b[027q", + KeyF28: "\x1b[028q", + KeyF29: "\x1b[029q", + KeyF30: "\x1b[030q", + KeyF31: "\x1b[031q", + KeyF32: "\x1b[032q", + KeyF33: "\x1b[033q", + KeyF34: "\x1b[034q", + KeyF35: "\x1b[035q", + KeyF36: "\x1b[036q", + KeyClear: "\x1b[144q", + KeyBacktab: "\x1b[Z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_ansi.go b/vendor/github.com/gdamore/tcell/terminfo/term_ansi.go new file mode 100644 index 00000000..52a68ea4 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_ansi.go @@ -0,0 +1,38 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // ansi/pc-term compatible with color + AddTerminfo(&Terminfo{ + Name: "ansi", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + AttrOff: "\x1b[0;10m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "+\x0020,\x0021-\x0030.\x190333`\x0004a261f370g361h260j331k277l332m300n305o~p304q304r304s_t303u264v301w302x263y363z362{343|330}234~376", + EnterAcs: "\x1b[11m", + ExitAcs: "\x1b[10m", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\x1b[D", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[L", + KeyBackspace: "\b", + KeyHome: "\x1b[H", + KeyBacktab: "\x1b[Z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_aterm.go b/vendor/github.com/gdamore/tcell/terminfo/term_aterm.go new file mode 100644 index 00000000..94daaafa --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_aterm.go @@ -0,0 +1,107 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // AfterStep terminal + AddTerminfo(&Terminfo{ + Name: "aterm", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b=", + ExitKeypad: "\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b(B\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[7~", + KeyEnd: "\x1b[8~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyF21: "\x1b[23$", + KeyF22: "\x1b[24$", + KeyF23: "\x1b[11^", + KeyF24: "\x1b[12^", + KeyF25: "\x1b[13^", + KeyF26: "\x1b[14^", + KeyF27: "\x1b[15^", + KeyF28: "\x1b[17^", + KeyF29: "\x1b[18^", + KeyF30: "\x1b[19^", + KeyF31: "\x1b[20^", + KeyF32: "\x1b[21^", + KeyF33: "\x1b[23^", + KeyF34: "\x1b[24^", + KeyF35: "\x1b[25^", + KeyF36: "\x1b[26^", + KeyF37: "\x1b[28^", + KeyF38: "\x1b[29^", + KeyF39: "\x1b[31^", + KeyF40: "\x1b[32^", + KeyF41: "\x1b[33^", + KeyF42: "\x1b[34^", + KeyF43: "\x1b[23@", + KeyF44: "\x1b[24@", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[d", + KeyShfRight: "\x1b[c", + KeyShfUp: "\x1b[a", + KeyShfDown: "\x1b[b", + KeyCtrlLeft: "\x1b[Od", + KeyCtrlRight: "\x1b[Oc", + KeyCtrlUp: "\x1b[Oa", + KeyCtrlDown: "\x1b[Ob", + KeyShfHome: "\x1b[7$", + KeyShfEnd: "\x1b[8$", + KeyCtrlHome: "\x1b[7^", + KeyCtrlEnd: "\x1b[8^", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_beterm.go b/vendor/github.com/gdamore/tcell/terminfo/term_beterm.go new file mode 100644 index 00000000..de1b5d9f --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_beterm.go @@ -0,0 +1,51 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // BeOS Terminal + AddTerminfo(&Terminfo{ + Name: "beterm", + Columns: 80, + Lines: 25, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + AttrOff: "\x1b[0;10m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?4h", + ExitKeypad: "\x1b[?4l", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[11~", + KeyF2: "\x1b[12~", + KeyF3: "\x1b[13~", + KeyF4: "\x1b[14~", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[16~", + KeyF7: "\x1b[17~", + KeyF8: "\x1b[18~", + KeyF9: "\x1b[19~", + KeyF10: "\x1b[20~", + KeyF11: "\x1b[21~", + KeyF12: "\x1b[22~", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_bsdos_pc.go b/vendor/github.com/gdamore/tcell/terminfo/term_bsdos_pc.go new file mode 100644 index 00000000..413ea649 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_bsdos_pc.go @@ -0,0 +1,39 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // IBM PC BSD/OS Console + AddTerminfo(&Terminfo{ + Name: "bsdos-pc", + Columns: 80, + Lines: 25, + Colors: 8, + Bell: "\a", + Clear: "\x1bc", + AttrOff: "\x1b[0;10m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "+\x0020,\x0021-\x0030.\x190333`\x0004a261f370g361h260j331k277l332m300n305o~p304q304r304s_t303u264v301w302x263y363z362{343|330}234~376", + EnterAcs: "\x1b[11m", + ExitAcs: "\x1b[10m", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[L", + KeyBackspace: "\b", + KeyHome: "\x1b[H", + KeyPgUp: "\x1b[I", + KeyPgDn: "\x1b[G", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_cygwin.go b/vendor/github.com/gdamore/tcell/terminfo/term_cygwin.go new file mode 100644 index 00000000..1fdc571c --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_cygwin.go @@ -0,0 +1,60 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // ansi emulation for Cygwin + AddTerminfo(&Terminfo{ + Name: "cygwin", + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + AttrOff: "\x1b[0;10m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "+\x0020,\x0021-\x0030.\x190333`\x0004a261f370g361h260j331k277l332m300n305o~p304q304r304s_t303u264v301w302x263y363z362{343|330}234~376", + EnterAcs: "\x1b[11m", + ExitAcs: "\x1b[10m", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[[A", + KeyF2: "\x1b[[B", + KeyF3: "\x1b[[C", + KeyF4: "\x1b[[D", + KeyF5: "\x1b[[E", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_d200.go b/vendor/github.com/gdamore/tcell/terminfo/term_d200.go new file mode 100644 index 00000000..e8016797 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_d200.go @@ -0,0 +1,94 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Data General DASHER D200 + AddTerminfo(&Terminfo{ + Name: "d200", + Aliases: []string{"d200-dg"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\f", + AttrOff: "\x0017\x0025\x0035\x0036E", + Underline: "\x14", + Bold: "\x1eD\x14", + Dim: "\x1c", + Blink: "\x0e", + Reverse: "\x1eD", + PadChar: "\x00", + SetCursor: "\x0020%p2%c%p1%c", + CursorBack1: "\x19", + CursorUp1: "\x17", + KeyUp: "\x17", + KeyDown: "\x1a", + KeyRight: "\x18", + KeyLeft: "\x19", + KeyHome: "\b", + KeyF1: "\x1eq", + KeyF2: "\x1er", + KeyF3: "\x1es", + KeyF4: "\x1et", + KeyF5: "\x1eu", + KeyF6: "\x1ev", + KeyF7: "\x1ew", + KeyF8: "\x1ex", + KeyF9: "\x1ey", + KeyF10: "\x1ez", + KeyF11: "\x1e{", + KeyF12: "\x1e|", + KeyF13: "\x1e}", + KeyF14: "\x1e~", + KeyF15: "\x1ep", + KeyF16: "\x1ea", + KeyF17: "\x1eb", + KeyF18: "\x1ec", + KeyF19: "\x1ed", + KeyF20: "\x1ee", + KeyF21: "\x1ef", + KeyF22: "\x1eg", + KeyF23: "\x1eh", + KeyF24: "\x1ei", + KeyF25: "\x1ej", + KeyF26: "\x1ek", + KeyF27: "\x1el", + KeyF28: "\x1em", + KeyF29: "\x1en", + KeyF30: "\x1e`", + KeyF31: "\x1e1", + KeyF32: "\x1e2", + KeyF33: "\x1e3", + KeyF34: "\x1e4", + KeyF35: "\x1e5", + KeyF36: "\x1e6", + KeyF37: "\x1e7", + KeyF38: "\x1e8", + KeyF39: "\x1e9", + KeyF40: "\x1e:", + KeyF41: "\x1e;", + KeyF42: "\x1e<", + KeyF43: "\x1e=", + KeyF44: "\x1e>", + KeyF45: "\x1e0", + KeyF46: "\x1e!", + KeyF47: "\x1e\"", + KeyF48: "\x1e#", + KeyF49: "\x1e$", + KeyF50: "\x1e%%", + KeyF51: "\x1e&", + KeyF52: "\x1e'", + KeyF53: "\x1e(", + KeyF54: "\x1e)", + KeyF55: "\x1e*", + KeyF56: "\x1e+", + KeyF57: "\x1e,", + KeyF58: "\x1e-", + KeyF59: "\x1e.", + KeyF60: "\x1e ", + KeyClear: "\f", + KeyShfLeft: "\x1e\x19", + KeyShfRight: "\x1e\x18", + KeyShfHome: "\x1e\b", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_d210.go b/vendor/github.com/gdamore/tcell/terminfo/term_d210.go new file mode 100644 index 00000000..87e0662d --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_d210.go @@ -0,0 +1,92 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Data General DASHER D210 series + AddTerminfo(&Terminfo{ + Name: "d210", + Aliases: []string{"d214"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b[2J", + AttrOff: "\x1b[m", + Underline: "\x1b[4m", + Bold: "\x1b[4;7m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + PadChar: "\x00", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyHome: "\x1b[H", + KeyF1: "\x1b[001z", + KeyF2: "\x1b[002z", + KeyF3: "\x1b[003z", + KeyF4: "\x1b[004z", + KeyF5: "\x1b[005z", + KeyF6: "\x1b[006z", + KeyF7: "\x1b[007z", + KeyF8: "\x1b[008z", + KeyF9: "\x1b[009z", + KeyF10: "\x1b[010z", + KeyF11: "\x1b[011z", + KeyF12: "\x1b[012z", + KeyF13: "\x1b[013z", + KeyF14: "\x1b[014z", + KeyF15: "\x1b[000z", + KeyF16: "\x1b[101z", + KeyF17: "\x1b[102z", + KeyF18: "\x1b[103z", + KeyF19: "\x1b[104z", + KeyF20: "\x1b[105z", + KeyF21: "\x1b[106z", + KeyF22: "\x1b[107z", + KeyF23: "\x1b[108z", + KeyF24: "\x1b[109z", + KeyF25: "\x1b[110z", + KeyF26: "\x1b[111z", + KeyF27: "\x1b[112z", + KeyF28: "\x1b[113z", + KeyF29: "\x1b[114z", + KeyF30: "\x1b[100z", + KeyF31: "\x1b[201z", + KeyF32: "\x1b[202z", + KeyF33: "\x1b[203z", + KeyF34: "\x1b[204z", + KeyF35: "\x1b[205z", + KeyF36: "\x1b[206z", + KeyF37: "\x1b[207z", + KeyF38: "\x1b[208z", + KeyF39: "\x1b[209z", + KeyF40: "\x1b[210z", + KeyF41: "\x1b[211z", + KeyF42: "\x1b[212z", + KeyF43: "\x1b[213z", + KeyF44: "\x1b[214z", + KeyF45: "\x1b[200z", + KeyF46: "\x1b[301z", + KeyF47: "\x1b[302z", + KeyF48: "\x1b[303z", + KeyF49: "\x1b[304z", + KeyF50: "\x1b[305z", + KeyF51: "\x1b[306z", + KeyF52: "\x1b[307z", + KeyF53: "\x1b[308z", + KeyF54: "\x1b[309z", + KeyF55: "\x1b[310z", + KeyF56: "\x1b[311z", + KeyF57: "\x1b[312z", + KeyF58: "\x1b[313z", + KeyF59: "\x1b[314z", + KeyF60: "\x1b[300z", + KeyPrint: "\x1b[i", + KeyClear: "\x1b[2J", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_dtterm.go b/vendor/github.com/gdamore/tcell/terminfo/term_dtterm.go new file mode 100644 index 00000000..c173d56b --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_dtterm.go @@ -0,0 +1,64 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // CDE desktop terminal + AddTerminfo(&Terminfo{ + Name: "dtterm", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b(B\x1b)0", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[11~", + KeyF2: "\x1b[12~", + KeyF3: "\x1b[13~", + KeyF4: "\x1b[14~", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyHelp: "\x1b[28~", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_gnome.go b/vendor/github.com/gdamore/tcell/terminfo/term_gnome.go new file mode 100644 index 00000000..0b7b85a7 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_gnome.go @@ -0,0 +1,153 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // GNOME Terminal + AddTerminfo(&Terminfo{ + Name: "gnome", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1bOH", + KeyEnd: "\x1bOF", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1bO1;2P", + KeyF14: "\x1bO1;2Q", + KeyF15: "\x1bO1;2R", + KeyF16: "\x1bO1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1bO1;5P", + KeyF26: "\x1bO1;5Q", + KeyF27: "\x1bO1;5R", + KeyF28: "\x1bO1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1bO1;6P", + KeyF38: "\x1bO1;6Q", + KeyF39: "\x1bO1;6R", + KeyF40: "\x1bO1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1bO1;3P", + KeyF50: "\x1bO1;3Q", + KeyF51: "\x1bO1;3R", + KeyF52: "\x1bO1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1bO1;4P", + KeyF62: "\x1bO1;4Q", + KeyF63: "\x1bO1;4R", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_gnome_256color.go b/vendor/github.com/gdamore/tcell/terminfo/term_gnome_256color.go new file mode 100644 index 00000000..23834898 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_gnome_256color.go @@ -0,0 +1,153 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // GNOME Terminal with xterm 256-colors + AddTerminfo(&Terminfo{ + Name: "gnome-256color", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + PadChar: "\x00", + AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1bOH", + KeyEnd: "\x1bOF", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1bO1;2P", + KeyF14: "\x1bO1;2Q", + KeyF15: "\x1bO1;2R", + KeyF16: "\x1bO1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1bO1;5P", + KeyF26: "\x1bO1;5Q", + KeyF27: "\x1bO1;5R", + KeyF28: "\x1bO1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1bO1;6P", + KeyF38: "\x1bO1;6Q", + KeyF39: "\x1bO1;6R", + KeyF40: "\x1bO1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1bO1;3P", + KeyF50: "\x1bO1;3Q", + KeyF51: "\x1bO1;3R", + KeyF52: "\x1bO1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1bO1;4P", + KeyF62: "\x1bO1;4Q", + KeyF63: "\x1bO1;4R", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_hpterm.go b/vendor/github.com/gdamore/tcell/terminfo/term_hpterm.go new file mode 100644 index 00000000..0fa30bc6 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_hpterm.go @@ -0,0 +1,47 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // hp X11 terminal emulator + AddTerminfo(&Terminfo{ + Name: "hpterm", + Aliases: []string{"X-hpterm"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b&a0y0C\x1bJ", + AttrOff: "\x1b&d@", + Underline: "\x1b&dD", + Bold: "\x1b&dB", + Dim: "\x1b&dH", + Reverse: "\x1b&dB", + EnterKeypad: "\x1b&s1A", + ExitKeypad: "\x1b&s0A", + PadChar: "\x00", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + SetCursor: "\x1b&a%p1%dy%p2%dC", + CursorBack1: "\b", + CursorUp1: "\x1bA", + KeyUp: "\x1bA", + KeyDown: "\x1bB", + KeyRight: "\x1bC", + KeyLeft: "\x1bD", + KeyInsert: "\x1bQ", + KeyDelete: "\x1bP", + KeyBackspace: "\b", + KeyHome: "\x1bh", + KeyPgUp: "\x1bV", + KeyPgDn: "\x1bU", + KeyF1: "\x1bp", + KeyF2: "\x1bq", + KeyF3: "\x1br", + KeyF4: "\x1bs", + KeyF5: "\x1bt", + KeyF6: "\x1bu", + KeyF7: "\x1bv", + KeyF8: "\x1bw", + KeyClear: "\x1bJ", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_hz1500.go b/vendor/github.com/gdamore/tcell/terminfo/term_hz1500.go new file mode 100644 index 00000000..8af0eff5 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_hz1500.go @@ -0,0 +1,23 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // hazeltine 1500 + AddTerminfo(&Terminfo{ + Name: "hz1500", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "~\x1c", + PadChar: "\x00", + SetCursor: "~\x0021%p2%p2%?%{30}%>%t%' '%+%;%'`'%+%c%p1%'`'%+%c", + CursorBack1: "\b", + CursorUp1: "~\f", + KeyUp: "~\f", + KeyDown: "\n", + KeyRight: "\x10", + KeyLeft: "\b", + KeyHome: "~\x12", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_konsole.go b/vendor/github.com/gdamore/tcell/terminfo/term_konsole.go new file mode 100644 index 00000000..c2689de4 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_konsole.go @@ -0,0 +1,112 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // KDE console window + AddTerminfo(&Terminfo{ + Name: "konsole", + Columns: 80, + Lines: 24, + Colors: 8, + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1bOH", + KeyEnd: "\x1bOF", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1bO2P", + KeyF14: "\x1bO2Q", + KeyF15: "\x1bO2R", + KeyF16: "\x1bO2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1bO5P", + KeyF26: "\x1bO5Q", + KeyF27: "\x1bO5R", + KeyF28: "\x1bO5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1bO6P", + KeyF38: "\x1bO6Q", + KeyF39: "\x1bO6R", + KeyF40: "\x1bO6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1bO3P", + KeyF50: "\x1bO3Q", + KeyF51: "\x1bO3R", + KeyF52: "\x1bO3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1bO4P", + KeyF62: "\x1bO4Q", + KeyF63: "\x1bO4R", + KeyBacktab: "\x1b[Z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_konsole_256color.go b/vendor/github.com/gdamore/tcell/terminfo/term_konsole_256color.go new file mode 100644 index 00000000..7adc8ea2 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_konsole_256color.go @@ -0,0 +1,112 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // KDE console window with xterm 256-colors + AddTerminfo(&Terminfo{ + Name: "konsole-256color", + Columns: 80, + Lines: 24, + Colors: 256, + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1bOH", + KeyEnd: "\x1bOF", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1bO2P", + KeyF14: "\x1bO2Q", + KeyF15: "\x1bO2R", + KeyF16: "\x1bO2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1bO5P", + KeyF26: "\x1bO5Q", + KeyF27: "\x1bO5R", + KeyF28: "\x1bO5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1bO6P", + KeyF38: "\x1bO6Q", + KeyF39: "\x1bO6R", + KeyF40: "\x1bO6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1bO3P", + KeyF50: "\x1bO3Q", + KeyF51: "\x1bO3R", + KeyF52: "\x1bO3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1bO4P", + KeyF62: "\x1bO4Q", + KeyF63: "\x1bO4R", + KeyBacktab: "\x1b[Z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_kterm.go b/vendor/github.com/gdamore/tcell/terminfo/term_kterm.go new file mode 100644 index 00000000..a7ec2f10 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_kterm.go @@ -0,0 +1,64 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // kterm kanji terminal emulator (X window system) + AddTerminfo(&Terminfo{ + Name: "kterm", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + AttrOff: "\x1b[m\x1b(B", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "``aajjkkllmmnnooppqqrrssttuuvvwwxx~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[11~", + KeyF2: "\x1b[12~", + KeyF3: "\x1b[13~", + KeyF4: "\x1b[14~", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_linux.go b/vendor/github.com/gdamore/tcell/terminfo/term_linux.go new file mode 100644 index 00000000..e35a4775 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_linux.go @@ -0,0 +1,65 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // linux console + AddTerminfo(&Terminfo{ + Name: "linux", + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + ShowCursor: "\x1b[?25h\x1b[?0c", + HideCursor: "\x1b[?25l\x1b[?1c", + AttrOff: "\x1b[0;10m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "+\x0020,\x0021-\x0030.\x190333`\x0004a261f370g361h260i316j331k277l332m300n305o~p304q304r304s_t303u264v301w302x263y363z362{343|330}234~376", + EnterAcs: "\x1b[11m", + ExitAcs: "\x1b[10m", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[[A", + KeyF2: "\x1b[[B", + KeyF3: "\x1b[[C", + KeyF4: "\x1b[[D", + KeyF5: "\x1b[[E", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyBacktab: "\x1b[Z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_pcansi.go b/vendor/github.com/gdamore/tcell/terminfo/term_pcansi.go new file mode 100644 index 00000000..055b3acf --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_pcansi.go @@ -0,0 +1,36 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // ibm-pc terminal programs claiming to be ansi + AddTerminfo(&Terminfo{ + Name: "pcansi", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + AttrOff: "\x1b[0;10m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "+\x0020,\x0021-\x0030.\x190333`\x0004a261f370g361h260j331k277l332m300n305o~p304q304r304s_t303u264v301w302x263y363z362{343|330}234~376", + EnterAcs: "\x1b[12m", + ExitAcs: "\x1b[10m", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\x1b[D", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyBackspace: "\b", + KeyHome: "\x1b[H", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_rxvt.go b/vendor/github.com/gdamore/tcell/terminfo/term_rxvt.go new file mode 100644 index 00000000..dab1758b --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_rxvt.go @@ -0,0 +1,107 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // rxvt terminal emulator (X Window System) + AddTerminfo(&Terminfo{ + Name: "rxvt", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b=", + ExitKeypad: "\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b(B\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1b[7~", + KeyEnd: "\x1b[8~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[11~", + KeyF2: "\x1b[12~", + KeyF3: "\x1b[13~", + KeyF4: "\x1b[14~", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyF21: "\x1b[23$", + KeyF22: "\x1b[24$", + KeyF23: "\x1b[11^", + KeyF24: "\x1b[12^", + KeyF25: "\x1b[13^", + KeyF26: "\x1b[14^", + KeyF27: "\x1b[15^", + KeyF28: "\x1b[17^", + KeyF29: "\x1b[18^", + KeyF30: "\x1b[19^", + KeyF31: "\x1b[20^", + KeyF32: "\x1b[21^", + KeyF33: "\x1b[23^", + KeyF34: "\x1b[24^", + KeyF35: "\x1b[25^", + KeyF36: "\x1b[26^", + KeyF37: "\x1b[28^", + KeyF38: "\x1b[29^", + KeyF39: "\x1b[31^", + KeyF40: "\x1b[32^", + KeyF41: "\x1b[33^", + KeyF42: "\x1b[34^", + KeyF43: "\x1b[23@", + KeyF44: "\x1b[24@", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[d", + KeyShfRight: "\x1b[c", + KeyShfUp: "\x1b[a", + KeyShfDown: "\x1b[b", + KeyCtrlLeft: "\x1b[Od", + KeyCtrlRight: "\x1b[Oc", + KeyCtrlUp: "\x1b[Oa", + KeyCtrlDown: "\x1b[Ob", + KeyShfHome: "\x1b[7$", + KeyShfEnd: "\x1b[8$", + KeyCtrlHome: "\x1b[7^", + KeyCtrlEnd: "\x1b[8^", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_256color.go b/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_256color.go new file mode 100644 index 00000000..5aceb4ee --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_256color.go @@ -0,0 +1,107 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // rxvt 2.7.9 with xterm 256-colors + AddTerminfo(&Terminfo{ + Name: "rxvt-256color", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b=", + ExitKeypad: "\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b(B\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1b[7~", + KeyEnd: "\x1b[8~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[11~", + KeyF2: "\x1b[12~", + KeyF3: "\x1b[13~", + KeyF4: "\x1b[14~", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyF21: "\x1b[23$", + KeyF22: "\x1b[24$", + KeyF23: "\x1b[11^", + KeyF24: "\x1b[12^", + KeyF25: "\x1b[13^", + KeyF26: "\x1b[14^", + KeyF27: "\x1b[15^", + KeyF28: "\x1b[17^", + KeyF29: "\x1b[18^", + KeyF30: "\x1b[19^", + KeyF31: "\x1b[20^", + KeyF32: "\x1b[21^", + KeyF33: "\x1b[23^", + KeyF34: "\x1b[24^", + KeyF35: "\x1b[25^", + KeyF36: "\x1b[26^", + KeyF37: "\x1b[28^", + KeyF38: "\x1b[29^", + KeyF39: "\x1b[31^", + KeyF40: "\x1b[32^", + KeyF41: "\x1b[33^", + KeyF42: "\x1b[34^", + KeyF43: "\x1b[23@", + KeyF44: "\x1b[24@", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[d", + KeyShfRight: "\x1b[c", + KeyShfUp: "\x1b[a", + KeyShfDown: "\x1b[b", + KeyCtrlLeft: "\x1b[Od", + KeyCtrlRight: "\x1b[Oc", + KeyCtrlUp: "\x1b[Oa", + KeyCtrlDown: "\x1b[Ob", + KeyShfHome: "\x1b[7$", + KeyShfEnd: "\x1b[8$", + KeyCtrlHome: "\x1b[7^", + KeyCtrlEnd: "\x1b[8^", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_unicode.go b/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_unicode.go new file mode 100644 index 00000000..6da67b72 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_unicode.go @@ -0,0 +1,81 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // rxvt-unicode terminal (X Window System) + AddTerminfo(&Terminfo{ + Name: "rxvt-unicode", + Columns: 80, + Lines: 24, + Colors: 88, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[r\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x1b(B", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b=", + ExitKeypad: "\x1b>", + SetFg: "\x1b[38;5;%p1%dm", + SetBg: "\x1b[48;5;%p1%dm", + SetFgBg: "\x1b[38;5;%p1%d;48;5;%p2%dm", + AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[7~", + KeyEnd: "\x1b[8~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[11~", + KeyF2: "\x1b[12~", + KeyF3: "\x1b[13~", + KeyF4: "\x1b[14~", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[d", + KeyShfRight: "\x1b[c", + KeyShfUp: "\x1b[a", + KeyShfDown: "\x1b[b", + KeyCtrlLeft: "\x1b[Od", + KeyCtrlRight: "\x1b[Oc", + KeyCtrlUp: "\x1b[Oa", + KeyCtrlDown: "\x1b[Ob", + KeyShfHome: "\x1b[7$", + KeyShfEnd: "\x1b[8$", + KeyCtrlHome: "\x1b[7^", + KeyCtrlEnd: "\x1b[8^", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_unicode_256color.go b/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_unicode_256color.go new file mode 100644 index 00000000..ac87fb96 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_rxvt_unicode_256color.go @@ -0,0 +1,81 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // rxvt-unicode terminal with 256 colors (X Window System) + AddTerminfo(&Terminfo{ + Name: "rxvt-unicode-256color", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[r\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x1b(B", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b=", + ExitKeypad: "\x1b>", + SetFg: "\x1b[38;5;%p1%dm", + SetBg: "\x1b[48;5;%p1%dm", + SetFgBg: "\x1b[38;5;%p1%d;48;5;%p2%dm", + AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[7~", + KeyEnd: "\x1b[8~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1b[11~", + KeyF2: "\x1b[12~", + KeyF3: "\x1b[13~", + KeyF4: "\x1b[14~", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[d", + KeyShfRight: "\x1b[c", + KeyShfUp: "\x1b[a", + KeyShfDown: "\x1b[b", + KeyCtrlLeft: "\x1b[Od", + KeyCtrlRight: "\x1b[Oc", + KeyCtrlUp: "\x1b[Oa", + KeyCtrlDown: "\x1b[Ob", + KeyShfHome: "\x1b[7$", + KeyShfEnd: "\x1b[8$", + KeyCtrlHome: "\x1b[7^", + KeyCtrlEnd: "\x1b[8^", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_screen.go b/vendor/github.com/gdamore/tcell/terminfo/term_screen.go new file mode 100644 index 00000000..17b6a0c8 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_screen.go @@ -0,0 +1,63 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // VT 100/ANSI X3.64 virtual terminal + AddTerminfo(&Terminfo{ + Name: "screen", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[34h\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b(B\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1bM", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyBacktab: "\x1b[Z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_screen_256color.go b/vendor/github.com/gdamore/tcell/terminfo/term_screen_256color.go new file mode 100644 index 00000000..fdc2c922 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_screen_256color.go @@ -0,0 +1,63 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // GNU Screen with 256 colors + AddTerminfo(&Terminfo{ + Name: "screen-256color", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[34h\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + PadChar: "\x00", + AltChars: "++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b(B\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1bM", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyBacktab: "\x1b[Z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_st.go b/vendor/github.com/gdamore/tcell/terminfo/term_st.go new file mode 100644 index 00000000..04500529 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_st.go @@ -0,0 +1,155 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // simpleterm + AddTerminfo(&Terminfo{ + Name: "st", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[1;2P", + KeyF14: "\x1b[1;2Q", + KeyF15: "\x1b[1;2R", + KeyF16: "\x1b[1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1b[1;5P", + KeyF26: "\x1b[1;5Q", + KeyF27: "\x1b[1;5R", + KeyF28: "\x1b[1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1b[1;6P", + KeyF38: "\x1b[1;6Q", + KeyF39: "\x1b[1;6R", + KeyF40: "\x1b[1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1b[1;3P", + KeyF50: "\x1b[1;3Q", + KeyF51: "\x1b[1;3R", + KeyF52: "\x1b[1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1b[1;4P", + KeyF62: "\x1b[1;4Q", + KeyF63: "\x1b[1;4R", + KeyClear: "\x1b[3;5~", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_st_meta.go b/vendor/github.com/gdamore/tcell/terminfo/term_st_meta.go new file mode 100644 index 00000000..f1cfd792 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_st_meta.go @@ -0,0 +1,155 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // simpleterm with meta key + AddTerminfo(&Terminfo{ + Name: "st-meta", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[1;2P", + KeyF14: "\x1b[1;2Q", + KeyF15: "\x1b[1;2R", + KeyF16: "\x1b[1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1b[1;5P", + KeyF26: "\x1b[1;5Q", + KeyF27: "\x1b[1;5R", + KeyF28: "\x1b[1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1b[1;6P", + KeyF38: "\x1b[1;6Q", + KeyF39: "\x1b[1;6R", + KeyF40: "\x1b[1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1b[1;3P", + KeyF50: "\x1b[1;3Q", + KeyF51: "\x1b[1;3R", + KeyF52: "\x1b[1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1b[1;4P", + KeyF62: "\x1b[1;4Q", + KeyF63: "\x1b[1;4R", + KeyClear: "\x1b[3;5~", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_st_meta_256color.go b/vendor/github.com/gdamore/tcell/terminfo/term_st_meta_256color.go new file mode 100644 index 00000000..10909993 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_st_meta_256color.go @@ -0,0 +1,155 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // simpleterm with meta key and 256 colors + AddTerminfo(&Terminfo{ + Name: "st-meta-256color", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[1;2P", + KeyF14: "\x1b[1;2Q", + KeyF15: "\x1b[1;2R", + KeyF16: "\x1b[1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1b[1;5P", + KeyF26: "\x1b[1;5Q", + KeyF27: "\x1b[1;5R", + KeyF28: "\x1b[1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1b[1;6P", + KeyF38: "\x1b[1;6Q", + KeyF39: "\x1b[1;6R", + KeyF40: "\x1b[1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1b[1;3P", + KeyF50: "\x1b[1;3Q", + KeyF51: "\x1b[1;3R", + KeyF52: "\x1b[1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1b[1;4P", + KeyF62: "\x1b[1;4Q", + KeyF63: "\x1b[1;4R", + KeyClear: "\x1b[3;5~", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_st_meta_truecolor.go b/vendor/github.com/gdamore/tcell/terminfo/term_st_meta_truecolor.go new file mode 100644 index 00000000..fc53a97f --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_st_meta_truecolor.go @@ -0,0 +1,158 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // simpleterm with meta key and 256 colors + AddTerminfo(&Terminfo{ + Name: "st-meta-truecolor", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + EnableAcs: "\x1b)0", + SetFgRGB: "\x1b[38;2;%p1%d;%p2%d;%p3%dm", + SetBgRGB: "\x1b[48;2;%p1%d;%p2%d;%p3%dm", + SetFgBgRGB: "\x1b[38;2;%p1%d;%p2%d;%p3%d;48;2;%p4%d;%p5%d;%p6%dm", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[1;2P", + KeyF14: "\x1b[1;2Q", + KeyF15: "\x1b[1;2R", + KeyF16: "\x1b[1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1b[1;5P", + KeyF26: "\x1b[1;5Q", + KeyF27: "\x1b[1;5R", + KeyF28: "\x1b[1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1b[1;6P", + KeyF38: "\x1b[1;6Q", + KeyF39: "\x1b[1;6R", + KeyF40: "\x1b[1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1b[1;3P", + KeyF50: "\x1b[1;3Q", + KeyF51: "\x1b[1;3R", + KeyF52: "\x1b[1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1b[1;4P", + KeyF62: "\x1b[1;4Q", + KeyF63: "\x1b[1;4R", + KeyClear: "\x1b[3;5~", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_st_truecolor.go b/vendor/github.com/gdamore/tcell/terminfo/term_st_truecolor.go new file mode 100644 index 00000000..006cd1c9 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_st_truecolor.go @@ -0,0 +1,158 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // simpleterm with 256 colors + AddTerminfo(&Terminfo{ + Name: "st-truecolor", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + EnableAcs: "\x1b)0", + SetFgRGB: "\x1b[38;2;%p1%d;%p2%d;%p3%dm", + SetBgRGB: "\x1b[48;2;%p1%d;%p2%d;%p3%dm", + SetFgBgRGB: "\x1b[38;2;%p1%d;%p2%d;%p3%d;48;2;%p4%d;%p5%d;%p6%dm", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[1~", + KeyEnd: "\x1b[4~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[1;2P", + KeyF14: "\x1b[1;2Q", + KeyF15: "\x1b[1;2R", + KeyF16: "\x1b[1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1b[1;5P", + KeyF26: "\x1b[1;5Q", + KeyF27: "\x1b[1;5R", + KeyF28: "\x1b[1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1b[1;6P", + KeyF38: "\x1b[1;6Q", + KeyF39: "\x1b[1;6R", + KeyF40: "\x1b[1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1b[1;3P", + KeyF50: "\x1b[1;3Q", + KeyF51: "\x1b[1;3R", + KeyF52: "\x1b[1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1b[1;4P", + KeyF62: "\x1b[1;4Q", + KeyF63: "\x1b[1;4R", + KeyClear: "\x1b[3;5~", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_sun.go b/vendor/github.com/gdamore/tcell/terminfo/term_sun.go new file mode 100644 index 00000000..5c0eaa49 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_sun.go @@ -0,0 +1,43 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Sun Microsystems Inc. workstation console + AddTerminfo(&Terminfo{ + Name: "sun", + Aliases: []string{"sun1", "sun2"}, + Columns: 80, + Lines: 34, + Bell: "\a", + Clear: "\f", + AttrOff: "\x1b[m", + Reverse: "\x1b[7m", + PadChar: "\x00", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyDelete: "177", + KeyBackspace: "\b", + KeyHome: "\x1b[214z", + KeyEnd: "\x1b[220z", + KeyPgUp: "\x1b[216z", + KeyPgDn: "\x1b[222z", + KeyF1: "\x1b[224z", + KeyF2: "\x1b[225z", + KeyF3: "\x1b[226z", + KeyF4: "\x1b[227z", + KeyF5: "\x1b[228z", + KeyF6: "\x1b[229z", + KeyF7: "\x1b[230z", + KeyF8: "\x1b[231z", + KeyF9: "\x1b[232z", + KeyF10: "\x1b[233z", + KeyF11: "\x1b[234z", + KeyF12: "\x1b[235z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_sun_color.go b/vendor/github.com/gdamore/tcell/terminfo/term_sun_color.go new file mode 100644 index 00000000..c5dd6ecc --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_sun_color.go @@ -0,0 +1,46 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Sun Microsystems Workstation console with color support (IA systems) + AddTerminfo(&Terminfo{ + Name: "sun-color", + Columns: 80, + Lines: 34, + Colors: 8, + Bell: "\a", + Clear: "\f", + AttrOff: "\x1b[m", + Reverse: "\x1b[7m", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyDelete: "177", + KeyBackspace: "\b", + KeyHome: "\x1b[214z", + KeyEnd: "\x1b[220z", + KeyPgUp: "\x1b[216z", + KeyPgDn: "\x1b[222z", + KeyF1: "\x1b[224z", + KeyF2: "\x1b[225z", + KeyF3: "\x1b[226z", + KeyF4: "\x1b[227z", + KeyF5: "\x1b[228z", + KeyF6: "\x1b[229z", + KeyF7: "\x1b[230z", + KeyF8: "\x1b[231z", + KeyF9: "\x1b[232z", + KeyF10: "\x1b[233z", + KeyF11: "\x1b[234z", + KeyF12: "\x1b[235z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_tvi910.go b/vendor/github.com/gdamore/tcell/terminfo/term_tvi910.go new file mode 100644 index 00000000..03b4bf98 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_tvi910.go @@ -0,0 +1,36 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // televideo model 910 + AddTerminfo(&Terminfo{ + Name: "tvi910", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1a", + AttrOff: "\x1bG0", + Underline: "\x1bG8", + Reverse: "\x1bG4", + PadChar: "\x00", + SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", + CursorBack1: "\b", + CursorUp1: "\v", + KeyUp: "\v", + KeyDown: "\n", + KeyRight: "\f", + KeyLeft: "\b", + KeyBackspace: "\b", + KeyHome: "\x1e", + KeyF1: "\x01@\r", + KeyF2: "\x01A\r", + KeyF3: "\x01B\r", + KeyF4: "\x01C\r", + KeyF5: "\x01D\r", + KeyF6: "\x01E\r", + KeyF7: "\x01F\r", + KeyF8: "\x01G\r", + KeyF9: "\x01H\r", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_tvi912.go b/vendor/github.com/gdamore/tcell/terminfo/term_tvi912.go new file mode 100644 index 00000000..a6eeb8f7 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_tvi912.go @@ -0,0 +1,35 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // old televideo 912/914/920 + AddTerminfo(&Terminfo{ + Name: "tvi912", + Aliases: []string{"tvi914", "tvi920"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1a", + Underline: "\x1bl", + PadChar: "\x00", + SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", + CursorBack1: "\b", + CursorUp1: "\v", + KeyUp: "\v", + KeyDown: "\n", + KeyRight: "\f", + KeyLeft: "\b", + KeyBackspace: "\b", + KeyHome: "\x1e", + KeyF1: "\x01@\r", + KeyF2: "\x01A\r", + KeyF3: "\x01B\r", + KeyF4: "\x01C\r", + KeyF5: "\x01D\r", + KeyF6: "\x01E\r", + KeyF7: "\x01F\r", + KeyF8: "\x01G\r", + KeyF9: "\x01H\r", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_tvi921.go b/vendor/github.com/gdamore/tcell/terminfo/term_tvi921.go new file mode 100644 index 00000000..10860cfa --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_tvi921.go @@ -0,0 +1,31 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // televideo model 921 with sysline same as page & real vi function + AddTerminfo(&Terminfo{ + Name: "tvi921", + Columns: 80, + Lines: 24, + Clear: "\x1a", + ShowCursor: "\x1b.3", + AttrOff: "\x1bG0", + Underline: "\x1bG8", + Reverse: "\x1bG4", + PadChar: "\x00", + EnterAcs: "\x1b$", + ExitAcs: "\x1b%%", + SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c$<3/>", + CursorBack1: "\b", + CursorUp1: "\v", + KeyUp: "\v", + KeyDown: "\x16", + KeyRight: "\f", + KeyLeft: "\b", + KeyInsert: "\x1bQ", + KeyDelete: "\x1bW", + KeyBackspace: "\b", + KeyClear: "\x1a", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_tvi925.go b/vendor/github.com/gdamore/tcell/terminfo/term_tvi925.go new file mode 100644 index 00000000..d678ac03 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_tvi925.go @@ -0,0 +1,40 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // televideo 925 + AddTerminfo(&Terminfo{ + Name: "tvi925", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1a", + ShowCursor: "\x1b.4", + AttrOff: "\x1bG0", + Underline: "\x1bG8", + Reverse: "\x1bG4", + PadChar: "\x00", + SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", + CursorBack1: "\b", + CursorUp1: "\v", + KeyUp: "\v", + KeyDown: "\x16", + KeyRight: "\f", + KeyLeft: "\b", + KeyInsert: "\x1bQ", + KeyDelete: "\x1bW", + KeyBackspace: "\b", + KeyHome: "\x1e", + KeyF1: "\x01@\r", + KeyF2: "\x01A\r", + KeyF3: "\x01B\r", + KeyF4: "\x01C\r", + KeyF5: "\x01D\r", + KeyF6: "\x01E\r", + KeyF7: "\x01F\r", + KeyF8: "\x01G\r", + KeyF9: "\x01H\r", + KeyClear: "\x1a", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_tvi950.go b/vendor/github.com/gdamore/tcell/terminfo/term_tvi950.go new file mode 100644 index 00000000..b8222dc1 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_tvi950.go @@ -0,0 +1,43 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // televideo 950 + AddTerminfo(&Terminfo{ + Name: "tvi950", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b*", + AttrOff: "\x1bG0", + Underline: "\x1bG8", + Reverse: "\x1bG4", + PadChar: "\x00", + AltChars: "b\x0011c\x0014d\re\ni\x0013", + EnterAcs: "\x15", + ExitAcs: "\x18", + SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", + CursorBack1: "\b", + CursorUp1: "\v", + KeyUp: "\v", + KeyDown: "\x16", + KeyRight: "\f", + KeyLeft: "\b", + KeyInsert: "\x1bQ", + KeyDelete: "\x1bW", + KeyBackspace: "\b", + KeyHome: "\x1e", + KeyF1: "\x01@\r", + KeyF2: "\x01A\r", + KeyF3: "\x01B\r", + KeyF4: "\x01C\r", + KeyF5: "\x01D\r", + KeyF6: "\x01E\r", + KeyF7: "\x01F\r", + KeyF8: "\x01G\r", + KeyF9: "\x01H\r", + KeyClear: "\x1b*", + KeyBacktab: "\x1bI", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_tvi970.go b/vendor/github.com/gdamore/tcell/terminfo/term_tvi970.go new file mode 100644 index 00000000..ef9166ee --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_tvi970.go @@ -0,0 +1,37 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // televideo 970 + AddTerminfo(&Terminfo{ + Name: "tvi970", + Columns: 80, + Lines: 24, + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?20l\x1b[?7h\x1b[1Q", + AttrOff: "\x1b[m", + Underline: "\x1b[4m", + PadChar: "\x00", + EnterAcs: "\x1b(B", + ExitAcs: "\x1b(B", + SetCursor: "\x1b[%i%p1%d;%p2%df", + CursorBack1: "\b", + CursorUp1: "\x1bM", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyBackspace: "\b", + KeyHome: "\x1b[H", + KeyF1: "\x1b?a", + KeyF2: "\x1b?b", + KeyF3: "\x1b?c", + KeyF4: "\x1b?d", + KeyF5: "\x1b?e", + KeyF6: "\x1b?f", + KeyF7: "\x1b?g", + KeyF8: "\x1b?h", + KeyF9: "\x1b?i", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_vt100.go b/vendor/github.com/gdamore/tcell/terminfo/term_vt100.go new file mode 100644 index 00000000..47c4996b --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_vt100.go @@ -0,0 +1,45 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // dec vt100 (w/advanced video) + AddTerminfo(&Terminfo{ + Name: "vt100", + Aliases: []string{"vt100-am"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b[H\x1b[J$<50>", + AttrOff: "\x1b[m\x0017$<2>", + Underline: "\x1b[4m$<2>", + Bold: "\x1b[1m$<2>", + Blink: "\x1b[5m$<2>", + Reverse: "\x1b[7m$<2>", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b(B\x1b)0", + SetCursor: "\x1b[%i%p1%d;%p2%dH$<5>", + CursorBack1: "\b", + CursorUp1: "\x1b[A$<2>", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyBackspace: "\b", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1bOt", + KeyF6: "\x1bOu", + KeyF7: "\x1bOv", + KeyF8: "\x1bOl", + KeyF9: "\x1bOw", + KeyF10: "\x1bOx", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_vt102.go b/vendor/github.com/gdamore/tcell/terminfo/term_vt102.go new file mode 100644 index 00000000..0199eb61 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_vt102.go @@ -0,0 +1,44 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // dec vt102 + AddTerminfo(&Terminfo{ + Name: "vt102", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b[H\x1b[J$<50>", + AttrOff: "\x1b[m\x0017$<2>", + Underline: "\x1b[4m$<2>", + Bold: "\x1b[1m$<2>", + Blink: "\x1b[5m$<2>", + Reverse: "\x1b[7m$<2>", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b(B\x1b)0", + SetCursor: "\x1b[%i%p1%d;%p2%dH$<5>", + CursorBack1: "\b", + CursorUp1: "\x1b[A$<2>", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyBackspace: "\b", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1bOt", + KeyF6: "\x1bOu", + KeyF7: "\x1bOv", + KeyF8: "\x1bOl", + KeyF9: "\x1bOw", + KeyF10: "\x1bOx", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_vt220.go b/vendor/github.com/gdamore/tcell/terminfo/term_vt220.go new file mode 100644 index 00000000..a0a2b77a --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_vt220.go @@ -0,0 +1,54 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // dec vt220 + AddTerminfo(&Terminfo{ + Name: "vt220", + Aliases: []string{"vt200"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b[H\x1b[J", + AttrOff: "\x1b[m\x1b(B", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0$<2>", + ExitAcs: "\x1b(B$<4>", + EnableAcs: "\x1b)0", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyBackspace: "\b", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + KeyHelp: "\x1b[28~", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_vt320.go b/vendor/github.com/gdamore/tcell/terminfo/term_vt320.go new file mode 100644 index 00000000..cb4da0ae --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_vt320.go @@ -0,0 +1,60 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // dec vt320 7 bit terminal + AddTerminfo(&Terminfo{ + Name: "vt320", + Aliases: []string{"vt300"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x1b(B", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1b[1~", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[25~", + KeyF14: "\x1b[26~", + KeyF15: "\x1b[28~", + KeyF16: "\x1b[29~", + KeyF17: "\x1b[31~", + KeyF18: "\x1b[32~", + KeyF19: "\x1b[33~", + KeyF20: "\x1b[34~", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_vt400.go b/vendor/github.com/gdamore/tcell/terminfo/term_vt400.go new file mode 100644 index 00000000..2a7cadad --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_vt400.go @@ -0,0 +1,43 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // dec vt400 24x80 column autowrap + AddTerminfo(&Terminfo{ + Name: "vt400", + Aliases: []string{"vt400-24", "dec-vt400"}, + Columns: 80, + Lines: 24, + Clear: "\x1b[H\x1b[J$<10/>", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x1b(B", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyBackspace: "\b", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_vt420.go b/vendor/github.com/gdamore/tcell/terminfo/term_vt420.go new file mode 100644 index 00000000..fbccd1f3 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_vt420.go @@ -0,0 +1,47 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // DEC VT420 + AddTerminfo(&Terminfo{ + Name: "vt420", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b[H\x1b[2J$<50>", + AttrOff: "\x1b[m$<2>", + Underline: "\x1b[4m", + Bold: "\x1b[1m$<2>", + Blink: "\x1b[5m$<2>", + Reverse: "\x1b[7m$<2>", + EnterKeypad: "\x1b=", + ExitKeypad: "\x1b>", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0$<2>", + ExitAcs: "\x1b(B$<4>", + SetCursor: "\x1b[%i%p1%d;%p2%dH$<10>", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1b[A", + KeyDown: "\x1b[B", + KeyRight: "\x1b[C", + KeyLeft: "\x1b[D", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[17~", + KeyF6: "\x1b[18~", + KeyF7: "\x1b[19~", + KeyF8: "\x1b[20~", + KeyF9: "\x1b[21~", + KeyF10: "\x1b[29~", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_vt52.go b/vendor/github.com/gdamore/tcell/terminfo/term_vt52.go new file mode 100644 index 00000000..a98d0fd3 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_vt52.go @@ -0,0 +1,26 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // dec vt52 + AddTerminfo(&Terminfo{ + Name: "vt52", + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1bH\x1bJ", + PadChar: "\x00", + AltChars: ".kffgghhompoqqss", + EnterAcs: "\x1bF", + ExitAcs: "\x1bG", + SetCursor: "\x1bY%p1%' '%+%c%p2%' '%+%c", + CursorBack1: "\x1bD", + CursorUp1: "\x1bA", + KeyUp: "\x1bA", + KeyDown: "\x1bB", + KeyRight: "\x1bC", + KeyLeft: "\x1bD", + KeyBackspace: "\b", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_wy50.go b/vendor/github.com/gdamore/tcell/terminfo/term_wy50.go new file mode 100644 index 00000000..1294629c --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_wy50.go @@ -0,0 +1,56 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Wyse 50 + AddTerminfo(&Terminfo{ + Name: "wy50", + Aliases: []string{"wyse50"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b+$<20>", + ShowCursor: "\x1b`1", + HideCursor: "\x1b`0", + AttrOff: "\x1b(\x1bH\x0003", + Dim: "\x1b`7\x1b)", + Reverse: "\x1b`6\x1b)", + PadChar: "\x00", + AltChars: "0wa_h[jukslrmqnxqzttuyv]wpxv", + EnterAcs: "\x1bH\x02", + ExitAcs: "\x1bH\x03", + SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", + CursorBack1: "\b", + CursorUp1: "\v", + KeyUp: "\v", + KeyDown: "\n", + KeyRight: "\f", + KeyLeft: "\b", + KeyInsert: "\x1bQ", + KeyDelete: "\x1bW", + KeyBackspace: "\b", + KeyHome: "\x1e", + KeyPgUp: "\x1bJ", + KeyPgDn: "\x1bK", + KeyF1: "\x01@\r", + KeyF2: "\x01A\r", + KeyF3: "\x01B\r", + KeyF4: "\x01C\r", + KeyF5: "\x01D\r", + KeyF6: "\x01E\r", + KeyF7: "\x01F\r", + KeyF8: "\x01G\r", + KeyF9: "\x01H\r", + KeyF10: "\x01I\r", + KeyF11: "\x01J\r", + KeyF12: "\x01K\r", + KeyF13: "\x01L\r", + KeyF14: "\x01M\r", + KeyF15: "\x01N\r", + KeyF16: "\x01O\r", + KeyPrint: "\x1bP", + KeyBacktab: "\x1bI", + KeyShfHome: "\x1b{", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_wy60.go b/vendor/github.com/gdamore/tcell/terminfo/term_wy60.go new file mode 100644 index 00000000..7427fdbf --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_wy60.go @@ -0,0 +1,60 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Wyse 60 + AddTerminfo(&Terminfo{ + Name: "wy60", + Aliases: []string{"wyse60"}, + Columns: 80, + Lines: 24, + Bell: "\a", + Clear: "\x1b+$<100>", + EnterCA: "\x1bw0", + ExitCA: "\x1bw1", + ShowCursor: "\x1b`1", + HideCursor: "\x1b`0", + AttrOff: "\x1b(\x1bH\x0003\x1bG0\x1bcD", + Underline: "\x1bG8", + Dim: "\x1bGp", + Blink: "\x1bG2", + Reverse: "\x1bG4", + PadChar: "\x00", + AltChars: "+/,.0[a2fxgqh1ihjYk?lZm@nEqDtCu4vAwBx3yszr{c~~", + EnterAcs: "\x1bcE", + ExitAcs: "\x1bcD", + SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", + CursorBack1: "\b", + CursorUp1: "\v", + KeyUp: "\v", + KeyDown: "\n", + KeyRight: "\f", + KeyLeft: "\b", + KeyInsert: "\x1bQ", + KeyDelete: "\x1bW", + KeyBackspace: "\b", + KeyHome: "\x1e", + KeyPgUp: "\x1bJ", + KeyPgDn: "\x1bK", + KeyF1: "\x01@\r", + KeyF2: "\x01A\r", + KeyF3: "\x01B\r", + KeyF4: "\x01C\r", + KeyF5: "\x01D\r", + KeyF6: "\x01E\r", + KeyF7: "\x01F\r", + KeyF8: "\x01G\r", + KeyF9: "\x01H\r", + KeyF10: "\x01I\r", + KeyF11: "\x01J\r", + KeyF12: "\x01K\r", + KeyF13: "\x01L\r", + KeyF14: "\x01M\r", + KeyF15: "\x01N\r", + KeyF16: "\x01O\r", + KeyPrint: "\x1bP", + KeyBacktab: "\x1bI", + KeyShfHome: "\x1b{", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_wy99_ansi.go b/vendor/github.com/gdamore/tcell/terminfo/term_wy99_ansi.go new file mode 100644 index 00000000..41e31c52 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_wy99_ansi.go @@ -0,0 +1,58 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Wyse WY-99GT in ansi mode (int'l PC keyboard) + AddTerminfo(&Terminfo{ + Name: "wy99-ansi", + Columns: 80, + Lines: 25, + Bell: "\a", + Clear: "\x1b[H\x1b[J$<200>", + ShowCursor: "\x1b[34h\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017\x1b[\"q", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h", + ExitKeypad: "\x1b[?1l", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooqqssttuuvvwwxx{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b)0", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\x0010$<1>", + CursorUp1: "\x1bM", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyBackspace: "\b", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[M", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF17: "\x1b[K", + KeyF18: "\x1b[31~", + KeyF19: "\x1b[32~", + KeyF20: "\x1b[33~", + KeyF21: "\x1b[34~", + KeyF22: "\x1b[35~", + KeyF23: "\x1b[1~", + KeyF24: "\x1b[2~", + KeyBacktab: "\x1b[z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_wy99a_ansi.go b/vendor/github.com/gdamore/tcell/terminfo/term_wy99a_ansi.go new file mode 100644 index 00000000..6cdac0db --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_wy99a_ansi.go @@ -0,0 +1,58 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Wyse WY-99GT in ansi mode (US PC keyboard) + AddTerminfo(&Terminfo{ + Name: "wy99a-ansi", + Columns: 80, + Lines: 25, + Bell: "\a", + Clear: "\x1b[H\x1b[J$<200>", + ShowCursor: "\x1b[34h\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[m\x0017\x1b[\"q", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h", + ExitKeypad: "\x1b[?1l", + PadChar: "\x00", + AltChars: "``aaffggjjkkllmmnnooqqssttuuvvwwxx{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b)0", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\x0010$<1>", + CursorUp1: "\x1bM", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyBackspace: "\b", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[M", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF17: "\x1b[K", + KeyF18: "\x1b[31~", + KeyF19: "\x1b[32~", + KeyF20: "\x1b[33~", + KeyF21: "\x1b[34~", + KeyF22: "\x1b[35~", + KeyF23: "\x1b[1~", + KeyF24: "\x1b[2~", + KeyBacktab: "\x1b[z", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_xfce.go b/vendor/github.com/gdamore/tcell/terminfo/term_xfce.go new file mode 100644 index 00000000..3651dd70 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_xfce.go @@ -0,0 +1,153 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Xfce Terminal + AddTerminfo(&Terminfo{ + Name: "xfce", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b7\x1b[?47h", + ExitCA: "\x1b[2J\x1b[?47l\x1b8", + ShowCursor: "\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b[0m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x0e", + ExitAcs: "\x0f", + EnableAcs: "\x1b)0", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "177", + KeyHome: "\x1bOH", + KeyEnd: "\x1bOF", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1bO1;2P", + KeyF14: "\x1bO1;2Q", + KeyF15: "\x1bO1;2R", + KeyF16: "\x1bO1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1bO1;5P", + KeyF26: "\x1bO1;5Q", + KeyF27: "\x1bO1;5R", + KeyF28: "\x1bO1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1bO1;6P", + KeyF38: "\x1bO1;6Q", + KeyF39: "\x1bO1;6R", + KeyF40: "\x1bO1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1bO1;3P", + KeyF50: "\x1bO1;3Q", + KeyF51: "\x1bO1;3R", + KeyF52: "\x1bO1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1bO1;4P", + KeyF62: "\x1bO1;4Q", + KeyF63: "\x1bO1;4R", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_xnuppc.go b/vendor/github.com/gdamore/tcell/terminfo/term_xnuppc.go new file mode 100644 index 00000000..d3d68820 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_xnuppc.go @@ -0,0 +1,31 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // Darwin PowerPC Console (color) + AddTerminfo(&Terminfo{ + Name: "xnuppc", + Aliases: []string{"darwin"}, + Colors: 8, + Clear: "\x1b[H\x1b[J", + AttrOff: "\x1b[m\x0017", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + PadChar: "\x00", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\x1b[D", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyBackspace: "177", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_xterm.go b/vendor/github.com/gdamore/tcell/terminfo/term_xterm.go new file mode 100644 index 00000000..9cab4a20 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_xterm.go @@ -0,0 +1,152 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // xterm terminal emulator (X Window System) + AddTerminfo(&Terminfo{ + Name: "xterm", + Columns: 80, + Lines: 24, + Colors: 8, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b(B\x1b[m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[3%p1%dm", + SetBg: "\x1b[4%p1%dm", + SetFgBg: "\x1b[3%p1%d;4%p2%dm", + AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1bOH", + KeyEnd: "\x1bOF", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[1;2P", + KeyF14: "\x1b[1;2Q", + KeyF15: "\x1b[1;2R", + KeyF16: "\x1b[1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1b[1;5P", + KeyF26: "\x1b[1;5Q", + KeyF27: "\x1b[1;5R", + KeyF28: "\x1b[1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1b[1;6P", + KeyF38: "\x1b[1;6Q", + KeyF39: "\x1b[1;6R", + KeyF40: "\x1b[1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1b[1;3P", + KeyF50: "\x1b[1;3Q", + KeyF51: "\x1b[1;3R", + KeyF52: "\x1b[1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1b[1;4P", + KeyF62: "\x1b[1;4Q", + KeyF63: "\x1b[1;4R", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_xterm_256color.go b/vendor/github.com/gdamore/tcell/terminfo/term_xterm_256color.go new file mode 100644 index 00000000..d30ceeef --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_xterm_256color.go @@ -0,0 +1,152 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // xterm with 256 colors + AddTerminfo(&Terminfo{ + Name: "xterm-256color", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b(B\x1b[m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1bOH", + KeyEnd: "\x1bOF", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[1;2P", + KeyF14: "\x1b[1;2Q", + KeyF15: "\x1b[1;2R", + KeyF16: "\x1b[1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1b[1;5P", + KeyF26: "\x1b[1;5Q", + KeyF27: "\x1b[1;5R", + KeyF28: "\x1b[1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1b[1;6P", + KeyF38: "\x1b[1;6Q", + KeyF39: "\x1b[1;6R", + KeyF40: "\x1b[1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1b[1;3P", + KeyF50: "\x1b[1;3Q", + KeyF51: "\x1b[1;3R", + KeyF52: "\x1b[1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1b[1;4P", + KeyF62: "\x1b[1;4Q", + KeyF63: "\x1b[1;4R", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/term_xterm_truecolor.go b/vendor/github.com/gdamore/tcell/terminfo/term_xterm_truecolor.go new file mode 100644 index 00000000..d035e44e --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/term_xterm_truecolor.go @@ -0,0 +1,155 @@ +// Generated automatically. DO NOT HAND-EDIT. + +package terminfo + +func init() { + // xterm with 256 colors + AddTerminfo(&Terminfo{ + Name: "xterm-truecolor", + Columns: 80, + Lines: 24, + Colors: 256, + Bell: "\a", + Clear: "\x1b[H\x1b[2J", + EnterCA: "\x1b[?1049h", + ExitCA: "\x1b[?1049l", + ShowCursor: "\x1b[?12l\x1b[?25h", + HideCursor: "\x1b[?25l", + AttrOff: "\x1b(B\x1b[m", + Underline: "\x1b[4m", + Bold: "\x1b[1m", + Blink: "\x1b[5m", + Reverse: "\x1b[7m", + EnterKeypad: "\x1b[?1h\x1b=", + ExitKeypad: "\x1b[?1l\x1b>", + SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", + SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", + SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", + AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", + EnterAcs: "\x1b(0", + ExitAcs: "\x1b(B", + SetFgRGB: "\x1b[38;2;%p1%d;%p2%d;%p3%dm", + SetBgRGB: "\x1b[48;2;%p1%d;%p2%d;%p3%dm", + SetFgBgRGB: "\x1b[38;2;%p1%d;%p2%d;%p3%d;48;2;%p4%d;%p5%d;%p6%dm", + Mouse: "\x1b[M", + MouseMode: "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c", + SetCursor: "\x1b[%i%p1%d;%p2%dH", + CursorBack1: "\b", + CursorUp1: "\x1b[A", + KeyUp: "\x1bOA", + KeyDown: "\x1bOB", + KeyRight: "\x1bOC", + KeyLeft: "\x1bOD", + KeyInsert: "\x1b[2~", + KeyDelete: "\x1b[3~", + KeyBackspace: "\b", + KeyHome: "\x1bOH", + KeyEnd: "\x1bOF", + KeyPgUp: "\x1b[5~", + KeyPgDn: "\x1b[6~", + KeyF1: "\x1bOP", + KeyF2: "\x1bOQ", + KeyF3: "\x1bOR", + KeyF4: "\x1bOS", + KeyF5: "\x1b[15~", + KeyF6: "\x1b[17~", + KeyF7: "\x1b[18~", + KeyF8: "\x1b[19~", + KeyF9: "\x1b[20~", + KeyF10: "\x1b[21~", + KeyF11: "\x1b[23~", + KeyF12: "\x1b[24~", + KeyF13: "\x1b[1;2P", + KeyF14: "\x1b[1;2Q", + KeyF15: "\x1b[1;2R", + KeyF16: "\x1b[1;2S", + KeyF17: "\x1b[15;2~", + KeyF18: "\x1b[17;2~", + KeyF19: "\x1b[18;2~", + KeyF20: "\x1b[19;2~", + KeyF21: "\x1b[20;2~", + KeyF22: "\x1b[21;2~", + KeyF23: "\x1b[23;2~", + KeyF24: "\x1b[24;2~", + KeyF25: "\x1b[1;5P", + KeyF26: "\x1b[1;5Q", + KeyF27: "\x1b[1;5R", + KeyF28: "\x1b[1;5S", + KeyF29: "\x1b[15;5~", + KeyF30: "\x1b[17;5~", + KeyF31: "\x1b[18;5~", + KeyF32: "\x1b[19;5~", + KeyF33: "\x1b[20;5~", + KeyF34: "\x1b[21;5~", + KeyF35: "\x1b[23;5~", + KeyF36: "\x1b[24;5~", + KeyF37: "\x1b[1;6P", + KeyF38: "\x1b[1;6Q", + KeyF39: "\x1b[1;6R", + KeyF40: "\x1b[1;6S", + KeyF41: "\x1b[15;6~", + KeyF42: "\x1b[17;6~", + KeyF43: "\x1b[18;6~", + KeyF44: "\x1b[19;6~", + KeyF45: "\x1b[20;6~", + KeyF46: "\x1b[21;6~", + KeyF47: "\x1b[23;6~", + KeyF48: "\x1b[24;6~", + KeyF49: "\x1b[1;3P", + KeyF50: "\x1b[1;3Q", + KeyF51: "\x1b[1;3R", + KeyF52: "\x1b[1;3S", + KeyF53: "\x1b[15;3~", + KeyF54: "\x1b[17;3~", + KeyF55: "\x1b[18;3~", + KeyF56: "\x1b[19;3~", + KeyF57: "\x1b[20;3~", + KeyF58: "\x1b[21;3~", + KeyF59: "\x1b[23;3~", + KeyF60: "\x1b[24;3~", + KeyF61: "\x1b[1;4P", + KeyF62: "\x1b[1;4Q", + KeyF63: "\x1b[1;4R", + KeyBacktab: "\x1b[Z", + KeyShfLeft: "\x1b[1;2D", + KeyShfRight: "\x1b[1;2C", + KeyShfUp: "\x1b[1;2A", + KeyShfDown: "\x1b[1;2B", + KeyCtrlLeft: "\x1b[1;5D", + KeyCtrlRight: "\x1b[1;5C", + KeyCtrlUp: "\x1b[1;5A", + KeyCtrlDown: "\x1b[1;5B", + KeyMetaLeft: "\x1b[1;9D", + KeyMetaRight: "\x1b[1;9C", + KeyMetaUp: "\x1b[1;9A", + KeyMetaDown: "\x1b[1;9B", + KeyAltLeft: "\x1b[1;3D", + KeyAltRight: "\x1b[1;3C", + KeyAltUp: "\x1b[1;3A", + KeyAltDown: "\x1b[1;3B", + KeyAltShfLeft: "\x1b[1;4D", + KeyAltShfRight: "\x1b[1;4C", + KeyAltShfUp: "\x1b[1;4A", + KeyAltShfDown: "\x1b[1;4B", + KeyMetaShfLeft: "\x1b[1;10D", + KeyMetaShfRight: "\x1b[1;10C", + KeyMetaShfUp: "\x1b[1;10A", + KeyMetaShfDown: "\x1b[1;10B", + KeyCtrlShfLeft: "\x1b[1;6D", + KeyCtrlShfRight: "\x1b[1;6C", + KeyCtrlShfUp: "\x1b[1;6A", + KeyCtrlShfDown: "\x1b[1;6B", + KeyShfHome: "\x1b[1;2H", + KeyShfEnd: "\x1b[1;2F", + KeyCtrlHome: "\x1b[1;5H", + KeyCtrlEnd: "\x1b[1;5F", + KeyAltHome: "\x1b[1;9H", + KeyAltEnd: "\x1b[1;9F", + KeyCtrlShfHome: "\x1b[1;6H", + KeyCtrlShfEnd: "\x1b[1;6F", + KeyMetaShfHome: "\x1b[1;10H", + KeyMetaShfEnd: "\x1b[1;10F", + KeyAltShfHome: "\x1b[1;4H", + KeyAltShfEnd: "\x1b[1;4F", + }) +} diff --git a/vendor/github.com/gdamore/tcell/terminfo/terminfo.go b/vendor/github.com/gdamore/tcell/terminfo/terminfo.go new file mode 100644 index 00000000..ea8c6d7b --- /dev/null +++ b/vendor/github.com/gdamore/tcell/terminfo/terminfo.go @@ -0,0 +1,831 @@ +// Copyright 2017 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package terminfo + +import ( + "bytes" + "compress/gzip" + "encoding/json" + "errors" + "fmt" + "io" + "os" + "path" + "strconv" + "strings" + "sync" +) + +var ( + // ErrTermNotFound indicates that a suitable terminal entry could + // not be found. This can result from either not having TERM set, + // or from the TERM failing to support certain minimal functionality, + // in particular absolute cursor addressability (the cup capability) + // is required. For example, legacy "adm3" lacks this capability, + // whereas the slightly newer "adm3a" supports it. This failure + // occurs most often with "dumb". + ErrTermNotFound = errors.New("terminal entry not found") +) + +// Terminfo represents a terminfo entry. Note that we use friendly names +// in Go, but when we write out JSON, we use the same names as terminfo. +// The name, aliases and smous, rmous fields do not come from terminfo directly. +type Terminfo struct { + Name string `json:"name"` + Aliases []string `json:"aliases,omitempty"` + Columns int `json:"cols,omitempty"` // cols + Lines int `json:"lines,omitempty"` // lines + Colors int `json:"colors,omitempty"` // colors + Bell string `json:"bell,omitempty"` // bell + Clear string `json:"clear,omitempty"` // clear + EnterCA string `json:"smcup,omitempty"` // smcup + ExitCA string `json:"rmcup,omitempty"` // rmcup + ShowCursor string `json:"cnorm,omitempty"` // cnorm + HideCursor string `json:"civis,omitempty"` // civis + AttrOff string `json:"sgr0,omitempty"` // sgr0 + Underline string `json:"smul,omitempty"` // smul + Bold string `json:"bold,omitempty"` // bold + Blink string `json:"blink,omitempty"` // blink + Reverse string `json:"rev,omitempty"` // rev + Dim string `json:"dim,omitempty"` // dim + EnterKeypad string `json:"smkx,omitempty"` // smkx + ExitKeypad string `json:"rmkx,omitempty"` // rmkx + SetFg string `json:"setaf,omitempty"` // setaf + SetBg string `json:"setbg,omitempty"` // setab + SetCursor string `json:"cup,omitempty"` // cup + CursorBack1 string `json:"cub1,omitempty"` // cub1 + CursorUp1 string `json:"cuu1,omitempty"` // cuu1 + PadChar string `json:"pad,omitempty"` // pad + KeyBackspace string `json:"kbs,omitempty"` // kbs + KeyF1 string `json:"kf1,omitempty"` // kf1 + KeyF2 string `json:"kf2,omitempty"` // kf2 + KeyF3 string `json:"kf3,omitempty"` // kf3 + KeyF4 string `json:"kf4,omitempty"` // kf4 + KeyF5 string `json:"kf5,omitempty"` // kf5 + KeyF6 string `json:"kf6,omitempty"` // kf6 + KeyF7 string `json:"kf7,omitempty"` // kf7 + KeyF8 string `json:"kf8,omitempty"` // kf8 + KeyF9 string `json:"kf9,omitempty"` // kf9 + KeyF10 string `json:"kf10,omitempty"` // kf10 + KeyF11 string `json:"kf11,omitempty"` // kf11 + KeyF12 string `json:"kf12,omitempty"` // kf12 + KeyF13 string `json:"kf13,omitempty"` // kf13 + KeyF14 string `json:"kf14,omitempty"` // kf14 + KeyF15 string `json:"kf15,omitempty"` // kf15 + KeyF16 string `json:"kf16,omitempty"` // kf16 + KeyF17 string `json:"kf17,omitempty"` // kf17 + KeyF18 string `json:"kf18,omitempty"` // kf18 + KeyF19 string `json:"kf19,omitempty"` // kf19 + KeyF20 string `json:"kf20,omitempty"` // kf20 + KeyF21 string `json:"kf21,omitempty"` // kf21 + KeyF22 string `json:"kf22,omitempty"` // kf22 + KeyF23 string `json:"kf23,omitempty"` // kf23 + KeyF24 string `json:"kf24,omitempty"` // kf24 + KeyF25 string `json:"kf25,omitempty"` // kf25 + KeyF26 string `json:"kf26,omitempty"` // kf26 + KeyF27 string `json:"kf27,omitempty"` // kf27 + KeyF28 string `json:"kf28,omitempty"` // kf28 + KeyF29 string `json:"kf29,omitempty"` // kf29 + KeyF30 string `json:"kf30,omitempty"` // kf30 + KeyF31 string `json:"kf31,omitempty"` // kf31 + KeyF32 string `json:"kf32,omitempty"` // kf32 + KeyF33 string `json:"kf33,omitempty"` // kf33 + KeyF34 string `json:"kf34,omitempty"` // kf34 + KeyF35 string `json:"kf35,omitempty"` // kf35 + KeyF36 string `json:"kf36,omitempty"` // kf36 + KeyF37 string `json:"kf37,omitempty"` // kf37 + KeyF38 string `json:"kf38,omitempty"` // kf38 + KeyF39 string `json:"kf39,omitempty"` // kf39 + KeyF40 string `json:"kf40,omitempty"` // kf40 + KeyF41 string `json:"kf41,omitempty"` // kf41 + KeyF42 string `json:"kf42,omitempty"` // kf42 + KeyF43 string `json:"kf43,omitempty"` // kf43 + KeyF44 string `json:"kf44,omitempty"` // kf44 + KeyF45 string `json:"kf45,omitempty"` // kf45 + KeyF46 string `json:"kf46,omitempty"` // kf46 + KeyF47 string `json:"kf47,omitempty"` // kf47 + KeyF48 string `json:"kf48,omitempty"` // kf48 + KeyF49 string `json:"kf49,omitempty"` // kf49 + KeyF50 string `json:"kf50,omitempty"` // kf50 + KeyF51 string `json:"kf51,omitempty"` // kf51 + KeyF52 string `json:"kf52,omitempty"` // kf52 + KeyF53 string `json:"kf53,omitempty"` // kf53 + KeyF54 string `json:"kf54,omitempty"` // kf54 + KeyF55 string `json:"kf55,omitempty"` // kf55 + KeyF56 string `json:"kf56,omitempty"` // kf56 + KeyF57 string `json:"kf57,omitempty"` // kf57 + KeyF58 string `json:"kf58,omitempty"` // kf58 + KeyF59 string `json:"kf59,omitempty"` // kf59 + KeyF60 string `json:"kf60,omitempty"` // kf60 + KeyF61 string `json:"kf61,omitempty"` // kf61 + KeyF62 string `json:"kf62,omitempty"` // kf62 + KeyF63 string `json:"kf63,omitempty"` // kf63 + KeyF64 string `json:"kf64,omitempty"` // kf64 + KeyInsert string `json:"kich,omitempty"` // kich1 + KeyDelete string `json:"kdch,omitempty"` // kdch1 + KeyHome string `json:"khome,omitempty"` // khome + KeyEnd string `json:"kend,omitempty"` // kend + KeyHelp string `json:"khlp,omitempty"` // khlp + KeyPgUp string `json:"kpp,omitempty"` // kpp + KeyPgDn string `json:"knp,omitempty"` // knp + KeyUp string `json:"kcuu1,omitempty"` // kcuu1 + KeyDown string `json:"kcud1,omitempty"` // kcud1 + KeyLeft string `json:"kcub1,omitempty"` // kcub1 + KeyRight string `json:"kcuf1,omitempty"` // kcuf1 + KeyBacktab string `json:"kcbt,omitempty"` // kcbt + KeyExit string `json:"kext,omitempty"` // kext + KeyClear string `json:"kclr,omitempty"` // kclr + KeyPrint string `json:"kprt,omitempty"` // kprt + KeyCancel string `json:"kcan,omitempty"` // kcan + Mouse string `json:"kmous,omitempty"` // kmous + MouseMode string `json:"XM,omitempty"` // XM + AltChars string `json:"acsc,omitempty"` // acsc + EnterAcs string `json:"smacs,omitempty"` // smacs + ExitAcs string `json:"rmacs,omitempty"` // rmacs + EnableAcs string `json:"enacs,omitempty"` // enacs + KeyShfRight string `json:"kRIT,omitempty"` // kRIT + KeyShfLeft string `json:"kLFT,omitempty"` // kLFT + KeyShfHome string `json:"kHOM,omitempty"` // kHOM + KeyShfEnd string `json:"kEND,omitempty"` // kEND + + // These are non-standard extensions to terminfo. This includes + // true color support, and some additional keys. Its kind of bizarre + // that shifted variants of left and right exist, but not up and down. + // Terminal support for these are going to vary amongst XTerm + // emulations, so don't depend too much on them in your application. + + SetFgBg string `json:"_setfgbg,omitempty"` // setfgbg + SetFgBgRGB string `json:"_setfgbgrgb,omitempty"` // setfgbgrgb + SetFgRGB string `json:"_setfrgb,omitempty"` // setfrgb + SetBgRGB string `json:"_setbrgb,omitempty"` // setbrgb + KeyShfUp string `json:"_kscu1,omitempty"` // shift-up + KeyShfDown string `json:"_kscud1,omitempty"` // shift-down + KeyCtrlUp string `json:"_kccu1,omitempty"` // ctrl-up + KeyCtrlDown string `json:"_kccud1,omitempty"` // ctrl-left + KeyCtrlRight string `json:"_kccuf1,omitempty"` // ctrl-right + KeyCtrlLeft string `json:"_kccub1,omitempty"` // ctrl-left + KeyMetaUp string `json:"_kmcu1,omitempty"` // meta-up + KeyMetaDown string `json:"_kmcud1,omitempty"` // meta-left + KeyMetaRight string `json:"_kmcuf1,omitempty"` // meta-right + KeyMetaLeft string `json:"_kmcub1,omitempty"` // meta-left + KeyAltUp string `json:"_kacu1,omitempty"` // alt-up + KeyAltDown string `json:"_kacud1,omitempty"` // alt-left + KeyAltRight string `json:"_kacuf1,omitempty"` // alt-right + KeyAltLeft string `json:"_kacub1,omitempty"` // alt-left + KeyCtrlHome string `json:"_kchome,omitempty"` + KeyCtrlEnd string `json:"_kcend,omitempty"` + KeyMetaHome string `json:"_kmhome,omitempty"` + KeyMetaEnd string `json:"_kmend,omitempty"` + KeyAltHome string `json:"_kahome,omitempty"` + KeyAltEnd string `json:"_kaend,omitempty"` + KeyAltShfUp string `json:"_kascu1,omitempty"` + KeyAltShfDown string `json:"_kascud1,omitempty"` + KeyAltShfLeft string `json:"_kascub1,omitempty"` + KeyAltShfRight string `json:"_kascuf1,omitempty"` + KeyMetaShfUp string `json:"_kmscu1,omitempty"` + KeyMetaShfDown string `json:"_kmscud1,omitempty"` + KeyMetaShfLeft string `json:"_kmscub1,omitempty"` + KeyMetaShfRight string `json:"_kmscuf1,omitempty"` + KeyCtrlShfUp string `json:"_kcscu1,omitempty"` + KeyCtrlShfDown string `json:"_kcscud1,omitempty"` + KeyCtrlShfLeft string `json:"_kcscub1,omitempty"` + KeyCtrlShfRight string `json:"_kcscuf1,omitempty"` + KeyCtrlShfHome string `json:"_kcHOME,omitempty"` + KeyCtrlShfEnd string `json:"_kcEND,omitempty"` + KeyAltShfHome string `json:"_kaHOME,omitempty"` + KeyAltShfEnd string `json:"_kaEND,omitempty"` + KeyMetaShfHome string `json:"_kmHOME,omitempty"` + KeyMetaShfEnd string `json:"_kmEND,omitempty"` +} + +type stackElem struct { + s string + i int + isStr bool + isInt bool +} + +type stack []stackElem + +func (st stack) Push(v string) stack { + e := stackElem{ + s: v, + isStr: true, + } + return append(st, e) +} + +func (st stack) Pop() (string, stack) { + v := "" + if len(st) > 0 { + e := st[len(st)-1] + st = st[:len(st)-1] + if e.isStr { + v = e.s + } else { + v = strconv.Itoa(e.i) + } + } + return v, st +} + +func (st stack) PopInt() (int, stack) { + if len(st) > 0 { + e := st[len(st)-1] + st = st[:len(st)-1] + if e.isInt { + return e.i, st + } else if e.isStr { + i, _ := strconv.Atoi(e.s) + return i, st + } + } + return 0, st +} + +func (st stack) PopBool() (bool, stack) { + if len(st) > 0 { + e := st[len(st)-1] + st = st[:len(st)-1] + if e.isStr { + if e.s == "1" { + return true, st + } + return false, st + } else if e.i == 1 { + return true, st + } else { + return false, st + } + } + return false, st +} + +func (st stack) PushInt(i int) stack { + e := stackElem{ + i: i, + isInt: true, + } + return append(st, e) +} + +func (st stack) PushBool(i bool) stack { + if i { + return st.PushInt(1) + } + return st.PushInt(0) +} + +func nextch(s string, index int) (byte, int) { + if index < len(s) { + return s[index], index + 1 + } + return 0, index +} + +// static vars +var svars [26]string + +// paramsBuffer handles some persistent state for TParam. Technically we +// could probably dispense with this, but caching buffer arrays gives us +// a nice little performance boost. Furthermore, we know that TParam is +// rarely (never?) called re-entrantly, so we can just reuse the same +// buffers, making it thread-safe by stashing a lock. +type paramsBuffer struct { + out bytes.Buffer + buf bytes.Buffer + lk sync.Mutex +} + +// Start initializes the params buffer with the initial string data. +// It also locks the paramsBuffer. The caller must call End() when +// finished. +func (pb *paramsBuffer) Start(s string) { + pb.lk.Lock() + pb.out.Reset() + pb.buf.Reset() + pb.buf.WriteString(s) +} + +// End returns the final output from TParam, but it also releases the lock. +func (pb *paramsBuffer) End() string { + s := pb.out.String() + pb.lk.Unlock() + return s +} + +// NextCh returns the next input character to the expander. +func (pb *paramsBuffer) NextCh() (byte, error) { + return pb.buf.ReadByte() +} + +// PutCh "emits" (rather schedules for output) a single byte character. +func (pb *paramsBuffer) PutCh(ch byte) { + pb.out.WriteByte(ch) +} + +// PutString schedules a string for output. +func (pb *paramsBuffer) PutString(s string) { + pb.out.WriteString(s) +} + +var pb = ¶msBuffer{} + +// TParm takes a terminfo parameterized string, such as setaf or cup, and +// evaluates the string, and returns the result with the parameter +// applied. +func (t *Terminfo) TParm(s string, p ...int) string { + var stk stack + var a, b string + var ai, bi int + var ab bool + var dvars [26]string + var params [9]int + + pb.Start(s) + + // make sure we always have 9 parameters -- makes it easier + // later to skip checks + for i := 0; i < len(params) && i < len(p); i++ { + params[i] = p[i] + } + + nest := 0 + + for { + + ch, err := pb.NextCh() + if err != nil { + break + } + + if ch != '%' { + pb.PutCh(ch) + continue + } + + ch, err = pb.NextCh() + if err != nil { + // XXX Error + break + } + + switch ch { + case '%': // quoted % + pb.PutCh(ch) + + case 'i': // increment both parameters (ANSI cup support) + params[0]++ + params[1]++ + + case 'c', 's': + // NB: these, and 'd' below are special cased for + // efficiency. They could be handled by the richer + // format support below, less efficiently. + a, stk = stk.Pop() + pb.PutString(a) + + case 'd': + ai, stk = stk.PopInt() + pb.PutString(strconv.Itoa(ai)) + + case '0', '1', '2', '3', '4', 'x', 'X', 'o', ':': + // This is pretty suboptimal, but this is rarely used. + // None of the mainstream terminals use any of this, + // and it would surprise me if this code is ever + // executed outside of test cases. + f := "%" + if ch == ':' { + ch, _ = pb.NextCh() + } + f += string(ch) + for ch == '+' || ch == '-' || ch == '#' || ch == ' ' { + ch, _ = pb.NextCh() + f += string(ch) + } + for (ch >= '0' && ch <= '9') || ch == '.' { + ch, _ = pb.NextCh() + f += string(ch) + } + switch ch { + case 'd', 'x', 'X', 'o': + ai, stk = stk.PopInt() + pb.PutString(fmt.Sprintf(f, ai)) + case 'c', 's': + a, stk = stk.Pop() + pb.PutString(fmt.Sprintf(f, a)) + } + + case 'p': // push parameter + ch, _ = pb.NextCh() + ai = int(ch - '1') + if ai >= 0 && ai < len(params) { + stk = stk.PushInt(params[ai]) + } else { + stk = stk.PushInt(0) + } + + case 'P': // pop & store variable + ch, _ = pb.NextCh() + if ch >= 'A' && ch <= 'Z' { + svars[int(ch-'A')], stk = stk.Pop() + } else if ch >= 'a' && ch <= 'z' { + dvars[int(ch-'a')], stk = stk.Pop() + } + + case 'g': // recall & push variable + ch, _ = pb.NextCh() + if ch >= 'A' && ch <= 'Z' { + stk = stk.Push(svars[int(ch-'A')]) + } else if ch >= 'a' && ch <= 'z' { + stk = stk.Push(dvars[int(ch-'a')]) + } + + case '\'': // push(char) + ch, _ = pb.NextCh() + pb.NextCh() // must be ' but we don't check + stk = stk.Push(string(ch)) + + case '{': // push(int) + ai = 0 + ch, _ = pb.NextCh() + for ch >= '0' && ch <= '9' { + ai *= 10 + ai += int(ch - '0') + ch, _ = pb.NextCh() + } + // ch must be '}' but no verification + stk = stk.PushInt(ai) + + case 'l': // push(strlen(pop)) + a, stk = stk.Pop() + stk = stk.PushInt(len(a)) + + case '+': + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + stk = stk.PushInt(ai + bi) + + case '-': + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + stk = stk.PushInt(ai - bi) + + case '*': + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + stk = stk.PushInt(ai * bi) + + case '/': + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + if bi != 0 { + stk = stk.PushInt(ai / bi) + } else { + stk = stk.PushInt(0) + } + + case 'm': // push(pop mod pop) + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + if bi != 0 { + stk = stk.PushInt(ai % bi) + } else { + stk = stk.PushInt(0) + } + + case '&': // AND + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + stk = stk.PushInt(ai & bi) + + case '|': // OR + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + stk = stk.PushInt(ai | bi) + + case '^': // XOR + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + stk = stk.PushInt(ai ^ bi) + + case '~': // bit complement + ai, stk = stk.PopInt() + stk = stk.PushInt(ai ^ -1) + + case '!': // logical NOT + ai, stk = stk.PopInt() + stk = stk.PushBool(ai != 0) + + case '=': // numeric compare or string compare + b, stk = stk.Pop() + a, stk = stk.Pop() + stk = stk.PushBool(a == b) + + case '>': // greater than, numeric + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + stk = stk.PushBool(ai > bi) + + case '<': // less than, numeric + bi, stk = stk.PopInt() + ai, stk = stk.PopInt() + stk = stk.PushBool(ai < bi) + + case '?': // start conditional + + case 't': + ab, stk = stk.PopBool() + if ab { + // just keep going + break + } + nest = 0 + ifloop: + // this loop consumes everything until we hit our else, + // or the end of the conditional + for { + ch, err = pb.NextCh() + if err != nil { + break + } + if ch != '%' { + continue + } + ch, _ = pb.NextCh() + switch ch { + case ';': + if nest == 0 { + break ifloop + } + nest-- + case '?': + nest++ + case 'e': + if nest == 0 { + break ifloop + } + } + } + + case 'e': + // if we got here, it means we didn't use the else + // in the 't' case above, and we should skip until + // the end of the conditional + nest = 0 + elloop: + for { + ch, err = pb.NextCh() + if err != nil { + break + } + if ch != '%' { + continue + } + ch, _ = pb.NextCh() + switch ch { + case ';': + if nest == 0 { + break elloop + } + nest-- + case '?': + nest++ + } + } + + case ';': // endif + + } + } + + return pb.End() +} + +// TPuts emits the string to the writer, but expands inline padding +// indications (of the form $<[delay]> where [delay] is msec) to +// a suitable number of padding characters (usually null bytes) based +// upon the supplied baud. At high baud rates, more padding characters +// will be inserted. All Terminfo based strings should be emitted using +// this function. +func (t *Terminfo) TPuts(w io.Writer, s string, baud int) { + for { + beg := strings.Index(s, "$<") + if beg < 0 { + // Most strings don't need padding, which is good news! + io.WriteString(w, s) + return + } + io.WriteString(w, s[:beg]) + s = s[beg+2:] + end := strings.Index(s, ">") + if end < 0 { + // unterminated.. just emit bytes unadulterated + io.WriteString(w, "$<"+s) + return + } + val := s[:end] + s = s[end+1:] + padus := 0 + unit := 1000 + dot := false + loop: + for i := range val { + switch val[i] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + padus *= 10 + padus += int(val[i] - '0') + if dot { + unit *= 10 + } + case '.': + if !dot { + dot = true + } else { + break loop + } + default: + break loop + } + } + cnt := int(((baud / 8) * padus) / unit) + for cnt > 0 { + io.WriteString(w, t.PadChar) + cnt-- + } + } +} + +// TGoto returns a string suitable for addressing the cursor at the given +// row and column. The origin 0, 0 is in the upper left corner of the screen. +func (t *Terminfo) TGoto(col, row int) string { + return t.TParm(t.SetCursor, row, col) +} + +// TColor returns a string corresponding to the given foreground and background +// colors. Either fg or bg can be set to -1 to elide. +func (t *Terminfo) TColor(fi, bi int) string { + rv := "" + // As a special case, we map bright colors to lower versions if the + // color table only holds 8. For the remaining 240 colors, the user + // is out of luck. Someday we could create a mapping table, but its + // not worth it. + if t.Colors == 8 { + if fi > 7 && fi < 16 { + fi -= 8 + } + if bi > 7 && bi < 16 { + bi -= 8 + } + } + if t.Colors > fi && fi >= 0 { + rv += t.TParm(t.SetFg, fi) + } + if t.Colors > bi && bi >= 0 { + rv += t.TParm(t.SetBg, bi) + } + return rv +} + +var ( + dblock sync.Mutex + terminfos = make(map[string]*Terminfo) + aliases = make(map[string]string) +) + +// AddTerminfo can be called to register a new Terminfo entry. +func AddTerminfo(t *Terminfo) { + dblock.Lock() + terminfos[t.Name] = t + for _, x := range t.Aliases { + terminfos[x] = t + } + dblock.Unlock() +} + +func loadFromFile(fname string, term string) (*Terminfo, error) { + var e error + var f io.Reader + if f, e = os.Open(fname); e != nil { + return nil, e + } + if strings.HasSuffix(fname, ".gz") { + if f, e = gzip.NewReader(f); e != nil { + return nil, e + } + } + d := json.NewDecoder(f) + for { + t := &Terminfo{} + if e := d.Decode(t); e != nil { + if e == io.EOF { + return nil, ErrTermNotFound + } + return nil, e + } + if t.SetCursor == "" { + // This must be an alias record, return it. + return t, nil + } + if t.Name == term { + return t, nil + } + for _, a := range t.Aliases { + if a == term { + return t, nil + } + } + } +} + +// LookupTerminfo attempts to find a definition for the named $TERM. +// It first looks in the builtin database, which should cover just about +// everyone. If it can't find one there, then it will attempt to read +// one from the JSON file located in either $TCELLDB, $HOME/.tcelldb +// or in this package's source directory as database.json). +func LookupTerminfo(name string) (*Terminfo, error) { + dblock.Lock() + t := terminfos[name] + dblock.Unlock() + + if t == nil { + + var files []string + letter := fmt.Sprintf("%02x", name[0]) + gzfile := path.Join(letter, name+".gz") + jsfile := path.Join(letter, name) + + // Build up the search path. Old versions of tcell used a + // single database file, whereas the new ones locate them + // in JSON (optionally compressed) files. + // + // The search path looks like: + // + // $TCELLDB/x/xterm.gz + // $TCELLDB/x/xterm + // $TCELLDB + // $HOME/.tcelldb/x/xterm.gz + // $HOME/.tcelldb/x/xterm + // $HOME/.tcelldb + // $GOPATH/terminfo/database/x/xterm.gz + // $GOPATH/terminfo/database/x/xterm + // + if pth := os.Getenv("TCELLDB"); pth != "" { + files = append(files, path.Join(pth, gzfile)) + files = append(files, path.Join(pth, jsfile)) + files = append(files, pth) + } + if pth := os.Getenv("HOME"); pth != "" { + pth = path.Join(pth, ".tcelldb") + files = append(files, path.Join(pth, gzfile)) + files = append(files, path.Join(pth, jsfile)) + files = append(files, pth) + } + + for _, pth := range strings.Split(os.Getenv("GOPATH"), string(os.PathListSeparator)) { + pth = path.Join(pth, "src", "github.com", "gdamore", "tcell", "terminfo", "database") + files = append(files, path.Join(pth, gzfile)) + files = append(files, path.Join(pth, jsfile)) + } + + for _, fname := range files { + t, _ = loadFromFile(fname, name) + if t != nil { + break + } + } + if t != nil { + if t.Name != name { + // Check for a database loop (no infinite + // recursion). + dblock.Lock() + if aliases[name] != "" { + dblock.Unlock() + return nil, ErrTermNotFound + } + aliases[name] = t.Name + dblock.Unlock() + return LookupTerminfo(t.Name) + } + dblock.Lock() + terminfos[name] = t + dblock.Unlock() + } + } + if t == nil { + return nil, ErrTermNotFound + } + return t, nil +} diff --git a/vendor/github.com/gdamore/tcell/tscreen.go b/vendor/github.com/gdamore/tcell/tscreen.go new file mode 100644 index 00000000..7e0d0b97 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/tscreen.go @@ -0,0 +1,1382 @@ +// Copyright 2017 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "bytes" + "io" + "os" + "strconv" + "sync" + "time" + "unicode/utf8" + + "golang.org/x/text/transform" + + "github.com/gdamore/tcell/terminfo" +) + +// NewTerminfoScreen returns a Screen that uses the stock TTY interface +// and POSIX termios, combined with a terminfo description taken from +// the $TERM environment variable. It returns an error if the terminal +// is not supported for any reason. +// +// For terminals that do not support dynamic resize events, the $LINES +// $COLUMNS environment variables can be set to the actual window size, +// otherwise defaults taken from the terminal database are used. +func NewTerminfoScreen() (Screen, error) { + ti, e := terminfo.LookupTerminfo(os.Getenv("TERM")) + if e != nil { + return nil, e + } + t := &tScreen{ti: ti} + + t.keyexist = make(map[Key]bool) + t.keycodes = make(map[string]*tKeyCode) + if len(ti.Mouse) > 0 { + t.mouse = []byte(ti.Mouse) + } + t.prepareKeys() + t.buildAcsMap() + t.sigwinch = make(chan os.Signal, 10) + t.fallback = make(map[rune]string) + for k, v := range RuneFallbacks { + t.fallback[k] = v + } + + return t, nil +} + +// tKeyCode represents a combination of a key code and modifiers. +type tKeyCode struct { + key Key + mod ModMask +} + +// tScreen represents a screen backed by a terminfo implementation. +type tScreen struct { + ti *terminfo.Terminfo + h int + w int + fini bool + cells CellBuffer + in *os.File + out *os.File + curstyle Style + style Style + evch chan Event + sigwinch chan os.Signal + quit chan struct{} + indoneq chan struct{} + keyexist map[Key]bool + keycodes map[string]*tKeyCode + keychan chan []byte + keytimer *time.Timer + keyexpire time.Time + cx int + cy int + mouse []byte + clear bool + cursorx int + cursory int + tiosp *termiosPrivate + baud int + wasbtn bool + acs map[rune]string + charset string + encoder transform.Transformer + decoder transform.Transformer + fallback map[rune]string + colors map[Color]Color + palette []Color + truecolor bool + escaped bool + buttondn bool + + sync.Mutex +} + +func (t *tScreen) Init() error { + t.evch = make(chan Event, 10) + t.indoneq = make(chan struct{}) + t.keychan = make(chan []byte, 10) + t.keytimer = time.NewTimer(time.Millisecond * 50) + t.charset = "UTF-8" + + t.charset = getCharset() + if enc := GetEncoding(t.charset); enc != nil { + t.encoder = enc.NewEncoder() + t.decoder = enc.NewDecoder() + } else { + return ErrNoCharset + } + ti := t.ti + + // environment overrides + w := ti.Columns + h := ti.Lines + if i, _ := strconv.Atoi(os.Getenv("LINES")); i != 0 { + h = i + } + if i, _ := strconv.Atoi(os.Getenv("COLUMNS")); i != 0 { + w = i + } + if e := t.termioInit(); e != nil { + return e + } + + if t.ti.SetFgBgRGB != "" || t.ti.SetFgRGB != "" || t.ti.SetBgRGB != "" { + t.truecolor = true + } + // A user who wants to have his themes honored can + // set this environment variable. + if os.Getenv("TCELL_TRUECOLOR") == "disable" { + t.truecolor = false + } + if !t.truecolor { + t.colors = make(map[Color]Color) + t.palette = make([]Color, t.Colors()) + for i := 0; i < t.Colors(); i++ { + t.palette[i] = Color(i) + // identity map for our builtin colors + t.colors[Color(i)] = Color(i) + } + } + + t.TPuts(ti.EnterCA) + t.TPuts(ti.HideCursor) + t.TPuts(ti.EnableAcs) + t.TPuts(ti.Clear) + + t.quit = make(chan struct{}) + + t.Lock() + t.cx = -1 + t.cy = -1 + t.style = StyleDefault + t.cells.Resize(w, h) + t.cursorx = -1 + t.cursory = -1 + t.resize() + t.Unlock() + + go t.mainLoop() + go t.inputLoop() + + return nil +} + +func (t *tScreen) prepareKeyMod(key Key, mod ModMask, val string) { + if val != "" { + // Do not overrride codes that already exist + if _, exist := t.keycodes[val]; !exist { + t.keyexist[key] = true + t.keycodes[val] = &tKeyCode{key: key, mod: mod} + } + } +} + +func (t *tScreen) prepareKey(key Key, val string) { + t.prepareKeyMod(key, ModNone, val) +} + +func (t *tScreen) prepareKeys() { + ti := t.ti + t.prepareKey(KeyBackspace, ti.KeyBackspace) + t.prepareKey(KeyF1, ti.KeyF1) + t.prepareKey(KeyF2, ti.KeyF2) + t.prepareKey(KeyF3, ti.KeyF3) + t.prepareKey(KeyF4, ti.KeyF4) + t.prepareKey(KeyF5, ti.KeyF5) + t.prepareKey(KeyF6, ti.KeyF6) + t.prepareKey(KeyF7, ti.KeyF7) + t.prepareKey(KeyF8, ti.KeyF8) + t.prepareKey(KeyF9, ti.KeyF9) + t.prepareKey(KeyF10, ti.KeyF10) + t.prepareKey(KeyF11, ti.KeyF11) + t.prepareKey(KeyF12, ti.KeyF12) + t.prepareKey(KeyF13, ti.KeyF13) + t.prepareKey(KeyF14, ti.KeyF14) + t.prepareKey(KeyF15, ti.KeyF15) + t.prepareKey(KeyF16, ti.KeyF16) + t.prepareKey(KeyF17, ti.KeyF17) + t.prepareKey(KeyF18, ti.KeyF18) + t.prepareKey(KeyF19, ti.KeyF19) + t.prepareKey(KeyF20, ti.KeyF20) + t.prepareKey(KeyF21, ti.KeyF21) + t.prepareKey(KeyF22, ti.KeyF22) + t.prepareKey(KeyF23, ti.KeyF23) + t.prepareKey(KeyF24, ti.KeyF24) + t.prepareKey(KeyF25, ti.KeyF25) + t.prepareKey(KeyF26, ti.KeyF26) + t.prepareKey(KeyF27, ti.KeyF27) + t.prepareKey(KeyF28, ti.KeyF28) + t.prepareKey(KeyF29, ti.KeyF29) + t.prepareKey(KeyF30, ti.KeyF30) + t.prepareKey(KeyF31, ti.KeyF31) + t.prepareKey(KeyF32, ti.KeyF32) + t.prepareKey(KeyF33, ti.KeyF33) + t.prepareKey(KeyF34, ti.KeyF34) + t.prepareKey(KeyF35, ti.KeyF35) + t.prepareKey(KeyF36, ti.KeyF36) + t.prepareKey(KeyF37, ti.KeyF37) + t.prepareKey(KeyF38, ti.KeyF38) + t.prepareKey(KeyF39, ti.KeyF39) + t.prepareKey(KeyF40, ti.KeyF40) + t.prepareKey(KeyF41, ti.KeyF41) + t.prepareKey(KeyF42, ti.KeyF42) + t.prepareKey(KeyF43, ti.KeyF43) + t.prepareKey(KeyF44, ti.KeyF44) + t.prepareKey(KeyF45, ti.KeyF45) + t.prepareKey(KeyF46, ti.KeyF46) + t.prepareKey(KeyF47, ti.KeyF47) + t.prepareKey(KeyF48, ti.KeyF48) + t.prepareKey(KeyF49, ti.KeyF49) + t.prepareKey(KeyF50, ti.KeyF50) + t.prepareKey(KeyF51, ti.KeyF51) + t.prepareKey(KeyF52, ti.KeyF52) + t.prepareKey(KeyF53, ti.KeyF53) + t.prepareKey(KeyF54, ti.KeyF54) + t.prepareKey(KeyF55, ti.KeyF55) + t.prepareKey(KeyF56, ti.KeyF56) + t.prepareKey(KeyF57, ti.KeyF57) + t.prepareKey(KeyF58, ti.KeyF58) + t.prepareKey(KeyF59, ti.KeyF59) + t.prepareKey(KeyF60, ti.KeyF60) + t.prepareKey(KeyF61, ti.KeyF61) + t.prepareKey(KeyF62, ti.KeyF62) + t.prepareKey(KeyF63, ti.KeyF63) + t.prepareKey(KeyF64, ti.KeyF64) + t.prepareKey(KeyInsert, ti.KeyInsert) + t.prepareKey(KeyDelete, ti.KeyDelete) + t.prepareKey(KeyHome, ti.KeyHome) + t.prepareKey(KeyEnd, ti.KeyEnd) + t.prepareKey(KeyUp, ti.KeyUp) + t.prepareKey(KeyDown, ti.KeyDown) + t.prepareKey(KeyLeft, ti.KeyLeft) + t.prepareKey(KeyRight, ti.KeyRight) + t.prepareKey(KeyPgUp, ti.KeyPgUp) + t.prepareKey(KeyPgDn, ti.KeyPgDn) + t.prepareKey(KeyHelp, ti.KeyHelp) + t.prepareKey(KeyPrint, ti.KeyPrint) + t.prepareKey(KeyCancel, ti.KeyCancel) + t.prepareKey(KeyExit, ti.KeyExit) + t.prepareKey(KeyBacktab, ti.KeyBacktab) + + t.prepareKeyMod(KeyRight, ModShift, ti.KeyShfRight) + t.prepareKeyMod(KeyLeft, ModShift, ti.KeyShfLeft) + t.prepareKeyMod(KeyUp, ModShift, ti.KeyShfUp) + t.prepareKeyMod(KeyDown, ModShift, ti.KeyShfDown) + t.prepareKeyMod(KeyHome, ModShift, ti.KeyShfHome) + t.prepareKeyMod(KeyEnd, ModShift, ti.KeyShfEnd) + + t.prepareKeyMod(KeyRight, ModCtrl, ti.KeyCtrlRight) + t.prepareKeyMod(KeyLeft, ModCtrl, ti.KeyCtrlLeft) + t.prepareKeyMod(KeyUp, ModCtrl, ti.KeyCtrlUp) + t.prepareKeyMod(KeyDown, ModCtrl, ti.KeyCtrlDown) + t.prepareKeyMod(KeyHome, ModCtrl, ti.KeyCtrlHome) + t.prepareKeyMod(KeyEnd, ModCtrl, ti.KeyCtrlEnd) + + t.prepareKeyMod(KeyRight, ModAlt, ti.KeyAltRight) + t.prepareKeyMod(KeyLeft, ModAlt, ti.KeyAltLeft) + t.prepareKeyMod(KeyUp, ModAlt, ti.KeyAltUp) + t.prepareKeyMod(KeyDown, ModAlt, ti.KeyAltDown) + t.prepareKeyMod(KeyHome, ModAlt, ti.KeyAltHome) + t.prepareKeyMod(KeyEnd, ModAlt, ti.KeyAltEnd) + + t.prepareKeyMod(KeyRight, ModAlt, ti.KeyMetaRight) + t.prepareKeyMod(KeyLeft, ModAlt, ti.KeyMetaLeft) + t.prepareKeyMod(KeyUp, ModAlt, ti.KeyMetaUp) + t.prepareKeyMod(KeyDown, ModAlt, ti.KeyMetaDown) + t.prepareKeyMod(KeyHome, ModAlt, ti.KeyMetaHome) + t.prepareKeyMod(KeyEnd, ModAlt, ti.KeyMetaEnd) + + t.prepareKeyMod(KeyRight, ModAlt|ModShift, ti.KeyAltShfRight) + t.prepareKeyMod(KeyLeft, ModAlt|ModShift, ti.KeyAltShfLeft) + t.prepareKeyMod(KeyUp, ModAlt|ModShift, ti.KeyAltShfUp) + t.prepareKeyMod(KeyDown, ModAlt|ModShift, ti.KeyAltShfDown) + t.prepareKeyMod(KeyHome, ModAlt|ModShift, ti.KeyAltShfHome) + t.prepareKeyMod(KeyEnd, ModAlt|ModShift, ti.KeyAltShfEnd) + + t.prepareKeyMod(KeyRight, ModAlt|ModShift, ti.KeyMetaShfRight) + t.prepareKeyMod(KeyLeft, ModAlt|ModShift, ti.KeyMetaShfLeft) + t.prepareKeyMod(KeyUp, ModAlt|ModShift, ti.KeyMetaShfUp) + t.prepareKeyMod(KeyDown, ModAlt|ModShift, ti.KeyMetaShfDown) + t.prepareKeyMod(KeyHome, ModAlt|ModShift, ti.KeyMetaShfHome) + t.prepareKeyMod(KeyEnd, ModAlt|ModShift, ti.KeyMetaShfEnd) + + t.prepareKeyMod(KeyRight, ModCtrl|ModShift, ti.KeyCtrlShfRight) + t.prepareKeyMod(KeyLeft, ModCtrl|ModShift, ti.KeyCtrlShfLeft) + t.prepareKeyMod(KeyUp, ModCtrl|ModShift, ti.KeyCtrlShfUp) + t.prepareKeyMod(KeyDown, ModCtrl|ModShift, ti.KeyCtrlShfDown) + t.prepareKeyMod(KeyHome, ModCtrl|ModShift, ti.KeyCtrlShfHome) + t.prepareKeyMod(KeyEnd, ModCtrl|ModShift, ti.KeyCtrlShfEnd) + + // Sadly, xterm handling of keycodes is somewhat erratic. In + // particular, different codes are sent depending on application + // mode is in use or not, and the entries for many of these are + // simply absent from terminfo on many systems. So we insert + // a number of escape sequences if they are not already used, in + // order to have the widest correct usage. Note that prepareKey + // will not inject codes if the escape sequence is already known. + // We also only do this for terminals that have the application + // mode present. + + // Cursor mode + if ti.EnterKeypad != "" { + t.prepareKey(KeyUp, "\x1b[A") + t.prepareKey(KeyDown, "\x1b[B") + t.prepareKey(KeyRight, "\x1b[C") + t.prepareKey(KeyLeft, "\x1b[D") + t.prepareKey(KeyEnd, "\x1b[F") + t.prepareKey(KeyHome, "\x1b[H") + t.prepareKey(KeyDelete, "\x1b[3~") + t.prepareKey(KeyHome, "\x1b[1~") + t.prepareKey(KeyEnd, "\x1b[4~") + t.prepareKey(KeyPgUp, "\x1b[5~") + t.prepareKey(KeyPgDn, "\x1b[6~") + + // Application mode + t.prepareKey(KeyUp, "\x1bOA") + t.prepareKey(KeyDown, "\x1bOB") + t.prepareKey(KeyRight, "\x1bOC") + t.prepareKey(KeyLeft, "\x1bOD") + t.prepareKey(KeyHome, "\x1bOH") + } + +outer: + // Add key mappings for control keys. + for i := 0; i < ' '; i++ { + // Do not insert direct key codes for ambiguous keys. + // For example, ESC is used for lots of other keys, so + // when parsing this we don't want to fast path handling + // of it, but instead wait a bit before parsing it as in + // isolation. + for esc := range t.keycodes { + if []byte(esc)[0] == byte(i) { + continue outer + } + } + + t.keyexist[Key(i)] = true + + mod := ModCtrl + switch Key(i) { + case KeyBS, KeyTAB, KeyESC, KeyCR: + // directly typeable- no control sequence + mod = ModNone + } + t.keycodes[string(rune(i))] = &tKeyCode{key: Key(i), mod: mod} + } +} + +func (t *tScreen) Fini() { + ti := t.ti + t.Lock() + t.cells.Resize(0, 0) + t.TPuts(ti.ShowCursor) + t.TPuts(ti.AttrOff) + t.TPuts(ti.Clear) + t.TPuts(ti.ExitCA) + t.TPuts(ti.ExitKeypad) + t.TPuts(ti.TParm(ti.MouseMode, 0)) + t.curstyle = Style(-1) + t.clear = false + t.fini = true + t.Unlock() + + if t.quit != nil { + close(t.quit) + } + t.termioFini() +} + +func (t *tScreen) SetStyle(style Style) { + t.Lock() + if !t.fini { + t.style = style + } + t.Unlock() +} + +func (t *tScreen) Clear() { + t.Fill(' ', t.style) +} + +func (t *tScreen) Fill(r rune, style Style) { + t.Lock() + if !t.fini { + t.cells.Fill(r, style) + } + t.Unlock() +} + +func (t *tScreen) SetContent(x, y int, mainc rune, combc []rune, style Style) { + t.Lock() + if !t.fini { + t.cells.SetContent(x, y, mainc, combc, style) + } + t.Unlock() +} + +func (t *tScreen) GetContent(x, y int) (rune, []rune, Style, int) { + t.Lock() + mainc, combc, style, width := t.cells.GetContent(x, y) + t.Unlock() + return mainc, combc, style, width +} + +func (t *tScreen) SetCell(x, y int, style Style, ch ...rune) { + if len(ch) > 0 { + t.SetContent(x, y, ch[0], ch[1:], style) + } else { + t.SetContent(x, y, ' ', nil, style) + } +} + +func (t *tScreen) encodeRune(r rune, buf []byte) []byte { + + nb := make([]byte, 6) + ob := make([]byte, 6) + num := utf8.EncodeRune(ob, r) + ob = ob[:num] + dst := 0 + var err error + if enc := t.encoder; enc != nil { + enc.Reset() + dst, _, err = enc.Transform(nb, ob, true) + } + if err != nil || dst == 0 || nb[0] == '\x1a' { + // Combining characters are elided + if len(buf) == 0 { + if acs, ok := t.acs[r]; ok { + buf = append(buf, []byte(acs)...) + } else if fb, ok := t.fallback[r]; ok { + buf = append(buf, []byte(fb)...) + } else { + buf = append(buf, '?') + } + } + } else { + buf = append(buf, nb[:dst]...) + } + + return buf +} + +func (t *tScreen) sendFgBg(fg Color, bg Color) { + ti := t.ti + if ti.Colors == 0 { + return + } + if t.truecolor { + if ti.SetFgBgRGB != "" && + fg != ColorDefault && bg != ColorDefault { + r1, g1, b1 := fg.RGB() + r2, g2, b2 := bg.RGB() + t.TPuts(ti.TParm(ti.SetFgBgRGB, + int(r1), int(g1), int(b1), + int(r2), int(g2), int(b2))) + } else { + if fg != ColorDefault && ti.SetFgRGB != "" { + r, g, b := fg.RGB() + t.TPuts(ti.TParm(ti.SetFgRGB, + int(r), int(g), int(b))) + } + if bg != ColorDefault && ti.SetBgRGB != "" { + r, g, b := bg.RGB() + t.TPuts(ti.TParm(ti.SetBgRGB, + int(r), int(g), int(b))) + } + } + return + } + + if fg != ColorDefault { + if v, ok := t.colors[fg]; ok { + fg = v + } else { + v = FindColor(fg, t.palette) + t.colors[fg] = v + fg = v + } + } + + if bg != ColorDefault { + if v, ok := t.colors[bg]; ok { + bg = v + } else { + v = FindColor(bg, t.palette) + t.colors[bg] = v + bg = v + } + } + + if ti.SetFgBg != "" && fg != ColorDefault && bg != ColorDefault { + t.TPuts(ti.TParm(ti.SetFgBg, int(fg), int(bg))) + } else { + if fg != ColorDefault && ti.SetFg != "" { + t.TPuts(ti.TParm(ti.SetFg, int(fg))) + } + if bg != ColorDefault && ti.SetBg != "" { + t.TPuts(ti.TParm(ti.SetBg, int(bg))) + } + } +} + +func (t *tScreen) drawCell(x, y int) int { + + ti := t.ti + + mainc, combc, style, width := t.cells.GetContent(x, y) + if !t.cells.Dirty(x, y) { + return width + } + + if t.cy != y || t.cx != x { + t.TPuts(ti.TGoto(x, y)) + t.cx = x + t.cy = y + } + + if style == StyleDefault { + style = t.style + } + if style != t.curstyle { + fg, bg, attrs := style.Decompose() + + t.TPuts(ti.AttrOff) + + t.sendFgBg(fg, bg) + if attrs&AttrBold != 0 { + t.TPuts(ti.Bold) + } + if attrs&AttrUnderline != 0 { + t.TPuts(ti.Underline) + } + if attrs&AttrReverse != 0 { + t.TPuts(ti.Reverse) + } + if attrs&AttrBlink != 0 { + t.TPuts(ti.Blink) + } + if attrs&AttrDim != 0 { + t.TPuts(ti.Dim) + } + t.curstyle = style + } + // now emit runes - taking care to not overrun width with a + // wide character, and to ensure that we emit exactly one regular + // character followed up by any residual combing characters + + if width < 1 { + width = 1 + } + + var str string + + buf := make([]byte, 0, 6) + + buf = t.encodeRune(mainc, buf) + for _, r := range combc { + buf = t.encodeRune(r, buf) + } + + str = string(buf) + if width > 1 && str == "?" { + // No FullWidth character support + str = "? " + t.cx = -1 + } + + // XXX: check for hazeltine not being able to display ~ + + if x > t.w-width { + // too wide to fit; emit a single space instead + width = 1 + str = " " + } + io.WriteString(t.out, str) + t.cx += width + t.cells.SetDirty(x, y, false) + if width > 1 { + t.cx = -1 + } + + return width +} + +func (t *tScreen) ShowCursor(x, y int) { + t.Lock() + t.cursorx = x + t.cursory = y + t.Unlock() +} + +func (t *tScreen) HideCursor() { + t.ShowCursor(-1, -1) +} + +func (t *tScreen) showCursor() { + + x, y := t.cursorx, t.cursory + w, h := t.cells.Size() + if x < 0 || y < 0 || x >= w || y >= h { + t.hideCursor() + return + } + t.TPuts(t.ti.TGoto(x, y)) + t.TPuts(t.ti.ShowCursor) + t.cx = x + t.cy = y +} + +func (t *tScreen) TPuts(s string) { + t.ti.TPuts(t.out, s, t.baud) +} + +func (t *tScreen) Show() { + t.Lock() + if !t.fini { + t.resize() + t.draw() + } + t.Unlock() +} + +func (t *tScreen) clearScreen() { + fg, bg, _ := t.style.Decompose() + t.sendFgBg(fg, bg) + t.TPuts(t.ti.Clear) + t.clear = false +} + +func (t *tScreen) hideCursor() { + // does not update cursor position + if t.ti.HideCursor != "" { + t.TPuts(t.ti.HideCursor) + } else { + // No way to hide cursor, stick it + // at bottom right of screen + t.cx, t.cy = t.cells.Size() + t.TPuts(t.ti.TGoto(t.cx, t.cy)) + } +} + +func (t *tScreen) draw() { + // clobber cursor position, because we're gonna change it all + t.cx = -1 + t.cy = -1 + + // hide the cursor while we move stuff around + t.hideCursor() + + if t.clear { + t.clearScreen() + } + + for y := 0; y < t.h; y++ { + for x := 0; x < t.w; x++ { + width := t.drawCell(x, y) + if width > 1 { + if x+1 < t.w { + // this is necessary so that if we ever + // go back to drawing that cell, we + // actually will *draw* it. + t.cells.SetDirty(x+1, y, true) + } + } + x += width - 1 + } + } + + // restore the cursor + t.showCursor() +} + +func (t *tScreen) EnableMouse() { + if len(t.mouse) != 0 { + t.TPuts(t.ti.TParm(t.ti.MouseMode, 1)) + } +} + +func (t *tScreen) DisableMouse() { + if len(t.mouse) != 0 { + t.TPuts(t.ti.TParm(t.ti.MouseMode, 0)) + } +} + +func (t *tScreen) Size() (int, int) { + t.Lock() + w, h := t.w, t.h + t.Unlock() + return w, h +} + +func (t *tScreen) resize() { + if w, h, e := t.getWinSize(); e == nil { + if w != t.w || h != t.h { + t.cx = -1 + t.cy = -1 + + t.cells.Resize(w, h) + t.cells.Invalidate() + t.h = h + t.w = w + ev := NewEventResize(w, h) + t.PostEvent(ev) + } + } +} + +func (t *tScreen) Colors() int { + // this doesn't change, no need for lock + if t.truecolor { + return 1 << 24 + } + return t.ti.Colors +} + +func (t *tScreen) PollEvent() Event { + select { + case <-t.quit: + return nil + case ev := <-t.evch: + return ev + } +} + +// vtACSNames is a map of bytes defined by terminfo that are used in +// the terminals Alternate Character Set to represent other glyphs. +// For example, the upper left corner of the box drawing set can be +// displayed by printing "l" while in the alternate character set. +// Its not quite that simple, since the "l" is the terminfo name, +// and it may be necessary to use a different character based on +// the terminal implementation (or the terminal may lack support for +// this altogether). See buildAcsMap below for detail. +var vtACSNames = map[byte]rune{ + '+': RuneRArrow, + ',': RuneLArrow, + '-': RuneUArrow, + '.': RuneDArrow, + '0': RuneBlock, + '`': RuneDiamond, + 'a': RuneCkBoard, + 'b': '␉', // VT100, Not defined by terminfo + 'c': '␌', // VT100, Not defined by terminfo + 'd': '␋', // VT100, Not defined by terminfo + 'e': '␊', // VT100, Not defined by terminfo + 'f': RuneDegree, + 'g': RunePlMinus, + 'h': RuneBoard, + 'i': RuneLantern, + 'j': RuneLRCorner, + 'k': RuneURCorner, + 'l': RuneULCorner, + 'm': RuneLLCorner, + 'n': RunePlus, + 'o': RuneS1, + 'p': RuneS3, + 'q': RuneHLine, + 'r': RuneS7, + 's': RuneS9, + 't': RuneLTee, + 'u': RuneRTee, + 'v': RuneBTee, + 'w': RuneTTee, + 'x': RuneVLine, + 'y': RuneLEqual, + 'z': RuneGEqual, + '{': RunePi, + '|': RuneNEqual, + '}': RuneSterling, + '~': RuneBullet, +} + +// buildAcsMap builds a map of characters that we translate from Unicode to +// alternate character encodings. To do this, we use the standard VT100 ACS +// maps. This is only done if the terminal lacks support for Unicode; we +// always prefer to emit Unicode glyphs when we are able. +func (t *tScreen) buildAcsMap() { + acsstr := t.ti.AltChars + t.acs = make(map[rune]string) + for len(acsstr) > 2 { + srcv := acsstr[0] + dstv := string(acsstr[1]) + if r, ok := vtACSNames[srcv]; ok { + t.acs[r] = t.ti.EnterAcs + dstv + t.ti.ExitAcs + } + acsstr = acsstr[2:] + } +} + +func (t *tScreen) PostEventWait(ev Event) { + t.evch <- ev +} + +func (t *tScreen) PostEvent(ev Event) error { + select { + case t.evch <- ev: + return nil + default: + return ErrEventQFull + } +} + +func (t *tScreen) clip(x, y int) (int, int) { + w, h := t.cells.Size() + if x < 0 { + x = 0 + } + if y < 0 { + y = 0 + } + if x > w-1 { + x = w - 1 + } + if y > h-1 { + y = h - 1 + } + return x, y +} + +func (t *tScreen) postMouseEvent(x, y, btn int) { + + // XTerm mouse events only report at most one button at a time, + // which may include a wheel button. Wheel motion events are + // reported as single impulses, while other button events are reported + // as separate press & release events. + + button := ButtonNone + mod := ModNone + + // Mouse wheel has bit 6 set, no release events. It should be noted + // that wheel events are sometimes misdelivered as mouse button events + // during a click-drag, so we debounce these, considering them to be + // button press events unless we see an intervening release event. + switch btn & 0x43 { + case 0: + button = Button1 + t.wasbtn = true + case 1: + button = Button2 + t.wasbtn = true + case 2: + button = Button3 + t.wasbtn = true + case 3: + button = ButtonNone + t.wasbtn = false + case 0x40: + if !t.wasbtn { + button = WheelUp + } else { + button = Button1 + } + case 0x41: + if !t.wasbtn { + button = WheelDown + } else { + button = Button2 + } + } + + if btn&0x4 != 0 { + mod |= ModShift + } + if btn&0x8 != 0 { + mod |= ModAlt + } + if btn&0x10 != 0 { + mod |= ModCtrl + } + + // Some terminals will report mouse coordinates outside the + // screen, especially with click-drag events. Clip the coordinates + // to the screen in that case. + x, y = t.clip(x, y) + + ev := NewEventMouse(x, y, button, mod) + t.PostEvent(ev) +} + +// parseSgrMouse attempts to locate an SGR mouse record at the start of the +// buffer. It returns true, true if it found one, and the associated bytes +// be removed from the buffer. It returns true, false if the buffer might +// contain such an event, but more bytes are necessary (partial match), and +// false, false if the content is definitely *not* an SGR mouse record. +func (t *tScreen) parseSgrMouse(buf *bytes.Buffer) (bool, bool) { + + b := buf.Bytes() + + var x, y, btn, state int + dig := false + neg := false + motion := false + i := 0 + val := 0 + + for i = range b { + switch b[i] { + case '\x1b': + if state != 0 { + return false, false + } + state = 1 + + case '\x9b': + if state != 0 { + return false, false + } + state = 2 + + case '[': + if state != 1 { + return false, false + } + state = 2 + + case '<': + if state != 2 { + return false, false + } + val = 0 + dig = false + neg = false + state = 3 + + case '-': + if state != 3 && state != 4 && state != 5 { + return false, false + } + if dig || neg { + return false, false + } + neg = true // stay in state + + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + if state != 3 && state != 4 && state != 5 { + return false, false + } + val *= 10 + val += int(b[i] - '0') + dig = true // stay in state + + case ';': + if neg { + val = -val + } + switch state { + case 3: + btn, val = val, 0 + neg, dig, state = false, false, 4 + case 4: + x, val = val-1, 0 + neg, dig, state = false, false, 5 + default: + return false, false + } + + case 'm', 'M': + if state != 5 { + return false, false + } + if neg { + val = -val + } + y = val - 1 + + motion = (btn & 32) != 0 + btn &^= 32 + if b[i] == 'm' { + // mouse release, clear all buttons + btn |= 3 + btn &^= 0x40 + t.buttondn = false + } else if motion { + /* + * Some broken terminals appear to send + * mouse button one motion events, instead of + * encoding 35 (no buttons) into these events. + * We resolve these by looking for a non-motion + * event first. + */ + if !t.buttondn { + btn |= 3 + btn &^= 0x40 + } + } else { + t.buttondn = true + } + // consume the event bytes + for i >= 0 { + buf.ReadByte() + i-- + } + t.postMouseEvent(x, y, btn) + return true, true + } + } + + // incomplete & inconclusve at this point + return true, false +} + +// parseXtermMouse is like parseSgrMouse, but it parses a legacy +// X11 mouse record. +func (t *tScreen) parseXtermMouse(buf *bytes.Buffer) (bool, bool) { + + b := buf.Bytes() + + state := 0 + btn := 0 + x := 0 + y := 0 + + for i := range b { + switch state { + case 0: + switch b[i] { + case '\x1b': + state = 1 + case '\x9b': + state = 2 + default: + return false, false + } + case 1: + if b[i] != '[' { + return false, false + } + state = 2 + case 2: + if b[i] != 'M' { + return false, false + } + state++ + case 3: + btn = int(b[i]) + state++ + case 4: + x = int(b[i]) - 32 - 1 + state++ + case 5: + y = int(b[i]) - 32 - 1 + for i >= 0 { + buf.ReadByte() + i-- + } + t.postMouseEvent(x, y, btn) + return true, true + } + } + return true, false +} + +func (t *tScreen) parseFunctionKey(buf *bytes.Buffer) (bool, bool) { + b := buf.Bytes() + partial := false + for e, k := range t.keycodes { + esc := []byte(e) + if (len(esc) == 1) && (esc[0] == '\x1b') { + continue + } + if bytes.HasPrefix(b, esc) { + // matched + var r rune + if len(esc) == 1 { + r = rune(b[0]) + } + mod := k.mod + if t.escaped { + mod |= ModAlt + t.escaped = false + } + ev := NewEventKey(k.key, r, mod) + t.PostEvent(ev) + for i := 0; i < len(esc); i++ { + buf.ReadByte() + } + return true, true + } + if bytes.HasPrefix(esc, b) { + partial = true + } + } + return partial, false +} + +func (t *tScreen) parseRune(buf *bytes.Buffer) (bool, bool) { + b := buf.Bytes() + if b[0] >= ' ' && b[0] <= 0x7F { + // printable ASCII easy to deal with -- no encodings + mod := ModNone + if t.escaped { + mod = ModAlt + t.escaped = false + } + ev := NewEventKey(KeyRune, rune(b[0]), mod) + t.PostEvent(ev) + buf.ReadByte() + return true, true + } + + if b[0] < 0x80 { + // Low numbered values are control keys, not runes. + return false, false + } + + utfb := make([]byte, 12) + for l := 1; l <= len(b); l++ { + t.decoder.Reset() + nout, nin, e := t.decoder.Transform(utfb, b[:l], true) + if e == transform.ErrShortSrc { + continue + } + if nout != 0 { + r, _ := utf8.DecodeRune(utfb[:nout]) + if r != utf8.RuneError { + mod := ModNone + if t.escaped { + mod = ModAlt + t.escaped = false + } + ev := NewEventKey(KeyRune, r, mod) + t.PostEvent(ev) + } + for nin > 0 { + buf.ReadByte() + nin-- + } + return true, true + } + } + // Looks like potential escape + return true, false +} + +func (t *tScreen) scanInput(buf *bytes.Buffer, expire bool) { + + t.Lock() + defer t.Unlock() + + for { + b := buf.Bytes() + if len(b) == 0 { + buf.Reset() + return + } + + partials := 0 + + if part, comp := t.parseRune(buf); comp { + continue + } else if part { + partials++ + } + + if part, comp := t.parseFunctionKey(buf); comp { + continue + } else if part { + partials++ + } + + // Only parse mouse records if this term claims to have + // mouse support + + if t.ti.Mouse != "" { + if part, comp := t.parseXtermMouse(buf); comp { + continue + } else if part { + partials++ + } + + if part, comp := t.parseSgrMouse(buf); comp { + continue + } else if part { + partials++ + } + } + + if partials == 0 || expire { + if b[0] == '\x1b' { + if len(b) == 1 { + ev := NewEventKey(KeyEsc, 0, ModNone) + t.PostEvent(ev) + t.escaped = false + } else { + t.escaped = true + } + buf.ReadByte() + continue + } + // Nothing was going to match, or we timed out + // waiting for more data -- just deliver the characters + // to the app & let them sort it out. Possibly we + // should only do this for control characters like ESC. + by, _ := buf.ReadByte() + mod := ModNone + if t.escaped { + t.escaped = false + mod = ModAlt + } + ev := NewEventKey(KeyRune, rune(by), mod) + t.PostEvent(ev) + continue + } + + // well we have some partial data, wait until we get + // some more + break + } +} + +func (t *tScreen) mainLoop() { + buf := &bytes.Buffer{} + for { + select { + case <-t.quit: + close(t.indoneq) + return + case <-t.sigwinch: + t.Lock() + t.cx = -1 + t.cy = -1 + t.resize() + t.cells.Invalidate() + t.draw() + t.Unlock() + continue + case <-t.keytimer.C: + // If the timer fired, and the current time + // is after the expiration of the escape sequence, + // then we assume the escape sequence reached it's + // conclusion, and process the chunk independently. + // This lets us detect conflicts such as a lone ESC. + if buf.Len() > 0 { + if time.Now().After(t.keyexpire) { + t.scanInput(buf, true) + } + } + if buf.Len() > 0 { + if !t.keytimer.Stop() { + select { + case <-t.keytimer.C: + default: + } + } + t.keytimer.Reset(time.Millisecond * 50) + } + case chunk := <-t.keychan: + buf.Write(chunk) + t.keyexpire = time.Now().Add(time.Millisecond * 50) + t.scanInput(buf, false) + if !t.keytimer.Stop() { + select { + case <-t.keytimer.C: + default: + } + } + if buf.Len() > 0 { + t.keytimer.Reset(time.Millisecond * 50) + } + } + } +} + +func (t *tScreen) inputLoop() { + + for { + chunk := make([]byte, 128) + n, e := t.in.Read(chunk) + switch e { + case io.EOF: + case nil: + default: + t.PostEvent(NewEventError(e)) + return + } + t.keychan <- chunk[:n] + } +} + +func (t *tScreen) Sync() { + t.Lock() + t.cx = -1 + t.cy = -1 + if !t.fini { + t.resize() + t.clear = true + t.cells.Invalidate() + t.draw() + } + t.Unlock() +} + +func (t *tScreen) CharacterSet() string { + return t.charset +} + +func (t *tScreen) RegisterRuneFallback(orig rune, fallback string) { + t.Lock() + t.fallback[orig] = fallback + t.Unlock() +} + +func (t *tScreen) UnregisterRuneFallback(orig rune) { + t.Lock() + delete(t.fallback, orig) + t.Unlock() +} + +func (t *tScreen) CanDisplay(r rune, checkFallbacks bool) bool { + + if enc := t.encoder; enc != nil { + nb := make([]byte, 6) + ob := make([]byte, 6) + num := utf8.EncodeRune(ob, r) + + enc.Reset() + dst, _, err := enc.Transform(nb, ob[:num], true) + if dst != 0 && err == nil && nb[0] != '\x1A' { + return true + } + } + // Terminal fallbacks always permitted, since we assume they are + // basically nearly perfect renditions. + if _, ok := t.acs[r]; ok { + return true + } + if !checkFallbacks { + return false + } + if _, ok := t.fallback[r]; ok { + return true + } + return false +} + +func (t *tScreen) HasMouse() bool { + return len(t.mouse) != 0 +} + +func (t *tScreen) HasKey(k Key) bool { + if k == KeyRune { + return true + } + return t.keyexist[k] +} + +func (t *tScreen) Resize(int, int, int, int) {} diff --git a/vendor/github.com/gdamore/tcell/tscreen_bsd.go b/vendor/github.com/gdamore/tcell/tscreen_bsd.go new file mode 100644 index 00000000..cce510ec --- /dev/null +++ b/vendor/github.com/gdamore/tcell/tscreen_bsd.go @@ -0,0 +1,119 @@ +// +build darwin freebsd netbsd openbsd dragonfly + +// Copyright 2017 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "os" + "os/signal" + "syscall" + "unsafe" +) + +type termiosPrivate syscall.Termios + +func (t *tScreen) termioInit() error { + var e error + var newtios termiosPrivate + var fd uintptr + var tios uintptr + var ioc uintptr + t.tiosp = &termiosPrivate{} + + if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil { + goto failed + } + if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil { + goto failed + } + + tios = uintptr(unsafe.Pointer(t.tiosp)) + ioc = uintptr(syscall.TIOCGETA) + fd = uintptr(t.out.Fd()) + if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 { + e = e1 + goto failed + } + + // On this platform (FreeBSD and family), the baud rate is stored + // directly as an integer in termios.c_ospeed. No bitmasking required. + t.baud = int(t.tiosp.Ospeed) + newtios = *t.tiosp + newtios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | + syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | + syscall.ICRNL | syscall.IXON + newtios.Oflag &^= syscall.OPOST + newtios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | + syscall.ISIG | syscall.IEXTEN + newtios.Cflag &^= syscall.CSIZE | syscall.PARENB + newtios.Cflag |= syscall.CS8 + + tios = uintptr(unsafe.Pointer(&newtios)) + + ioc = uintptr(syscall.TIOCSETA) + if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 { + e = e1 + goto failed + } + + signal.Notify(t.sigwinch, syscall.SIGWINCH) + + if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 { + t.cells.Resize(w, h) + } + + return nil + +failed: + if t.in != nil { + t.in.Close() + } + if t.out != nil { + t.out.Close() + } + return e +} + +func (t *tScreen) termioFini() { + + signal.Stop(t.sigwinch) + + <-t.indoneq + + if t.out != nil { + fd := uintptr(t.out.Fd()) + ioc := uintptr(syscall.TIOCSETAF) + tios := uintptr(unsafe.Pointer(t.tiosp)) + syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0) + t.out.Close() + } + if t.in != nil { + t.in.Close() + } +} + +func (t *tScreen) getWinSize() (int, int, error) { + + fd := uintptr(t.out.Fd()) + dim := [4]uint16{} + dimp := uintptr(unsafe.Pointer(&dim)) + ioc := uintptr(syscall.TIOCGWINSZ) + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, + fd, ioc, dimp, 0, 0, 0); err != 0 { + return -1, -1, err + } + return int(dim[1]), int(dim[0]), nil +} diff --git a/vendor/github.com/gdamore/tcell/tscreen_linux.go b/vendor/github.com/gdamore/tcell/tscreen_linux.go new file mode 100644 index 00000000..79602f4c --- /dev/null +++ b/vendor/github.com/gdamore/tcell/tscreen_linux.go @@ -0,0 +1,129 @@ +// +build linux + +// Copyright 2017 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "os" + "os/signal" + "syscall" + "unsafe" +) + +type termiosPrivate syscall.Termios + +func (t *tScreen) termioInit() error { + var e error + var newtios termiosPrivate + var fd uintptr + var tios uintptr + var ioc uintptr + t.tiosp = &termiosPrivate{} + + if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil { + goto failed + } + if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil { + goto failed + } + + tios = uintptr(unsafe.Pointer(t.tiosp)) + ioc = uintptr(syscall.TCGETS) + fd = uintptr(t.out.Fd()) + if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 { + e = e1 + goto failed + } + + // On this platform, the baud rate is stored + // directly as an integer in termios.c_ospeed. + t.baud = int(t.tiosp.Ospeed) + newtios = *t.tiosp + newtios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | + syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | + syscall.ICRNL | syscall.IXON + newtios.Oflag &^= syscall.OPOST + newtios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | + syscall.ISIG | syscall.IEXTEN + newtios.Cflag &^= syscall.CSIZE | syscall.PARENB + newtios.Cflag |= syscall.CS8 + + // This is setup for blocking reads. In the past we attempted to + // use non-blocking reads, but now a separate input loop and timer + // copes with the problems we had on some systems (BSD/Darwin) + // where close hung forever. + newtios.Cc[syscall.VMIN] = 1 + newtios.Cc[syscall.VTIME] = 0 + + tios = uintptr(unsafe.Pointer(&newtios)) + + // Well this kind of sucks, because we don't have TCSETSF, but only + // TCSETS. This can leave some output unflushed. + ioc = uintptr(syscall.TCSETS) + if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 { + e = e1 + goto failed + } + + signal.Notify(t.sigwinch, syscall.SIGWINCH) + + if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 { + t.cells.Resize(w, h) + } + + return nil + +failed: + if t.in != nil { + t.in.Close() + } + if t.out != nil { + t.out.Close() + } + return e +} + +func (t *tScreen) termioFini() { + + signal.Stop(t.sigwinch) + + <-t.indoneq + + if t.out != nil { + fd := uintptr(t.out.Fd()) + // XXX: We'd really rather do TCSETSF here! + ioc := uintptr(syscall.TCSETS) + tios := uintptr(unsafe.Pointer(t.tiosp)) + syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0) + t.out.Close() + } + if t.in != nil { + t.in.Close() + } +} + +func (t *tScreen) getWinSize() (int, int, error) { + + fd := uintptr(t.out.Fd()) + dim := [4]uint16{} + dimp := uintptr(unsafe.Pointer(&dim)) + ioc := uintptr(syscall.TIOCGWINSZ) + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, + fd, ioc, dimp, 0, 0, 0); err != 0 { + return -1, -1, err + } + return int(dim[1]), int(dim[0]), nil +} diff --git a/vendor/github.com/gdamore/tcell/tscreen_posix.go b/vendor/github.com/gdamore/tcell/tscreen_posix.go new file mode 100644 index 00000000..66fbe04b --- /dev/null +++ b/vendor/github.com/gdamore/tcell/tscreen_posix.go @@ -0,0 +1,206 @@ +// +build solaris + +// Copyright 2017 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +import ( + "os" + "os/signal" + "syscall" +) + +// #include +// #include +// +// int getwinsize(int fd, int *cols, int *rows) { +// #if defined TIOCGWINSZ +// struct winsize w; +// if (ioctl(fd, TIOCGWINSZ, &w) < 0) { +// return (-1); +// } +// *cols = w.ws_col; +// *rows = w.ws_row; +// return (0); +// #else +// return (-1); +// #endif +// } +// +// int getbaud(struct termios *tios) { +// switch (cfgetospeed(tios)) { +// #ifdef B0 +// case B0: return (0); +// #endif +// #ifdef B50 +// case B50: return (50); +// #endif +// #ifdef B75 +// case B75: return (75); +// #endif +// #ifdef B110 +// case B110: return (110); +// #endif +// #ifdef B134 +// case B134: return (134); +// #endif +// #ifdef B150 +// case B150: return (150); +// #endif +// #ifdef B200 +// case B200: return (200); +// #endif +// #ifdef B300 +// case B300: return (300); +// #endif +// #ifdef B600 +// case B600: return (600); +// #endif +// #ifdef B1200 +// case B1200: return (1200); +// #endif +// #ifdef B1800 +// case B1800: return (1800); +// #endif +// #ifdef B2400 +// case B2400: return (2400); +// #endif +// #ifdef B4800 +// case B4800: return (4800); +// #endif +// #ifdef B9600 +// case B9600: return (9600); +// #endif +// #ifdef B19200 +// case B19200: return (19200); +// #endif +// #ifdef B38400 +// case B38400: return (38400); +// #endif +// #ifdef B57600 +// case B57600: return (57600); +// #endif +// #ifdef B76800 +// case B76800: return (76800); +// #endif +// #ifdef B115200 +// case B115200: return (115200); +// #endif +// #ifdef B153600 +// case B153600: return (153600); +// #endif +// #ifdef B230400 +// case B230400: return (230400); +// #endif +// #ifdef B307200 +// case B307200: return (307200); +// #endif +// #ifdef B460800 +// case B460800: return (460800); +// #endif +// #ifdef B921600 +// case B921600: return (921600); +// #endif +// } +// return (0); +// } +import "C" + +type termiosPrivate struct { + tios C.struct_termios +} + +func (t *tScreen) termioInit() error { + var e error + var rv C.int + var newtios C.struct_termios + var fd C.int + + if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil { + goto failed + } + if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil { + goto failed + } + + t.tiosp = &termiosPrivate{} + + fd = C.int(t.out.Fd()) + if rv, e = C.tcgetattr(fd, &t.tiosp.tios); rv != 0 { + goto failed + } + t.baud = int(C.getbaud(&t.tiosp.tios)) + newtios = t.tiosp.tios + newtios.c_iflag &^= C.IGNBRK | C.BRKINT | C.PARMRK | + C.ISTRIP | C.INLCR | C.IGNCR | + C.ICRNL | C.IXON + newtios.c_oflag &^= C.OPOST + newtios.c_lflag &^= C.ECHO | C.ECHONL | C.ICANON | + C.ISIG | C.IEXTEN + newtios.c_cflag &^= C.CSIZE | C.PARENB + newtios.c_cflag |= C.CS8 + + // This is setup for blocking reads. In the past we attempted to + // use non-blocking reads, but now a separate input loop and timer + // copes with the problems we had on some systems (BSD/Darwin) + // where close hung forever. + newtios.Cc[syscall.VMIN] = 1 + newtios.Cc[syscall.VTIME] = 0 + + if rv, e = C.tcsetattr(fd, C.TCSANOW|C.TCSAFLUSH, &newtios); rv != 0 { + goto failed + } + + signal.Notify(t.sigwinch, syscall.SIGWINCH) + + if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 { + t.cells.Resize(w, h) + } + + return nil + +failed: + if t.in != nil { + t.in.Close() + } + if t.out != nil { + t.out.Close() + } + return e +} + +func (t *tScreen) termioFini() { + + signal.Stop(t.sigwinch) + + <-t.indoneq + + if t.out != nil { + fd := C.int(t.out.Fd()) + C.tcsetattr(fd, C.TCSANOW|C.TCSAFLUSH, &t.tiosp.tios) + t.out.Close() + } + if t.in != nil { + t.in.Close() + } +} + +func (t *tScreen) getWinSize() (int, int, error) { + var cx, cy C.int + if r, e := C.getwinsize(C.int(t.out.Fd()), &cx, &cy); r != 0 { + return 0, 0, e + } + return int(cx), int(cy), nil +} diff --git a/vendor/github.com/gdamore/tcell/tscreen_stub.go b/vendor/github.com/gdamore/tcell/tscreen_stub.go new file mode 100644 index 00000000..91de26e1 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/tscreen_stub.go @@ -0,0 +1,32 @@ +// +build nacl plan9 + +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +// This stub file is for systems that have no termios. + +type termiosPrivate struct{} + +func (t *tScreen) termioInit() error { + return ErrNoScreen +} + +func (t *tScreen) termioFini() { +} + +func (t *tScreen) getWinSize() (int, int, error) { + return 0, 0, ErrNoScreen +} diff --git a/vendor/github.com/gdamore/tcell/tscreen_windows.go b/vendor/github.com/gdamore/tcell/tscreen_windows.go new file mode 100644 index 00000000..daac0976 --- /dev/null +++ b/vendor/github.com/gdamore/tcell/tscreen_windows.go @@ -0,0 +1,40 @@ +// +build windows + +// Copyright 2015 The TCell Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcell + +// On Windows we don't have support for termios. We probably could, and +// may should, in a cygwin type environment. Its not clear how to make +// this all work nicely with both cygwin and Windows console, so we +// decline to do so here. + +func (t *tScreen) termioInit() error { + return ErrNoScreen +} + +func (t *tScreen) termioFini() { + return +} + +func (t *tScreen) getWinSize() (int, int, error) { + return 0, 0, ErrNoScreen +} + +func (t *tScreen) getCharset() string { + return "UTF-16LE" +} + +type termiosPrivate struct{} diff --git a/vendor/github.com/go-test/deep/.gitignore b/vendor/github.com/go-test/deep/.gitignore new file mode 100644 index 00000000..53f12f0f --- /dev/null +++ b/vendor/github.com/go-test/deep/.gitignore @@ -0,0 +1,2 @@ +*.swp +*.out diff --git a/vendor/github.com/go-test/deep/.travis.yml b/vendor/github.com/go-test/deep/.travis.yml new file mode 100644 index 00000000..2279c614 --- /dev/null +++ b/vendor/github.com/go-test/deep/.travis.yml @@ -0,0 +1,13 @@ +language: go + +go: + - 1.7 + - 1.8 + - 1.9 + +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cover + +script: + - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/go-test/deep/CHANGES.md b/vendor/github.com/go-test/deep/CHANGES.md new file mode 100644 index 00000000..4351819d --- /dev/null +++ b/vendor/github.com/go-test/deep/CHANGES.md @@ -0,0 +1,9 @@ +# go-test/deep Changelog + +## v1.0.1 released 2018-01-28 + +* Fixed #12: Arrays are not properly compared (samlitowitz) + +## v1.0.0 releaesd 2017-10-27 + +* First release diff --git a/vendor/github.com/go-test/deep/LICENSE b/vendor/github.com/go-test/deep/LICENSE new file mode 100644 index 00000000..228ef16f --- /dev/null +++ b/vendor/github.com/go-test/deep/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright 2015-2017 Daniel Nichter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-test/deep/README.md b/vendor/github.com/go-test/deep/README.md new file mode 100644 index 00000000..3b78eac7 --- /dev/null +++ b/vendor/github.com/go-test/deep/README.md @@ -0,0 +1,51 @@ +# Deep Variable Equality for Humans + +[![Go Report Card](https://goreportcard.com/badge/github.com/go-test/deep)](https://goreportcard.com/report/github.com/go-test/deep) [![Build Status](https://travis-ci.org/go-test/deep.svg?branch=master)](https://travis-ci.org/go-test/deep) [![Coverage Status](https://coveralls.io/repos/github/go-test/deep/badge.svg?branch=master)](https://coveralls.io/github/go-test/deep?branch=master) [![GoDoc](https://godoc.org/github.com/go-test/deep?status.svg)](https://godoc.org/github.com/go-test/deep) + +This package provides a single function: `deep.Equal`. It's like [reflect.DeepEqual](http://golang.org/pkg/reflect/#DeepEqual) but much friendlier to humans (or any sentient being) for two reason: + +* `deep.Equal` returns a list of differences +* `deep.Equal` does not compare unexported fields (by default) + +`reflect.DeepEqual` is good (like all things Golang!), but it's a game of [Hunt the Wumpus](https://en.wikipedia.org/wiki/Hunt_the_Wumpus). For large maps, slices, and structs, finding the difference is difficult. + +`deep.Equal` doesn't play games with you, it lists the differences: + +```go +package main_test + +import ( + "testing" + "github.com/go-test/deep" +) + +type T struct { + Name string + Numbers []float64 +} + +func TestDeepEqual(t *testing.T) { + // Can you spot the difference? + t1 := T{ + Name: "Isabella", + Numbers: []float64{1.13459, 2.29343, 3.010100010}, + } + t2 := T{ + Name: "Isabella", + Numbers: []float64{1.13459, 2.29843, 3.010100010}, + } + + if diff := deep.Equal(t1, t2); diff != nil { + t.Error(diff) + } +} +``` + + +``` +$ go test +--- FAIL: TestDeepEqual (0.00s) + main_test.go:25: [Numbers.slice[1]: 2.29343 != 2.29843] +``` + +The difference is in `Numbers.slice[1]`: the two values aren't equal using Go `==`. diff --git a/vendor/github.com/go-test/deep/deep.go b/vendor/github.com/go-test/deep/deep.go new file mode 100644 index 00000000..4ea14cb0 --- /dev/null +++ b/vendor/github.com/go-test/deep/deep.go @@ -0,0 +1,352 @@ +// Package deep provides function deep.Equal which is like reflect.DeepEqual but +// returns a list of differences. This is helpful when comparing complex types +// like structures and maps. +package deep + +import ( + "errors" + "fmt" + "log" + "reflect" + "strings" +) + +var ( + // FloatPrecision is the number of decimal places to round float values + // to when comparing. + FloatPrecision = 10 + + // MaxDiff specifies the maximum number of differences to return. + MaxDiff = 10 + + // MaxDepth specifies the maximum levels of a struct to recurse into. + MaxDepth = 10 + + // LogErrors causes errors to be logged to STDERR when true. + LogErrors = false + + // CompareUnexportedFields causes unexported struct fields, like s in + // T{s int}, to be comparsed when true. + CompareUnexportedFields = false +) + +var ( + // ErrMaxRecursion is logged when MaxDepth is reached. + ErrMaxRecursion = errors.New("recursed to MaxDepth") + + // ErrTypeMismatch is logged when Equal passed two different types of values. + ErrTypeMismatch = errors.New("variables are different reflect.Type") + + // ErrNotHandled is logged when a primitive Go kind is not handled. + ErrNotHandled = errors.New("cannot compare the reflect.Kind") +) + +type cmp struct { + diff []string + buff []string + floatFormat string +} + +var errorType = reflect.TypeOf((*error)(nil)).Elem() + +// Equal compares variables a and b, recursing into their structure up to +// MaxDepth levels deep, and returns a list of differences, or nil if there are +// none. Some differences may not be found if an error is also returned. +// +// If a type has an Equal method, like time.Equal, it is called to check for +// equality. +func Equal(a, b interface{}) []string { + aVal := reflect.ValueOf(a) + bVal := reflect.ValueOf(b) + c := &cmp{ + diff: []string{}, + buff: []string{}, + floatFormat: fmt.Sprintf("%%.%df", FloatPrecision), + } + if a == nil && b == nil { + return nil + } else if a == nil && b != nil { + c.saveDiff(b, "") + } else if a != nil && b == nil { + c.saveDiff(a, "") + } + if len(c.diff) > 0 { + return c.diff + } + + c.equals(aVal, bVal, 0) + if len(c.diff) > 0 { + return c.diff // diffs + } + return nil // no diffs +} + +func (c *cmp) equals(a, b reflect.Value, level int) { + if level > MaxDepth { + logError(ErrMaxRecursion) + return + } + + // Check if one value is nil, e.g. T{x: *X} and T.x is nil + if !a.IsValid() || !b.IsValid() { + if a.IsValid() && !b.IsValid() { + c.saveDiff(a.Type(), "") + } else if !a.IsValid() && b.IsValid() { + c.saveDiff("", b.Type()) + } + return + } + + // If differenet types, they can't be equal + aType := a.Type() + bType := b.Type() + if aType != bType { + c.saveDiff(aType, bType) + logError(ErrTypeMismatch) + return + } + + // Primitive https://golang.org/pkg/reflect/#Kind + aKind := a.Kind() + bKind := b.Kind() + + // If both types implement the error interface, compare the error strings. + // This must be done before dereferencing because the interface is on a + // pointer receiver. + if aType.Implements(errorType) && bType.Implements(errorType) { + if a.Elem().IsValid() && b.Elem().IsValid() { // both err != nil + aString := a.MethodByName("Error").Call(nil)[0].String() + bString := b.MethodByName("Error").Call(nil)[0].String() + if aString != bString { + c.saveDiff(aString, bString) + } + return + } + } + + // Dereference pointers and interface{} + if aElem, bElem := (aKind == reflect.Ptr || aKind == reflect.Interface), + (bKind == reflect.Ptr || bKind == reflect.Interface); aElem || bElem { + + if aElem { + a = a.Elem() + } + + if bElem { + b = b.Elem() + } + + c.equals(a, b, level+1) + return + } + + // Types with an Equal(), like time.Time. + eqFunc := a.MethodByName("Equal") + if eqFunc.IsValid() { + retVals := eqFunc.Call([]reflect.Value{b}) + if !retVals[0].Bool() { + c.saveDiff(a, b) + } + return + } + + switch aKind { + + ///////////////////////////////////////////////////////////////////// + // Iterable kinds + ///////////////////////////////////////////////////////////////////// + + case reflect.Struct: + /* + The variables are structs like: + type T struct { + FirstName string + LastName string + } + Type = .T, Kind = reflect.Struct + + Iterate through the fields (FirstName, LastName), recurse into their values. + */ + for i := 0; i < a.NumField(); i++ { + if aType.Field(i).PkgPath != "" && !CompareUnexportedFields { + continue // skip unexported field, e.g. s in type T struct {s string} + } + + c.push(aType.Field(i).Name) // push field name to buff + + // Get the Value for each field, e.g. FirstName has Type = string, + // Kind = reflect.String. + af := a.Field(i) + bf := b.Field(i) + + // Recurse to compare the field values + c.equals(af, bf, level+1) + + c.pop() // pop field name from buff + + if len(c.diff) >= MaxDiff { + break + } + } + case reflect.Map: + /* + The variables are maps like: + map[string]int{ + "foo": 1, + "bar": 2, + } + Type = map[string]int, Kind = reflect.Map + + Or: + type T map[string]int{} + Type = .T, Kind = reflect.Map + + Iterate through the map keys (foo, bar), recurse into their values. + */ + + if a.IsNil() || b.IsNil() { + if a.IsNil() && !b.IsNil() { + c.saveDiff("", b) + } else if !a.IsNil() && b.IsNil() { + c.saveDiff(a, "") + } + return + } + + if a.Pointer() == b.Pointer() { + return + } + + for _, key := range a.MapKeys() { + c.push(fmt.Sprintf("map[%s]", key)) + + aVal := a.MapIndex(key) + bVal := b.MapIndex(key) + if bVal.IsValid() { + c.equals(aVal, bVal, level+1) + } else { + c.saveDiff(aVal, "") + } + + c.pop() + + if len(c.diff) >= MaxDiff { + return + } + } + + for _, key := range b.MapKeys() { + if aVal := a.MapIndex(key); aVal.IsValid() { + continue + } + + c.push(fmt.Sprintf("map[%s]", key)) + c.saveDiff("", b.MapIndex(key)) + c.pop() + if len(c.diff) >= MaxDiff { + return + } + } + case reflect.Array: + n := a.Len() + for i := 0; i < n; i++ { + c.push(fmt.Sprintf("array[%d]", i)) + c.equals(a.Index(i), b.Index(i), level+1) + c.pop() + if len(c.diff) >= MaxDiff { + break + } + } + case reflect.Slice: + if a.IsNil() || b.IsNil() { + if a.IsNil() && !b.IsNil() { + c.saveDiff("", b) + } else if !a.IsNil() && b.IsNil() { + c.saveDiff(a, "") + } + return + } + + if a.Pointer() == b.Pointer() { + return + } + + aLen := a.Len() + bLen := b.Len() + n := aLen + if bLen > aLen { + n = bLen + } + for i := 0; i < n; i++ { + c.push(fmt.Sprintf("slice[%d]", i)) + if i < aLen && i < bLen { + c.equals(a.Index(i), b.Index(i), level+1) + } else if i < aLen { + c.saveDiff(a.Index(i), "") + } else { + c.saveDiff("", b.Index(i)) + } + c.pop() + if len(c.diff) >= MaxDiff { + break + } + } + + ///////////////////////////////////////////////////////////////////// + // Primitive kinds + ///////////////////////////////////////////////////////////////////// + + case reflect.Float32, reflect.Float64: + // Avoid 0.04147685731961082 != 0.041476857319611 + // 6 decimal places is close enough + aval := fmt.Sprintf(c.floatFormat, a.Float()) + bval := fmt.Sprintf(c.floatFormat, b.Float()) + if aval != bval { + c.saveDiff(a.Float(), b.Float()) + } + case reflect.Bool: + if a.Bool() != b.Bool() { + c.saveDiff(a.Bool(), b.Bool()) + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if a.Int() != b.Int() { + c.saveDiff(a.Int(), b.Int()) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if a.Uint() != b.Uint() { + c.saveDiff(a.Uint(), b.Uint()) + } + case reflect.String: + if a.String() != b.String() { + c.saveDiff(a.String(), b.String()) + } + + default: + logError(ErrNotHandled) + } +} + +func (c *cmp) push(name string) { + c.buff = append(c.buff, name) +} + +func (c *cmp) pop() { + if len(c.buff) > 0 { + c.buff = c.buff[0 : len(c.buff)-1] + } +} + +func (c *cmp) saveDiff(aval, bval interface{}) { + if len(c.buff) > 0 { + varName := strings.Join(c.buff, ".") + c.diff = append(c.diff, fmt.Sprintf("%s: %v != %v", varName, aval, bval)) + } else { + c.diff = append(c.diff, fmt.Sprintf("%v != %v", aval, bval)) + } +} + +func logError(err error) { + if LogErrors { + log.Println(err) + } +} diff --git a/vendor/github.com/golang/protobuf/AUTHORS b/vendor/github.com/golang/protobuf/AUTHORS new file mode 100644 index 00000000..15167cd7 --- /dev/null +++ b/vendor/github.com/golang/protobuf/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/github.com/golang/protobuf/CONTRIBUTORS b/vendor/github.com/golang/protobuf/CONTRIBUTORS new file mode 100644 index 00000000..1c4577e9 --- /dev/null +++ b/vendor/github.com/golang/protobuf/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/github.com/golang/protobuf/LICENSE b/vendor/github.com/golang/protobuf/LICENSE new file mode 100644 index 00000000..1b1b1921 --- /dev/null +++ b/vendor/github.com/golang/protobuf/LICENSE @@ -0,0 +1,31 @@ +Go support for Protocol Buffers - Google's data interchange format + +Copyright 2010 The Go Authors. All rights reserved. +https://github.com/golang/protobuf + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/github.com/golang/protobuf/proto/clone.go b/vendor/github.com/golang/protobuf/proto/clone.go new file mode 100644 index 00000000..3cd3249f --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/clone.go @@ -0,0 +1,253 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Protocol buffer deep copy and merge. +// TODO: RawMessage. + +package proto + +import ( + "fmt" + "log" + "reflect" + "strings" +) + +// Clone returns a deep copy of a protocol buffer. +func Clone(src Message) Message { + in := reflect.ValueOf(src) + if in.IsNil() { + return src + } + out := reflect.New(in.Type().Elem()) + dst := out.Interface().(Message) + Merge(dst, src) + return dst +} + +// Merger is the interface representing objects that can merge messages of the same type. +type Merger interface { + // Merge merges src into this message. + // Required and optional fields that are set in src will be set to that value in dst. + // Elements of repeated fields will be appended. + // + // Merge may panic if called with a different argument type than the receiver. + Merge(src Message) +} + +// generatedMerger is the custom merge method that generated protos will have. +// We must add this method since a generate Merge method will conflict with +// many existing protos that have a Merge data field already defined. +type generatedMerger interface { + XXX_Merge(src Message) +} + +// Merge merges src into dst. +// Required and optional fields that are set in src will be set to that value in dst. +// Elements of repeated fields will be appended. +// Merge panics if src and dst are not the same type, or if dst is nil. +func Merge(dst, src Message) { + if m, ok := dst.(Merger); ok { + m.Merge(src) + return + } + + in := reflect.ValueOf(src) + out := reflect.ValueOf(dst) + if out.IsNil() { + panic("proto: nil destination") + } + if in.Type() != out.Type() { + panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src)) + } + if in.IsNil() { + return // Merge from nil src is a noop + } + if m, ok := dst.(generatedMerger); ok { + m.XXX_Merge(src) + return + } + mergeStruct(out.Elem(), in.Elem()) +} + +func mergeStruct(out, in reflect.Value) { + sprop := GetProperties(in.Type()) + for i := 0; i < in.NumField(); i++ { + f := in.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) + } + + if emIn, err := extendable(in.Addr().Interface()); err == nil { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } + } + + uf := in.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return + } + uin := uf.Bytes() + if len(uin) > 0 { + out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...)) + } +} + +// mergeAny performs a merge between two values of the same type. +// viaPtr indicates whether the values were indirected through a pointer (implying proto2). +// prop is set if this is a struct field (it may be nil). +func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) { + if in.Type() == protoMessageType { + if !in.IsNil() { + if out.IsNil() { + out.Set(reflect.ValueOf(Clone(in.Interface().(Message)))) + } else { + Merge(out.Interface().(Message), in.Interface().(Message)) + } + } + return + } + switch in.Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + if !viaPtr && isProto3Zero(in) { + return + } + out.Set(in) + case reflect.Interface: + // Probably a oneof field; copy non-nil values. + if in.IsNil() { + return + } + // Allocate destination if it is not set, or set to a different type. + // Otherwise we will merge as normal. + if out.IsNil() || out.Elem().Type() != in.Elem().Type() { + out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T) + } + mergeAny(out.Elem(), in.Elem(), false, nil) + case reflect.Map: + if in.Len() == 0 { + return + } + if out.IsNil() { + out.Set(reflect.MakeMap(in.Type())) + } + // For maps with value types of *T or []byte we need to deep copy each value. + elemKind := in.Type().Elem().Kind() + for _, key := range in.MapKeys() { + var val reflect.Value + switch elemKind { + case reflect.Ptr: + val = reflect.New(in.Type().Elem().Elem()) + mergeAny(val, in.MapIndex(key), false, nil) + case reflect.Slice: + val = in.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + default: + val = in.MapIndex(key) + } + out.SetMapIndex(key, val) + } + case reflect.Ptr: + if in.IsNil() { + return + } + if out.IsNil() { + out.Set(reflect.New(in.Elem().Type())) + } + mergeAny(out.Elem(), in.Elem(), true, nil) + case reflect.Slice: + if in.IsNil() { + return + } + if in.Type().Elem().Kind() == reflect.Uint8 { + // []byte is a scalar bytes field, not a repeated field. + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value, and should not + // be merged. + if prop != nil && prop.proto3 && in.Len() == 0 { + return + } + + // Make a deep copy. + // Append to []byte{} instead of []byte(nil) so that we never end up + // with a nil result. + out.SetBytes(append([]byte{}, in.Bytes()...)) + return + } + n := in.Len() + if out.IsNil() { + out.Set(reflect.MakeSlice(in.Type(), 0, n)) + } + switch in.Type().Elem().Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + out.Set(reflect.AppendSlice(out, in)) + default: + for i := 0; i < n; i++ { + x := reflect.Indirect(reflect.New(in.Type().Elem())) + mergeAny(x, in.Index(i), false, nil) + out.Set(reflect.Append(out, x)) + } + } + case reflect.Struct: + mergeStruct(out, in) + default: + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to copy %v", in) + } +} + +func mergeExtension(out, in map[int32]Extension) { + for extNum, eIn := range in { + eOut := Extension{desc: eIn.desc} + if eIn.value != nil { + v := reflect.New(reflect.TypeOf(eIn.value)).Elem() + mergeAny(v, reflect.ValueOf(eIn.value), false, nil) + eOut.value = v.Interface() + } + if eIn.enc != nil { + eOut.enc = make([]byte, len(eIn.enc)) + copy(eOut.enc, eIn.enc) + } + + out[extNum] = eOut + } +} diff --git a/vendor/github.com/golang/protobuf/proto/decode.go b/vendor/github.com/golang/protobuf/proto/decode.go new file mode 100644 index 00000000..d9aa3c42 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/decode.go @@ -0,0 +1,428 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for decoding protocol buffer data to construct in-memory representations. + */ + +import ( + "errors" + "fmt" + "io" +) + +// errOverflow is returned when an integer is too large to be represented. +var errOverflow = errors.New("proto: integer overflow") + +// ErrInternalBadWireType is returned by generated code when an incorrect +// wire type is encountered. It does not get returned to user code. +var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") + +// DecodeVarint reads a varint-encoded integer from the slice. +// It returns the integer and the number of bytes consumed, or +// zero if there is not enough. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func DecodeVarint(buf []byte) (x uint64, n int) { + for shift := uint(0); shift < 64; shift += 7 { + if n >= len(buf) { + return 0, 0 + } + b := uint64(buf[n]) + n++ + x |= (b & 0x7F) << shift + if (b & 0x80) == 0 { + return x, n + } + } + + // The number is too large to represent in a 64-bit value. + return 0, 0 +} + +func (p *Buffer) decodeVarintSlow() (x uint64, err error) { + i := p.index + l := len(p.buf) + + for shift := uint(0); shift < 64; shift += 7 { + if i >= l { + err = io.ErrUnexpectedEOF + return + } + b := p.buf[i] + i++ + x |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + p.index = i + return + } + } + + // The number is too large to represent in a 64-bit value. + err = errOverflow + return +} + +// DecodeVarint reads a varint-encoded integer from the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) DecodeVarint() (x uint64, err error) { + i := p.index + buf := p.buf + + if i >= len(buf) { + return 0, io.ErrUnexpectedEOF + } else if buf[i] < 0x80 { + p.index++ + return uint64(buf[i]), nil + } else if len(buf)-i < 10 { + return p.decodeVarintSlow() + } + + var b uint64 + // we already checked the first byte + x = uint64(buf[i]) - 0x80 + i++ + + b = uint64(buf[i]) + i++ + x += b << 7 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 7 + + b = uint64(buf[i]) + i++ + x += b << 14 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 14 + + b = uint64(buf[i]) + i++ + x += b << 21 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 21 + + b = uint64(buf[i]) + i++ + x += b << 28 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 28 + + b = uint64(buf[i]) + i++ + x += b << 35 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 35 + + b = uint64(buf[i]) + i++ + x += b << 42 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 42 + + b = uint64(buf[i]) + i++ + x += b << 49 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 49 + + b = uint64(buf[i]) + i++ + x += b << 56 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 56 + + b = uint64(buf[i]) + i++ + x += b << 63 + if b&0x80 == 0 { + goto done + } + // x -= 0x80 << 63 // Always zero. + + return 0, errOverflow + +done: + p.index = i + return x, nil +} + +// DecodeFixed64 reads a 64-bit integer from the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) DecodeFixed64() (x uint64, err error) { + // x, err already 0 + i := p.index + 8 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-8]) + x |= uint64(p.buf[i-7]) << 8 + x |= uint64(p.buf[i-6]) << 16 + x |= uint64(p.buf[i-5]) << 24 + x |= uint64(p.buf[i-4]) << 32 + x |= uint64(p.buf[i-3]) << 40 + x |= uint64(p.buf[i-2]) << 48 + x |= uint64(p.buf[i-1]) << 56 + return +} + +// DecodeFixed32 reads a 32-bit integer from the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) DecodeFixed32() (x uint64, err error) { + // x, err already 0 + i := p.index + 4 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-4]) + x |= uint64(p.buf[i-3]) << 8 + x |= uint64(p.buf[i-2]) << 16 + x |= uint64(p.buf[i-1]) << 24 + return +} + +// DecodeZigzag64 reads a zigzag-encoded 64-bit integer +// from the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) DecodeZigzag64() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63) + return +} + +// DecodeZigzag32 reads a zigzag-encoded 32-bit integer +// from the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) DecodeZigzag32() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31)) + return +} + +// DecodeRawBytes reads a count-delimited byte buffer from the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) { + n, err := p.DecodeVarint() + if err != nil { + return nil, err + } + + nb := int(n) + if nb < 0 { + return nil, fmt.Errorf("proto: bad byte length %d", nb) + } + end := p.index + nb + if end < p.index || end > len(p.buf) { + return nil, io.ErrUnexpectedEOF + } + + if !alloc { + // todo: check if can get more uses of alloc=false + buf = p.buf[p.index:end] + p.index += nb + return + } + + buf = make([]byte, nb) + copy(buf, p.buf[p.index:]) + p.index += nb + return +} + +// DecodeStringBytes reads an encoded string from the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) DecodeStringBytes() (s string, err error) { + buf, err := p.DecodeRawBytes(false) + if err != nil { + return + } + return string(buf), nil +} + +// Unmarshaler is the interface representing objects that can +// unmarshal themselves. The argument points to data that may be +// overwritten, so implementations should not keep references to the +// buffer. +// Unmarshal implementations should not clear the receiver. +// Any unmarshaled data should be merged into the receiver. +// Callers of Unmarshal that do not want to retain existing data +// should Reset the receiver before calling Unmarshal. +type Unmarshaler interface { + Unmarshal([]byte) error +} + +// newUnmarshaler is the interface representing objects that can +// unmarshal themselves. The semantics are identical to Unmarshaler. +// +// This exists to support protoc-gen-go generated messages. +// The proto package will stop type-asserting to this interface in the future. +// +// DO NOT DEPEND ON THIS. +type newUnmarshaler interface { + XXX_Unmarshal([]byte) error +} + +// Unmarshal parses the protocol buffer representation in buf and places the +// decoded result in pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// Unmarshal resets pb before starting to unmarshal, so any +// existing data in pb is always removed. Use UnmarshalMerge +// to preserve and append to existing data. +func Unmarshal(buf []byte, pb Message) error { + pb.Reset() + if u, ok := pb.(newUnmarshaler); ok { + return u.XXX_Unmarshal(buf) + } + if u, ok := pb.(Unmarshaler); ok { + return u.Unmarshal(buf) + } + return NewBuffer(buf).Unmarshal(pb) +} + +// UnmarshalMerge parses the protocol buffer representation in buf and +// writes the decoded result to pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// UnmarshalMerge merges into existing data in pb. +// Most code should use Unmarshal instead. +func UnmarshalMerge(buf []byte, pb Message) error { + if u, ok := pb.(newUnmarshaler); ok { + return u.XXX_Unmarshal(buf) + } + if u, ok := pb.(Unmarshaler); ok { + // NOTE: The history of proto have unfortunately been inconsistent + // whether Unmarshaler should or should not implicitly clear itself. + // Some implementations do, most do not. + // Thus, calling this here may or may not do what people want. + // + // See https://github.com/golang/protobuf/issues/424 + return u.Unmarshal(buf) + } + return NewBuffer(buf).Unmarshal(pb) +} + +// DecodeMessage reads a count-delimited message from the Buffer. +func (p *Buffer) DecodeMessage(pb Message) error { + enc, err := p.DecodeRawBytes(false) + if err != nil { + return err + } + return NewBuffer(enc).Unmarshal(pb) +} + +// DecodeGroup reads a tag-delimited group from the Buffer. +// StartGroup tag is already consumed. This function consumes +// EndGroup tag. +func (p *Buffer) DecodeGroup(pb Message) error { + b := p.buf[p.index:] + x, y := findEndGroup(b) + if x < 0 { + return io.ErrUnexpectedEOF + } + err := Unmarshal(b[:x], pb) + p.index += y + return err +} + +// Unmarshal parses the protocol buffer representation in the +// Buffer and places the decoded result in pb. If the struct +// underlying pb does not match the data in the buffer, the results can be +// unpredictable. +// +// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal. +func (p *Buffer) Unmarshal(pb Message) error { + // If the object can unmarshal itself, let it. + if u, ok := pb.(newUnmarshaler); ok { + err := u.XXX_Unmarshal(p.buf[p.index:]) + p.index = len(p.buf) + return err + } + if u, ok := pb.(Unmarshaler); ok { + // NOTE: The history of proto have unfortunately been inconsistent + // whether Unmarshaler should or should not implicitly clear itself. + // Some implementations do, most do not. + // Thus, calling this here may or may not do what people want. + // + // See https://github.com/golang/protobuf/issues/424 + err := u.Unmarshal(p.buf[p.index:]) + p.index = len(p.buf) + return err + } + + // Slow workaround for messages that aren't Unmarshalers. + // This includes some hand-coded .pb.go files and + // bootstrap protos. + // TODO: fix all of those and then add Unmarshal to + // the Message interface. Then: + // The cast above and code below can be deleted. + // The old unmarshaler can be deleted. + // Clients can call Unmarshal directly (can already do that, actually). + var info InternalMessageInfo + err := info.Unmarshal(pb, p.buf[p.index:]) + p.index = len(p.buf) + return err +} diff --git a/vendor/github.com/golang/protobuf/proto/discard.go b/vendor/github.com/golang/protobuf/proto/discard.go new file mode 100644 index 00000000..dea2617c --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/discard.go @@ -0,0 +1,350 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2017 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "fmt" + "reflect" + "strings" + "sync" + "sync/atomic" +) + +type generatedDiscarder interface { + XXX_DiscardUnknown() +} + +// DiscardUnknown recursively discards all unknown fields from this message +// and all embedded messages. +// +// When unmarshaling a message with unrecognized fields, the tags and values +// of such fields are preserved in the Message. This allows a later call to +// marshal to be able to produce a message that continues to have those +// unrecognized fields. To avoid this, DiscardUnknown is used to +// explicitly clear the unknown fields after unmarshaling. +// +// For proto2 messages, the unknown fields of message extensions are only +// discarded from messages that have been accessed via GetExtension. +func DiscardUnknown(m Message) { + if m, ok := m.(generatedDiscarder); ok { + m.XXX_DiscardUnknown() + return + } + // TODO: Dynamically populate a InternalMessageInfo for legacy messages, + // but the master branch has no implementation for InternalMessageInfo, + // so it would be more work to replicate that approach. + discardLegacy(m) +} + +// DiscardUnknown recursively discards all unknown fields. +func (a *InternalMessageInfo) DiscardUnknown(m Message) { + di := atomicLoadDiscardInfo(&a.discard) + if di == nil { + di = getDiscardInfo(reflect.TypeOf(m).Elem()) + atomicStoreDiscardInfo(&a.discard, di) + } + di.discard(toPointer(&m)) +} + +type discardInfo struct { + typ reflect.Type + + initialized int32 // 0: only typ is valid, 1: everything is valid + lock sync.Mutex + + fields []discardFieldInfo + unrecognized field +} + +type discardFieldInfo struct { + field field // Offset of field, guaranteed to be valid + discard func(src pointer) +} + +var ( + discardInfoMap = map[reflect.Type]*discardInfo{} + discardInfoLock sync.Mutex +) + +func getDiscardInfo(t reflect.Type) *discardInfo { + discardInfoLock.Lock() + defer discardInfoLock.Unlock() + di := discardInfoMap[t] + if di == nil { + di = &discardInfo{typ: t} + discardInfoMap[t] = di + } + return di +} + +func (di *discardInfo) discard(src pointer) { + if src.isNil() { + return // Nothing to do. + } + + if atomic.LoadInt32(&di.initialized) == 0 { + di.computeDiscardInfo() + } + + for _, fi := range di.fields { + sfp := src.offset(fi.field) + fi.discard(sfp) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil { + // Ignore lock since DiscardUnknown is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + DiscardUnknown(m) + } + } + } + + if di.unrecognized.IsValid() { + *src.offset(di.unrecognized).toBytes() = nil + } +} + +func (di *discardInfo) computeDiscardInfo() { + di.lock.Lock() + defer di.lock.Unlock() + if di.initialized != 0 { + return + } + t := di.typ + n := t.NumField() + + for i := 0; i < n; i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + + dfi := discardFieldInfo{field: toField(&f)} + tf := f.Type + + // Unwrap tf to get its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name)) + case isSlice: // E.g., []*pb.T + di := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sps := src.getPointerSlice() + for _, sp := range sps { + if !sp.isNil() { + di.discard(sp) + } + } + } + default: // E.g., *pb.T + di := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sp := src.getPointer() + if !sp.isNil() { + di.discard(sp) + } + } + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name)) + default: // E.g., map[K]V + if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T) + dfi.discard = func(src pointer) { + sm := src.asPointerTo(tf).Elem() + if sm.Len() == 0 { + return + } + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + DiscardUnknown(val.Interface().(Message)) + } + } + } else { + dfi.discard = func(pointer) {} // Noop + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name)) + default: // E.g., interface{} + // TODO: Make this faster? + dfi.discard = func(src pointer) { + su := src.asPointerTo(tf).Elem() + if !su.IsNil() { + sv := su.Elem().Elem().Field(0) + if sv.Kind() == reflect.Ptr && sv.IsNil() { + return + } + switch sv.Type().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + DiscardUnknown(sv.Interface().(Message)) + } + } + } + } + default: + continue + } + di.fields = append(di.fields, dfi) + } + + di.unrecognized = invalidField + if f, ok := t.FieldByName("XXX_unrecognized"); ok { + if f.Type != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + di.unrecognized = toField(&f) + } + + atomic.StoreInt32(&di.initialized, 1) +} + +func discardLegacy(m Message) { + v := reflect.ValueOf(m) + if v.Kind() != reflect.Ptr || v.IsNil() { + return + } + v = v.Elem() + if v.Kind() != reflect.Struct { + return + } + t := v.Type() + + for i := 0; i < v.NumField(); i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + vf := v.Field(i) + tf := f.Type + + // Unwrap tf to get its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name)) + case isSlice: // E.g., []*pb.T + for j := 0; j < vf.Len(); j++ { + discardLegacy(vf.Index(j).Interface().(Message)) + } + default: // E.g., *pb.T + discardLegacy(vf.Interface().(Message)) + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name)) + default: // E.g., map[K]V + tv := vf.Type().Elem() + if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T) + for _, key := range vf.MapKeys() { + val := vf.MapIndex(key) + discardLegacy(val.Interface().(Message)) + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name)) + default: // E.g., test_proto.isCommunique_Union interface + if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" { + vf = vf.Elem() // E.g., *test_proto.Communique_Msg + if !vf.IsNil() { + vf = vf.Elem() // E.g., test_proto.Communique_Msg + vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value + if vf.Kind() == reflect.Ptr { + discardLegacy(vf.Interface().(Message)) + } + } + } + } + } + } + + if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() { + if vf.Type() != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + vf.Set(reflect.ValueOf([]byte(nil))) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, err := extendable(m); err == nil { + // Ignore lock since discardLegacy is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + discardLegacy(m) + } + } + } +} diff --git a/vendor/github.com/golang/protobuf/proto/encode.go b/vendor/github.com/golang/protobuf/proto/encode.go new file mode 100644 index 00000000..c27d35f8 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/encode.go @@ -0,0 +1,221 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "errors" + "fmt" + "reflect" +) + +// RequiredNotSetError is the error returned if Marshal is called with +// a protocol buffer struct whose required fields have not +// all been initialized. It is also the error returned if Unmarshal is +// called with an encoded protocol buffer that does not include all the +// required fields. +// +// When printed, RequiredNotSetError reports the first unset required field in a +// message. If the field cannot be precisely determined, it is reported as +// "{Unknown}". +type RequiredNotSetError struct { + field string +} + +func (e *RequiredNotSetError) Error() string { + return fmt.Sprintf("proto: required field %q not set", e.field) +} + +var ( + // errRepeatedHasNil is the error returned if Marshal is called with + // a struct with a repeated field containing a nil element. + errRepeatedHasNil = errors.New("proto: repeated field has nil element") + + // errOneofHasNil is the error returned if Marshal is called with + // a struct with a oneof field containing a nil element. + errOneofHasNil = errors.New("proto: oneof field has nil value") + + // ErrNil is the error returned if Marshal is called with nil. + ErrNil = errors.New("proto: Marshal called with nil") + + // ErrTooLarge is the error returned if Marshal is called with a + // message that encodes to >2GB. + ErrTooLarge = errors.New("proto: message encodes to over 2 GB") +) + +// The fundamental encoders that put bytes on the wire. +// Those that take integer types all accept uint64 and are +// therefore of type valueEncoder. + +const maxVarintBytes = 10 // maximum length of a varint + +// EncodeVarint returns the varint encoding of x. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +// Not used by the package itself, but helpful to clients +// wishing to use the same encoding. +func EncodeVarint(x uint64) []byte { + var buf [maxVarintBytes]byte + var n int + for n = 0; x > 127; n++ { + buf[n] = 0x80 | uint8(x&0x7F) + x >>= 7 + } + buf[n] = uint8(x) + n++ + return buf[0:n] +} + +// EncodeVarint writes a varint-encoded integer to the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) EncodeVarint(x uint64) error { + for x >= 1<<7 { + p.buf = append(p.buf, uint8(x&0x7f|0x80)) + x >>= 7 + } + p.buf = append(p.buf, uint8(x)) + return nil +} + +// SizeVarint returns the varint encoding size of an integer. +func SizeVarint(x uint64) int { + switch { + case x < 1<<7: + return 1 + case x < 1<<14: + return 2 + case x < 1<<21: + return 3 + case x < 1<<28: + return 4 + case x < 1<<35: + return 5 + case x < 1<<42: + return 6 + case x < 1<<49: + return 7 + case x < 1<<56: + return 8 + case x < 1<<63: + return 9 + } + return 10 +} + +// EncodeFixed64 writes a 64-bit integer to the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) EncodeFixed64(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24), + uint8(x>>32), + uint8(x>>40), + uint8(x>>48), + uint8(x>>56)) + return nil +} + +// EncodeFixed32 writes a 32-bit integer to the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) EncodeFixed32(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24)) + return nil +} + +// EncodeZigzag64 writes a zigzag-encoded 64-bit integer +// to the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) EncodeZigzag64(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} + +// EncodeZigzag32 writes a zigzag-encoded 32-bit integer +// to the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) EncodeZigzag32(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) +} + +// EncodeRawBytes writes a count-delimited byte buffer to the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) EncodeRawBytes(b []byte) error { + p.EncodeVarint(uint64(len(b))) + p.buf = append(p.buf, b...) + return nil +} + +// EncodeStringBytes writes an encoded string to the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) EncodeStringBytes(s string) error { + p.EncodeVarint(uint64(len(s))) + p.buf = append(p.buf, s...) + return nil +} + +// Marshaler is the interface representing objects that can marshal themselves. +type Marshaler interface { + Marshal() ([]byte, error) +} + +// EncodeMessage writes the protocol buffer to the Buffer, +// prefixed by a varint-encoded length. +func (p *Buffer) EncodeMessage(pb Message) error { + siz := Size(pb) + p.EncodeVarint(uint64(siz)) + return p.Marshal(pb) +} + +// All protocol buffer fields are nillable, but be careful. +func isNil(v reflect.Value) bool { + switch v.Kind() { + case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return v.IsNil() + } + return false +} diff --git a/vendor/github.com/golang/protobuf/proto/equal.go b/vendor/github.com/golang/protobuf/proto/equal.go new file mode 100644 index 00000000..d4db5a1c --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/equal.go @@ -0,0 +1,300 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Protocol buffer comparison. + +package proto + +import ( + "bytes" + "log" + "reflect" + "strings" +) + +/* +Equal returns true iff protocol buffers a and b are equal. +The arguments must both be pointers to protocol buffer structs. + +Equality is defined in this way: + - Two messages are equal iff they are the same type, + corresponding fields are equal, unknown field sets + are equal, and extensions sets are equal. + - Two set scalar fields are equal iff their values are equal. + If the fields are of a floating-point type, remember that + NaN != x for all x, including NaN. If the message is defined + in a proto3 .proto file, fields are not "set"; specifically, + zero length proto3 "bytes" fields are equal (nil == {}). + - Two repeated fields are equal iff their lengths are the same, + and their corresponding elements are equal. Note a "bytes" field, + although represented by []byte, is not a repeated field and the + rule for the scalar fields described above applies. + - Two unset fields are equal. + - Two unknown field sets are equal if their current + encoded state is equal. + - Two extension sets are equal iff they have corresponding + elements that are pairwise equal. + - Two map fields are equal iff their lengths are the same, + and they contain the same set of elements. Zero-length map + fields are equal. + - Every other combination of things are not equal. + +The return value is undefined if a and b are not protocol buffers. +*/ +func Equal(a, b Message) bool { + if a == nil || b == nil { + return a == b + } + v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b) + if v1.Type() != v2.Type() { + return false + } + if v1.Kind() == reflect.Ptr { + if v1.IsNil() { + return v2.IsNil() + } + if v2.IsNil() { + return false + } + v1, v2 = v1.Elem(), v2.Elem() + } + if v1.Kind() != reflect.Struct { + return false + } + return equalStruct(v1, v2) +} + +// v1 and v2 are known to have the same type. +func equalStruct(v1, v2 reflect.Value) bool { + sprop := GetProperties(v1.Type()) + for i := 0; i < v1.NumField(); i++ { + f := v1.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + f1, f2 := v1.Field(i), v2.Field(i) + if f.Type.Kind() == reflect.Ptr { + if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 { + // both unset + continue + } else if n1 != n2 { + // set/unset mismatch + return false + } + f1, f2 = f1.Elem(), f2.Elem() + } + if !equalAny(f1, f2, sprop.Prop[i]) { + return false + } + } + + if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_InternalExtensions") + if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) { + return false + } + } + + if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_extensions") + if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { + return false + } + } + + uf := v1.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return true + } + + u1 := uf.Bytes() + u2 := v2.FieldByName("XXX_unrecognized").Bytes() + return bytes.Equal(u1, u2) +} + +// v1 and v2 are known to have the same type. +// prop may be nil. +func equalAny(v1, v2 reflect.Value, prop *Properties) bool { + if v1.Type() == protoMessageType { + m1, _ := v1.Interface().(Message) + m2, _ := v2.Interface().(Message) + return Equal(m1, m2) + } + switch v1.Kind() { + case reflect.Bool: + return v1.Bool() == v2.Bool() + case reflect.Float32, reflect.Float64: + return v1.Float() == v2.Float() + case reflect.Int32, reflect.Int64: + return v1.Int() == v2.Int() + case reflect.Interface: + // Probably a oneof field; compare the inner values. + n1, n2 := v1.IsNil(), v2.IsNil() + if n1 || n2 { + return n1 == n2 + } + e1, e2 := v1.Elem(), v2.Elem() + if e1.Type() != e2.Type() { + return false + } + return equalAny(e1, e2, nil) + case reflect.Map: + if v1.Len() != v2.Len() { + return false + } + for _, key := range v1.MapKeys() { + val2 := v2.MapIndex(key) + if !val2.IsValid() { + // This key was not found in the second map. + return false + } + if !equalAny(v1.MapIndex(key), val2, nil) { + return false + } + } + return true + case reflect.Ptr: + // Maps may have nil values in them, so check for nil. + if v1.IsNil() && v2.IsNil() { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } + return equalAny(v1.Elem(), v2.Elem(), prop) + case reflect.Slice: + if v1.Type().Elem().Kind() == reflect.Uint8 { + // short circuit: []byte + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value. + if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } + return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte)) + } + + if v1.Len() != v2.Len() { + return false + } + for i := 0; i < v1.Len(); i++ { + if !equalAny(v1.Index(i), v2.Index(i), prop) { + return false + } + } + return true + case reflect.String: + return v1.Interface().(string) == v2.Interface().(string) + case reflect.Struct: + return equalStruct(v1, v2) + case reflect.Uint32, reflect.Uint64: + return v1.Uint() == v2.Uint() + } + + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to compare %v", v1) + return false +} + +// base is the struct type that the extensions are based on. +// x1 and x2 are InternalExtensions. +func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool { + em1, _ := x1.extensionsRead() + em2, _ := x2.extensionsRead() + return equalExtMap(base, em1, em2) +} + +func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { + if len(em1) != len(em2) { + return false + } + + for extNum, e1 := range em1 { + e2, ok := em2[extNum] + if !ok { + return false + } + + m1, m2 := e1.value, e2.value + + if m1 == nil && m2 == nil { + // Both have only encoded form. + if bytes.Equal(e1.enc, e2.enc) { + continue + } + // The bytes are different, but the extensions might still be + // equal. We need to decode them to compare. + } + + if m1 != nil && m2 != nil { + // Both are unencoded. + if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { + return false + } + continue + } + + // At least one is encoded. To do a semantically correct comparison + // we need to unmarshal them first. + var desc *ExtensionDesc + if m := extensionMaps[base]; m != nil { + desc = m[extNum] + } + if desc == nil { + // If both have only encoded form and the bytes are the same, + // it is handled above. We get here when the bytes are different. + // We don't know how to decode it, so just compare them as byte + // slices. + log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) + return false + } + var err error + if m1 == nil { + m1, err = decodeExtension(e1.enc, desc) + } + if m2 == nil && err == nil { + m2, err = decodeExtension(e2.enc, desc) + } + if err != nil { + // The encoded form is invalid. + log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err) + return false + } + if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { + return false + } + } + + return true +} diff --git a/vendor/github.com/golang/protobuf/proto/extensions.go b/vendor/github.com/golang/protobuf/proto/extensions.go new file mode 100644 index 00000000..816a3b9d --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/extensions.go @@ -0,0 +1,543 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Types and routines for supporting protocol buffer extensions. + */ + +import ( + "errors" + "fmt" + "io" + "reflect" + "strconv" + "sync" +) + +// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message. +var ErrMissingExtension = errors.New("proto: missing extension") + +// ExtensionRange represents a range of message extensions for a protocol buffer. +// Used in code generated by the protocol compiler. +type ExtensionRange struct { + Start, End int32 // both inclusive +} + +// extendableProto is an interface implemented by any protocol buffer generated by the current +// proto compiler that may be extended. +type extendableProto interface { + Message + ExtensionRangeArray() []ExtensionRange + extensionsWrite() map[int32]Extension + extensionsRead() (map[int32]Extension, sync.Locker) +} + +// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous +// version of the proto compiler that may be extended. +type extendableProtoV1 interface { + Message + ExtensionRangeArray() []ExtensionRange + ExtensionMap() map[int32]Extension +} + +// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto. +type extensionAdapter struct { + extendableProtoV1 +} + +func (e extensionAdapter) extensionsWrite() map[int32]Extension { + return e.ExtensionMap() +} + +func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) { + return e.ExtensionMap(), notLocker{} +} + +// notLocker is a sync.Locker whose Lock and Unlock methods are nops. +type notLocker struct{} + +func (n notLocker) Lock() {} +func (n notLocker) Unlock() {} + +// extendable returns the extendableProto interface for the given generated proto message. +// If the proto message has the old extension format, it returns a wrapper that implements +// the extendableProto interface. +func extendable(p interface{}) (extendableProto, error) { + switch p := p.(type) { + case extendableProto: + if isNilPtr(p) { + return nil, fmt.Errorf("proto: nil %T is not extendable", p) + } + return p, nil + case extendableProtoV1: + if isNilPtr(p) { + return nil, fmt.Errorf("proto: nil %T is not extendable", p) + } + return extensionAdapter{p}, nil + } + // Don't allocate a specific error containing %T: + // this is the hot path for Clone and MarshalText. + return nil, errNotExtendable +} + +var errNotExtendable = errors.New("proto: not an extendable proto.Message") + +func isNilPtr(x interface{}) bool { + v := reflect.ValueOf(x) + return v.Kind() == reflect.Ptr && v.IsNil() +} + +// XXX_InternalExtensions is an internal representation of proto extensions. +// +// Each generated message struct type embeds an anonymous XXX_InternalExtensions field, +// thus gaining the unexported 'extensions' method, which can be called only from the proto package. +// +// The methods of XXX_InternalExtensions are not concurrency safe in general, +// but calls to logically read-only methods such as has and get may be executed concurrently. +type XXX_InternalExtensions struct { + // The struct must be indirect so that if a user inadvertently copies a + // generated message and its embedded XXX_InternalExtensions, they + // avoid the mayhem of a copied mutex. + // + // The mutex serializes all logically read-only operations to p.extensionMap. + // It is up to the client to ensure that write operations to p.extensionMap are + // mutually exclusive with other accesses. + p *struct { + mu sync.Mutex + extensionMap map[int32]Extension + } +} + +// extensionsWrite returns the extension map, creating it on first use. +func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension { + if e.p == nil { + e.p = new(struct { + mu sync.Mutex + extensionMap map[int32]Extension + }) + e.p.extensionMap = make(map[int32]Extension) + } + return e.p.extensionMap +} + +// extensionsRead returns the extensions map for read-only use. It may be nil. +// The caller must hold the returned mutex's lock when accessing Elements within the map. +func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) { + if e.p == nil { + return nil, nil + } + return e.p.extensionMap, &e.p.mu +} + +// ExtensionDesc represents an extension specification. +// Used in generated code from the protocol compiler. +type ExtensionDesc struct { + ExtendedType Message // nil pointer to the type that is being extended + ExtensionType interface{} // nil pointer to the extension type + Field int32 // field number + Name string // fully-qualified name of extension, for text formatting + Tag string // protobuf tag style + Filename string // name of the file in which the extension is defined +} + +func (ed *ExtensionDesc) repeated() bool { + t := reflect.TypeOf(ed.ExtensionType) + return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 +} + +// Extension represents an extension in a message. +type Extension struct { + // When an extension is stored in a message using SetExtension + // only desc and value are set. When the message is marshaled + // enc will be set to the encoded form of the message. + // + // When a message is unmarshaled and contains extensions, each + // extension will have only enc set. When such an extension is + // accessed using GetExtension (or GetExtensions) desc and value + // will be set. + desc *ExtensionDesc + value interface{} + enc []byte +} + +// SetRawExtension is for testing only. +func SetRawExtension(base Message, id int32, b []byte) { + epb, err := extendable(base) + if err != nil { + return + } + extmap := epb.extensionsWrite() + extmap[id] = Extension{enc: b} +} + +// isExtensionField returns true iff the given field number is in an extension range. +func isExtensionField(pb extendableProto, field int32) bool { + for _, er := range pb.ExtensionRangeArray() { + if er.Start <= field && field <= er.End { + return true + } + } + return false +} + +// checkExtensionTypes checks that the given extension is valid for pb. +func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { + var pbi interface{} = pb + // Check the extended type. + if ea, ok := pbi.(extensionAdapter); ok { + pbi = ea.extendableProtoV1 + } + if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b { + return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a) + } + // Check the range. + if !isExtensionField(pb, extension.Field) { + return errors.New("proto: bad extension number; not in declared ranges") + } + return nil +} + +// extPropKey is sufficient to uniquely identify an extension. +type extPropKey struct { + base reflect.Type + field int32 +} + +var extProp = struct { + sync.RWMutex + m map[extPropKey]*Properties +}{ + m: make(map[extPropKey]*Properties), +} + +func extensionProperties(ed *ExtensionDesc) *Properties { + key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field} + + extProp.RLock() + if prop, ok := extProp.m[key]; ok { + extProp.RUnlock() + return prop + } + extProp.RUnlock() + + extProp.Lock() + defer extProp.Unlock() + // Check again. + if prop, ok := extProp.m[key]; ok { + return prop + } + + prop := new(Properties) + prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil) + extProp.m[key] = prop + return prop +} + +// HasExtension returns whether the given extension is present in pb. +func HasExtension(pb Message, extension *ExtensionDesc) bool { + // TODO: Check types, field numbers, etc.? + epb, err := extendable(pb) + if err != nil { + return false + } + extmap, mu := epb.extensionsRead() + if extmap == nil { + return false + } + mu.Lock() + _, ok := extmap[extension.Field] + mu.Unlock() + return ok +} + +// ClearExtension removes the given extension from pb. +func ClearExtension(pb Message, extension *ExtensionDesc) { + epb, err := extendable(pb) + if err != nil { + return + } + // TODO: Check types, field numbers, etc.? + extmap := epb.extensionsWrite() + delete(extmap, extension.Field) +} + +// GetExtension retrieves a proto2 extended field from pb. +// +// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil), +// then GetExtension parses the encoded field and returns a Go value of the specified type. +// If the field is not present, then the default value is returned (if one is specified), +// otherwise ErrMissingExtension is reported. +// +// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil), +// then GetExtension returns the raw encoded bytes of the field extension. +func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { + epb, err := extendable(pb) + if err != nil { + return nil, err + } + + if extension.ExtendedType != nil { + // can only check type if this is a complete descriptor + if err := checkExtensionTypes(epb, extension); err != nil { + return nil, err + } + } + + emap, mu := epb.extensionsRead() + if emap == nil { + return defaultExtensionValue(extension) + } + mu.Lock() + defer mu.Unlock() + e, ok := emap[extension.Field] + if !ok { + // defaultExtensionValue returns the default value or + // ErrMissingExtension if there is no default. + return defaultExtensionValue(extension) + } + + if e.value != nil { + // Already decoded. Check the descriptor, though. + if e.desc != extension { + // This shouldn't happen. If it does, it means that + // GetExtension was called twice with two different + // descriptors with the same field number. + return nil, errors.New("proto: descriptor conflict") + } + return e.value, nil + } + + if extension.ExtensionType == nil { + // incomplete descriptor + return e.enc, nil + } + + v, err := decodeExtension(e.enc, extension) + if err != nil { + return nil, err + } + + // Remember the decoded version and drop the encoded version. + // That way it is safe to mutate what we return. + e.value = v + e.desc = extension + e.enc = nil + emap[extension.Field] = e + return e.value, nil +} + +// defaultExtensionValue returns the default value for extension. +// If no default for an extension is defined ErrMissingExtension is returned. +func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) { + if extension.ExtensionType == nil { + // incomplete descriptor, so no default + return nil, ErrMissingExtension + } + + t := reflect.TypeOf(extension.ExtensionType) + props := extensionProperties(extension) + + sf, _, err := fieldDefault(t, props) + if err != nil { + return nil, err + } + + if sf == nil || sf.value == nil { + // There is no default value. + return nil, ErrMissingExtension + } + + if t.Kind() != reflect.Ptr { + // We do not need to return a Ptr, we can directly return sf.value. + return sf.value, nil + } + + // We need to return an interface{} that is a pointer to sf.value. + value := reflect.New(t).Elem() + value.Set(reflect.New(value.Type().Elem())) + if sf.kind == reflect.Int32 { + // We may have an int32 or an enum, but the underlying data is int32. + // Since we can't set an int32 into a non int32 reflect.value directly + // set it as a int32. + value.Elem().SetInt(int64(sf.value.(int32))) + } else { + value.Elem().Set(reflect.ValueOf(sf.value)) + } + return value.Interface(), nil +} + +// decodeExtension decodes an extension encoded in b. +func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { + t := reflect.TypeOf(extension.ExtensionType) + unmarshal := typeUnmarshaler(t, extension.Tag) + + // t is a pointer to a struct, pointer to basic type or a slice. + // Allocate space to store the pointer/slice. + value := reflect.New(t).Elem() + + var err error + for { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + wire := int(x) & 7 + + b, err = unmarshal(b, valToPointer(value.Addr()), wire) + if err != nil { + return nil, err + } + + if len(b) == 0 { + break + } + } + return value.Interface(), nil +} + +// GetExtensions returns a slice of the extensions present in pb that are also listed in es. +// The returned slice has the same length as es; missing extensions will appear as nil elements. +func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { + epb, err := extendable(pb) + if err != nil { + return nil, err + } + extensions = make([]interface{}, len(es)) + for i, e := range es { + extensions[i], err = GetExtension(epb, e) + if err == ErrMissingExtension { + err = nil + } + if err != nil { + return + } + } + return +} + +// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. +// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing +// just the Field field, which defines the extension's field number. +func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { + epb, err := extendable(pb) + if err != nil { + return nil, err + } + registeredExtensions := RegisteredExtensions(pb) + + emap, mu := epb.extensionsRead() + if emap == nil { + return nil, nil + } + mu.Lock() + defer mu.Unlock() + extensions := make([]*ExtensionDesc, 0, len(emap)) + for extid, e := range emap { + desc := e.desc + if desc == nil { + desc = registeredExtensions[extid] + if desc == nil { + desc = &ExtensionDesc{Field: extid} + } + } + + extensions = append(extensions, desc) + } + return extensions, nil +} + +// SetExtension sets the specified extension of pb to the specified value. +func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { + epb, err := extendable(pb) + if err != nil { + return err + } + if err := checkExtensionTypes(epb, extension); err != nil { + return err + } + typ := reflect.TypeOf(extension.ExtensionType) + if typ != reflect.TypeOf(value) { + return errors.New("proto: bad extension value type") + } + // nil extension values need to be caught early, because the + // encoder can't distinguish an ErrNil due to a nil extension + // from an ErrNil due to a missing field. Extensions are + // always optional, so the encoder would just swallow the error + // and drop all the extensions from the encoded message. + if reflect.ValueOf(value).IsNil() { + return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) + } + + extmap := epb.extensionsWrite() + extmap[extension.Field] = Extension{desc: extension, value: value} + return nil +} + +// ClearAllExtensions clears all extensions from pb. +func ClearAllExtensions(pb Message) { + epb, err := extendable(pb) + if err != nil { + return + } + m := epb.extensionsWrite() + for k := range m { + delete(m, k) + } +} + +// A global registry of extensions. +// The generated code will register the generated descriptors by calling RegisterExtension. + +var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc) + +// RegisterExtension is called from the generated code. +func RegisterExtension(desc *ExtensionDesc) { + st := reflect.TypeOf(desc.ExtendedType).Elem() + m := extensionMaps[st] + if m == nil { + m = make(map[int32]*ExtensionDesc) + extensionMaps[st] = m + } + if _, ok := m[desc.Field]; ok { + panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field))) + } + m[desc.Field] = desc +} + +// RegisteredExtensions returns a map of the registered extensions of a +// protocol buffer struct, indexed by the extension number. +// The argument pb should be a nil pointer to the struct type. +func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { + return extensionMaps[reflect.TypeOf(pb).Elem()] +} diff --git a/vendor/github.com/golang/protobuf/proto/lib.go b/vendor/github.com/golang/protobuf/proto/lib.go new file mode 100644 index 00000000..0e2191b8 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/lib.go @@ -0,0 +1,921 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Package proto converts data structures to and from the wire format of +protocol buffers. It works in concert with the Go source code generated +for .proto files by the protocol compiler. + +A summary of the properties of the protocol buffer interface +for a protocol buffer variable v: + + - Names are turned from camel_case to CamelCase for export. + - There are no methods on v to set fields; just treat + them as structure fields. + - There are getters that return a field's value if set, + and return the field's default value if unset. + The getters work even if the receiver is a nil message. + - The zero value for a struct is its correct initialization state. + All desired fields must be set before marshaling. + - A Reset() method will restore a protobuf struct to its zero state. + - Non-repeated fields are pointers to the values; nil means unset. + That is, optional or required field int32 f becomes F *int32. + - Repeated fields are slices. + - Helper functions are available to aid the setting of fields. + msg.Foo = proto.String("hello") // set field + - Constants are defined to hold the default values of all fields that + have them. They have the form Default_StructName_FieldName. + Because the getter methods handle defaulted values, + direct use of these constants should be rare. + - Enums are given type names and maps from names to values. + Enum values are prefixed by the enclosing message's name, or by the + enum's type name if it is a top-level enum. Enum types have a String + method, and a Enum method to assist in message construction. + - Nested messages, groups and enums have type names prefixed with the name of + the surrounding message type. + - Extensions are given descriptor names that start with E_, + followed by an underscore-delimited list of the nested messages + that contain it (if any) followed by the CamelCased name of the + extension field itself. HasExtension, ClearExtension, GetExtension + and SetExtension are functions for manipulating extensions. + - Oneof field sets are given a single field in their message, + with distinguished wrapper types for each possible field value. + - Marshal and Unmarshal are functions to encode and decode the wire format. + +When the .proto file specifies `syntax="proto3"`, there are some differences: + + - Non-repeated fields of non-message type are values instead of pointers. + - Enum types do not get an Enum method. + +The simplest way to describe this is to see an example. +Given file test.proto, containing + + package example; + + enum FOO { X = 17; } + + message Test { + required string label = 1; + optional int32 type = 2 [default=77]; + repeated int64 reps = 3; + optional group OptionalGroup = 4 { + required string RequiredField = 5; + } + oneof union { + int32 number = 6; + string name = 7; + } + } + +The resulting file, test.pb.go, is: + + package example + + import proto "github.com/golang/protobuf/proto" + import math "math" + + type FOO int32 + const ( + FOO_X FOO = 17 + ) + var FOO_name = map[int32]string{ + 17: "X", + } + var FOO_value = map[string]int32{ + "X": 17, + } + + func (x FOO) Enum() *FOO { + p := new(FOO) + *p = x + return p + } + func (x FOO) String() string { + return proto.EnumName(FOO_name, int32(x)) + } + func (x *FOO) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FOO_value, data) + if err != nil { + return err + } + *x = FOO(value) + return nil + } + + type Test struct { + Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"` + Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"` + Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"` + Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` + // Types that are valid to be assigned to Union: + // *Test_Number + // *Test_Name + Union isTest_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` + } + func (m *Test) Reset() { *m = Test{} } + func (m *Test) String() string { return proto.CompactTextString(m) } + func (*Test) ProtoMessage() {} + + type isTest_Union interface { + isTest_Union() + } + + type Test_Number struct { + Number int32 `protobuf:"varint,6,opt,name=number"` + } + type Test_Name struct { + Name string `protobuf:"bytes,7,opt,name=name"` + } + + func (*Test_Number) isTest_Union() {} + func (*Test_Name) isTest_Union() {} + + func (m *Test) GetUnion() isTest_Union { + if m != nil { + return m.Union + } + return nil + } + const Default_Test_Type int32 = 77 + + func (m *Test) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" + } + + func (m *Test) GetType() int32 { + if m != nil && m.Type != nil { + return *m.Type + } + return Default_Test_Type + } + + func (m *Test) GetOptionalgroup() *Test_OptionalGroup { + if m != nil { + return m.Optionalgroup + } + return nil + } + + type Test_OptionalGroup struct { + RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"` + } + func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} } + func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) } + + func (m *Test_OptionalGroup) GetRequiredField() string { + if m != nil && m.RequiredField != nil { + return *m.RequiredField + } + return "" + } + + func (m *Test) GetNumber() int32 { + if x, ok := m.GetUnion().(*Test_Number); ok { + return x.Number + } + return 0 + } + + func (m *Test) GetName() string { + if x, ok := m.GetUnion().(*Test_Name); ok { + return x.Name + } + return "" + } + + func init() { + proto.RegisterEnum("example.FOO", FOO_name, FOO_value) + } + +To create and play with a Test object: + + package main + + import ( + "log" + + "github.com/golang/protobuf/proto" + pb "./example.pb" + ) + + func main() { + test := &pb.Test{ + Label: proto.String("hello"), + Type: proto.Int32(17), + Reps: []int64{1, 2, 3}, + Optionalgroup: &pb.Test_OptionalGroup{ + RequiredField: proto.String("good bye"), + }, + Union: &pb.Test_Name{"fred"}, + } + data, err := proto.Marshal(test) + if err != nil { + log.Fatal("marshaling error: ", err) + } + newTest := &pb.Test{} + err = proto.Unmarshal(data, newTest) + if err != nil { + log.Fatal("unmarshaling error: ", err) + } + // Now test and newTest contain the same data. + if test.GetLabel() != newTest.GetLabel() { + log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) + } + // Use a type switch to determine which oneof was set. + switch u := test.Union.(type) { + case *pb.Test_Number: // u.Number contains the number. + case *pb.Test_Name: // u.Name contains the string. + } + // etc. + } +*/ +package proto + +import ( + "encoding/json" + "errors" + "fmt" + "log" + "reflect" + "sort" + "strconv" + "sync" +) + +var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string") + +// Message is implemented by generated protocol buffer messages. +type Message interface { + Reset() + String() string + ProtoMessage() +} + +// Stats records allocation details about the protocol buffer encoders +// and decoders. Useful for tuning the library itself. +type Stats struct { + Emalloc uint64 // mallocs in encode + Dmalloc uint64 // mallocs in decode + Encode uint64 // number of encodes + Decode uint64 // number of decodes + Chit uint64 // number of cache hits + Cmiss uint64 // number of cache misses + Size uint64 // number of sizes +} + +// Set to true to enable stats collection. +const collectStats = false + +var stats Stats + +// GetStats returns a copy of the global Stats structure. +func GetStats() Stats { return stats } + +// A Buffer is a buffer manager for marshaling and unmarshaling +// protocol buffers. It may be reused between invocations to +// reduce memory usage. It is not necessary to use a Buffer; +// the global functions Marshal and Unmarshal create a +// temporary Buffer and are fine for most applications. +type Buffer struct { + buf []byte // encode/decode byte stream + index int // read point + + deterministic bool +} + +// NewBuffer allocates a new Buffer and initializes its internal data to +// the contents of the argument slice. +func NewBuffer(e []byte) *Buffer { + return &Buffer{buf: e} +} + +// Reset resets the Buffer, ready for marshaling a new protocol buffer. +func (p *Buffer) Reset() { + p.buf = p.buf[0:0] // for reading/writing + p.index = 0 // for reading +} + +// SetBuf replaces the internal buffer with the slice, +// ready for unmarshaling the contents of the slice. +func (p *Buffer) SetBuf(s []byte) { + p.buf = s + p.index = 0 +} + +// Bytes returns the contents of the Buffer. +func (p *Buffer) Bytes() []byte { return p.buf } + +// SetDeterministic sets whether to use deterministic serialization. +// +// Deterministic serialization guarantees that for a given binary, equal +// messages will always be serialized to the same bytes. This implies: +// +// - Repeated serialization of a message will return the same bytes. +// - Different processes of the same binary (which may be executing on +// different machines) will serialize equal messages to the same bytes. +// +// Note that the deterministic serialization is NOT canonical across +// languages. It is not guaranteed to remain stable over time. It is unstable +// across different builds with schema changes due to unknown fields. +// Users who need canonical serialization (e.g., persistent storage in a +// canonical form, fingerprinting, etc.) should define their own +// canonicalization specification and implement their own serializer rather +// than relying on this API. +// +// If deterministic serialization is requested, map entries will be sorted +// by keys in lexographical order. This is an implementation detail and +// subject to change. +func (p *Buffer) SetDeterministic(deterministic bool) { + p.deterministic = deterministic +} + +/* + * Helper routines for simplifying the creation of optional fields of basic type. + */ + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { + return &v +} + +// Int32 is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it. +func Int32(v int32) *int32 { + return &v +} + +// Int is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it, but unlike Int32 +// its argument value is an int. +func Int(v int) *int32 { + p := new(int32) + *p = int32(v) + return p +} + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +func Int64(v int64) *int64 { + return &v +} + +// Float32 is a helper routine that allocates a new float32 value +// to store v and returns a pointer to it. +func Float32(v float32) *float32 { + return &v +} + +// Float64 is a helper routine that allocates a new float64 value +// to store v and returns a pointer to it. +func Float64(v float64) *float64 { + return &v +} + +// Uint32 is a helper routine that allocates a new uint32 value +// to store v and returns a pointer to it. +func Uint32(v uint32) *uint32 { + return &v +} + +// Uint64 is a helper routine that allocates a new uint64 value +// to store v and returns a pointer to it. +func Uint64(v uint64) *uint64 { + return &v +} + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { + return &v +} + +// EnumName is a helper function to simplify printing protocol buffer enums +// by name. Given an enum map and a value, it returns a useful string. +func EnumName(m map[int32]string, v int32) string { + s, ok := m[v] + if ok { + return s + } + return strconv.Itoa(int(v)) +} + +// UnmarshalJSONEnum is a helper function to simplify recovering enum int values +// from their JSON-encoded representation. Given a map from the enum's symbolic +// names to its int values, and a byte buffer containing the JSON-encoded +// value, it returns an int32 that can be cast to the enum type by the caller. +// +// The function can deal with both JSON representations, numeric and symbolic. +func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) { + if data[0] == '"' { + // New style: enums are strings. + var repr string + if err := json.Unmarshal(data, &repr); err != nil { + return -1, err + } + val, ok := m[repr] + if !ok { + return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr) + } + return val, nil + } + // Old style: enums are ints. + var val int32 + if err := json.Unmarshal(data, &val); err != nil { + return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName) + } + return val, nil +} + +// DebugPrint dumps the encoded data in b in a debugging format with a header +// including the string s. Used in testing but made available for general debugging. +func (p *Buffer) DebugPrint(s string, b []byte) { + var u uint64 + + obuf := p.buf + index := p.index + p.buf = b + p.index = 0 + depth := 0 + + fmt.Printf("\n--- %s ---\n", s) + +out: + for { + for i := 0; i < depth; i++ { + fmt.Print(" ") + } + + index := p.index + if index == len(p.buf) { + break + } + + op, err := p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: fetching op err %v\n", index, err) + break out + } + tag := op >> 3 + wire := op & 7 + + switch wire { + default: + fmt.Printf("%3d: t=%3d unknown wire=%d\n", + index, tag, wire) + break out + + case WireBytes: + var r []byte + + r, err = p.DecodeRawBytes(false) + if err != nil { + break out + } + fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r)) + if len(r) <= 6 { + for i := 0; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } else { + for i := 0; i < 3; i++ { + fmt.Printf(" %.2x", r[i]) + } + fmt.Printf(" ..") + for i := len(r) - 3; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } + fmt.Printf("\n") + + case WireFixed32: + u, err = p.DecodeFixed32() + if err != nil { + fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u) + + case WireFixed64: + u, err = p.DecodeFixed64() + if err != nil { + fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u) + + case WireVarint: + u, err = p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u) + + case WireStartGroup: + fmt.Printf("%3d: t=%3d start\n", index, tag) + depth++ + + case WireEndGroup: + depth-- + fmt.Printf("%3d: t=%3d end\n", index, tag) + } + } + + if depth != 0 { + fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth) + } + fmt.Printf("\n") + + p.buf = obuf + p.index = index +} + +// SetDefaults sets unset protocol buffer fields to their default values. +// It only modifies fields that are both unset and have defined defaults. +// It recursively sets default values in any non-nil sub-messages. +func SetDefaults(pb Message) { + setDefaults(reflect.ValueOf(pb), true, false) +} + +// v is a pointer to a struct. +func setDefaults(v reflect.Value, recur, zeros bool) { + v = v.Elem() + + defaultMu.RLock() + dm, ok := defaults[v.Type()] + defaultMu.RUnlock() + if !ok { + dm = buildDefaultMessage(v.Type()) + defaultMu.Lock() + defaults[v.Type()] = dm + defaultMu.Unlock() + } + + for _, sf := range dm.scalars { + f := v.Field(sf.index) + if !f.IsNil() { + // field already set + continue + } + dv := sf.value + if dv == nil && !zeros { + // no explicit default, and don't want to set zeros + continue + } + fptr := f.Addr().Interface() // **T + // TODO: Consider batching the allocations we do here. + switch sf.kind { + case reflect.Bool: + b := new(bool) + if dv != nil { + *b = dv.(bool) + } + *(fptr.(**bool)) = b + case reflect.Float32: + f := new(float32) + if dv != nil { + *f = dv.(float32) + } + *(fptr.(**float32)) = f + case reflect.Float64: + f := new(float64) + if dv != nil { + *f = dv.(float64) + } + *(fptr.(**float64)) = f + case reflect.Int32: + // might be an enum + if ft := f.Type(); ft != int32PtrType { + // enum + f.Set(reflect.New(ft.Elem())) + if dv != nil { + f.Elem().SetInt(int64(dv.(int32))) + } + } else { + // int32 field + i := new(int32) + if dv != nil { + *i = dv.(int32) + } + *(fptr.(**int32)) = i + } + case reflect.Int64: + i := new(int64) + if dv != nil { + *i = dv.(int64) + } + *(fptr.(**int64)) = i + case reflect.String: + s := new(string) + if dv != nil { + *s = dv.(string) + } + *(fptr.(**string)) = s + case reflect.Uint8: + // exceptional case: []byte + var b []byte + if dv != nil { + db := dv.([]byte) + b = make([]byte, len(db)) + copy(b, db) + } else { + b = []byte{} + } + *(fptr.(*[]byte)) = b + case reflect.Uint32: + u := new(uint32) + if dv != nil { + *u = dv.(uint32) + } + *(fptr.(**uint32)) = u + case reflect.Uint64: + u := new(uint64) + if dv != nil { + *u = dv.(uint64) + } + *(fptr.(**uint64)) = u + default: + log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind) + } + } + + for _, ni := range dm.nested { + f := v.Field(ni) + // f is *T or []*T or map[T]*T + switch f.Kind() { + case reflect.Ptr: + if f.IsNil() { + continue + } + setDefaults(f, recur, zeros) + + case reflect.Slice: + for i := 0; i < f.Len(); i++ { + e := f.Index(i) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + + case reflect.Map: + for _, k := range f.MapKeys() { + e := f.MapIndex(k) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + } + } +} + +var ( + // defaults maps a protocol buffer struct type to a slice of the fields, + // with its scalar fields set to their proto-declared non-zero default values. + defaultMu sync.RWMutex + defaults = make(map[reflect.Type]defaultMessage) + + int32PtrType = reflect.TypeOf((*int32)(nil)) +) + +// defaultMessage represents information about the default values of a message. +type defaultMessage struct { + scalars []scalarField + nested []int // struct field index of nested messages +} + +type scalarField struct { + index int // struct field index + kind reflect.Kind // element type (the T in *T or []T) + value interface{} // the proto-declared default value, or nil +} + +// t is a struct type. +func buildDefaultMessage(t reflect.Type) (dm defaultMessage) { + sprop := GetProperties(t) + for _, prop := range sprop.Prop { + fi, ok := sprop.decoderTags.get(prop.Tag) + if !ok { + // XXX_unrecognized + continue + } + ft := t.Field(fi).Type + + sf, nested, err := fieldDefault(ft, prop) + switch { + case err != nil: + log.Print(err) + case nested: + dm.nested = append(dm.nested, fi) + case sf != nil: + sf.index = fi + dm.scalars = append(dm.scalars, *sf) + } + } + + return dm +} + +// fieldDefault returns the scalarField for field type ft. +// sf will be nil if the field can not have a default. +// nestedMessage will be true if this is a nested message. +// Note that sf.index is not set on return. +func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) { + var canHaveDefault bool + switch ft.Kind() { + case reflect.Ptr: + if ft.Elem().Kind() == reflect.Struct { + nestedMessage = true + } else { + canHaveDefault = true // proto2 scalar field + } + + case reflect.Slice: + switch ft.Elem().Kind() { + case reflect.Ptr: + nestedMessage = true // repeated message + case reflect.Uint8: + canHaveDefault = true // bytes field + } + + case reflect.Map: + if ft.Elem().Kind() == reflect.Ptr { + nestedMessage = true // map with message values + } + } + + if !canHaveDefault { + if nestedMessage { + return nil, true, nil + } + return nil, false, nil + } + + // We now know that ft is a pointer or slice. + sf = &scalarField{kind: ft.Elem().Kind()} + + // scalar fields without defaults + if !prop.HasDefault { + return sf, false, nil + } + + // a scalar field: either *T or []byte + switch ft.Elem().Kind() { + case reflect.Bool: + x, err := strconv.ParseBool(prop.Default) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Float32: + x, err := strconv.ParseFloat(prop.Default, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err) + } + sf.value = float32(x) + case reflect.Float64: + x, err := strconv.ParseFloat(prop.Default, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Int32: + x, err := strconv.ParseInt(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err) + } + sf.value = int32(x) + case reflect.Int64: + x, err := strconv.ParseInt(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.String: + sf.value = prop.Default + case reflect.Uint8: + // []byte (not *uint8) + sf.value = []byte(prop.Default) + case reflect.Uint32: + x, err := strconv.ParseUint(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err) + } + sf.value = uint32(x) + case reflect.Uint64: + x, err := strconv.ParseUint(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err) + } + sf.value = x + default: + return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind()) + } + + return sf, false, nil +} + +// mapKeys returns a sort.Interface to be used for sorting the map keys. +// Map fields may have key types of non-float scalars, strings and enums. +func mapKeys(vs []reflect.Value) sort.Interface { + s := mapKeySorter{vs: vs} + + // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps. + if len(vs) == 0 { + return s + } + switch vs[0].Kind() { + case reflect.Int32, reflect.Int64: + s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() } + case reflect.Uint32, reflect.Uint64: + s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() } + case reflect.Bool: + s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true + case reflect.String: + s.less = func(a, b reflect.Value) bool { return a.String() < b.String() } + default: + panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind())) + } + + return s +} + +type mapKeySorter struct { + vs []reflect.Value + less func(a, b reflect.Value) bool +} + +func (s mapKeySorter) Len() int { return len(s.vs) } +func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] } +func (s mapKeySorter) Less(i, j int) bool { + return s.less(s.vs[i], s.vs[j]) +} + +// isProto3Zero reports whether v is a zero proto3 value. +func isProto3Zero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return !v.Bool() + case reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint32, reflect.Uint64: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.String: + return v.String() == "" + } + return false +} + +// ProtoPackageIsVersion2 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const ProtoPackageIsVersion2 = true + +// ProtoPackageIsVersion1 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const ProtoPackageIsVersion1 = true + +// InternalMessageInfo is a type used internally by generated .pb.go files. +// This type is not intended to be used by non-generated code. +// This type is not subject to any compatibility guarantee. +type InternalMessageInfo struct { + marshal *marshalInfo + unmarshal *unmarshalInfo + merge *mergeInfo + discard *discardInfo +} diff --git a/vendor/github.com/golang/protobuf/proto/message_set.go b/vendor/github.com/golang/protobuf/proto/message_set.go new file mode 100644 index 00000000..3b6ca41d --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/message_set.go @@ -0,0 +1,314 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Support for message sets. + */ + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "reflect" + "sort" + "sync" +) + +// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. +// A message type ID is required for storing a protocol buffer in a message set. +var errNoMessageTypeID = errors.New("proto does not have a message type ID") + +// The first two types (_MessageSet_Item and messageSet) +// model what the protocol compiler produces for the following protocol message: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } +// That is the MessageSet wire format. We can't use a proto to generate these +// because that would introduce a circular dependency between it and this package. + +type _MessageSet_Item struct { + TypeId *int32 `protobuf:"varint,2,req,name=type_id"` + Message []byte `protobuf:"bytes,3,req,name=message"` +} + +type messageSet struct { + Item []*_MessageSet_Item `protobuf:"group,1,rep"` + XXX_unrecognized []byte + // TODO: caching? +} + +// Make sure messageSet is a Message. +var _ Message = (*messageSet)(nil) + +// messageTypeIder is an interface satisfied by a protocol buffer type +// that may be stored in a MessageSet. +type messageTypeIder interface { + MessageTypeId() int32 +} + +func (ms *messageSet) find(pb Message) *_MessageSet_Item { + mti, ok := pb.(messageTypeIder) + if !ok { + return nil + } + id := mti.MessageTypeId() + for _, item := range ms.Item { + if *item.TypeId == id { + return item + } + } + return nil +} + +func (ms *messageSet) Has(pb Message) bool { + return ms.find(pb) != nil +} + +func (ms *messageSet) Unmarshal(pb Message) error { + if item := ms.find(pb); item != nil { + return Unmarshal(item.Message, pb) + } + if _, ok := pb.(messageTypeIder); !ok { + return errNoMessageTypeID + } + return nil // TODO: return error instead? +} + +func (ms *messageSet) Marshal(pb Message) error { + msg, err := Marshal(pb) + if err != nil { + return err + } + if item := ms.find(pb); item != nil { + // reuse existing item + item.Message = msg + return nil + } + + mti, ok := pb.(messageTypeIder) + if !ok { + return errNoMessageTypeID + } + + mtid := mti.MessageTypeId() + ms.Item = append(ms.Item, &_MessageSet_Item{ + TypeId: &mtid, + Message: msg, + }) + return nil +} + +func (ms *messageSet) Reset() { *ms = messageSet{} } +func (ms *messageSet) String() string { return CompactTextString(ms) } +func (*messageSet) ProtoMessage() {} + +// Support for the message_set_wire_format message option. + +func skipVarint(buf []byte) []byte { + i := 0 + for ; buf[i]&0x80 != 0; i++ { + } + return buf[i+1:] +} + +// MarshalMessageSet encodes the extension map represented by m in the message set wire format. +// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. +func MarshalMessageSet(exts interface{}) ([]byte, error) { + return marshalMessageSet(exts, false) +} + +// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal. +func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) { + switch exts := exts.(type) { + case *XXX_InternalExtensions: + var u marshalInfo + siz := u.sizeMessageSet(exts) + b := make([]byte, 0, siz) + return u.appendMessageSet(b, exts, deterministic) + + case map[int32]Extension: + // This is an old-style extension map. + // Wrap it in a new-style XXX_InternalExtensions. + ie := XXX_InternalExtensions{ + p: &struct { + mu sync.Mutex + extensionMap map[int32]Extension + }{ + extensionMap: exts, + }, + } + + var u marshalInfo + siz := u.sizeMessageSet(&ie) + b := make([]byte, 0, siz) + return u.appendMessageSet(b, &ie, deterministic) + + default: + return nil, errors.New("proto: not an extension map") + } +} + +// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. +// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option. +func UnmarshalMessageSet(buf []byte, exts interface{}) error { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + m = exts.extensionsWrite() + case map[int32]Extension: + m = exts + default: + return errors.New("proto: not an extension map") + } + + ms := new(messageSet) + if err := Unmarshal(buf, ms); err != nil { + return err + } + for _, item := range ms.Item { + id := *item.TypeId + msg := item.Message + + // Restore wire type and field number varint, plus length varint. + // Be careful to preserve duplicate items. + b := EncodeVarint(uint64(id)<<3 | WireBytes) + if ext, ok := m[id]; ok { + // Existing data; rip off the tag and length varint + // so we join the new data correctly. + // We can assume that ext.enc is set because we are unmarshaling. + o := ext.enc[len(b):] // skip wire type and field number + _, n := DecodeVarint(o) // calculate length of length varint + o = o[n:] // skip length varint + msg = append(o, msg...) // join old data and new data + } + b = append(b, EncodeVarint(uint64(len(msg)))...) + b = append(b, msg...) + + m[id] = Extension{enc: b} + } + return nil +} + +// MarshalMessageSetJSON encodes the extension map represented by m in JSON format. +// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. +func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + var mu sync.Locker + m, mu = exts.extensionsRead() + if m != nil { + // Keep the extensions map locked until we're done marshaling to prevent + // races between marshaling and unmarshaling the lazily-{en,de}coded + // values. + mu.Lock() + defer mu.Unlock() + } + case map[int32]Extension: + m = exts + default: + return nil, errors.New("proto: not an extension map") + } + var b bytes.Buffer + b.WriteByte('{') + + // Process the map in key order for deterministic output. + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) // int32Slice defined in text.go + + for i, id := range ids { + ext := m[id] + msd, ok := messageSetMap[id] + if !ok { + // Unknown type; we can't render it, so skip it. + continue + } + + if i > 0 && b.Len() > 1 { + b.WriteByte(',') + } + + fmt.Fprintf(&b, `"[%s]":`, msd.name) + + x := ext.value + if x == nil { + x = reflect.New(msd.t.Elem()).Interface() + if err := Unmarshal(ext.enc, x.(Message)); err != nil { + return nil, err + } + } + d, err := json.Marshal(x) + if err != nil { + return nil, err + } + b.Write(d) + } + b.WriteByte('}') + return b.Bytes(), nil +} + +// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. +// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. +func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error { + // Common-case fast path. + if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { + return nil + } + + // This is fairly tricky, and it's not clear that it is needed. + return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") +} + +// A global registry of types that can be used in a MessageSet. + +var messageSetMap = make(map[int32]messageSetDesc) + +type messageSetDesc struct { + t reflect.Type // pointer to struct + name string +} + +// RegisterMessageSetType is called from the generated code. +func RegisterMessageSetType(m Message, fieldNum int32, name string) { + messageSetMap[fieldNum] = messageSetDesc{ + t: reflect.TypeOf(m), + name: name, + } +} diff --git a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go new file mode 100644 index 00000000..b6cad908 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go @@ -0,0 +1,357 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build purego appengine js + +// This file contains an implementation of proto field accesses using package reflect. +// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can +// be used on App Engine. + +package proto + +import ( + "reflect" + "sync" +) + +const unsafeAllowed = false + +// A field identifies a field in a struct, accessible from a pointer. +// In this implementation, a field is identified by the sequence of field indices +// passed to reflect's FieldByIndex. +type field []int + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return f.Index +} + +// invalidField is an invalid field identifier. +var invalidField = field(nil) + +// zeroField is a noop when calling pointer.offset. +var zeroField = field([]int{}) + +// IsValid reports whether the field identifier is valid. +func (f field) IsValid() bool { return f != nil } + +// The pointer type is for the table-driven decoder. +// The implementation here uses a reflect.Value of pointer type to +// create a generic pointer. In pointer_unsafe.go we use unsafe +// instead of reflect to implement the same (but faster) interface. +type pointer struct { + v reflect.Value +} + +// toPointer converts an interface of pointer type to a pointer +// that points to the same target. +func toPointer(i *Message) pointer { + return pointer{v: reflect.ValueOf(*i)} +} + +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr bool) pointer { + v := reflect.ValueOf(*i) + u := reflect.New(v.Type()) + u.Elem().Set(v) + return pointer{v: u} +} + +// valToPointer converts v to a pointer. v must be of pointer type. +func valToPointer(v reflect.Value) pointer { + return pointer{v: v} +} + +// offset converts from a pointer to a structure to a pointer to +// one of its fields. +func (p pointer) offset(f field) pointer { + return pointer{v: p.v.Elem().FieldByIndex(f).Addr()} +} + +func (p pointer) isNil() bool { + return p.v.IsNil() +} + +// grow updates the slice s in place to make it one element longer. +// s must be addressable. +// Returns the (addressable) new element. +func grow(s reflect.Value) reflect.Value { + n, m := s.Len(), s.Cap() + if n < m { + s.SetLen(n + 1) + } else { + s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem()))) + } + return s.Index(n) +} + +func (p pointer) toInt64() *int64 { + return p.v.Interface().(*int64) +} +func (p pointer) toInt64Ptr() **int64 { + return p.v.Interface().(**int64) +} +func (p pointer) toInt64Slice() *[]int64 { + return p.v.Interface().(*[]int64) +} + +var int32ptr = reflect.TypeOf((*int32)(nil)) + +func (p pointer) toInt32() *int32 { + return p.v.Convert(int32ptr).Interface().(*int32) +} + +// The toInt32Ptr/Slice methods don't work because of enums. +// Instead, we must use set/get methods for the int32ptr/slice case. +/* + func (p pointer) toInt32Ptr() **int32 { + return p.v.Interface().(**int32) +} + func (p pointer) toInt32Slice() *[]int32 { + return p.v.Interface().(*[]int32) +} +*/ +func (p pointer) getInt32Ptr() *int32 { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + return p.v.Elem().Interface().(*int32) + } + // an enum + return p.v.Elem().Convert(int32PtrType).Interface().(*int32) +} +func (p pointer) setInt32Ptr(v int32) { + // Allocate value in a *int32. Possibly convert that to a *enum. + // Then assign it to a **int32 or **enum. + // Note: we can convert *int32 to *enum, but we can't convert + // **int32 to **enum! + p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem())) +} + +// getInt32Slice copies []int32 from p as a new slice. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) getInt32Slice() []int32 { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + return p.v.Elem().Interface().([]int32) + } + // an enum + // Allocate a []int32, then assign []enum's values into it. + // Note: we can't convert []enum to []int32. + slice := p.v.Elem() + s := make([]int32, slice.Len()) + for i := 0; i < slice.Len(); i++ { + s[i] = int32(slice.Index(i).Int()) + } + return s +} + +// setInt32Slice copies []int32 into p as a new slice. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) setInt32Slice(v []int32) { + if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { + // raw int32 type + p.v.Elem().Set(reflect.ValueOf(v)) + return + } + // an enum + // Allocate a []enum, then assign []int32's values into it. + // Note: we can't convert []enum to []int32. + slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v)) + for i, x := range v { + slice.Index(i).SetInt(int64(x)) + } + p.v.Elem().Set(slice) +} +func (p pointer) appendInt32Slice(v int32) { + grow(p.v.Elem()).SetInt(int64(v)) +} + +func (p pointer) toUint64() *uint64 { + return p.v.Interface().(*uint64) +} +func (p pointer) toUint64Ptr() **uint64 { + return p.v.Interface().(**uint64) +} +func (p pointer) toUint64Slice() *[]uint64 { + return p.v.Interface().(*[]uint64) +} +func (p pointer) toUint32() *uint32 { + return p.v.Interface().(*uint32) +} +func (p pointer) toUint32Ptr() **uint32 { + return p.v.Interface().(**uint32) +} +func (p pointer) toUint32Slice() *[]uint32 { + return p.v.Interface().(*[]uint32) +} +func (p pointer) toBool() *bool { + return p.v.Interface().(*bool) +} +func (p pointer) toBoolPtr() **bool { + return p.v.Interface().(**bool) +} +func (p pointer) toBoolSlice() *[]bool { + return p.v.Interface().(*[]bool) +} +func (p pointer) toFloat64() *float64 { + return p.v.Interface().(*float64) +} +func (p pointer) toFloat64Ptr() **float64 { + return p.v.Interface().(**float64) +} +func (p pointer) toFloat64Slice() *[]float64 { + return p.v.Interface().(*[]float64) +} +func (p pointer) toFloat32() *float32 { + return p.v.Interface().(*float32) +} +func (p pointer) toFloat32Ptr() **float32 { + return p.v.Interface().(**float32) +} +func (p pointer) toFloat32Slice() *[]float32 { + return p.v.Interface().(*[]float32) +} +func (p pointer) toString() *string { + return p.v.Interface().(*string) +} +func (p pointer) toStringPtr() **string { + return p.v.Interface().(**string) +} +func (p pointer) toStringSlice() *[]string { + return p.v.Interface().(*[]string) +} +func (p pointer) toBytes() *[]byte { + return p.v.Interface().(*[]byte) +} +func (p pointer) toBytesSlice() *[][]byte { + return p.v.Interface().(*[][]byte) +} +func (p pointer) toExtensions() *XXX_InternalExtensions { + return p.v.Interface().(*XXX_InternalExtensions) +} +func (p pointer) toOldExtensions() *map[int32]Extension { + return p.v.Interface().(*map[int32]Extension) +} +func (p pointer) getPointer() pointer { + return pointer{v: p.v.Elem()} +} +func (p pointer) setPointer(q pointer) { + p.v.Elem().Set(q.v) +} +func (p pointer) appendPointer(q pointer) { + grow(p.v.Elem()).Set(q.v) +} + +// getPointerSlice copies []*T from p as a new []pointer. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) getPointerSlice() []pointer { + if p.v.IsNil() { + return nil + } + n := p.v.Elem().Len() + s := make([]pointer, n) + for i := 0; i < n; i++ { + s[i] = pointer{v: p.v.Elem().Index(i)} + } + return s +} + +// setPointerSlice copies []pointer into p as a new []*T. +// This behavior differs from the implementation in pointer_unsafe.go. +func (p pointer) setPointerSlice(v []pointer) { + if v == nil { + p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem()) + return + } + s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v)) + for _, p := range v { + s = reflect.Append(s, p.v) + } + p.v.Elem().Set(s) +} + +// getInterfacePointer returns a pointer that points to the +// interface data of the interface pointed by p. +func (p pointer) getInterfacePointer() pointer { + if p.v.Elem().IsNil() { + return pointer{v: p.v.Elem()} + } + return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct +} + +func (p pointer) asPointerTo(t reflect.Type) reflect.Value { + // TODO: check that p.v.Type().Elem() == t? + return p.v +} + +func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} +func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { + atomicLock.Lock() + defer atomicLock.Unlock() + return *p +} +func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { + atomicLock.Lock() + defer atomicLock.Unlock() + *p = v +} + +var atomicLock sync.Mutex diff --git a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go new file mode 100644 index 00000000..d55a335d --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go @@ -0,0 +1,308 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build !purego,!appengine,!js + +// This file contains the implementation of the proto field accesses using package unsafe. + +package proto + +import ( + "reflect" + "sync/atomic" + "unsafe" +) + +const unsafeAllowed = true + +// A field identifies a field in a struct, accessible from a pointer. +// In this implementation, a field is identified by its byte offset from the start of the struct. +type field uintptr + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return field(f.Offset) +} + +// invalidField is an invalid field identifier. +const invalidField = ^field(0) + +// zeroField is a noop when calling pointer.offset. +const zeroField = field(0) + +// IsValid reports whether the field identifier is valid. +func (f field) IsValid() bool { + return f != invalidField +} + +// The pointer type below is for the new table-driven encoder/decoder. +// The implementation here uses unsafe.Pointer to create a generic pointer. +// In pointer_reflect.go we use reflect instead of unsafe to implement +// the same (but slower) interface. +type pointer struct { + p unsafe.Pointer +} + +// size of pointer +var ptrSize = unsafe.Sizeof(uintptr(0)) + +// toPointer converts an interface of pointer type to a pointer +// that points to the same target. +func toPointer(i *Message) pointer { + // Super-tricky - read pointer out of data word of interface value. + // Saves ~25ns over the equivalent: + // return valToPointer(reflect.ValueOf(*i)) + return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} +} + +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr bool) pointer { + // Super-tricky - read or get the address of data word of interface value. + if isptr { + // The interface is of pointer type, thus it is a direct interface. + // The data word is the pointer data itself. We take its address. + return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} + } + // The interface is not of pointer type. The data word is the pointer + // to the data. + return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} +} + +// valToPointer converts v to a pointer. v must be of pointer type. +func valToPointer(v reflect.Value) pointer { + return pointer{p: unsafe.Pointer(v.Pointer())} +} + +// offset converts from a pointer to a structure to a pointer to +// one of its fields. +func (p pointer) offset(f field) pointer { + // For safety, we should panic if !f.IsValid, however calling panic causes + // this to no longer be inlineable, which is a serious performance cost. + /* + if !f.IsValid() { + panic("invalid field") + } + */ + return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} +} + +func (p pointer) isNil() bool { + return p.p == nil +} + +func (p pointer) toInt64() *int64 { + return (*int64)(p.p) +} +func (p pointer) toInt64Ptr() **int64 { + return (**int64)(p.p) +} +func (p pointer) toInt64Slice() *[]int64 { + return (*[]int64)(p.p) +} +func (p pointer) toInt32() *int32 { + return (*int32)(p.p) +} + +// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist. +/* + func (p pointer) toInt32Ptr() **int32 { + return (**int32)(p.p) + } + func (p pointer) toInt32Slice() *[]int32 { + return (*[]int32)(p.p) + } +*/ +func (p pointer) getInt32Ptr() *int32 { + return *(**int32)(p.p) +} +func (p pointer) setInt32Ptr(v int32) { + *(**int32)(p.p) = &v +} + +// getInt32Slice loads a []int32 from p. +// The value returned is aliased with the original slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) getInt32Slice() []int32 { + return *(*[]int32)(p.p) +} + +// setInt32Slice stores a []int32 to p. +// The value set is aliased with the input slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) setInt32Slice(v []int32) { + *(*[]int32)(p.p) = v +} + +// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead? +func (p pointer) appendInt32Slice(v int32) { + s := (*[]int32)(p.p) + *s = append(*s, v) +} + +func (p pointer) toUint64() *uint64 { + return (*uint64)(p.p) +} +func (p pointer) toUint64Ptr() **uint64 { + return (**uint64)(p.p) +} +func (p pointer) toUint64Slice() *[]uint64 { + return (*[]uint64)(p.p) +} +func (p pointer) toUint32() *uint32 { + return (*uint32)(p.p) +} +func (p pointer) toUint32Ptr() **uint32 { + return (**uint32)(p.p) +} +func (p pointer) toUint32Slice() *[]uint32 { + return (*[]uint32)(p.p) +} +func (p pointer) toBool() *bool { + return (*bool)(p.p) +} +func (p pointer) toBoolPtr() **bool { + return (**bool)(p.p) +} +func (p pointer) toBoolSlice() *[]bool { + return (*[]bool)(p.p) +} +func (p pointer) toFloat64() *float64 { + return (*float64)(p.p) +} +func (p pointer) toFloat64Ptr() **float64 { + return (**float64)(p.p) +} +func (p pointer) toFloat64Slice() *[]float64 { + return (*[]float64)(p.p) +} +func (p pointer) toFloat32() *float32 { + return (*float32)(p.p) +} +func (p pointer) toFloat32Ptr() **float32 { + return (**float32)(p.p) +} +func (p pointer) toFloat32Slice() *[]float32 { + return (*[]float32)(p.p) +} +func (p pointer) toString() *string { + return (*string)(p.p) +} +func (p pointer) toStringPtr() **string { + return (**string)(p.p) +} +func (p pointer) toStringSlice() *[]string { + return (*[]string)(p.p) +} +func (p pointer) toBytes() *[]byte { + return (*[]byte)(p.p) +} +func (p pointer) toBytesSlice() *[][]byte { + return (*[][]byte)(p.p) +} +func (p pointer) toExtensions() *XXX_InternalExtensions { + return (*XXX_InternalExtensions)(p.p) +} +func (p pointer) toOldExtensions() *map[int32]Extension { + return (*map[int32]Extension)(p.p) +} + +// getPointerSlice loads []*T from p as a []pointer. +// The value returned is aliased with the original slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) getPointerSlice() []pointer { + // Super-tricky - p should point to a []*T where T is a + // message type. We load it as []pointer. + return *(*[]pointer)(p.p) +} + +// setPointerSlice stores []pointer into p as a []*T. +// The value set is aliased with the input slice. +// This behavior differs from the implementation in pointer_reflect.go. +func (p pointer) setPointerSlice(v []pointer) { + // Super-tricky - p should point to a []*T where T is a + // message type. We store it as []pointer. + *(*[]pointer)(p.p) = v +} + +// getPointer loads the pointer at p and returns it. +func (p pointer) getPointer() pointer { + return pointer{p: *(*unsafe.Pointer)(p.p)} +} + +// setPointer stores the pointer q at p. +func (p pointer) setPointer(q pointer) { + *(*unsafe.Pointer)(p.p) = q.p +} + +// append q to the slice pointed to by p. +func (p pointer) appendPointer(q pointer) { + s := (*[]unsafe.Pointer)(p.p) + *s = append(*s, q.p) +} + +// getInterfacePointer returns a pointer that points to the +// interface data of the interface pointed by p. +func (p pointer) getInterfacePointer() pointer { + // Super-tricky - read pointer out of data word of interface value. + return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]} +} + +// asPointerTo returns a reflect.Value that is a pointer to an +// object of type t stored at p. +func (p pointer) asPointerTo(t reflect.Type) reflect.Value { + return reflect.NewAt(t, p.p) +} + +func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { + return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { + return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { + return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} +func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { + return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) +} diff --git a/vendor/github.com/golang/protobuf/proto/properties.go b/vendor/github.com/golang/protobuf/proto/properties.go new file mode 100644 index 00000000..f710adab --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/properties.go @@ -0,0 +1,544 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "fmt" + "log" + "os" + "reflect" + "sort" + "strconv" + "strings" + "sync" +) + +const debug bool = false + +// Constants that identify the encoding of a value on the wire. +const ( + WireVarint = 0 + WireFixed64 = 1 + WireBytes = 2 + WireStartGroup = 3 + WireEndGroup = 4 + WireFixed32 = 5 +) + +// tagMap is an optimization over map[int]int for typical protocol buffer +// use-cases. Encoded protocol buffers are often in tag order with small tag +// numbers. +type tagMap struct { + fastTags []int + slowTags map[int]int +} + +// tagMapFastLimit is the upper bound on the tag number that will be stored in +// the tagMap slice rather than its map. +const tagMapFastLimit = 1024 + +func (p *tagMap) get(t int) (int, bool) { + if t > 0 && t < tagMapFastLimit { + if t >= len(p.fastTags) { + return 0, false + } + fi := p.fastTags[t] + return fi, fi >= 0 + } + fi, ok := p.slowTags[t] + return fi, ok +} + +func (p *tagMap) put(t int, fi int) { + if t > 0 && t < tagMapFastLimit { + for len(p.fastTags) < t+1 { + p.fastTags = append(p.fastTags, -1) + } + p.fastTags[t] = fi + return + } + if p.slowTags == nil { + p.slowTags = make(map[int]int) + } + p.slowTags[t] = fi +} + +// StructProperties represents properties for all the fields of a struct. +// decoderTags and decoderOrigNames should only be used by the decoder. +type StructProperties struct { + Prop []*Properties // properties for each field + reqCount int // required count + decoderTags tagMap // map from proto tag to struct field number + decoderOrigNames map[string]int // map from original name to struct field number + order []int // list of struct field numbers in tag order + + // OneofTypes contains information about the oneof fields in this message. + // It is keyed by the original name of a field. + OneofTypes map[string]*OneofProperties +} + +// OneofProperties represents information about a specific field in a oneof. +type OneofProperties struct { + Type reflect.Type // pointer to generated struct type for this oneof field + Field int // struct field number of the containing oneof in the message + Prop *Properties +} + +// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec. +// See encode.go, (*Buffer).enc_struct. + +func (sp *StructProperties) Len() int { return len(sp.order) } +func (sp *StructProperties) Less(i, j int) bool { + return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag +} +func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] } + +// Properties represents the protocol-specific behavior of a single struct field. +type Properties struct { + Name string // name of the field, for error messages + OrigName string // original name before protocol compiler (always set) + JSONName string // name to use for JSON; determined by protoc + Wire string + WireType int + Tag int + Required bool + Optional bool + Repeated bool + Packed bool // relevant for repeated primitives only + Enum string // set for enum types only + proto3 bool // whether this is known to be a proto3 field; set for []byte only + oneof bool // whether this is a oneof field + + Default string // default value + HasDefault bool // whether an explicit default was provided + + stype reflect.Type // set for struct types only + sprop *StructProperties // set for struct types only + + mtype reflect.Type // set for map types only + mkeyprop *Properties // set for map types only + mvalprop *Properties // set for map types only +} + +// String formats the properties in the protobuf struct field tag style. +func (p *Properties) String() string { + s := p.Wire + s += "," + s += strconv.Itoa(p.Tag) + if p.Required { + s += ",req" + } + if p.Optional { + s += ",opt" + } + if p.Repeated { + s += ",rep" + } + if p.Packed { + s += ",packed" + } + s += ",name=" + p.OrigName + if p.JSONName != p.OrigName { + s += ",json=" + p.JSONName + } + if p.proto3 { + s += ",proto3" + } + if p.oneof { + s += ",oneof" + } + if len(p.Enum) > 0 { + s += ",enum=" + p.Enum + } + if p.HasDefault { + s += ",def=" + p.Default + } + return s +} + +// Parse populates p by parsing a string in the protobuf struct field tag style. +func (p *Properties) Parse(s string) { + // "bytes,49,opt,name=foo,def=hello!" + fields := strings.Split(s, ",") // breaks def=, but handled below. + if len(fields) < 2 { + fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) + return + } + + p.Wire = fields[0] + switch p.Wire { + case "varint": + p.WireType = WireVarint + case "fixed32": + p.WireType = WireFixed32 + case "fixed64": + p.WireType = WireFixed64 + case "zigzag32": + p.WireType = WireVarint + case "zigzag64": + p.WireType = WireVarint + case "bytes", "group": + p.WireType = WireBytes + // no numeric converter for non-numeric types + default: + fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) + return + } + + var err error + p.Tag, err = strconv.Atoi(fields[1]) + if err != nil { + return + } + +outer: + for i := 2; i < len(fields); i++ { + f := fields[i] + switch { + case f == "req": + p.Required = true + case f == "opt": + p.Optional = true + case f == "rep": + p.Repeated = true + case f == "packed": + p.Packed = true + case strings.HasPrefix(f, "name="): + p.OrigName = f[5:] + case strings.HasPrefix(f, "json="): + p.JSONName = f[5:] + case strings.HasPrefix(f, "enum="): + p.Enum = f[5:] + case f == "proto3": + p.proto3 = true + case f == "oneof": + p.oneof = true + case strings.HasPrefix(f, "def="): + p.HasDefault = true + p.Default = f[4:] // rest of string + if i+1 < len(fields) { + // Commas aren't escaped, and def is always last. + p.Default += "," + strings.Join(fields[i+1:], ",") + break outer + } + } + } +} + +var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() + +// setFieldProps initializes the field properties for submessages and maps. +func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { + switch t1 := typ; t1.Kind() { + case reflect.Ptr: + if t1.Elem().Kind() == reflect.Struct { + p.stype = t1.Elem() + } + + case reflect.Slice: + if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct { + p.stype = t2.Elem() + } + + case reflect.Map: + p.mtype = t1 + p.mkeyprop = &Properties{} + p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) + p.mvalprop = &Properties{} + vtype := p.mtype.Elem() + if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { + // The value type is not a message (*T) or bytes ([]byte), + // so we need encoders for the pointer to this type. + vtype = reflect.PtrTo(vtype) + } + p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) + } + + if p.stype != nil { + if lockGetProp { + p.sprop = GetProperties(p.stype) + } else { + p.sprop = getPropertiesLocked(p.stype) + } + } +} + +var ( + marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() +) + +// Init populates the properties from a protocol buffer struct tag. +func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { + p.init(typ, name, tag, f, true) +} + +func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) { + // "bytes,49,opt,def=hello!" + p.Name = name + p.OrigName = name + if tag == "" { + return + } + p.Parse(tag) + p.setFieldProps(typ, f, lockGetProp) +} + +var ( + propertiesMu sync.RWMutex + propertiesMap = make(map[reflect.Type]*StructProperties) +) + +// GetProperties returns the list of properties for the type represented by t. +// t must represent a generated struct type of a protocol message. +func GetProperties(t reflect.Type) *StructProperties { + if t.Kind() != reflect.Struct { + panic("proto: type must have kind struct") + } + + // Most calls to GetProperties in a long-running program will be + // retrieving details for types we have seen before. + propertiesMu.RLock() + sprop, ok := propertiesMap[t] + propertiesMu.RUnlock() + if ok { + if collectStats { + stats.Chit++ + } + return sprop + } + + propertiesMu.Lock() + sprop = getPropertiesLocked(t) + propertiesMu.Unlock() + return sprop +} + +// getPropertiesLocked requires that propertiesMu is held. +func getPropertiesLocked(t reflect.Type) *StructProperties { + if prop, ok := propertiesMap[t]; ok { + if collectStats { + stats.Chit++ + } + return prop + } + if collectStats { + stats.Cmiss++ + } + + prop := new(StructProperties) + // in case of recursive protos, fill this in now. + propertiesMap[t] = prop + + // build properties + prop.Prop = make([]*Properties, t.NumField()) + prop.order = make([]int, t.NumField()) + + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + p := new(Properties) + name := f.Name + p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) + + oneof := f.Tag.Get("protobuf_oneof") // special case + if oneof != "" { + // Oneof fields don't use the traditional protobuf tag. + p.OrigName = oneof + } + prop.Prop[i] = p + prop.order[i] = i + if debug { + print(i, " ", f.Name, " ", t.String(), " ") + if p.Tag > 0 { + print(p.String()) + } + print("\n") + } + } + + // Re-order prop.order. + sort.Sort(prop) + + type oneofMessage interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) + } + if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { + var oots []interface{} + _, _, _, oots = om.XXX_OneofFuncs() + + // Interpret oneof metadata. + prop.OneofTypes = make(map[string]*OneofProperties) + for _, oot := range oots { + oop := &OneofProperties{ + Type: reflect.ValueOf(oot).Type(), // *T + Prop: new(Properties), + } + sft := oop.Type.Elem().Field(0) + oop.Prop.Name = sft.Name + oop.Prop.Parse(sft.Tag.Get("protobuf")) + // There will be exactly one interface field that + // this new value is assignable to. + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if f.Type.Kind() != reflect.Interface { + continue + } + if !oop.Type.AssignableTo(f.Type) { + continue + } + oop.Field = i + break + } + prop.OneofTypes[oop.Prop.OrigName] = oop + } + } + + // build required counts + // build tags + reqCount := 0 + prop.decoderOrigNames = make(map[string]int) + for i, p := range prop.Prop { + if strings.HasPrefix(p.Name, "XXX_") { + // Internal fields should not appear in tags/origNames maps. + // They are handled specially when encoding and decoding. + continue + } + if p.Required { + reqCount++ + } + prop.decoderTags.put(p.Tag, i) + prop.decoderOrigNames[p.OrigName] = i + } + prop.reqCount = reqCount + + return prop +} + +// A global registry of enum types. +// The generated code will register the generated maps by calling RegisterEnum. + +var enumValueMaps = make(map[string]map[string]int32) + +// RegisterEnum is called from the generated code to install the enum descriptor +// maps into the global table to aid parsing text format protocol buffers. +func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { + if _, ok := enumValueMaps[typeName]; ok { + panic("proto: duplicate enum registered: " + typeName) + } + enumValueMaps[typeName] = valueMap +} + +// EnumValueMap returns the mapping from names to integers of the +// enum type enumType, or a nil if not found. +func EnumValueMap(enumType string) map[string]int32 { + return enumValueMaps[enumType] +} + +// A registry of all linked message types. +// The string is a fully-qualified proto name ("pkg.Message"). +var ( + protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers + protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types + revProtoTypes = make(map[reflect.Type]string) +) + +// RegisterType is called from generated code and maps from the fully qualified +// proto name to the type (pointer to struct) of the protocol buffer. +func RegisterType(x Message, name string) { + if _, ok := protoTypedNils[name]; ok { + // TODO: Some day, make this a panic. + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 { + // Generated code always calls RegisterType with nil x. + // This check is just for extra safety. + protoTypedNils[name] = x + } else { + protoTypedNils[name] = reflect.Zero(t).Interface().(Message) + } + revProtoTypes[t] = name +} + +// RegisterMapType is called from generated code and maps from the fully qualified +// proto name to the native map type of the proto map definition. +func RegisterMapType(x interface{}, name string) { + if reflect.TypeOf(x).Kind() != reflect.Map { + panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name)) + } + if _, ok := protoMapTypes[name]; ok { + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + protoMapTypes[name] = t + revProtoTypes[t] = name +} + +// MessageName returns the fully-qualified proto name for the given message type. +func MessageName(x Message) string { + type xname interface { + XXX_MessageName() string + } + if m, ok := x.(xname); ok { + return m.XXX_MessageName() + } + return revProtoTypes[reflect.TypeOf(x)] +} + +// MessageType returns the message type (pointer to struct) for a named message. +// The type is not guaranteed to implement proto.Message if the name refers to a +// map entry. +func MessageType(name string) reflect.Type { + if t, ok := protoTypedNils[name]; ok { + return reflect.TypeOf(t) + } + return protoMapTypes[name] +} + +// A registry of all linked proto files. +var ( + protoFiles = make(map[string][]byte) // file name => fileDescriptor +) + +// RegisterFile is called from generated code and maps from the +// full file name of a .proto file to its compressed FileDescriptorProto. +func RegisterFile(filename string, fileDescriptor []byte) { + protoFiles[filename] = fileDescriptor +} + +// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. +func FileDescriptor(filename string) []byte { return protoFiles[filename] } diff --git a/vendor/github.com/golang/protobuf/proto/table_marshal.go b/vendor/github.com/golang/protobuf/proto/table_marshal.go new file mode 100644 index 00000000..0f212b30 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/table_marshal.go @@ -0,0 +1,2681 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "errors" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// a sizer takes a pointer to a field and the size of its tag, computes the size of +// the encoded data. +type sizer func(pointer, int) int + +// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format), +// marshals the field to the end of the slice, returns the slice and error (if any). +type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) + +// marshalInfo is the information used for marshaling a message. +type marshalInfo struct { + typ reflect.Type + fields []*marshalFieldInfo + unrecognized field // offset of XXX_unrecognized + extensions field // offset of XXX_InternalExtensions + v1extensions field // offset of XXX_extensions + sizecache field // offset of XXX_sizecache + initialized int32 // 0 -- only typ is set, 1 -- fully initialized + messageset bool // uses message set wire format + hasmarshaler bool // has custom marshaler + sync.RWMutex // protect extElems map, also for initialization + extElems map[int32]*marshalElemInfo // info of extension elements +} + +// marshalFieldInfo is the information used for marshaling a field of a message. +type marshalFieldInfo struct { + field field + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isPointer bool + required bool // field is required + name string // name of the field, for error reporting + oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements +} + +// marshalElemInfo is the information used for marshaling an extension or oneof element. +type marshalElemInfo struct { + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only) +} + +var ( + marshalInfoMap = map[reflect.Type]*marshalInfo{} + marshalInfoLock sync.Mutex +) + +// getMarshalInfo returns the information to marshal a given type of message. +// The info it returns may not necessarily initialized. +// t is the type of the message (NOT the pointer to it). +func getMarshalInfo(t reflect.Type) *marshalInfo { + marshalInfoLock.Lock() + u, ok := marshalInfoMap[t] + if !ok { + u = &marshalInfo{typ: t} + marshalInfoMap[t] = u + } + marshalInfoLock.Unlock() + return u +} + +// Size is the entry point from generated code, +// and should be ONLY called by generated code. +// It computes the size of encoded data of msg. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Size(msg Message) int { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return 0 + } + return u.size(ptr) +} + +// Marshal is the entry point from generated code, +// and should be ONLY called by generated code. +// It marshals msg to the end of b. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return b, ErrNil + } + return u.marshal(b, ptr, deterministic) +} + +func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo { + // u := a.marshal, but atomically. + // We use an atomic here to ensure memory consistency. + u := atomicLoadMarshalInfo(&a.marshal) + if u == nil { + // Get marshal information from type of message. + t := reflect.ValueOf(msg).Type() + if t.Kind() != reflect.Ptr { + panic(fmt.Sprintf("cannot handle non-pointer message type %v", t)) + } + u = getMarshalInfo(t.Elem()) + // Store it in the cache for later users. + // a.marshal = u, but atomically. + atomicStoreMarshalInfo(&a.marshal, u) + } + return u +} + +// size is the main function to compute the size of the encoded data of a message. +// ptr is the pointer to the message. +func (u *marshalInfo) size(ptr pointer) int { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b, _ := m.Marshal() + return len(b) + } + + n := 0 + for _, f := range u.fields { + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + n += f.sizer(ptr.offset(f.field), f.tagsize) + } + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + n += u.sizeMessageSet(e) + } else { + n += u.sizeExtensions(e) + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + n += u.sizeV1Extensions(m) + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + n += len(s) + } + // cache the result for use in marshal + if u.sizecache.IsValid() { + atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n)) + } + return n +} + +// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated), +// fall back to compute the size. +func (u *marshalInfo) cachedsize(ptr pointer) int { + if u.sizecache.IsValid() { + return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32())) + } + return u.size(ptr) +} + +// marshal is the main function to marshal a message. It takes a byte slice and appends +// the encoded data to the end of the slice, returns the slice and error (if any). +// ptr is the pointer to the message. +// If deterministic is true, map is marshaled in deterministic order. +func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b1, err := m.Marshal() + b = append(b, b1...) + return b, err + } + + var err, errreq error + // The old marshaler encodes extensions at beginning. + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + b, err = u.appendMessageSet(b, e, deterministic) + } else { + b, err = u.appendExtensions(b, e, deterministic) + } + if err != nil { + return b, err + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + b, err = u.appendV1Extensions(b, m, deterministic) + if err != nil { + return b, err + } + } + for _, f := range u.fields { + if f.required && errreq == nil { + if ptr.offset(f.field).getPointer().isNil() { + // Required field is not set. + // We record the error but keep going, to give a complete marshaling. + errreq = &RequiredNotSetError{f.name} + continue + } + } + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic) + if err != nil { + if err1, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errreq == nil { + errreq = &RequiredNotSetError{f.name + "." + err1.field} + } + continue + } + if err == errRepeatedHasNil { + err = errors.New("proto: repeated field " + f.name + " has nil element") + } + return b, err + } + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + b = append(b, s...) + } + return b, errreq +} + +// computeMarshalInfo initializes the marshal info. +func (u *marshalInfo) computeMarshalInfo() { + u.Lock() + defer u.Unlock() + if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock + return + } + + t := u.typ + u.unrecognized = invalidField + u.extensions = invalidField + u.v1extensions = invalidField + u.sizecache = invalidField + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if reflect.PtrTo(t).Implements(marshalerType) { + u.hasmarshaler = true + atomic.StoreInt32(&u.initialized, 1) + return + } + + // get oneof implementers + var oneofImplementers []interface{} + if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { + _, _, _, oneofImplementers = m.XXX_OneofFuncs() + } + + n := t.NumField() + + // deal with XXX fields first + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if !strings.HasPrefix(f.Name, "XXX_") { + continue + } + switch f.Name { + case "XXX_sizecache": + u.sizecache = toField(&f) + case "XXX_unrecognized": + u.unrecognized = toField(&f) + case "XXX_InternalExtensions": + u.extensions = toField(&f) + u.messageset = f.Tag.Get("protobuf_messageset") == "1" + case "XXX_extensions": + u.v1extensions = toField(&f) + case "XXX_NoUnkeyedLiteral": + // nothing to do + default: + panic("unknown XXX field: " + f.Name) + } + n-- + } + + // normal fields + fields := make([]marshalFieldInfo, n) // batch allocation + u.fields = make([]*marshalFieldInfo, 0, n) + for i, j := 0, 0; i < t.NumField(); i++ { + f := t.Field(i) + + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + field := &fields[j] + j++ + field.name = f.Name + u.fields = append(u.fields, field) + if f.Tag.Get("protobuf_oneof") != "" { + field.computeOneofFieldInfo(&f, oneofImplementers) + continue + } + if f.Tag.Get("protobuf") == "" { + // field has no tag (not in generated message), ignore it + u.fields = u.fields[:len(u.fields)-1] + j-- + continue + } + field.computeMarshalFieldInfo(&f) + } + + // fields are marshaled in tag order on the wire. + sort.Sort(byTag(u.fields)) + + atomic.StoreInt32(&u.initialized, 1) +} + +// helper for sorting fields by tag +type byTag []*marshalFieldInfo + +func (a byTag) Len() int { return len(a) } +func (a byTag) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag } + +// getExtElemInfo returns the information to marshal an extension element. +// The info it returns is initialized. +func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo { + // get from cache first + u.RLock() + e, ok := u.extElems[desc.Field] + u.RUnlock() + if ok { + return e + } + + t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct + tags := strings.Split(desc.Tag, ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizer, marshaler := typeMarshaler(t, tags, false, false) + e = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizer, + marshaler: marshaler, + isptr: t.Kind() == reflect.Ptr, + } + + // update cache + u.Lock() + if u.extElems == nil { + u.extElems = make(map[int32]*marshalElemInfo) + } + u.extElems[desc.Field] = e + u.Unlock() + return e +} + +// computeMarshalFieldInfo fills up the information to marshal a field. +func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) { + // parse protobuf tag of the field. + // tag has format of "bytes,49,opt,name=foo,def=hello!" + tags := strings.Split(f.Tag.Get("protobuf"), ",") + if tags[0] == "" { + return + } + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + if tags[2] == "req" { + fi.required = true + } + fi.setTag(f, tag, wt) + fi.setMarshaler(f, tags) +} + +func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) { + fi.field = toField(f) + fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire. + fi.isPointer = true + fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f) + fi.oneofElems = make(map[reflect.Type]*marshalElemInfo) + + ityp := f.Type // interface type + for _, o := range oneofImplementers { + t := reflect.TypeOf(o) + if !t.Implements(ityp) { + continue + } + sf := t.Elem().Field(0) // oneof implementer is a struct with a single field + tags := strings.Split(sf.Tag.Get("protobuf"), ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizer, marshaler := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value + fi.oneofElems[t.Elem()] = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizer, + marshaler: marshaler, + } + } +} + +type oneofMessage interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) +} + +// wiretype returns the wire encoding of the type. +func wiretype(encoding string) uint64 { + switch encoding { + case "fixed32": + return WireFixed32 + case "fixed64": + return WireFixed64 + case "varint", "zigzag32", "zigzag64": + return WireVarint + case "bytes": + return WireBytes + case "group": + return WireStartGroup + } + panic("unknown wire type " + encoding) +} + +// setTag fills up the tag (in wire format) and its size in the info of a field. +func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) { + fi.field = toField(f) + fi.wiretag = uint64(tag)<<3 | wt + fi.tagsize = SizeVarint(uint64(tag) << 3) +} + +// setMarshaler fills up the sizer and marshaler in the info of a field. +func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) { + switch f.Type.Kind() { + case reflect.Map: + // map field + fi.isPointer = true + fi.sizer, fi.marshaler = makeMapMarshaler(f) + return + case reflect.Ptr, reflect.Slice: + fi.isPointer = true + } + fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false) +} + +// typeMarshaler returns the sizer and marshaler of a given field. +// t is the type of the field. +// tags is the generated "protobuf" tag of the field. +// If nozero is true, zero value is not marshaled to the wire. +// If oneof is true, it is a oneof field. +func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) { + encoding := tags[0] + + pointer := false + slice := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + packed := false + proto3 := false + for i := 2; i < len(tags); i++ { + if tags[i] == "packed" { + packed = true + } + if tags[i] == "proto3" { + proto3 = true + } + } + + switch t.Kind() { + case reflect.Bool: + if pointer { + return sizeBoolPtr, appendBoolPtr + } + if slice { + if packed { + return sizeBoolPackedSlice, appendBoolPackedSlice + } + return sizeBoolSlice, appendBoolSlice + } + if nozero { + return sizeBoolValueNoZero, appendBoolValueNoZero + } + return sizeBoolValue, appendBoolValue + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixed32Ptr, appendFixed32Ptr + } + if slice { + if packed { + return sizeFixed32PackedSlice, appendFixed32PackedSlice + } + return sizeFixed32Slice, appendFixed32Slice + } + if nozero { + return sizeFixed32ValueNoZero, appendFixed32ValueNoZero + } + return sizeFixed32Value, appendFixed32Value + case "varint": + if pointer { + return sizeVarint32Ptr, appendVarint32Ptr + } + if slice { + if packed { + return sizeVarint32PackedSlice, appendVarint32PackedSlice + } + return sizeVarint32Slice, appendVarint32Slice + } + if nozero { + return sizeVarint32ValueNoZero, appendVarint32ValueNoZero + } + return sizeVarint32Value, appendVarint32Value + } + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixedS32Ptr, appendFixedS32Ptr + } + if slice { + if packed { + return sizeFixedS32PackedSlice, appendFixedS32PackedSlice + } + return sizeFixedS32Slice, appendFixedS32Slice + } + if nozero { + return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero + } + return sizeFixedS32Value, appendFixedS32Value + case "varint": + if pointer { + return sizeVarintS32Ptr, appendVarintS32Ptr + } + if slice { + if packed { + return sizeVarintS32PackedSlice, appendVarintS32PackedSlice + } + return sizeVarintS32Slice, appendVarintS32Slice + } + if nozero { + return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero + } + return sizeVarintS32Value, appendVarintS32Value + case "zigzag32": + if pointer { + return sizeZigzag32Ptr, appendZigzag32Ptr + } + if slice { + if packed { + return sizeZigzag32PackedSlice, appendZigzag32PackedSlice + } + return sizeZigzag32Slice, appendZigzag32Slice + } + if nozero { + return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero + } + return sizeZigzag32Value, appendZigzag32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixed64Ptr, appendFixed64Ptr + } + if slice { + if packed { + return sizeFixed64PackedSlice, appendFixed64PackedSlice + } + return sizeFixed64Slice, appendFixed64Slice + } + if nozero { + return sizeFixed64ValueNoZero, appendFixed64ValueNoZero + } + return sizeFixed64Value, appendFixed64Value + case "varint": + if pointer { + return sizeVarint64Ptr, appendVarint64Ptr + } + if slice { + if packed { + return sizeVarint64PackedSlice, appendVarint64PackedSlice + } + return sizeVarint64Slice, appendVarint64Slice + } + if nozero { + return sizeVarint64ValueNoZero, appendVarint64ValueNoZero + } + return sizeVarint64Value, appendVarint64Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixedS64Ptr, appendFixedS64Ptr + } + if slice { + if packed { + return sizeFixedS64PackedSlice, appendFixedS64PackedSlice + } + return sizeFixedS64Slice, appendFixedS64Slice + } + if nozero { + return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero + } + return sizeFixedS64Value, appendFixedS64Value + case "varint": + if pointer { + return sizeVarintS64Ptr, appendVarintS64Ptr + } + if slice { + if packed { + return sizeVarintS64PackedSlice, appendVarintS64PackedSlice + } + return sizeVarintS64Slice, appendVarintS64Slice + } + if nozero { + return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero + } + return sizeVarintS64Value, appendVarintS64Value + case "zigzag64": + if pointer { + return sizeZigzag64Ptr, appendZigzag64Ptr + } + if slice { + if packed { + return sizeZigzag64PackedSlice, appendZigzag64PackedSlice + } + return sizeZigzag64Slice, appendZigzag64Slice + } + if nozero { + return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero + } + return sizeZigzag64Value, appendZigzag64Value + } + case reflect.Float32: + if pointer { + return sizeFloat32Ptr, appendFloat32Ptr + } + if slice { + if packed { + return sizeFloat32PackedSlice, appendFloat32PackedSlice + } + return sizeFloat32Slice, appendFloat32Slice + } + if nozero { + return sizeFloat32ValueNoZero, appendFloat32ValueNoZero + } + return sizeFloat32Value, appendFloat32Value + case reflect.Float64: + if pointer { + return sizeFloat64Ptr, appendFloat64Ptr + } + if slice { + if packed { + return sizeFloat64PackedSlice, appendFloat64PackedSlice + } + return sizeFloat64Slice, appendFloat64Slice + } + if nozero { + return sizeFloat64ValueNoZero, appendFloat64ValueNoZero + } + return sizeFloat64Value, appendFloat64Value + case reflect.String: + if pointer { + return sizeStringPtr, appendStringPtr + } + if slice { + return sizeStringSlice, appendStringSlice + } + if nozero { + return sizeStringValueNoZero, appendStringValueNoZero + } + return sizeStringValue, appendStringValue + case reflect.Slice: + if slice { + return sizeBytesSlice, appendBytesSlice + } + if oneof { + // Oneof bytes field may also have "proto3" tag. + // We want to marshal it as a oneof field. Do this + // check before the proto3 check. + return sizeBytesOneof, appendBytesOneof + } + if proto3 { + return sizeBytes3, appendBytes3 + } + return sizeBytes, appendBytes + case reflect.Struct: + switch encoding { + case "group": + if slice { + return makeGroupSliceMarshaler(getMarshalInfo(t)) + } + return makeGroupMarshaler(getMarshalInfo(t)) + case "bytes": + if slice { + return makeMessageSliceMarshaler(getMarshalInfo(t)) + } + return makeMessageMarshaler(getMarshalInfo(t)) + } + } + panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding)) +} + +// Below are functions to size/marshal a specific type of a field. +// They are stored in the field's info, and called by function pointers. +// They have type sizer or marshaler. + +func sizeFixed32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixed32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixedS32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFloat32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + return (4 + tagsize) * len(s) +} +func sizeFloat32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixed64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixed64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFixedS64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFloat64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + return (8 + tagsize) * len(s) +} +func sizeFloat64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeVarint32Value(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarint32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarint32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarint64Value(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + return SizeVarint(v) + tagsize +} +func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return SizeVarint(v) + tagsize +} +func sizeVarint64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return SizeVarint(*p) + tagsize +} +func sizeVarint64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(v) + tagsize + } + return n +} +func sizeVarint64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize + } + return n +} +func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize + } + return n +} +func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeBoolValue(_ pointer, tagsize int) int { + return 1 + tagsize +} +func sizeBoolValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toBool() + if !v { + return 0 + } + return 1 + tagsize +} +func sizeBoolPtr(ptr pointer, tagsize int) int { + p := *ptr.toBoolPtr() + if p == nil { + return 0 + } + return 1 + tagsize +} +func sizeBoolSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + return (1 + tagsize) * len(s) +} +func sizeBoolPackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return 0 + } + return len(s) + SizeVarint(uint64(len(s))) + tagsize +} +func sizeStringValue(ptr pointer, tagsize int) int { + v := *ptr.toString() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toString() + if v == "" { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringPtr(ptr pointer, tagsize int) int { + p := *ptr.toStringPtr() + if p == nil { + return 0 + } + v := *p + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringSlice(ptr pointer, tagsize int) int { + s := *ptr.toStringSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} +func sizeBytes(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if v == nil { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytes3(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if len(v) == 0 { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesOneof(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesSlice(ptr pointer, tagsize int) int { + s := *ptr.toBytesSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} + +// appendFixed32 appends an encoded fixed32 to b. +func appendFixed32(b []byte, v uint32) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24)) + return b +} + +// appendFixed64 appends an encoded fixed64 to b. +func appendFixed64(b []byte, v uint64) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + byte(v>>32), + byte(v>>40), + byte(v>>48), + byte(v>>56)) + return b +} + +// appendVarint appends an encoded varint to b. +func appendVarint(b []byte, v uint64) []byte { + // TODO: make 1-byte (maybe 2-byte) case inline-able, once we + // have non-leaf inliner. + switch { + case v < 1<<7: + b = append(b, byte(v)) + case v < 1<<14: + b = append(b, + byte(v&0x7f|0x80), + byte(v>>7)) + case v < 1<<21: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte(v>>14)) + case v < 1<<28: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte(v>>21)) + case v < 1<<35: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte(v>>28)) + case v < 1<<42: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte(v>>35)) + case v < 1<<49: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte(v>>42)) + case v < 1<<56: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte(v>>49)) + case v < 1<<63: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte(v>>56)) + default: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte((v>>56)&0x7f|0x80), + 1) + } + return b +} + +func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, *p) + return b, nil +} +func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(*p)) + return b, nil +} +func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(*p)) + return b, nil +} +func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, *p) + return b, nil +} +func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(*p)) + return b, nil +} +func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(*p)) + return b, nil +} +func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, *p) + return b, nil +} +func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + } + return b, nil +} +func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, v) + } + return b, nil +} +func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + if !v { + return b, nil + } + b = appendVarint(b, wiretag) + b = append(b, 1) + return b, nil +} + +func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toBoolPtr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + if *p { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(len(s))) + for _, v := range s { + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + if v == "" { + return b, nil + } + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toStringPtr() + if p == nil { + return b, nil + } + v := *p + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toStringSlice() + for _, v := range s { + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} +func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if v == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if len(v) == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBytesSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} + +// makeGroupMarshaler returns the sizer and marshaler for a group. +// u is the marshal info of the underlying message. +func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + return u.size(p) + 2*tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + var err error + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, p, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + return b, err + } +} + +// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice. +// u is the marshal info of the underlying message. +func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + n += u.size(v) + 2*tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err, errreq error + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, v, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + if err != nil { + if _, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errreq == nil { + errreq = err + } + continue + } + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, errreq + } +} + +// makeMessageMarshaler returns the sizer and marshaler for a message field. +// u is the marshal info of the message. +func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + siz := u.size(p) + return siz + SizeVarint(uint64(siz)) + tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(p) + b = appendVarint(b, uint64(siz)) + return u.marshal(b, p, deterministic) + } +} + +// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice. +// u is the marshal info of the message. +func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + siz := u.size(v) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err, errreq error + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(v) + b = appendVarint(b, uint64(siz)) + b, err = u.marshal(b, v, deterministic) + + if err != nil { + if _, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errreq == nil { + errreq = err + } + continue + } + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, errreq + } +} + +// makeMapMarshaler returns the sizer and marshaler for a map field. +// f is the pointer to the reflect data structure of the field. +func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) { + // figure out key and value type + t := f.Type + keyType := t.Key() + valType := t.Elem() + keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",") + valTags := strings.Split(f.Tag.Get("protobuf_val"), ",") + keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map + valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map + keyWireTag := 1<<3 | wiretype(keyTags[0]) + valWireTag := 2<<3 | wiretype(valTags[0]) + + // We create an interface to get the addresses of the map key and value. + // If value is pointer-typed, the interface is a direct interface, the + // idata itself is the value. Otherwise, the idata is the pointer to the + // value. + // Key cannot be pointer-typed. + valIsPtr := valType.Kind() == reflect.Ptr + return func(ptr pointer, tagsize int) int { + m := ptr.asPointerTo(t).Elem() // the map + n := 0 + for _, k := range m.MapKeys() { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value + siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) { + m := ptr.asPointerTo(t).Elem() // the map + var err error + keys := m.MapKeys() + if len(keys) > 1 && deterministic { + sort.Sort(mapKeys(keys)) + } + for _, k := range keys { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value + b = appendVarint(b, tag) + siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + b = appendVarint(b, uint64(siz)) + b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic) + if err != nil { + return b, err + } + b, err = valMarshaler(b, vaddr, valWireTag, deterministic) + if err != nil && err != ErrNil { // allow nil value in map + return b, err + } + } + return b, nil + } +} + +// makeOneOfMarshaler returns the sizer and marshaler for a oneof field. +// fi is the marshal info of the field. +// f is the pointer to the reflect data structure of the field. +func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) { + // Oneof field is an interface. We need to get the actual data type on the fly. + t := f.Type + return func(ptr pointer, _ int) int { + p := ptr.getInterfacePointer() + if p.isNil() { + return 0 + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + e := fi.oneofElems[telem] + return e.sizer(p, e.tagsize) + }, + func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) { + p := ptr.getInterfacePointer() + if p.isNil() { + return b, nil + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() { + return b, errOneofHasNil + } + e := fi.oneofElems[telem] + return e.marshaler(b, p, e.wiretag, deterministic) + } +} + +// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field. +func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, ei.tagsize) + } + mu.Unlock() + return n +} + +// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b. +func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if err != nil { + return b, err + } + } + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + // Not sure this is required, but the old code does it. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if err != nil { + return b, err + } + } + return b, nil +} + +// message set format is: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } + +// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field +// in message set format (above). +func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for id, e := range m { + n += 2 // start group, end group. tag = 1 (size=1) + n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + siz := len(msgWithLen) + n += siz + 1 // message, tag = 3 (size=1) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, 1) // message, tag = 3 (size=1) + } + mu.Unlock() + return n +} + +// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above) +// to the end of byte slice b. +func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for id, e := range m { + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + if err != nil { + return b, err + } + b = append(b, 1<<3|WireEndGroup) + } + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, id := range keys { + e := m[int32(id)] + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + b = append(b, 1<<3|WireEndGroup) + if err != nil { + return b, err + } + } + return b, nil +} + +// sizeV1Extensions computes the size of encoded data for a V1-API extension field. +func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int { + if m == nil { + return 0 + } + + n := 0 + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + n += len(e.enc) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + n += ei.sizer(p, ei.tagsize) + } + return n +} + +// appendV1Extensions marshals a V1-API extension field to the end of byte slice b. +func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) { + if m == nil { + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + var err error + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, e.enc...) + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if err != nil { + return b, err + } + } + return b, nil +} + +// newMarshaler is the interface representing objects that can marshal themselves. +// +// This exists to support protoc-gen-go generated messages. +// The proto package will stop type-asserting to this interface in the future. +// +// DO NOT DEPEND ON THIS. +type newMarshaler interface { + XXX_Size() int + XXX_Marshal(b []byte, deterministic bool) ([]byte, error) +} + +// Size returns the encoded size of a protocol buffer message. +// This is the main entry point. +func Size(pb Message) int { + if m, ok := pb.(newMarshaler); ok { + return m.XXX_Size() + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, _ := m.Marshal() + return len(b) + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return 0 + } + var info InternalMessageInfo + return info.Size(pb) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, returning the data. +// This is the main entry point. +func Marshal(pb Message) ([]byte, error) { + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + b := make([]byte, 0, siz) + return m.XXX_Marshal(b, false) + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + return m.Marshal() + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return nil, ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + b := make([]byte, 0, siz) + return info.Marshal(b, pb, false) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, writing the result to the +// Buffer. +// This is an alternative entry point. It is not necessary to use +// a Buffer for most applications. +func (p *Buffer) Marshal(pb Message) error { + var err error + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + p.grow(siz) // make sure buf has enough capacity + p.buf, err = m.XXX_Marshal(p.buf, p.deterministic) + return err + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, err := m.Marshal() + p.buf = append(p.buf, b...) + return err + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + p.grow(siz) // make sure buf has enough capacity + p.buf, err = info.Marshal(p.buf, pb, p.deterministic) + return err +} + +// grow grows the buffer's capacity, if necessary, to guarantee space for +// another n bytes. After grow(n), at least n bytes can be written to the +// buffer without another allocation. +func (p *Buffer) grow(n int) { + need := len(p.buf) + n + if need <= cap(p.buf) { + return + } + newCap := len(p.buf) * 2 + if newCap < need { + newCap = need + } + p.buf = append(make([]byte, 0, newCap), p.buf...) +} diff --git a/vendor/github.com/golang/protobuf/proto/table_merge.go b/vendor/github.com/golang/protobuf/proto/table_merge.go new file mode 100644 index 00000000..5525def6 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/table_merge.go @@ -0,0 +1,654 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "fmt" + "reflect" + "strings" + "sync" + "sync/atomic" +) + +// Merge merges the src message into dst. +// This assumes that dst and src of the same type and are non-nil. +func (a *InternalMessageInfo) Merge(dst, src Message) { + mi := atomicLoadMergeInfo(&a.merge) + if mi == nil { + mi = getMergeInfo(reflect.TypeOf(dst).Elem()) + atomicStoreMergeInfo(&a.merge, mi) + } + mi.merge(toPointer(&dst), toPointer(&src)) +} + +type mergeInfo struct { + typ reflect.Type + + initialized int32 // 0: only typ is valid, 1: everything is valid + lock sync.Mutex + + fields []mergeFieldInfo + unrecognized field // Offset of XXX_unrecognized +} + +type mergeFieldInfo struct { + field field // Offset of field, guaranteed to be valid + + // isPointer reports whether the value in the field is a pointer. + // This is true for the following situations: + // * Pointer to struct + // * Pointer to basic type (proto2 only) + // * Slice (first value in slice header is a pointer) + // * String (first value in string header is a pointer) + isPointer bool + + // basicWidth reports the width of the field assuming that it is directly + // embedded in the struct (as is the case for basic types in proto3). + // The possible values are: + // 0: invalid + // 1: bool + // 4: int32, uint32, float32 + // 8: int64, uint64, float64 + basicWidth int + + // Where dst and src are pointers to the types being merged. + merge func(dst, src pointer) +} + +var ( + mergeInfoMap = map[reflect.Type]*mergeInfo{} + mergeInfoLock sync.Mutex +) + +func getMergeInfo(t reflect.Type) *mergeInfo { + mergeInfoLock.Lock() + defer mergeInfoLock.Unlock() + mi := mergeInfoMap[t] + if mi == nil { + mi = &mergeInfo{typ: t} + mergeInfoMap[t] = mi + } + return mi +} + +// merge merges src into dst assuming they are both of type *mi.typ. +func (mi *mergeInfo) merge(dst, src pointer) { + if dst.isNil() { + panic("proto: nil destination") + } + if src.isNil() { + return // Nothing to do. + } + + if atomic.LoadInt32(&mi.initialized) == 0 { + mi.computeMergeInfo() + } + + for _, fi := range mi.fields { + sfp := src.offset(fi.field) + + // As an optimization, we can avoid the merge function call cost + // if we know for sure that the source will have no effect + // by checking if it is the zero value. + if unsafeAllowed { + if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string + continue + } + if fi.basicWidth > 0 { + switch { + case fi.basicWidth == 1 && !*sfp.toBool(): + continue + case fi.basicWidth == 4 && *sfp.toUint32() == 0: + continue + case fi.basicWidth == 8 && *sfp.toUint64() == 0: + continue + } + } + } + + dfp := dst.offset(fi.field) + fi.merge(dfp, sfp) + } + + // TODO: Make this faster? + out := dst.asPointerTo(mi.typ).Elem() + in := src.asPointerTo(mi.typ).Elem() + if emIn, err := extendable(in.Addr().Interface()); err == nil { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } + } + + if mi.unrecognized.IsValid() { + if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 { + *dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...) + } + } +} + +func (mi *mergeInfo) computeMergeInfo() { + mi.lock.Lock() + defer mi.lock.Unlock() + if mi.initialized != 0 { + return + } + t := mi.typ + n := t.NumField() + + props := GetProperties(t) + for i := 0; i < n; i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + + mfi := mergeFieldInfo{field: toField(&f)} + tf := f.Type + + // As an optimization, we can avoid the merge function call cost + // if we know for sure that the source will have no effect + // by checking if it is the zero value. + if unsafeAllowed { + switch tf.Kind() { + case reflect.Ptr, reflect.Slice, reflect.String: + // As a special case, we assume slices and strings are pointers + // since we know that the first field in the SliceSlice or + // StringHeader is a data pointer. + mfi.isPointer = true + case reflect.Bool: + mfi.basicWidth = 1 + case reflect.Int32, reflect.Uint32, reflect.Float32: + mfi.basicWidth = 4 + case reflect.Int64, reflect.Uint64, reflect.Float64: + mfi.basicWidth = 8 + } + } + + // Unwrap tf to get at its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + tf.Name()) + } + + switch tf.Kind() { + case reflect.Int32: + switch { + case isSlice: // E.g., []int32 + mfi.merge = func(dst, src pointer) { + // NOTE: toInt32Slice is not defined (see pointer_reflect.go). + /* + sfsp := src.toInt32Slice() + if *sfsp != nil { + dfsp := dst.toInt32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []int64{} + } + } + */ + sfs := src.getInt32Slice() + if sfs != nil { + dfs := dst.getInt32Slice() + dfs = append(dfs, sfs...) + if dfs == nil { + dfs = []int32{} + } + dst.setInt32Slice(dfs) + } + } + case isPointer: // E.g., *int32 + mfi.merge = func(dst, src pointer) { + // NOTE: toInt32Ptr is not defined (see pointer_reflect.go). + /* + sfpp := src.toInt32Ptr() + if *sfpp != nil { + dfpp := dst.toInt32Ptr() + if *dfpp == nil { + *dfpp = Int32(**sfpp) + } else { + **dfpp = **sfpp + } + } + */ + sfp := src.getInt32Ptr() + if sfp != nil { + dfp := dst.getInt32Ptr() + if dfp == nil { + dst.setInt32Ptr(*sfp) + } else { + *dfp = *sfp + } + } + } + default: // E.g., int32 + mfi.merge = func(dst, src pointer) { + if v := *src.toInt32(); v != 0 { + *dst.toInt32() = v + } + } + } + case reflect.Int64: + switch { + case isSlice: // E.g., []int64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toInt64Slice() + if *sfsp != nil { + dfsp := dst.toInt64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []int64{} + } + } + } + case isPointer: // E.g., *int64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toInt64Ptr() + if *sfpp != nil { + dfpp := dst.toInt64Ptr() + if *dfpp == nil { + *dfpp = Int64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., int64 + mfi.merge = func(dst, src pointer) { + if v := *src.toInt64(); v != 0 { + *dst.toInt64() = v + } + } + } + case reflect.Uint32: + switch { + case isSlice: // E.g., []uint32 + mfi.merge = func(dst, src pointer) { + sfsp := src.toUint32Slice() + if *sfsp != nil { + dfsp := dst.toUint32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []uint32{} + } + } + } + case isPointer: // E.g., *uint32 + mfi.merge = func(dst, src pointer) { + sfpp := src.toUint32Ptr() + if *sfpp != nil { + dfpp := dst.toUint32Ptr() + if *dfpp == nil { + *dfpp = Uint32(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., uint32 + mfi.merge = func(dst, src pointer) { + if v := *src.toUint32(); v != 0 { + *dst.toUint32() = v + } + } + } + case reflect.Uint64: + switch { + case isSlice: // E.g., []uint64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toUint64Slice() + if *sfsp != nil { + dfsp := dst.toUint64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []uint64{} + } + } + } + case isPointer: // E.g., *uint64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toUint64Ptr() + if *sfpp != nil { + dfpp := dst.toUint64Ptr() + if *dfpp == nil { + *dfpp = Uint64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., uint64 + mfi.merge = func(dst, src pointer) { + if v := *src.toUint64(); v != 0 { + *dst.toUint64() = v + } + } + } + case reflect.Float32: + switch { + case isSlice: // E.g., []float32 + mfi.merge = func(dst, src pointer) { + sfsp := src.toFloat32Slice() + if *sfsp != nil { + dfsp := dst.toFloat32Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []float32{} + } + } + } + case isPointer: // E.g., *float32 + mfi.merge = func(dst, src pointer) { + sfpp := src.toFloat32Ptr() + if *sfpp != nil { + dfpp := dst.toFloat32Ptr() + if *dfpp == nil { + *dfpp = Float32(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., float32 + mfi.merge = func(dst, src pointer) { + if v := *src.toFloat32(); v != 0 { + *dst.toFloat32() = v + } + } + } + case reflect.Float64: + switch { + case isSlice: // E.g., []float64 + mfi.merge = func(dst, src pointer) { + sfsp := src.toFloat64Slice() + if *sfsp != nil { + dfsp := dst.toFloat64Slice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []float64{} + } + } + } + case isPointer: // E.g., *float64 + mfi.merge = func(dst, src pointer) { + sfpp := src.toFloat64Ptr() + if *sfpp != nil { + dfpp := dst.toFloat64Ptr() + if *dfpp == nil { + *dfpp = Float64(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., float64 + mfi.merge = func(dst, src pointer) { + if v := *src.toFloat64(); v != 0 { + *dst.toFloat64() = v + } + } + } + case reflect.Bool: + switch { + case isSlice: // E.g., []bool + mfi.merge = func(dst, src pointer) { + sfsp := src.toBoolSlice() + if *sfsp != nil { + dfsp := dst.toBoolSlice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []bool{} + } + } + } + case isPointer: // E.g., *bool + mfi.merge = func(dst, src pointer) { + sfpp := src.toBoolPtr() + if *sfpp != nil { + dfpp := dst.toBoolPtr() + if *dfpp == nil { + *dfpp = Bool(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., bool + mfi.merge = func(dst, src pointer) { + if v := *src.toBool(); v { + *dst.toBool() = v + } + } + } + case reflect.String: + switch { + case isSlice: // E.g., []string + mfi.merge = func(dst, src pointer) { + sfsp := src.toStringSlice() + if *sfsp != nil { + dfsp := dst.toStringSlice() + *dfsp = append(*dfsp, *sfsp...) + if *dfsp == nil { + *dfsp = []string{} + } + } + } + case isPointer: // E.g., *string + mfi.merge = func(dst, src pointer) { + sfpp := src.toStringPtr() + if *sfpp != nil { + dfpp := dst.toStringPtr() + if *dfpp == nil { + *dfpp = String(**sfpp) + } else { + **dfpp = **sfpp + } + } + } + default: // E.g., string + mfi.merge = func(dst, src pointer) { + if v := *src.toString(); v != "" { + *dst.toString() = v + } + } + } + case reflect.Slice: + isProto3 := props.Prop[i].proto3 + switch { + case isPointer: + panic("bad pointer in byte slice case in " + tf.Name()) + case tf.Elem().Kind() != reflect.Uint8: + panic("bad element kind in byte slice case in " + tf.Name()) + case isSlice: // E.g., [][]byte + mfi.merge = func(dst, src pointer) { + sbsp := src.toBytesSlice() + if *sbsp != nil { + dbsp := dst.toBytesSlice() + for _, sb := range *sbsp { + if sb == nil { + *dbsp = append(*dbsp, nil) + } else { + *dbsp = append(*dbsp, append([]byte{}, sb...)) + } + } + if *dbsp == nil { + *dbsp = [][]byte{} + } + } + } + default: // E.g., []byte + mfi.merge = func(dst, src pointer) { + sbp := src.toBytes() + if *sbp != nil { + dbp := dst.toBytes() + if !isProto3 || len(*sbp) > 0 { + *dbp = append([]byte{}, *sbp...) + } + } + } + } + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("message field %s without pointer", tf)) + case isSlice: // E.g., []*pb.T + mi := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + sps := src.getPointerSlice() + if sps != nil { + dps := dst.getPointerSlice() + for _, sp := range sps { + var dp pointer + if !sp.isNil() { + dp = valToPointer(reflect.New(tf)) + mi.merge(dp, sp) + } + dps = append(dps, dp) + } + if dps == nil { + dps = []pointer{} + } + dst.setPointerSlice(dps) + } + } + default: // E.g., *pb.T + mi := getMergeInfo(tf) + mfi.merge = func(dst, src pointer) { + sp := src.getPointer() + if !sp.isNil() { + dp := dst.getPointer() + if dp.isNil() { + dp = valToPointer(reflect.New(tf)) + dst.setPointer(dp) + } + mi.merge(dp, sp) + } + } + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic("bad pointer or slice in map case in " + tf.Name()) + default: // E.g., map[K]V + mfi.merge = func(dst, src pointer) { + sm := src.asPointerTo(tf).Elem() + if sm.Len() == 0 { + return + } + dm := dst.asPointerTo(tf).Elem() + if dm.IsNil() { + dm.Set(reflect.MakeMap(tf)) + } + + switch tf.Elem().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + val = reflect.ValueOf(Clone(val.Interface().(Message))) + dm.SetMapIndex(key, val) + } + case reflect.Slice: // E.g. Bytes type (e.g., []byte) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + dm.SetMapIndex(key, val) + } + default: // Basic type (e.g., string) + for _, key := range sm.MapKeys() { + val := sm.MapIndex(key) + dm.SetMapIndex(key, val) + } + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic("bad pointer or slice in interface case in " + tf.Name()) + default: // E.g., interface{} + // TODO: Make this faster? + mfi.merge = func(dst, src pointer) { + su := src.asPointerTo(tf).Elem() + if !su.IsNil() { + du := dst.asPointerTo(tf).Elem() + typ := su.Elem().Type() + if du.IsNil() || du.Elem().Type() != typ { + du.Set(reflect.New(typ.Elem())) // Initialize interface if empty + } + sv := su.Elem().Elem().Field(0) + if sv.Kind() == reflect.Ptr && sv.IsNil() { + return + } + dv := du.Elem().Elem().Field(0) + if dv.Kind() == reflect.Ptr && dv.IsNil() { + dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty + } + switch sv.Type().Kind() { + case reflect.Ptr: // Proto struct (e.g., *T) + Merge(dv.Interface().(Message), sv.Interface().(Message)) + case reflect.Slice: // E.g. Bytes type (e.g., []byte) + dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...))) + default: // Basic type (e.g., string) + dv.Set(sv) + } + } + } + } + default: + panic(fmt.Sprintf("merger not found for type:%s", tf)) + } + mi.fields = append(mi.fields, mfi) + } + + mi.unrecognized = invalidField + if f, ok := t.FieldByName("XXX_unrecognized"); ok { + if f.Type != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + mi.unrecognized = toField(&f) + } + + atomic.StoreInt32(&mi.initialized, 1) +} diff --git a/vendor/github.com/golang/protobuf/proto/table_unmarshal.go b/vendor/github.com/golang/protobuf/proto/table_unmarshal.go new file mode 100644 index 00000000..55f0340a --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/table_unmarshal.go @@ -0,0 +1,1967 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "errors" + "fmt" + "io" + "math" + "reflect" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// Unmarshal is the entry point from the generated .pb.go files. +// This function is not intended to be used by non-generated code. +// This function is not subject to any compatibility guarantee. +// msg contains a pointer to a protocol buffer struct. +// b is the data to be unmarshaled into the protocol buffer. +// a is a pointer to a place to store cached unmarshal information. +func (a *InternalMessageInfo) Unmarshal(msg Message, b []byte) error { + // Load the unmarshal information for this message type. + // The atomic load ensures memory consistency. + u := atomicLoadUnmarshalInfo(&a.unmarshal) + if u == nil { + // Slow path: find unmarshal info for msg, update a with it. + u = getUnmarshalInfo(reflect.TypeOf(msg).Elem()) + atomicStoreUnmarshalInfo(&a.unmarshal, u) + } + // Then do the unmarshaling. + err := u.unmarshal(toPointer(&msg), b) + return err +} + +type unmarshalInfo struct { + typ reflect.Type // type of the protobuf struct + + // 0 = only typ field is initialized + // 1 = completely initialized + initialized int32 + lock sync.Mutex // prevents double initialization + dense []unmarshalFieldInfo // fields indexed by tag # + sparse map[uint64]unmarshalFieldInfo // fields indexed by tag # + reqFields []string // names of required fields + reqMask uint64 // 1< 0 { + // Read tag and wire type. + // Special case 1 and 2 byte varints. + var x uint64 + if b[0] < 128 { + x = uint64(b[0]) + b = b[1:] + } else if len(b) >= 2 && b[1] < 128 { + x = uint64(b[0]&0x7f) + uint64(b[1])<<7 + b = b[2:] + } else { + var n int + x, n = decodeVarint(b) + if n == 0 { + return io.ErrUnexpectedEOF + } + b = b[n:] + } + tag := x >> 3 + wire := int(x) & 7 + + // Dispatch on the tag to one of the unmarshal* functions below. + var f unmarshalFieldInfo + if tag < uint64(len(u.dense)) { + f = u.dense[tag] + } else { + f = u.sparse[tag] + } + if fn := f.unmarshal; fn != nil { + var err error + b, err = fn(b, m.offset(f.field), wire) + if err == nil { + reqMask |= f.reqMask + continue + } + if r, ok := err.(*RequiredNotSetError); ok { + // Remember this error, but keep parsing. We need to produce + // a full parse even if a required field is missing. + rnse = r + reqMask |= f.reqMask + continue + } + if err != errInternalBadWireType { + return err + } + // Fragments with bad wire type are treated as unknown fields. + } + + // Unknown tag. + if !u.unrecognized.IsValid() { + // Don't keep unrecognized data; just skip it. + var err error + b, err = skipField(b, wire) + if err != nil { + return err + } + continue + } + // Keep unrecognized data around. + // maybe in extensions, maybe in the unrecognized field. + z := m.offset(u.unrecognized).toBytes() + var emap map[int32]Extension + var e Extension + for _, r := range u.extensionRanges { + if uint64(r.Start) <= tag && tag <= uint64(r.End) { + if u.extensions.IsValid() { + mp := m.offset(u.extensions).toExtensions() + emap = mp.extensionsWrite() + e = emap[int32(tag)] + z = &e.enc + break + } + if u.oldExtensions.IsValid() { + p := m.offset(u.oldExtensions).toOldExtensions() + emap = *p + if emap == nil { + emap = map[int32]Extension{} + *p = emap + } + e = emap[int32(tag)] + z = &e.enc + break + } + panic("no extensions field available") + } + } + + // Use wire type to skip data. + var err error + b0 := b + b, err = skipField(b, wire) + if err != nil { + return err + } + *z = encodeVarint(*z, tag<<3|uint64(wire)) + *z = append(*z, b0[:len(b0)-len(b)]...) + + if emap != nil { + emap[int32(tag)] = e + } + } + if rnse != nil { + // A required field of a submessage/group is missing. Return that error. + return rnse + } + if reqMask != u.reqMask { + // A required field of this message is missing. + for _, n := range u.reqFields { + if reqMask&1 == 0 { + return &RequiredNotSetError{n} + } + reqMask >>= 1 + } + } + return nil +} + +// computeUnmarshalInfo fills in u with information for use +// in unmarshaling protocol buffers of type u.typ. +func (u *unmarshalInfo) computeUnmarshalInfo() { + u.lock.Lock() + defer u.lock.Unlock() + if u.initialized != 0 { + return + } + t := u.typ + n := t.NumField() + + // Set up the "not found" value for the unrecognized byte buffer. + // This is the default for proto3. + u.unrecognized = invalidField + u.extensions = invalidField + u.oldExtensions = invalidField + + // List of the generated type and offset for each oneof field. + type oneofField struct { + ityp reflect.Type // interface type of oneof field + field field // offset in containing message + } + var oneofFields []oneofField + + for i := 0; i < n; i++ { + f := t.Field(i) + if f.Name == "XXX_unrecognized" { + // The byte slice used to hold unrecognized input is special. + if f.Type != reflect.TypeOf(([]byte)(nil)) { + panic("bad type for XXX_unrecognized field: " + f.Type.Name()) + } + u.unrecognized = toField(&f) + continue + } + if f.Name == "XXX_InternalExtensions" { + // Ditto here. + if f.Type != reflect.TypeOf(XXX_InternalExtensions{}) { + panic("bad type for XXX_InternalExtensions field: " + f.Type.Name()) + } + u.extensions = toField(&f) + if f.Tag.Get("protobuf_messageset") == "1" { + u.isMessageSet = true + } + continue + } + if f.Name == "XXX_extensions" { + // An older form of the extensions field. + if f.Type != reflect.TypeOf((map[int32]Extension)(nil)) { + panic("bad type for XXX_extensions field: " + f.Type.Name()) + } + u.oldExtensions = toField(&f) + continue + } + if f.Name == "XXX_NoUnkeyedLiteral" || f.Name == "XXX_sizecache" { + continue + } + + oneof := f.Tag.Get("protobuf_oneof") + if oneof != "" { + oneofFields = append(oneofFields, oneofField{f.Type, toField(&f)}) + // The rest of oneof processing happens below. + continue + } + + tags := f.Tag.Get("protobuf") + tagArray := strings.Split(tags, ",") + if len(tagArray) < 2 { + panic("protobuf tag not enough fields in " + t.Name() + "." + f.Name + ": " + tags) + } + tag, err := strconv.Atoi(tagArray[1]) + if err != nil { + panic("protobuf tag field not an integer: " + tagArray[1]) + } + + name := "" + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + } + + // Extract unmarshaling function from the field (its type and tags). + unmarshal := fieldUnmarshaler(&f) + + // Required field? + var reqMask uint64 + if tagArray[2] == "req" { + bit := len(u.reqFields) + u.reqFields = append(u.reqFields, name) + reqMask = uint64(1) << uint(bit) + // TODO: if we have more than 64 required fields, we end up + // not verifying that all required fields are present. + // Fix this, perhaps using a count of required fields? + } + + // Store the info in the correct slot in the message. + u.setTag(tag, toField(&f), unmarshal, reqMask) + } + + // Find any types associated with oneof fields. + // TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it? + fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs") + if fn.IsValid() { + res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{} + for i := res.Len() - 1; i >= 0; i-- { + v := res.Index(i) // interface{} + tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X + typ := tptr.Elem() // Msg_X + + f := typ.Field(0) // oneof implementers have one field + baseUnmarshal := fieldUnmarshaler(&f) + tagstr := strings.Split(f.Tag.Get("protobuf"), ",")[1] + tag, err := strconv.Atoi(tagstr) + if err != nil { + panic("protobuf tag field not an integer: " + tagstr) + } + + // Find the oneof field that this struct implements. + // Might take O(n^2) to process all of the oneofs, but who cares. + for _, of := range oneofFields { + if tptr.Implements(of.ityp) { + // We have found the corresponding interface for this struct. + // That lets us know where this struct should be stored + // when we encounter it during unmarshaling. + unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) + u.setTag(tag, of.field, unmarshal, 0) + } + } + } + } + + // Get extension ranges, if any. + fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") + if fn.IsValid() { + if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { + panic("a message with extensions, but no extensions field in " + t.Name()) + } + u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange) + } + + // Explicitly disallow tag 0. This will ensure we flag an error + // when decoding a buffer of all zeros. Without this code, we + // would decode and skip an all-zero buffer of even length. + // [0 0] is [tag=0/wiretype=varint varint-encoded-0]. + u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) { + return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w) + }, 0) + + // Set mask for required field check. + u.reqMask = uint64(1)<= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here? + for len(u.dense) <= tag { + u.dense = append(u.dense, unmarshalFieldInfo{}) + } + u.dense[tag] = i + return + } + if u.sparse == nil { + u.sparse = map[uint64]unmarshalFieldInfo{} + } + u.sparse[uint64(tag)] = i +} + +// fieldUnmarshaler returns an unmarshaler for the given field. +func fieldUnmarshaler(f *reflect.StructField) unmarshaler { + if f.Type.Kind() == reflect.Map { + return makeUnmarshalMap(f) + } + return typeUnmarshaler(f.Type, f.Tag.Get("protobuf")) +} + +// typeUnmarshaler returns an unmarshaler for the given field type / field tag pair. +func typeUnmarshaler(t reflect.Type, tags string) unmarshaler { + tagArray := strings.Split(tags, ",") + encoding := tagArray[0] + name := "unknown" + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + } + + // Figure out packaging (pointer, slice, or both) + slice := false + pointer := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + // We'll never have both pointer and slice for basic types. + if pointer && slice && t.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + t.Name()) + } + + switch t.Kind() { + case reflect.Bool: + if pointer { + return unmarshalBoolPtr + } + if slice { + return unmarshalBoolSlice + } + return unmarshalBoolValue + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixedS32Ptr + } + if slice { + return unmarshalFixedS32Slice + } + return unmarshalFixedS32Value + case "varint": + // this could be int32 or enum + if pointer { + return unmarshalInt32Ptr + } + if slice { + return unmarshalInt32Slice + } + return unmarshalInt32Value + case "zigzag32": + if pointer { + return unmarshalSint32Ptr + } + if slice { + return unmarshalSint32Slice + } + return unmarshalSint32Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixedS64Ptr + } + if slice { + return unmarshalFixedS64Slice + } + return unmarshalFixedS64Value + case "varint": + if pointer { + return unmarshalInt64Ptr + } + if slice { + return unmarshalInt64Slice + } + return unmarshalInt64Value + case "zigzag64": + if pointer { + return unmarshalSint64Ptr + } + if slice { + return unmarshalSint64Slice + } + return unmarshalSint64Value + } + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixed32Ptr + } + if slice { + return unmarshalFixed32Slice + } + return unmarshalFixed32Value + case "varint": + if pointer { + return unmarshalUint32Ptr + } + if slice { + return unmarshalUint32Slice + } + return unmarshalUint32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixed64Ptr + } + if slice { + return unmarshalFixed64Slice + } + return unmarshalFixed64Value + case "varint": + if pointer { + return unmarshalUint64Ptr + } + if slice { + return unmarshalUint64Slice + } + return unmarshalUint64Value + } + case reflect.Float32: + if pointer { + return unmarshalFloat32Ptr + } + if slice { + return unmarshalFloat32Slice + } + return unmarshalFloat32Value + case reflect.Float64: + if pointer { + return unmarshalFloat64Ptr + } + if slice { + return unmarshalFloat64Slice + } + return unmarshalFloat64Value + case reflect.Map: + panic("map type in typeUnmarshaler in " + t.Name()) + case reflect.Slice: + if pointer { + panic("bad pointer in slice case in " + t.Name()) + } + if slice { + return unmarshalBytesSlice + } + return unmarshalBytesValue + case reflect.String: + if pointer { + return unmarshalStringPtr + } + if slice { + return unmarshalStringSlice + } + return unmarshalStringValue + case reflect.Struct: + // message or group field + if !pointer { + panic(fmt.Sprintf("message/group field %s:%s without pointer", t, encoding)) + } + switch encoding { + case "bytes": + if slice { + return makeUnmarshalMessageSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalMessagePtr(getUnmarshalInfo(t), name) + case "group": + if slice { + return makeUnmarshalGroupSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalGroupPtr(getUnmarshalInfo(t), name) + } + } + panic(fmt.Sprintf("unmarshaler not found type:%s encoding:%s", t, encoding)) +} + +// Below are all the unmarshalers for individual fields of various types. + +func unmarshalInt64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64() = v + return b, nil +} + +func unmarshalInt64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalInt64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalSint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64() = v + return b, nil +} + +func unmarshalSint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalSint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalUint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64() = v + return b, nil +} + +func unmarshalUint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64Ptr() = &v + return b, nil +} + +func unmarshalUint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalInt32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + *f.toInt32() = v + return b, nil +} + +func unmarshalInt32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalInt32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalSint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + *f.toInt32() = v + return b, nil +} + +func unmarshalSint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalSint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalUint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32() = v + return b, nil +} + +func unmarshalUint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32Ptr() = &v + return b, nil +} + +func unmarshalUint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalFixed64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64() = v + return b[8:], nil +} + +func unmarshalFixed64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixed64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixedS64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64() = v + return b[8:], nil +} + +func unmarshalFixedS64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixedS64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixed32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32() = v + return b[4:], nil +} + +func unmarshalFixed32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32Ptr() = &v + return b[4:], nil +} + +func unmarshalFixed32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalFixedS32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + *f.toInt32() = v + return b[4:], nil +} + +func unmarshalFixedS32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.setInt32Ptr(v) + return b[4:], nil +} + +func unmarshalFixedS32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + return b[4:], nil +} + +func unmarshalBoolValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + // Note: any length varint is allowed, even though any sane + // encoder will use one byte. + // See https://github.com/golang/protobuf/issues/76 + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + // TODO: check if x>1? Tests seem to indicate no. + v := x != 0 + *f.toBool() = v + return b[n:], nil +} + +func unmarshalBoolPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + *f.toBoolPtr() = &v + return b[n:], nil +} + +func unmarshalBoolSlice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + b = b[n:] + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + return b[n:], nil +} + +func unmarshalFloat64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64() = v + return b[8:], nil +} + +func unmarshalFloat64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64Ptr() = &v + return b[8:], nil +} + +func unmarshalFloat64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFloat32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32() = v + return b[4:], nil +} + +func unmarshalFloat32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32Ptr() = &v + return b[4:], nil +} + +func unmarshalFloat32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + *f.toString() = v + return b[x:], nil +} + +func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + *f.toStringPtr() = &v + return b[x:], nil +} + +func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := string(b[:x]) + if !utf8.ValidString(v) { + return nil, errInvalidUTF8 + } + s := f.toStringSlice() + *s = append(*s, v) + return b[x:], nil +} + +var emptyBuf [0]byte + +func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // The use of append here is a trick which avoids the zeroing + // that would be required if we used a make/copy pair. + // We append to emptyBuf instead of nil because we want + // a non-nil result even when the length is 0. + v := append(emptyBuf[:], b[:x]...) + *f.toBytes() = v + return b[x:], nil +} + +func unmarshalBytesSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := append(emptyBuf[:], b[:x]...) + s := f.toBytesSlice() + *s = append(*s, v) + return b[x:], nil +} + +func makeUnmarshalMessagePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // First read the message field to see if something is there. + // The semantics of multiple submessages are weird. Instead of + // the last one winning (as it is for all other fields), multiple + // submessages are merged. + v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[x:], err + } +} + +func makeUnmarshalMessageSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendPointer(v) + return b[x:], err + } +} + +func makeUnmarshalGroupPtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + v := f.getPointer() + if v.isNil() { + v = valToPointer(reflect.New(sub.typ)) + f.setPointer(v) + } + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + return b[y:], err + } +} + +func makeUnmarshalGroupSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + v := valToPointer(reflect.New(sub.typ)) + err := sub.unmarshal(v, b[:x]) + if err != nil { + if r, ok := err.(*RequiredNotSetError); ok { + r.field = name + "." + r.field + } else { + return nil, err + } + } + f.appendPointer(v) + return b[y:], err + } +} + +func makeUnmarshalMap(f *reflect.StructField) unmarshaler { + t := f.Type + kt := t.Key() + vt := t.Elem() + unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key")) + unmarshalVal := typeUnmarshaler(vt, f.Tag.Get("protobuf_val")) + return func(b []byte, f pointer, w int) ([]byte, error) { + // The map entry is a submessage. Figure out how big it is. + if w != WireBytes { + return nil, fmt.Errorf("proto: bad wiretype for map field: got %d want %d", w, WireBytes) + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + r := b[x:] // unused data to return + b = b[:x] // data for map entry + + // Note: we could use #keys * #values ~= 200 functions + // to do map decoding without reflection. Probably not worth it. + // Maps will be somewhat slow. Oh well. + + // Read key and value from data. + k := reflect.New(kt) + v := reflect.New(vt) + for len(b) > 0 { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + wire := int(x) & 7 + b = b[n:] + + var err error + switch x >> 3 { + case 1: + b, err = unmarshalKey(b, valToPointer(k), wire) + case 2: + b, err = unmarshalVal(b, valToPointer(v), wire) + default: + err = errInternalBadWireType // skip unknown tag + } + + if err == nil { + continue + } + if err != errInternalBadWireType { + return nil, err + } + + // Skip past unknown fields. + b, err = skipField(b, wire) + if err != nil { + return nil, err + } + } + + // Get map, allocate if needed. + m := f.asPointerTo(t).Elem() // an addressable map[K]T + if m.IsNil() { + m.Set(reflect.MakeMap(t)) + } + + // Insert into map. + m.SetMapIndex(k.Elem(), v.Elem()) + + return r, nil + } +} + +// makeUnmarshalOneof makes an unmarshaler for oneof fields. +// for: +// message Msg { +// oneof F { +// int64 X = 1; +// float64 Y = 2; +// } +// } +// typ is the type of the concrete entry for a oneof case (e.g. Msg_X). +// ityp is the interface type of the oneof field (e.g. isMsg_F). +// unmarshal is the unmarshaler for the base type of the oneof case (e.g. int64). +// Note that this function will be called once for each case in the oneof. +func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshaler { + sf := typ.Field(0) + field0 := toField(&sf) + return func(b []byte, f pointer, w int) ([]byte, error) { + // Allocate holder for value. + v := reflect.New(typ) + + // Unmarshal data into holder. + // We unmarshal into the first field of the holder object. + var err error + b, err = unmarshal(b, valToPointer(v).offset(field0), w) + if err != nil { + return nil, err + } + + // Write pointer to holder into target field. + f.asPointerTo(ityp).Elem().Set(v) + + return b, nil + } +} + +// Error used by decode internally. +var errInternalBadWireType = errors.New("proto: internal error: bad wiretype") + +// skipField skips past a field of type wire and returns the remaining bytes. +func skipField(b []byte, wire int) ([]byte, error) { + switch wire { + case WireVarint: + _, k := decodeVarint(b) + if k == 0 { + return b, io.ErrUnexpectedEOF + } + b = b[k:] + case WireFixed32: + if len(b) < 4 { + return b, io.ErrUnexpectedEOF + } + b = b[4:] + case WireFixed64: + if len(b) < 8 { + return b, io.ErrUnexpectedEOF + } + b = b[8:] + case WireBytes: + m, k := decodeVarint(b) + if k == 0 || uint64(len(b)-k) < m { + return b, io.ErrUnexpectedEOF + } + b = b[uint64(k)+m:] + case WireStartGroup: + _, i := findEndGroup(b) + if i == -1 { + return b, io.ErrUnexpectedEOF + } + b = b[i:] + default: + return b, fmt.Errorf("proto: can't skip unknown wire type %d", wire) + } + return b, nil +} + +// findEndGroup finds the index of the next EndGroup tag. +// Groups may be nested, so the "next" EndGroup tag is the first +// unpaired EndGroup. +// findEndGroup returns the indexes of the start and end of the EndGroup tag. +// Returns (-1,-1) if it can't find one. +func findEndGroup(b []byte) (int, int) { + depth := 1 + i := 0 + for { + x, n := decodeVarint(b[i:]) + if n == 0 { + return -1, -1 + } + j := i + i += n + switch x & 7 { + case WireVarint: + _, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + case WireFixed32: + if len(b)-4 < i { + return -1, -1 + } + i += 4 + case WireFixed64: + if len(b)-8 < i { + return -1, -1 + } + i += 8 + case WireBytes: + m, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + if uint64(len(b)-i) < m { + return -1, -1 + } + i += int(m) + case WireStartGroup: + depth++ + case WireEndGroup: + depth-- + if depth == 0 { + return j, i + } + default: + return -1, -1 + } + } +} + +// encodeVarint appends a varint-encoded integer to b and returns the result. +func encodeVarint(b []byte, x uint64) []byte { + for x >= 1<<7 { + b = append(b, byte(x&0x7f|0x80)) + x >>= 7 + } + return append(b, byte(x)) +} + +// decodeVarint reads a varint-encoded integer from b. +// Returns the decoded integer and the number of bytes read. +// If there is an error, it returns 0,0. +func decodeVarint(b []byte) (uint64, int) { + var x, y uint64 + if len(b) <= 0 { + goto bad + } + x = uint64(b[0]) + if x < 0x80 { + return x, 1 + } + x -= 0x80 + + if len(b) <= 1 { + goto bad + } + y = uint64(b[1]) + x += y << 7 + if y < 0x80 { + return x, 2 + } + x -= 0x80 << 7 + + if len(b) <= 2 { + goto bad + } + y = uint64(b[2]) + x += y << 14 + if y < 0x80 { + return x, 3 + } + x -= 0x80 << 14 + + if len(b) <= 3 { + goto bad + } + y = uint64(b[3]) + x += y << 21 + if y < 0x80 { + return x, 4 + } + x -= 0x80 << 21 + + if len(b) <= 4 { + goto bad + } + y = uint64(b[4]) + x += y << 28 + if y < 0x80 { + return x, 5 + } + x -= 0x80 << 28 + + if len(b) <= 5 { + goto bad + } + y = uint64(b[5]) + x += y << 35 + if y < 0x80 { + return x, 6 + } + x -= 0x80 << 35 + + if len(b) <= 6 { + goto bad + } + y = uint64(b[6]) + x += y << 42 + if y < 0x80 { + return x, 7 + } + x -= 0x80 << 42 + + if len(b) <= 7 { + goto bad + } + y = uint64(b[7]) + x += y << 49 + if y < 0x80 { + return x, 8 + } + x -= 0x80 << 49 + + if len(b) <= 8 { + goto bad + } + y = uint64(b[8]) + x += y << 56 + if y < 0x80 { + return x, 9 + } + x -= 0x80 << 56 + + if len(b) <= 9 { + goto bad + } + y = uint64(b[9]) + x += y << 63 + if y < 2 { + return x, 10 + } + +bad: + return 0, 0 +} diff --git a/vendor/github.com/golang/protobuf/proto/text.go b/vendor/github.com/golang/protobuf/proto/text.go new file mode 100644 index 00000000..2205fdaa --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text.go @@ -0,0 +1,843 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +// Functions for writing the text protocol buffer format. + +import ( + "bufio" + "bytes" + "encoding" + "errors" + "fmt" + "io" + "log" + "math" + "reflect" + "sort" + "strings" +) + +var ( + newline = []byte("\n") + spaces = []byte(" ") + endBraceNewline = []byte("}\n") + backslashN = []byte{'\\', 'n'} + backslashR = []byte{'\\', 'r'} + backslashT = []byte{'\\', 't'} + backslashDQ = []byte{'\\', '"'} + backslashBS = []byte{'\\', '\\'} + posInf = []byte("inf") + negInf = []byte("-inf") + nan = []byte("nan") +) + +type writer interface { + io.Writer + WriteByte(byte) error +} + +// textWriter is an io.Writer that tracks its indentation level. +type textWriter struct { + ind int + complete bool // if the current position is a complete line + compact bool // whether to write out as a one-liner + w writer +} + +func (w *textWriter) WriteString(s string) (n int, err error) { + if !strings.Contains(s, "\n") { + if !w.compact && w.complete { + w.writeIndent() + } + w.complete = false + return io.WriteString(w.w, s) + } + // WriteString is typically called without newlines, so this + // codepath and its copy are rare. We copy to avoid + // duplicating all of Write's logic here. + return w.Write([]byte(s)) +} + +func (w *textWriter) Write(p []byte) (n int, err error) { + newlines := bytes.Count(p, newline) + if newlines == 0 { + if !w.compact && w.complete { + w.writeIndent() + } + n, err = w.w.Write(p) + w.complete = false + return n, err + } + + frags := bytes.SplitN(p, newline, newlines+1) + if w.compact { + for i, frag := range frags { + if i > 0 { + if err := w.w.WriteByte(' '); err != nil { + return n, err + } + n++ + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + } + return n, nil + } + + for i, frag := range frags { + if w.complete { + w.writeIndent() + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + if i+1 < len(frags) { + if err := w.w.WriteByte('\n'); err != nil { + return n, err + } + n++ + } + } + w.complete = len(frags[len(frags)-1]) == 0 + return n, nil +} + +func (w *textWriter) WriteByte(c byte) error { + if w.compact && c == '\n' { + c = ' ' + } + if !w.compact && w.complete { + w.writeIndent() + } + err := w.w.WriteByte(c) + w.complete = c == '\n' + return err +} + +func (w *textWriter) indent() { w.ind++ } + +func (w *textWriter) unindent() { + if w.ind == 0 { + log.Print("proto: textWriter unindented too far") + return + } + w.ind-- +} + +func writeName(w *textWriter, props *Properties) error { + if _, err := w.WriteString(props.OrigName); err != nil { + return err + } + if props.Wire != "group" { + return w.WriteByte(':') + } + return nil +} + +func requiresQuotes(u string) bool { + // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. + for _, ch := range u { + switch { + case ch == '.' || ch == '/' || ch == '_': + continue + case '0' <= ch && ch <= '9': + continue + case 'A' <= ch && ch <= 'Z': + continue + case 'a' <= ch && ch <= 'z': + continue + default: + return true + } + } + return false +} + +// isAny reports whether sv is a google.protobuf.Any message +func isAny(sv reflect.Value) bool { + type wkt interface { + XXX_WellKnownType() string + } + t, ok := sv.Addr().Interface().(wkt) + return ok && t.XXX_WellKnownType() == "Any" +} + +// writeProto3Any writes an expanded google.protobuf.Any message. +// +// It returns (false, nil) if sv value can't be unmarshaled (e.g. because +// required messages are not linked in). +// +// It returns (true, error) when sv was written in expanded format or an error +// was encountered. +func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) { + turl := sv.FieldByName("TypeUrl") + val := sv.FieldByName("Value") + if !turl.IsValid() || !val.IsValid() { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + b, ok := val.Interface().([]byte) + if !ok { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + parts := strings.Split(turl.String(), "/") + mt := MessageType(parts[len(parts)-1]) + if mt == nil { + return false, nil + } + m := reflect.New(mt.Elem()) + if err := Unmarshal(b, m.Interface().(Message)); err != nil { + return false, nil + } + w.Write([]byte("[")) + u := turl.String() + if requiresQuotes(u) { + writeString(w, u) + } else { + w.Write([]byte(u)) + } + if w.compact { + w.Write([]byte("]:<")) + } else { + w.Write([]byte("]: <\n")) + w.ind++ + } + if err := tm.writeStruct(w, m.Elem()); err != nil { + return true, err + } + if w.compact { + w.Write([]byte("> ")) + } else { + w.ind-- + w.Write([]byte(">\n")) + } + return true, nil +} + +func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { + if tm.ExpandAny && isAny(sv) { + if canExpand, err := tm.writeProto3Any(w, sv); canExpand { + return err + } + } + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < sv.NumField(); i++ { + fv := sv.Field(i) + props := sprops.Prop[i] + name := st.Field(i).Name + + if name == "XXX_NoUnkeyedLiteral" { + continue + } + + if strings.HasPrefix(name, "XXX_") { + // There are two XXX_ fields: + // XXX_unrecognized []byte + // XXX_extensions map[int32]proto.Extension + // The first is handled here; + // the second is handled at the bottom of this function. + if name == "XXX_unrecognized" && !fv.IsNil() { + if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Field not filled in. This could be an optional field or + // a required field that wasn't filled in. Either way, there + // isn't anything we can show for it. + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + // Repeated field that is empty, or a bytes field that is unused. + continue + } + + if props.Repeated && fv.Kind() == reflect.Slice { + // Repeated field. + for j := 0; j < fv.Len(); j++ { + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + v := fv.Index(j) + if v.Kind() == reflect.Ptr && v.IsNil() { + // A nil message in a repeated field is not valid, + // but we can handle that more gracefully than panicking. + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + continue + } + if err := tm.writeAny(w, v, props); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Map { + // Map fields are rendered as a repeated struct with key/value fields. + keys := fv.MapKeys() + sort.Sort(mapKeys(keys)) + for _, key := range keys { + val := fv.MapIndex(key) + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + // open struct + if err := w.WriteByte('<'); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + // key + if _, err := w.WriteString("key:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, key, props.mkeyprop); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + // nil values aren't legal, but we can avoid panicking because of them. + if val.Kind() != reflect.Ptr || !val.IsNil() { + // value + if _, err := w.WriteString("value:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, val, props.mvalprop); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + // close struct + w.unindent() + if err := w.WriteByte('>'); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 { + // empty bytes field + continue + } + if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { + // proto3 non-repeated scalar field; skip if zero value + if isProto3Zero(fv) { + continue + } + } + + if fv.Kind() == reflect.Interface { + // Check if it is a oneof. + if st.Field(i).Tag.Get("protobuf_oneof") != "" { + // fv is nil, or holds a pointer to generated struct. + // That generated struct has exactly one field, + // which has a protobuf struct tag. + if fv.IsNil() { + continue + } + inner := fv.Elem().Elem() // interface -> *T -> T + tag := inner.Type().Field(0).Tag.Get("protobuf") + props = new(Properties) // Overwrite the outer props var, but not its pointee. + props.Parse(tag) + // Write the value in the oneof, not the oneof itself. + fv = inner.Field(0) + + // Special case to cope with malformed messages gracefully: + // If the value in the oneof is a nil pointer, don't panic + // in writeAny. + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Use errors.New so writeAny won't render quotes. + msg := errors.New("/* nil */") + fv = reflect.ValueOf(&msg).Elem() + } + } + } + + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + + // Enums have a String method, so writeAny will work fine. + if err := tm.writeAny(w, fv, props); err != nil { + return err + } + + if err := w.WriteByte('\n'); err != nil { + return err + } + } + + // Extensions (the XXX_extensions field). + pv := sv.Addr() + if _, err := extendable(pv.Interface()); err == nil { + if err := tm.writeExtensions(w, pv); err != nil { + return err + } + } + + return nil +} + +// writeAny writes an arbitrary field. +func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { + v = reflect.Indirect(v) + + // Floats have special cases. + if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { + x := v.Float() + var b []byte + switch { + case math.IsInf(x, 1): + b = posInf + case math.IsInf(x, -1): + b = negInf + case math.IsNaN(x): + b = nan + } + if b != nil { + _, err := w.Write(b) + return err + } + // Other values are handled below. + } + + // We don't attempt to serialise every possible value type; only those + // that can occur in protocol buffers. + switch v.Kind() { + case reflect.Slice: + // Should only be a []byte; repeated fields are handled in writeStruct. + if err := writeString(w, string(v.Bytes())); err != nil { + return err + } + case reflect.String: + if err := writeString(w, v.String()); err != nil { + return err + } + case reflect.Struct: + // Required/optional group/message. + var bra, ket byte = '<', '>' + if props != nil && props.Wire == "group" { + bra, ket = '{', '}' + } + if err := w.WriteByte(bra); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + if v.CanAddr() { + // Calling v.Interface on a struct causes the reflect package to + // copy the entire struct. This is racy with the new Marshaler + // since we atomically update the XXX_sizecache. + // + // Thus, we retrieve a pointer to the struct if possible to avoid + // a race since v.Interface on the pointer doesn't copy the struct. + // + // If v is not addressable, then we are not worried about a race + // since it implies that the binary Marshaler cannot possibly be + // mutating this value. + v = v.Addr() + } + if etm, ok := v.Interface().(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() + if err != nil { + return err + } + if _, err = w.Write(text); err != nil { + return err + } + } else { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if err := tm.writeStruct(w, v); err != nil { + return err + } + } + w.unindent() + if err := w.WriteByte(ket); err != nil { + return err + } + default: + _, err := fmt.Fprint(w, v.Interface()) + return err + } + return nil +} + +// equivalent to C's isprint. +func isprint(c byte) bool { + return c >= 0x20 && c < 0x7f +} + +// writeString writes a string in the protocol buffer text format. +// It is similar to strconv.Quote except we don't use Go escape sequences, +// we treat the string as a byte sequence, and we use octal escapes. +// These differences are to maintain interoperability with the other +// languages' implementations of the text format. +func writeString(w *textWriter, s string) error { + // use WriteByte here to get any needed indent + if err := w.WriteByte('"'); err != nil { + return err + } + // Loop over the bytes, not the runes. + for i := 0; i < len(s); i++ { + var err error + // Divergence from C++: we don't escape apostrophes. + // There's no need to escape them, and the C++ parser + // copes with a naked apostrophe. + switch c := s[i]; c { + case '\n': + _, err = w.w.Write(backslashN) + case '\r': + _, err = w.w.Write(backslashR) + case '\t': + _, err = w.w.Write(backslashT) + case '"': + _, err = w.w.Write(backslashDQ) + case '\\': + _, err = w.w.Write(backslashBS) + default: + if isprint(c) { + err = w.w.WriteByte(c) + } else { + _, err = fmt.Fprintf(w.w, "\\%03o", c) + } + } + if err != nil { + return err + } + } + return w.WriteByte('"') +} + +func writeUnknownStruct(w *textWriter, data []byte) (err error) { + if !w.compact { + if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil { + return err + } + } + b := NewBuffer(data) + for b.index < len(b.buf) { + x, err := b.DecodeVarint() + if err != nil { + _, err := fmt.Fprintf(w, "/* %v */\n", err) + return err + } + wire, tag := x&7, x>>3 + if wire == WireEndGroup { + w.unindent() + if _, err := w.Write(endBraceNewline); err != nil { + return err + } + continue + } + if _, err := fmt.Fprint(w, tag); err != nil { + return err + } + if wire != WireStartGroup { + if err := w.WriteByte(':'); err != nil { + return err + } + } + if !w.compact || wire == WireStartGroup { + if err := w.WriteByte(' '); err != nil { + return err + } + } + switch wire { + case WireBytes: + buf, e := b.DecodeRawBytes(false) + if e == nil { + _, err = fmt.Fprintf(w, "%q", buf) + } else { + _, err = fmt.Fprintf(w, "/* %v */", e) + } + case WireFixed32: + x, err = b.DecodeFixed32() + err = writeUnknownInt(w, x, err) + case WireFixed64: + x, err = b.DecodeFixed64() + err = writeUnknownInt(w, x, err) + case WireStartGroup: + err = w.WriteByte('{') + w.indent() + case WireVarint: + x, err = b.DecodeVarint() + err = writeUnknownInt(w, x, err) + default: + _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire) + } + if err != nil { + return err + } + if err = w.WriteByte('\n'); err != nil { + return err + } + } + return nil +} + +func writeUnknownInt(w *textWriter, x uint64, err error) error { + if err == nil { + _, err = fmt.Fprint(w, x) + } else { + _, err = fmt.Fprintf(w, "/* %v */", err) + } + return err +} + +type int32Slice []int32 + +func (s int32Slice) Len() int { return len(s) } +func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// writeExtensions writes all the extensions in pv. +// pv is assumed to be a pointer to a protocol message struct that is extendable. +func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error { + emap := extensionMaps[pv.Type().Elem()] + ep, _ := extendable(pv.Interface()) + + // Order the extensions by ID. + // This isn't strictly necessary, but it will give us + // canonical output, which will also make testing easier. + m, mu := ep.extensionsRead() + if m == nil { + return nil + } + mu.Lock() + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) + mu.Unlock() + + for _, extNum := range ids { + ext := m[extNum] + var desc *ExtensionDesc + if emap != nil { + desc = emap[extNum] + } + if desc == nil { + // Unknown extension. + if err := writeUnknownStruct(w, ext.enc); err != nil { + return err + } + continue + } + + pb, err := GetExtension(ep, desc) + if err != nil { + return fmt.Errorf("failed getting extension: %v", err) + } + + // Repeated extensions will appear as a slice. + if !desc.repeated() { + if err := tm.writeExtension(w, desc.Name, pb); err != nil { + return err + } + } else { + v := reflect.ValueOf(pb) + for i := 0; i < v.Len(); i++ { + if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { + return err + } + } + } + } + return nil +} + +func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error { + if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + return nil +} + +func (w *textWriter) writeIndent() { + if !w.complete { + return + } + remain := w.ind * 2 + for remain > 0 { + n := remain + if n > len(spaces) { + n = len(spaces) + } + w.w.Write(spaces[:n]) + remain -= n + } + w.complete = false +} + +// TextMarshaler is a configurable text format marshaler. +type TextMarshaler struct { + Compact bool // use compact text format (one line). + ExpandAny bool // expand google.protobuf.Any messages of known types +} + +// Marshal writes a given protocol buffer in text format. +// The only errors returned are from w. +func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error { + val := reflect.ValueOf(pb) + if pb == nil || val.IsNil() { + w.Write([]byte("")) + return nil + } + var bw *bufio.Writer + ww, ok := w.(writer) + if !ok { + bw = bufio.NewWriter(w) + ww = bw + } + aw := &textWriter{ + w: ww, + complete: true, + compact: tm.Compact, + } + + if etm, ok := pb.(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() + if err != nil { + return err + } + if _, err = aw.Write(text); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil + } + // Dereference the received pointer so we don't have outer < and >. + v := reflect.Indirect(val) + if err := tm.writeStruct(aw, v); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil +} + +// Text is the same as Marshal, but returns the string directly. +func (tm *TextMarshaler) Text(pb Message) string { + var buf bytes.Buffer + tm.Marshal(&buf, pb) + return buf.String() +} + +var ( + defaultTextMarshaler = TextMarshaler{} + compactTextMarshaler = TextMarshaler{Compact: true} +) + +// TODO: consider removing some of the Marshal functions below. + +// MarshalText writes a given protocol buffer in text format. +// The only errors returned are from w. +func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) } + +// MarshalTextString is the same as MarshalText, but returns the string directly. +func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) } + +// CompactText writes a given protocol buffer in compact text format (one line). +func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) } + +// CompactTextString is the same as CompactText, but returns the string directly. +func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) } diff --git a/vendor/github.com/golang/protobuf/proto/text_parser.go b/vendor/github.com/golang/protobuf/proto/text_parser.go new file mode 100644 index 00000000..0685bae3 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text_parser.go @@ -0,0 +1,880 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +// Functions for parsing the Text protocol buffer format. +// TODO: message sets. + +import ( + "encoding" + "errors" + "fmt" + "reflect" + "strconv" + "strings" + "unicode/utf8" +) + +// Error string emitted when deserializing Any and fields are already set +const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set" + +type ParseError struct { + Message string + Line int // 1-based line number + Offset int // 0-based byte offset from start of input +} + +func (p *ParseError) Error() string { + if p.Line == 1 { + // show offset only for first line + return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message) + } + return fmt.Sprintf("line %d: %v", p.Line, p.Message) +} + +type token struct { + value string + err *ParseError + line int // line number + offset int // byte number from start of input, not start of line + unquoted string // the unquoted version of value, if it was a quoted string +} + +func (t *token) String() string { + if t.err == nil { + return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset) + } + return fmt.Sprintf("parse error: %v", t.err) +} + +type textParser struct { + s string // remaining input + done bool // whether the parsing is finished (success or error) + backed bool // whether back() was called + offset, line int + cur token +} + +func newTextParser(s string) *textParser { + p := new(textParser) + p.s = s + p.line = 1 + p.cur.line = 1 + return p +} + +func (p *textParser) errorf(format string, a ...interface{}) *ParseError { + pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset} + p.cur.err = pe + p.done = true + return pe +} + +// Numbers and identifiers are matched by [-+._A-Za-z0-9] +func isIdentOrNumberChar(c byte) bool { + switch { + case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z': + return true + case '0' <= c && c <= '9': + return true + } + switch c { + case '-', '+', '.', '_': + return true + } + return false +} + +func isWhitespace(c byte) bool { + switch c { + case ' ', '\t', '\n', '\r': + return true + } + return false +} + +func isQuote(c byte) bool { + switch c { + case '"', '\'': + return true + } + return false +} + +func (p *textParser) skipWhitespace() { + i := 0 + for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') { + if p.s[i] == '#' { + // comment; skip to end of line or input + for i < len(p.s) && p.s[i] != '\n' { + i++ + } + if i == len(p.s) { + break + } + } + if p.s[i] == '\n' { + p.line++ + } + i++ + } + p.offset += i + p.s = p.s[i:len(p.s)] + if len(p.s) == 0 { + p.done = true + } +} + +func (p *textParser) advance() { + // Skip whitespace + p.skipWhitespace() + if p.done { + return + } + + // Start of non-whitespace + p.cur.err = nil + p.cur.offset, p.cur.line = p.offset, p.line + p.cur.unquoted = "" + switch p.s[0] { + case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/': + // Single symbol + p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] + case '"', '\'': + // Quoted string + i := 1 + for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' { + if p.s[i] == '\\' && i+1 < len(p.s) { + // skip escaped char + i++ + } + i++ + } + if i >= len(p.s) || p.s[i] != p.s[0] { + p.errorf("unmatched quote") + return + } + unq, err := unquoteC(p.s[1:i], rune(p.s[0])) + if err != nil { + p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err) + return + } + p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)] + p.cur.unquoted = unq + default: + i := 0 + for i < len(p.s) && isIdentOrNumberChar(p.s[i]) { + i++ + } + if i == 0 { + p.errorf("unexpected byte %#x", p.s[0]) + return + } + p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)] + } + p.offset += len(p.cur.value) +} + +var ( + errBadUTF8 = errors.New("proto: bad UTF-8") +) + +func unquoteC(s string, quote rune) (string, error) { + // This is based on C++'s tokenizer.cc. + // Despite its name, this is *not* parsing C syntax. + // For instance, "\0" is an invalid quoted string. + + // Avoid allocation in trivial cases. + simple := true + for _, r := range s { + if r == '\\' || r == quote { + simple = false + break + } + } + if simple { + return s, nil + } + + buf := make([]byte, 0, 3*len(s)/2) + for len(s) > 0 { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", errBadUTF8 + } + s = s[n:] + if r != '\\' { + if r < utf8.RuneSelf { + buf = append(buf, byte(r)) + } else { + buf = append(buf, string(r)...) + } + continue + } + + ch, tail, err := unescape(s) + if err != nil { + return "", err + } + buf = append(buf, ch...) + s = tail + } + return string(buf), nil +} + +func unescape(s string) (ch string, tail string, err error) { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", "", errBadUTF8 + } + s = s[n:] + switch r { + case 'a': + return "\a", s, nil + case 'b': + return "\b", s, nil + case 'f': + return "\f", s, nil + case 'n': + return "\n", s, nil + case 'r': + return "\r", s, nil + case 't': + return "\t", s, nil + case 'v': + return "\v", s, nil + case '?': + return "?", s, nil // trigraph workaround + case '\'', '"', '\\': + return string(r), s, nil + case '0', '1', '2', '3', '4', '5', '6', '7': + if len(s) < 2 { + return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) + } + ss := string(r) + s[:2] + s = s[2:] + i, err := strconv.ParseUint(ss, 8, 8) + if err != nil { + return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss) + } + return string([]byte{byte(i)}), s, nil + case 'x', 'X', 'u', 'U': + var n int + switch r { + case 'x', 'X': + n = 2 + case 'u': + n = 4 + case 'U': + n = 8 + } + if len(s) < n { + return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n) + } + ss := s[:n] + s = s[n:] + i, err := strconv.ParseUint(ss, 16, 64) + if err != nil { + return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss) + } + if r == 'x' || r == 'X' { + return string([]byte{byte(i)}), s, nil + } + if i > utf8.MaxRune { + return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss) + } + return string(i), s, nil + } + return "", "", fmt.Errorf(`unknown escape \%c`, r) +} + +// Back off the parser by one token. Can only be done between calls to next(). +// It makes the next advance() a no-op. +func (p *textParser) back() { p.backed = true } + +// Advances the parser and returns the new current token. +func (p *textParser) next() *token { + if p.backed || p.done { + p.backed = false + return &p.cur + } + p.advance() + if p.done { + p.cur.value = "" + } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) { + // Look for multiple quoted strings separated by whitespace, + // and concatenate them. + cat := p.cur + for { + p.skipWhitespace() + if p.done || !isQuote(p.s[0]) { + break + } + p.advance() + if p.cur.err != nil { + return &p.cur + } + cat.value += " " + p.cur.value + cat.unquoted += p.cur.unquoted + } + p.done = false // parser may have seen EOF, but we want to return cat + p.cur = cat + } + return &p.cur +} + +func (p *textParser) consumeToken(s string) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != s { + p.back() + return p.errorf("expected %q, found %q", s, tok.value) + } + return nil +} + +// Return a RequiredNotSetError indicating which required field was not set. +func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError { + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < st.NumField(); i++ { + if !isNil(sv.Field(i)) { + continue + } + + props := sprops.Prop[i] + if props.Required { + return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)} + } + } + return &RequiredNotSetError{fmt.Sprintf("%v.", st)} // should not happen +} + +// Returns the index in the struct for the named field, as well as the parsed tag properties. +func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) { + i, ok := sprops.decoderOrigNames[name] + if ok { + return i, sprops.Prop[i], true + } + return -1, nil, false +} + +// Consume a ':' from the input stream (if the next token is a colon), +// returning an error if a colon is needed but not present. +func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ":" { + // Colon is optional when the field is a group or message. + needColon := true + switch props.Wire { + case "group": + needColon = false + case "bytes": + // A "bytes" field is either a message, a string, or a repeated field; + // those three become *T, *string and []T respectively, so we can check for + // this field being a pointer to a non-string. + if typ.Kind() == reflect.Ptr { + // *T or *string + if typ.Elem().Kind() == reflect.String { + break + } + } else if typ.Kind() == reflect.Slice { + // []T or []*T + if typ.Elem().Kind() != reflect.Ptr { + break + } + } else if typ.Kind() == reflect.String { + // The proto3 exception is for a string field, + // which requires a colon. + break + } + needColon = false + } + if needColon { + return p.errorf("expected ':', found %q", tok.value) + } + p.back() + } + return nil +} + +func (p *textParser) readStruct(sv reflect.Value, terminator string) error { + st := sv.Type() + sprops := GetProperties(st) + reqCount := sprops.reqCount + var reqFieldErr error + fieldSet := make(map[string]bool) + // A struct is a sequence of "name: value", terminated by one of + // '>' or '}', or the end of the input. A name may also be + // "[extension]" or "[type/url]". + // + // The whole struct can also be an expanded Any message, like: + // [type/url] < ... struct contents ... > + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + if tok.value == "[" { + // Looks like an extension or an Any. + // + // TODO: Check whether we need to handle + // namespace rooted names (e.g. ".something.Foo"). + extName, err := p.consumeExtName() + if err != nil { + return err + } + + if s := strings.LastIndex(extName, "/"); s >= 0 { + // If it contains a slash, it's an Any type URL. + messageName := extName[s+1:] + mt := MessageType(messageName) + if mt == nil { + return p.errorf("unrecognized message %q in google.protobuf.Any", messageName) + } + tok = p.next() + if tok.err != nil { + return tok.err + } + // consume an optional colon + if tok.value == ":" { + tok = p.next() + if tok.err != nil { + return tok.err + } + } + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + v := reflect.New(mt.Elem()) + if pe := p.readStruct(v.Elem(), terminator); pe != nil { + return pe + } + b, err := Marshal(v.Interface().(Message)) + if err != nil { + return p.errorf("failed to marshal message of type %q: %v", messageName, err) + } + if fieldSet["type_url"] { + return p.errorf(anyRepeatedlyUnpacked, "type_url") + } + if fieldSet["value"] { + return p.errorf(anyRepeatedlyUnpacked, "value") + } + sv.FieldByName("TypeUrl").SetString(extName) + sv.FieldByName("Value").SetBytes(b) + fieldSet["type_url"] = true + fieldSet["value"] = true + continue + } + + var desc *ExtensionDesc + // This could be faster, but it's functional. + // TODO: Do something smarter than a linear scan. + for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { + if d.Name == extName { + desc = d + break + } + } + if desc == nil { + return p.errorf("unrecognized extension %q", extName) + } + + props := &Properties{} + props.Parse(desc.Tag) + + typ := reflect.TypeOf(desc.ExtensionType) + if err := p.checkForColon(props, typ); err != nil { + return err + } + + rep := desc.repeated() + + // Read the extension structure, and set it in + // the value we're constructing. + var ext reflect.Value + if !rep { + ext = reflect.New(typ).Elem() + } else { + ext = reflect.New(typ.Elem()).Elem() + } + if err := p.readAny(ext, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + ep := sv.Addr().Interface().(Message) + if !rep { + SetExtension(ep, desc, ext.Interface()) + } else { + old, err := GetExtension(ep, desc) + var sl reflect.Value + if err == nil { + sl = reflect.ValueOf(old) // existing slice + } else { + sl = reflect.MakeSlice(typ, 0, 1) + } + sl = reflect.Append(sl, ext) + SetExtension(ep, desc, sl.Interface()) + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + continue + } + + // This is a normal, non-extension field. + name := tok.value + var dst reflect.Value + fi, props, ok := structFieldByName(sprops, name) + if ok { + dst = sv.Field(fi) + } else if oop, ok := sprops.OneofTypes[name]; ok { + // It is a oneof. + props = oop.Prop + nv := reflect.New(oop.Type.Elem()) + dst = nv.Elem().Field(0) + field := sv.Field(oop.Field) + if !field.IsNil() { + return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name) + } + field.Set(nv) + } + if !dst.IsValid() { + return p.errorf("unknown field name %q in %v", name, st) + } + + if dst.Kind() == reflect.Map { + // Consume any colon. + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Construct the map if it doesn't already exist. + if dst.IsNil() { + dst.Set(reflect.MakeMap(dst.Type())) + } + key := reflect.New(dst.Type().Key()).Elem() + val := reflect.New(dst.Type().Elem()).Elem() + + // The map entry should be this sequence of tokens: + // < key : KEY value : VALUE > + // However, implementations may omit key or value, and technically + // we should support them in any order. See b/28924776 for a time + // this went wrong. + + tok := p.next() + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + switch tok.value { + case "key": + if err := p.consumeToken(":"); err != nil { + return err + } + if err := p.readAny(key, props.mkeyprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + case "value": + if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { + return err + } + if err := p.readAny(val, props.mvalprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + default: + p.back() + return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) + } + } + + dst.SetMapIndex(key, val) + continue + } + + // Check that it's not already set if it's not a repeated field. + if !props.Repeated && fieldSet[name] { + return p.errorf("non-repeated field %q was repeated", name) + } + + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Parse into the field. + fieldSet[name] = true + if err := p.readAny(dst, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + if props.Required { + reqCount-- + } + + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + + } + + if reqCount > 0 { + return p.missingRequiredFieldError(sv) + } + return reqFieldErr +} + +// consumeExtName consumes extension name or expanded Any type URL and the +// following ']'. It returns the name or URL consumed. +func (p *textParser) consumeExtName() (string, error) { + tok := p.next() + if tok.err != nil { + return "", tok.err + } + + // If extension name or type url is quoted, it's a single token. + if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] { + name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) + if err != nil { + return "", err + } + return name, p.consumeToken("]") + } + + // Consume everything up to "]" + var parts []string + for tok.value != "]" { + parts = append(parts, tok.value) + tok = p.next() + if tok.err != nil { + return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) + } + if p.done && tok.value != "]" { + return "", p.errorf("unclosed type_url or extension name") + } + } + return strings.Join(parts, ""), nil +} + +// consumeOptionalSeparator consumes an optional semicolon or comma. +// It is used in readStruct to provide backward compatibility. +func (p *textParser) consumeOptionalSeparator() error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ";" && tok.value != "," { + p.back() + } + return nil +} + +func (p *textParser) readAny(v reflect.Value, props *Properties) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "" { + return p.errorf("unexpected EOF") + } + + switch fv := v; fv.Kind() { + case reflect.Slice: + at := v.Type() + if at.Elem().Kind() == reflect.Uint8 { + // Special case for []byte + if tok.value[0] != '"' && tok.value[0] != '\'' { + // Deliberately written out here, as the error after + // this switch statement would write "invalid []byte: ...", + // which is not as user-friendly. + return p.errorf("invalid string: %v", tok.value) + } + bytes := []byte(tok.unquoted) + fv.Set(reflect.ValueOf(bytes)) + return nil + } + // Repeated field. + if tok.value == "[" { + // Repeated field with list notation, like [1,2,3]. + for { + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + err := p.readAny(fv.Index(fv.Len()-1), props) + if err != nil { + return err + } + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "]" { + break + } + if tok.value != "," { + return p.errorf("Expected ']' or ',' found %q", tok.value) + } + } + return nil + } + // One value of the repeated field. + p.back() + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + return p.readAny(fv.Index(fv.Len()-1), props) + case reflect.Bool: + // true/1/t/True or false/f/0/False. + switch tok.value { + case "true", "1", "t", "True": + fv.SetBool(true) + return nil + case "false", "0", "f", "False": + fv.SetBool(false) + return nil + } + case reflect.Float32, reflect.Float64: + v := tok.value + // Ignore 'f' for compatibility with output generated by C++, but don't + // remove 'f' when the value is "-inf" or "inf". + if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" { + v = v[:len(v)-1] + } + if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil { + fv.SetFloat(f) + return nil + } + case reflect.Int32: + if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { + fv.SetInt(x) + return nil + } + + if len(props.Enum) == 0 { + break + } + m, ok := enumValueMaps[props.Enum] + if !ok { + break + } + x, ok := m[tok.value] + if !ok { + break + } + fv.SetInt(int64(x)) + return nil + case reflect.Int64: + if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil { + fv.SetInt(x) + return nil + } + + case reflect.Ptr: + // A basic field (indirected through pointer), or a repeated message/group + p.back() + fv.Set(reflect.New(fv.Type().Elem())) + return p.readAny(fv.Elem(), props) + case reflect.String: + if tok.value[0] == '"' || tok.value[0] == '\'' { + fv.SetString(tok.unquoted) + return nil + } + case reflect.Struct: + var terminator string + switch tok.value { + case "{": + terminator = "}" + case "<": + terminator = ">" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + // TODO: Handle nested messages which implement encoding.TextUnmarshaler. + return p.readStruct(fv, terminator) + case reflect.Uint32: + if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { + fv.SetUint(uint64(x)) + return nil + } + case reflect.Uint64: + if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil { + fv.SetUint(x) + return nil + } + } + return p.errorf("invalid %v: %v", v.Type(), tok.value) +} + +// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb +// before starting to unmarshal, so any existing data in pb is always removed. +// If a required field is not set and no other error occurs, +// UnmarshalText returns *RequiredNotSetError. +func UnmarshalText(s string, pb Message) error { + if um, ok := pb.(encoding.TextUnmarshaler); ok { + return um.UnmarshalText([]byte(s)) + } + pb.Reset() + v := reflect.ValueOf(pb) + return newTextParser(s).readStruct(v.Elem(), "") +} diff --git a/vendor/github.com/google/go-github/AUTHORS b/vendor/github.com/google/go-github/AUTHORS new file mode 100644 index 00000000..4c2ad9b4 --- /dev/null +++ b/vendor/github.com/google/go-github/AUTHORS @@ -0,0 +1,173 @@ +# This is the official list of go-github authors for copyright purposes. +# +# This does not necessarily list everyone who has contributed code, since in +# some cases, their employer may be the copyright holder. To see the full list +# of contributors, see the revision history in source control or +# https://github.com/google/go-github/graphs/contributors. +# +# Authors who wish to be recognized in this file should add themselves (or +# their employer, as appropriate). + +178inaba +Abhinav Gupta +Ahmed Hagy +Ainsley Chong +Akeda Bagus +Alec Thomas +Aleks Clark +Alex Bramley +Alexander Harkness +Allen Sun +Amey Sakhadeo +Andreas Garnæs +Andrew Ryabchun +Andy Hume +Andy Lindeman +Anshuman Bhartiya +Antoine Pelisse +Anubha Kushwaha +Aravind +Arıl Bozoluk +Austin Dizzy +Beshr Kayali +Beyang Liu +Billy Lynch +Björn Häuser +Brad Harris +Bradley Falzon +Brian Egizi +Bryan Boreham +Cami Diez +Carlos Alexandro Becker +chandresh-pancholi +Charles Fenwick Elliott +Charlie Yan +Chris King +Chris Roche +Chris Schaefer +Christoph Sassenberg +Colin Misare +Craig Peterson +Cristian Maglie +Daehyeok Mun +Daniel Leavitt +Dave Du Cros +Dave Henderson +David Deng +Dennis Webb +Diego Lapiduz +Dmitri Shuralyov +dmnlk +Don Petersen +Doug Turner +Drew Fradette +Eli Uriegas +Elliott Beach +erwinvaneyk +Fabrice +Filippo Valsorda +Florian Forster +Francesc Gil +Francis +Fredrik Jönsson +Garrett Squire +Georgy Buranov +Gnahz +Google Inc. +griffin_stewie +Guz Alexander +Hanno Hecker +Hari haran +haya14busa +Huy Tr +huydx +i2bskn +Isao Jonas +isqua +Jameel Haffejee +Jan Kosecki +Jeremy Morris +Jihoon Chung +Jimmi Dyson +Joe Tsai +John Barton +John Engelman +jpbelanger-mtl +Juan Basso +Julien Rostand +Justin Abrahms +jzhoucliqr +Katrina Owen +Keita Urashima +Kevin Burke +Konrad Malawski +Kookheon Kwon +Krzysztof Kowalczyk +Kshitij Saraogi +kyokomi +Lucas Alcantara +Luke Evers +Luke Kysow +Luke Roberts +Luke Young +Maksim Zhylinski +Martin-Louis Bright +Mat Geist +Matt Brender +Matt Landis +Maxime Bury +Michael Tiller +Michał Glapa +Nathan VanBenschoten +Neil O'Toole +Nick Miyake +Nick Spragg +Nikhita Raghunath +Noah Zoschke +ns-cweber +Ondřej Kupka +Panagiotis Moustafellos +Parker Moore +Pavel Shtanko +Petr Shevtsov +Pierre Carrier +Piotr Zurek +Quinn Slack +Rackspace US, Inc. +Rajendra arora +RaviTeja Pothana +rc1140 +Red Hat, Inc. +Rob Figueiredo +Ronak Jain +Ruben Vereecken +Ryan Lower +Sahil Dua +saisi +Sam Minnée +Sander van Harmelen +Sarasa Kisaragi +Sean Wang +Sebastian Mandrean +Sebastian Mæland Pedersen +Sevki +Shawn Catanzarite +Shawn Smith +sona-tar +SoundCloud, Ltd. +Stian Eikeland +Thomas Bruyelle +Timothée Peignier +Trey Tacon +ttacon +Varadarajan Aravamudhan +Victor Castell +Victor Vrantchan +Vlad Ungureanu +Will Maier +William Bailey +Yann Malet +Yannick Utard +Yicheng Qin +Yumikiyo Osanai +Zach Latta diff --git a/vendor/github.com/google/go-github/LICENSE b/vendor/github.com/google/go-github/LICENSE new file mode 100644 index 00000000..28b6486f --- /dev/null +++ b/vendor/github.com/google/go-github/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 The go-github AUTHORS. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/go-github/github/activity.go b/vendor/github.com/google/go-github/github/activity.go new file mode 100644 index 00000000..d6c992c7 --- /dev/null +++ b/vendor/github.com/google/go-github/github/activity.go @@ -0,0 +1,69 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// ActivityService handles communication with the activity related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/activity/ +type ActivityService service + +// FeedLink represents a link to a related resource. +type FeedLink struct { + HRef *string `json:"href,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Feeds represents timeline resources in Atom format. +type Feeds struct { + TimelineURL *string `json:"timeline_url,omitempty"` + UserURL *string `json:"user_url,omitempty"` + CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` + CurrentUserURL *string `json:"current_user_url,omitempty"` + CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` + CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` + CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` + Links *struct { + Timeline *FeedLink `json:"timeline,omitempty"` + User *FeedLink `json:"user,omitempty"` + CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` + CurrentUser *FeedLink `json:"current_user,omitempty"` + CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` + CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` + CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"` + } `json:"_links,omitempty"` +} + +// ListFeeds lists all the feeds available to the authenticated user. +// +// GitHub provides several timeline resources in Atom format: +// Timeline: The GitHub global public timeline +// User: The public timeline for any user, using URI template +// Current user public: The public timeline for the authenticated user +// Current user: The private timeline for the authenticated user +// Current user actor: The private timeline for activity created by the +// authenticated user +// Current user organizations: The private timeline for the organizations +// the authenticated user is a member of. +// +// Note: Private feeds are only returned when authenticating via Basic Auth +// since current feed URIs use the older, non revocable auth tokens. +func (s *ActivityService) ListFeeds(ctx context.Context) (*Feeds, *Response, error) { + req, err := s.client.NewRequest("GET", "feeds", nil) + if err != nil { + return nil, nil, err + } + + f := &Feeds{} + resp, err := s.client.Do(ctx, req, f) + if err != nil { + return nil, resp, err + } + + return f, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/activity_events.go b/vendor/github.com/google/go-github/github/activity_events.go new file mode 100644 index 00000000..f337fcd2 --- /dev/null +++ b/vendor/github.com/google/go-github/github/activity_events.go @@ -0,0 +1,324 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "time" +) + +// Event represents a GitHub event. +type Event struct { + Type *string `json:"type,omitempty"` + Public *bool `json:"public,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` + Repo *Repository `json:"repo,omitempty"` + Actor *User `json:"actor,omitempty"` + Org *Organization `json:"org,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + ID *string `json:"id,omitempty"` +} + +func (e Event) String() string { + return Stringify(e) +} + +// ParsePayload parses the event payload. For recognized event types, +// a value of the corresponding struct type will be returned. +func (e *Event) ParsePayload() (payload interface{}, err error) { + switch *e.Type { + case "CommitCommentEvent": + payload = &CommitCommentEvent{} + case "CreateEvent": + payload = &CreateEvent{} + case "DeleteEvent": + payload = &DeleteEvent{} + case "DeploymentEvent": + payload = &DeploymentEvent{} + case "DeploymentStatusEvent": + payload = &DeploymentStatusEvent{} + case "ForkEvent": + payload = &ForkEvent{} + case "GollumEvent": + payload = &GollumEvent{} + case "InstallationEvent": + payload = &InstallationEvent{} + case "InstallationRepositoriesEvent": + payload = &InstallationRepositoriesEvent{} + case "IssueCommentEvent": + payload = &IssueCommentEvent{} + case "IssuesEvent": + payload = &IssuesEvent{} + case "LabelEvent": + payload = &LabelEvent{} + case "MarketplacePurchaseEvent": + payload = &MarketplacePurchaseEvent{} + case "MemberEvent": + payload = &MemberEvent{} + case "MembershipEvent": + payload = &MembershipEvent{} + case "MilestoneEvent": + payload = &MilestoneEvent{} + case "OrganizationEvent": + payload = &OrganizationEvent{} + case "OrgBlockEvent": + payload = &OrgBlockEvent{} + case "PageBuildEvent": + payload = &PageBuildEvent{} + case "PingEvent": + payload = &PingEvent{} + case "ProjectEvent": + payload = &ProjectEvent{} + case "ProjectCardEvent": + payload = &ProjectCardEvent{} + case "ProjectColumnEvent": + payload = &ProjectColumnEvent{} + case "PublicEvent": + payload = &PublicEvent{} + case "PullRequestEvent": + payload = &PullRequestEvent{} + case "PullRequestReviewEvent": + payload = &PullRequestReviewEvent{} + case "PullRequestReviewCommentEvent": + payload = &PullRequestReviewCommentEvent{} + case "PushEvent": + payload = &PushEvent{} + case "ReleaseEvent": + payload = &ReleaseEvent{} + case "RepositoryEvent": + payload = &RepositoryEvent{} + case "StatusEvent": + payload = &StatusEvent{} + case "TeamEvent": + payload = &TeamEvent{} + case "TeamAddEvent": + payload = &TeamAddEvent{} + case "WatchEvent": + payload = &WatchEvent{} + } + err = json.Unmarshal(*e.RawPayload, &payload) + return payload, err +} + +// Payload returns the parsed event payload. For recognized event types, +// a value of the corresponding struct type will be returned. +// +// Deprecated: Use ParsePayload instead, which returns an error +// rather than panics if JSON unmarshaling raw payload fails. +func (e *Event) Payload() (payload interface{}) { + var err error + payload, err = e.ParsePayload() + if err != nil { + panic(err) + } + return payload +} + +// ListEvents drinks from the firehose of all public events across GitHub. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events +func (s *ActivityService) ListEvents(ctx context.Context, opt *ListOptions) ([]*Event, *Response, error) { + u, err := addOptions("events", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for a repository. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events +func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/events", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListIssueEventsForRepository lists issue events for a repository. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-issue-events-for-a-repository +func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForRepoNetwork lists public events for a network of repositories. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-a-network-of-repositories +func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("networks/%v/%v/events", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForOrganization lists public events for an organization. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-an-organization +func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opt *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("orgs/%v/events", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-performed-by-a-user +func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/events/public", user) + } else { + u = fmt.Sprintf("users/%v/events", user) + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsReceivedByUser lists the events received by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-that-a-user-has-received +func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/received_events/public", user) + } else { + u = fmt.Sprintf("users/%v/received_events", user) + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListUserEventsForOrganization provides the user’s organization dashboard. You +// must be authenticated as the user to view this. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-an-organization +func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opt *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("users/%v/events/orgs/%v", user, org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/activity_notifications.go b/vendor/github.com/google/go-github/github/activity_notifications.go new file mode 100644 index 00000000..45c8b2ae --- /dev/null +++ b/vendor/github.com/google/go-github/github/activity_notifications.go @@ -0,0 +1,223 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// Notification identifies a GitHub notification for a user. +type Notification struct { + ID *string `json:"id,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Subject *NotificationSubject `json:"subject,omitempty"` + + // Reason identifies the event that triggered the notification. + // + // GitHub API docs: https://developer.github.com/v3/activity/notifications/#notification-reasons + Reason *string `json:"reason,omitempty"` + + Unread *bool `json:"unread,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + LastReadAt *time.Time `json:"last_read_at,omitempty"` + URL *string `json:"url,omitempty"` +} + +// NotificationSubject identifies the subject of a notification. +type NotificationSubject struct { + Title *string `json:"title,omitempty"` + URL *string `json:"url,omitempty"` + LatestCommentURL *string `json:"latest_comment_url,omitempty"` + Type *string `json:"type,omitempty"` +} + +// NotificationListOptions specifies the optional parameters to the +// ActivityService.ListNotifications method. +type NotificationListOptions struct { + All bool `url:"all,omitempty"` + Participating bool `url:"participating,omitempty"` + Since time.Time `url:"since,omitempty"` + Before time.Time `url:"before,omitempty"` + + ListOptions +} + +// ListNotifications lists all notifications for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications +func (s *ActivityService) ListNotifications(ctx context.Context, opt *NotificationListOptions) ([]*Notification, *Response, error) { + u := fmt.Sprintf("notifications") + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var notifications []*Notification + resp, err := s.client.Do(ctx, req, ¬ifications) + if err != nil { + return nil, resp, err + } + + return notifications, resp, nil +} + +// ListRepositoryNotifications lists all notifications in a given repository +// for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications-in-a-repository +func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opt *NotificationListOptions) ([]*Notification, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var notifications []*Notification + resp, err := s.client.Do(ctx, req, ¬ifications) + if err != nil { + return nil, resp, err + } + + return notifications, resp, nil +} + +type markReadOptions struct { + LastReadAt time.Time `json:"last_read_at,omitempty"` +} + +// MarkNotificationsRead marks all notifications up to lastRead as read. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-as-read +func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead time.Time) (*Response, error) { + opts := &markReadOptions{ + LastReadAt: lastRead, + } + req, err := s.client.NewRequest("PUT", "notifications", opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// MarkRepositoryNotificationsRead marks all notifications up to lastRead in +// the specified repository as read. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-notifications-as-read-in-a-repository +func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead time.Time) (*Response, error) { + opts := &markReadOptions{ + LastReadAt: lastRead, + } + u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetThread gets the specified notification thread. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#view-a-single-thread +func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + notification := new(Notification) + resp, err := s.client.Do(ctx, req, notification) + if err != nil { + return nil, resp, err + } + + return notification, resp, nil +} + +// MarkThreadRead marks the specified thread as read. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-a-thread-as-read +func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("notifications/threads/%v", id) + + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetThreadSubscription checks to see if the authenticated user is subscribed +// to a thread. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#get-a-thread-subscription +func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// SetThreadSubscription sets the subscription for the specified thread for the +// authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#set-a-thread-subscription +func (s *ActivityService) SetThreadSubscription(ctx context.Context, id string, subscription *Subscription) (*Subscription, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + + req, err := s.client.NewRequest("PUT", u, subscription) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// DeleteThreadSubscription deletes the subscription for the specified thread +// for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/notifications/#delete-a-thread-subscription +func (s *ActivityService) DeleteThreadSubscription(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/activity_star.go b/vendor/github.com/google/go-github/github/activity_star.go new file mode 100644 index 00000000..d5b06712 --- /dev/null +++ b/vendor/github.com/google/go-github/github/activity_star.go @@ -0,0 +1,135 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// StarredRepository is returned by ListStarred. +type StarredRepository struct { + StarredAt *Timestamp `json:"starred_at,omitempty"` + Repository *Repository `json:"repo,omitempty"` +} + +// Stargazer represents a user that has starred a repository. +type Stargazer struct { + StarredAt *Timestamp `json:"starred_at,omitempty"` + User *User `json:"user,omitempty"` +} + +// ListStargazers lists people who have starred the specified repo. +// +// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-stargazers +func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Stargazer, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeStarringPreview) + + var stargazers []*Stargazer + resp, err := s.client.Do(ctx, req, &stargazers) + if err != nil { + return nil, resp, err + } + + return stargazers, resp, nil +} + +// ActivityListStarredOptions specifies the optional parameters to the +// ActivityService.ListStarred method. +type ActivityListStarredOptions struct { + // How to sort the repository list. Possible values are: created, updated, + // pushed, full_name. Default is "full_name". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Possible values are: asc, desc. + // Default is "asc" when sort is "full_name", otherwise default is "desc". + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListStarred lists all the repos starred by a user. Passing the empty string +// will list the starred repositories for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-being-starred +func (s *ActivityService) ListStarred(ctx context.Context, user string, opt *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/starred", user) + } else { + u = "user/starred" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeStarringPreview) + + var repos []*StarredRepository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// IsStarred checks if a repository is starred by authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository +func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bool, *Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + resp, err := s.client.Do(ctx, req, nil) + starred, err := parseBoolResponse(err) + return starred, resp, err +} + +// Star a repository as the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/starring/#star-a-repository +func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// Unstar a repository as the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository +func (s *ActivityService) Unstar(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/activity_watching.go b/vendor/github.com/google/go-github/github/activity_watching.go new file mode 100644 index 00000000..c749ca86 --- /dev/null +++ b/vendor/github.com/google/go-github/github/activity_watching.go @@ -0,0 +1,146 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Subscription identifies a repository or thread subscription. +type Subscription struct { + Subscribed *bool `json:"subscribed,omitempty"` + Ignored *bool `json:"ignored,omitempty"` + Reason *string `json:"reason,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + + // only populated for repository subscriptions + RepositoryURL *string `json:"repository_url,omitempty"` + + // only populated for thread subscriptions + ThreadURL *string `json:"thread_url,omitempty"` +} + +// ListWatchers lists watchers of a particular repo. +// +// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-watchers +func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var watchers []*User + resp, err := s.client.Do(ctx, req, &watchers) + if err != nil { + return nil, resp, err + } + + return watchers, resp, nil +} + +// ListWatched lists the repositories the specified user is watching. Passing +// the empty string will fetch watched repos for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-being-watched +func (s *ActivityService) ListWatched(ctx context.Context, user string, opt *ListOptions) ([]*Repository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/subscriptions", user) + } else { + u = "user/subscriptions" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var watched []*Repository + resp, err := s.client.Do(ctx, req, &watched) + if err != nil { + return nil, resp, err + } + + return watched, resp, nil +} + +// GetRepositorySubscription returns the subscription for the specified +// repository for the authenticated user. If the authenticated user is not +// watching the repository, a nil Subscription is returned. +// +// GitHub API docs: https://developer.github.com/v3/activity/watching/#get-a-repository-subscription +func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + // if it's just a 404, don't return that as an error + _, err = parseBoolResponse(err) + return nil, resp, err + } + + return sub, resp, nil +} + +// SetRepositorySubscription sets the subscription for the specified repository +// for the authenticated user. +// +// To watch a repository, set subscription.Subscribed to true. +// To ignore notifications made within a repository, set subscription.Ignored to true. +// To stop watching a repository, use DeleteRepositorySubscription. +// +// GitHub API docs: https://developer.github.com/v3/activity/watching/#set-a-repository-subscription +func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + + req, err := s.client.NewRequest("PUT", u, subscription) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// DeleteRepositorySubscription deletes the subscription for the specified +// repository for the authenticated user. +// +// This is used to stop watching a repository. To control whether or not to +// receive notifications from a repository, use SetRepositorySubscription. +// +// GitHub API docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription +func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/admin.go b/vendor/github.com/google/go-github/github/admin.go new file mode 100644 index 00000000..2d96733a --- /dev/null +++ b/vendor/github.com/google/go-github/github/admin.go @@ -0,0 +1,101 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AdminService handles communication with the admin related methods of the +// GitHub API. These API routes are normally only accessible for GitHub +// Enterprise installations. +// +// GitHub API docs: https://developer.github.com/v3/enterprise/ +type AdminService service + +// TeamLDAPMapping represents the mapping between a GitHub team and an LDAP group. +type TeamLDAPMapping struct { + ID *int64 `json:"id,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Slug *string `json:"slug,omitempty"` + Description *string `json:"description,omitempty"` + Privacy *string `json:"privacy,omitempty"` + Permission *string `json:"permission,omitempty"` + + MembersURL *string `json:"members_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` +} + +func (m TeamLDAPMapping) String() string { + return Stringify(m) +} + +// UserLDAPMapping represents the mapping between a GitHub user and an LDAP user. +type UserLDAPMapping struct { + ID *int64 `json:"id,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` + Login *string `json:"login,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` +} + +func (m UserLDAPMapping) String() string { + return Stringify(m) +} + +// UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user. +// +// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-user +func (s *AdminService) UpdateUserLDAPMapping(ctx context.Context, user string, mapping *UserLDAPMapping) (*UserLDAPMapping, *Response, error) { + u := fmt.Sprintf("admin/ldap/users/%v/mapping", user) + req, err := s.client.NewRequest("PATCH", u, mapping) + if err != nil { + return nil, nil, err + } + + m := new(UserLDAPMapping) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// UpdateTeamLDAPMapping updates the mapping between a GitHub team and an LDAP group. +// +// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-team +func (s *AdminService) UpdateTeamLDAPMapping(ctx context.Context, team int64, mapping *TeamLDAPMapping) (*TeamLDAPMapping, *Response, error) { + u := fmt.Sprintf("admin/ldap/teams/%v/mapping", team) + req, err := s.client.NewRequest("PATCH", u, mapping) + if err != nil { + return nil, nil, err + } + + m := new(TeamLDAPMapping) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/admin_stats.go b/vendor/github.com/google/go-github/github/admin_stats.go new file mode 100644 index 00000000..b5645f8c --- /dev/null +++ b/vendor/github.com/google/go-github/github/admin_stats.go @@ -0,0 +1,171 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AdminStats represents a variety of stats of a Github Enterprise +// installation. +type AdminStats struct { + Issues *IssueStats `json:"issues,omitempty"` + Hooks *HookStats `json:"hooks,omitempty"` + Milestones *MilestoneStats `json:"milestones,omitempty"` + Orgs *OrgStats `json:"orgs,omitempty"` + Comments *CommentStats `json:"comments,omitempty"` + Pages *PageStats `json:"pages,omitempty"` + Users *UserStats `json:"users,omitempty"` + Gists *GistStats `json:"gists,omitempty"` + Pulls *PullStats `json:"pulls,omitempty"` + Repos *RepoStats `json:"repos,omitempty"` +} + +func (s AdminStats) String() string { + return Stringify(s) +} + +// IssueStats represents the number of total, open and closed issues. +type IssueStats struct { + TotalIssues *int `json:"total_issues,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` + ClosedIssues *int `json:"closed_issues,omitempty"` +} + +func (s IssueStats) String() string { + return Stringify(s) +} + +// HookStats represents the number of total, active and inactive hooks. +type HookStats struct { + TotalHooks *int `json:"total_hooks,omitempty"` + ActiveHooks *int `json:"active_hooks,omitempty"` + InactiveHooks *int `json:"inactive_hooks,omitempty"` +} + +func (s HookStats) String() string { + return Stringify(s) +} + +// MilestoneStats represents the number of total, open and close milestones. +type MilestoneStats struct { + TotalMilestones *int `json:"total_milestones,omitempty"` + OpenMilestones *int `json:"open_milestones,omitempty"` + ClosedMilestones *int `json:"closed_milestones,omitempty"` +} + +func (s MilestoneStats) String() string { + return Stringify(s) +} + +// OrgStats represents the number of total, disabled organizations and the team +// and team member count. +type OrgStats struct { + TotalOrgs *int `json:"total_orgs,omitempty"` + DisabledOrgs *int `json:"disabled_orgs,omitempty"` + TotalTeams *int `json:"total_teams,omitempty"` + TotalTeamMembers *int `json:"total_team_members,omitempty"` +} + +func (s OrgStats) String() string { + return Stringify(s) +} + +// CommentStats represents the number of total comments on commits, gists, issues +// and pull requests. +type CommentStats struct { + TotalCommitComments *int `json:"total_commit_comments,omitempty"` + TotalGistComments *int `json:"total_gist_comments,omitempty"` + TotalIssueComments *int `json:"total_issue_comments,omitempty"` + TotalPullRequestComments *int `json:"total_pull_request_comments,omitempty"` +} + +func (s CommentStats) String() string { + return Stringify(s) +} + +// PageStats represents the total number of github pages. +type PageStats struct { + TotalPages *int `json:"total_pages,omitempty"` +} + +func (s PageStats) String() string { + return Stringify(s) +} + +// UserStats represents the number of total, admin and suspended users. +type UserStats struct { + TotalUsers *int `json:"total_users,omitempty"` + AdminUsers *int `json:"admin_users,omitempty"` + SuspendedUsers *int `json:"suspended_users,omitempty"` +} + +func (s UserStats) String() string { + return Stringify(s) +} + +// GistStats represents the number of total, private and public gists. +type GistStats struct { + TotalGists *int `json:"total_gists,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` +} + +func (s GistStats) String() string { + return Stringify(s) +} + +// PullStats represents the number of total, merged, mergable and unmergeable +// pull-requests. +type PullStats struct { + TotalPulls *int `json:"total_pulls,omitempty"` + MergedPulls *int `json:"merged_pulls,omitempty"` + MergablePulls *int `json:"mergeable_pulls,omitempty"` + UnmergablePulls *int `json:"unmergeable_pulls,omitempty"` +} + +func (s PullStats) String() string { + return Stringify(s) +} + +// RepoStats represents the number of total, root, fork, organization repositories +// together with the total number of pushes and wikis. +type RepoStats struct { + TotalRepos *int `json:"total_repos,omitempty"` + RootRepos *int `json:"root_repos,omitempty"` + ForkRepos *int `json:"fork_repos,omitempty"` + OrgRepos *int `json:"org_repos,omitempty"` + TotalPushes *int `json:"total_pushes,omitempty"` + TotalWikis *int `json:"total_wikis,omitempty"` +} + +func (s RepoStats) String() string { + return Stringify(s) +} + +// GetAdminStats returns a variety of metrics about a Github Enterprise +// installation. +// +// Please note that this is only available to site administrators, +// otherwise it will error with a 404 not found (instead of 401 or 403). +// +// GitHub API docs: https://developer.github.com/v3/enterprise-admin/admin_stats/ +func (s *AdminService) GetAdminStats(ctx context.Context) (*AdminStats, *Response, error) { + u := fmt.Sprintf("enterprise/stats/all") + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + m := new(AdminStats) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/apps.go b/vendor/github.com/google/go-github/github/apps.go new file mode 100644 index 00000000..c1f7f138 --- /dev/null +++ b/vendor/github.com/google/go-github/github/apps.go @@ -0,0 +1,197 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// AppsService provides access to the installation related functions +// in the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/apps/ +type AppsService service + +// App represents a GitHub App. +type App struct { + ID *int64 `json:"id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + ExternalURL *string `json:"external_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +// InstallationToken represents an installation token. +type InstallationToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *time.Time `json:"expires_at,omitempty"` +} + +// InstallationPermissions lists the permissions for metadata, contents, issues and single file for an installation. +type InstallationPermissions struct { + Metadata *string `json:"metadata,omitempty"` + Contents *string `json:"contents,omitempty"` + Issues *string `json:"issues,omitempty"` + SingleFile *string `json:"single_file,omitempty"` +} + +// Installation represents a GitHub Apps installation. +type Installation struct { + ID *int64 `json:"id,omitempty"` + AppID *int64 `json:"app_id,omitempty"` + TargetID *int64 `json:"target_id,omitempty"` + Account *User `json:"account,omitempty"` + AccessTokensURL *string `json:"access_tokens_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + TargetType *string `json:"target_type,omitempty"` + SingleFileName *string `json:"single_file_name,omitempty"` + RepositorySelection *string `json:"repository_selection,omitempty"` + Events []string `json:"events,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` +} + +func (i Installation) String() string { + return Stringify(i) +} + +// Get a single GitHub App. Passing the empty string will get +// the authenticated GitHub App. +// +// Note: appSlug is just the URL-friendly name of your GitHub App. +// You can find this on the settings page for your GitHub App +// (e.g., https://github.com/settings/apps/:app_slug). +// +// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-github-app +func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) { + var u string + if appSlug != "" { + u = fmt.Sprintf("apps/%v", appSlug) + } else { + u = "app" + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeIntegrationPreview) + + app := new(App) + resp, err := s.client.Do(ctx, req, app) + if err != nil { + return nil, resp, err + } + + return app, resp, nil +} + +// ListInstallations lists the installations that the current GitHub App has. +// +// GitHub API docs: https://developer.github.com/v3/apps/#find-installations +func (s *AppsService) ListInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) { + u, err := addOptions("app/installations", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeIntegrationPreview) + + var i []*Installation + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// GetInstallation returns the specified installation. +// +// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-installation +func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) { + u := fmt.Sprintf("app/installations/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeIntegrationPreview) + + i := new(Installation) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// ListUserInstallations lists installations that are accessible to the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/apps/#list-installations-for-user +func (s *AppsService) ListUserInstallations(ctx context.Context, opt *ListOptions) ([]*Installation, *Response, error) { + u, err := addOptions("user/installations", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeIntegrationPreview) + + var i struct { + Installations []*Installation `json:"installations"` + } + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i.Installations, resp, nil +} + +// CreateInstallationToken creates a new installation token. +// +// GitHub API docs: https://developer.github.com/v3/apps/#create-a-new-installation-token +func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64) (*InstallationToken, *Response, error) { + u := fmt.Sprintf("installations/%v/access_tokens", id) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeIntegrationPreview) + + t := new(InstallationToken) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/apps_installation.go b/vendor/github.com/google/go-github/github/apps_installation.go new file mode 100644 index 00000000..ccfecb8d --- /dev/null +++ b/vendor/github.com/google/go-github/github/apps_installation.go @@ -0,0 +1,101 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListRepos lists the repositories that are accessible to the authenticated installation. +// +// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories +func (s *AppsService) ListRepos(ctx context.Context, opt *ListOptions) ([]*Repository, *Response, error) { + u, err := addOptions("installation/repositories", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeIntegrationPreview) + + var r struct { + Repositories []*Repository `json:"repositories"` + } + resp, err := s.client.Do(ctx, req, &r) + if err != nil { + return nil, resp, err + } + + return r.Repositories, resp, nil +} + +// ListUserRepos lists repositories that are accessible +// to the authenticated user for an installation. +// +// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-user-for-an-installation +func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opt *ListOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories", id) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeIntegrationPreview) + + var r struct { + Repositories []*Repository `json:"repositories"` + } + resp, err := s.client.Do(ctx, req, &r) + if err != nil { + return nil, resp, err + } + + return r.Repositories, resp, nil +} + +// AddRepository adds a single repository to an installation. +// +// GitHub API docs: https://developer.github.com/v3/apps/installations/#add-repository-to-installation +func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) { + u := fmt.Sprintf("apps/installations/%v/repositories/%v", instID, repoID) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemoveRepository removes a single repository from an installation. +// +// GitHub docs: https://developer.github.com/v3/apps/installations/#remove-repository-from-installation +func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) { + u := fmt.Sprintf("apps/installations/%v/repositories/%v", instID, repoID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/apps_marketplace.go b/vendor/github.com/google/go-github/github/apps_marketplace.go new file mode 100644 index 00000000..089cdbf7 --- /dev/null +++ b/vendor/github.com/google/go-github/github/apps_marketplace.go @@ -0,0 +1,180 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// MarketplaceService handles communication with the marketplace related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/apps/marketplace/ +type MarketplaceService struct { + client *Client + // Stubbed controls whether endpoints that return stubbed data are used + // instead of production endpoints. Stubbed data is fake data that's useful + // for testing your GitHub Apps. Stubbed data is hard-coded and will not + // change based on actual subscriptions. + // + // GitHub API docs: https://developer.github.com/v3/apps/marketplace/ + Stubbed bool +} + +// MarketplacePlan represents a GitHub Apps Marketplace Listing Plan. +type MarketplacePlan struct { + URL *string `json:"url,omitempty"` + AccountsURL *string `json:"accounts_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + MonthlyPriceInCents *int `json:"monthly_price_in_cents,omitempty"` + YearlyPriceInCents *int `json:"yearly_price_in_cents,omitempty"` + PriceModel *string `json:"price_model,omitempty"` + UnitName *string `json:"unit_name,omitempty"` + Bullets *[]string `json:"bullets,omitempty"` +} + +// MarketplacePurchase represents a GitHub Apps Marketplace Purchase. +type MarketplacePurchase struct { + BillingCycle *string `json:"billing_cycle,omitempty"` + NextBillingDate *string `json:"next_billing_date,omitempty"` + UnitCount *int `json:"unit_count,omitempty"` + Plan *MarketplacePlan `json:"plan,omitempty"` + Account *MarketplacePlanAccount `json:"account,omitempty"` +} + +// MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan. +type MarketplacePlanAccount struct { + URL *string `json:"url,omitempty"` + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` + Login *string `json:"login,omitempty"` + Email *string `json:"email,omitempty"` + OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` + MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` +} + +// ListPlans lists all plans for your Marketplace listing. +// +// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-plans-for-your-marketplace-listing +func (s *MarketplaceService) ListPlans(ctx context.Context, opt *ListOptions) ([]*MarketplacePlan, *Response, error) { + uri := s.marketplaceURI("plans") + u, err := addOptions(uri, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMarketplacePreview) + + var plans []*MarketplacePlan + resp, err := s.client.Do(ctx, req, &plans) + if err != nil { + return nil, resp, err + } + + return plans, resp, nil +} + +// ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan. +// +// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-github-accounts-user-or-organization-on-a-specific-plan +func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { + uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID)) + u, err := addOptions(uri, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMarketplacePreview) + + var accounts []*MarketplacePlanAccount + resp, err := s.client.Do(ctx, req, &accounts) + if err != nil { + return nil, resp, err + } + + return accounts, resp, nil +} + +// ListPlanAccountsForAccount lists all GitHub accounts (user or organization) associated with an account. +// +// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#check-if-a-github-account-is-associated-with-any-marketplace-listing +func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, accountID int64, opt *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { + uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID)) + u, err := addOptions(uri, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMarketplacePreview) + + var accounts []*MarketplacePlanAccount + resp, err := s.client.Do(ctx, req, &accounts) + if err != nil { + return nil, resp, err + } + + return accounts, resp, nil +} + +// ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. +// +// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#get-a-users-marketplace-purchases +func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opt *ListOptions) ([]*MarketplacePurchase, *Response, error) { + uri := "user/marketplace_purchases" + if s.Stubbed { + uri = "user/marketplace_purchases/stubbed" + } + + u, err := addOptions(uri, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMarketplacePreview) + + var purchases []*MarketplacePurchase + resp, err := s.client.Do(ctx, req, &purchases) + if err != nil { + return nil, resp, err + } + + return purchases, resp, nil +} + +func (s *MarketplaceService) marketplaceURI(endpoint string) string { + url := "marketplace_listing" + if s.Stubbed { + url = "marketplace_listing/stubbed" + } + return url + "/" + endpoint +} diff --git a/vendor/github.com/google/go-github/github/authorizations.go b/vendor/github.com/google/go-github/github/authorizations.go new file mode 100644 index 00000000..190205b0 --- /dev/null +++ b/vendor/github.com/google/go-github/github/authorizations.go @@ -0,0 +1,435 @@ +// Copyright 2015 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Scope models a GitHub authorization scope. +// +// GitHub API docs: https://developer.github.com/v3/oauth/#scopes +type Scope string + +// This is the set of scopes for GitHub API V3 +const ( + ScopeNone Scope = "(no scope)" // REVISIT: is this actually returned, or just a documentation artifact? + ScopeUser Scope = "user" + ScopeUserEmail Scope = "user:email" + ScopeUserFollow Scope = "user:follow" + ScopePublicRepo Scope = "public_repo" + ScopeRepo Scope = "repo" + ScopeRepoDeployment Scope = "repo_deployment" + ScopeRepoStatus Scope = "repo:status" + ScopeDeleteRepo Scope = "delete_repo" + ScopeNotifications Scope = "notifications" + ScopeGist Scope = "gist" + ScopeReadRepoHook Scope = "read:repo_hook" + ScopeWriteRepoHook Scope = "write:repo_hook" + ScopeAdminRepoHook Scope = "admin:repo_hook" + ScopeAdminOrgHook Scope = "admin:org_hook" + ScopeReadOrg Scope = "read:org" + ScopeWriteOrg Scope = "write:org" + ScopeAdminOrg Scope = "admin:org" + ScopeReadPublicKey Scope = "read:public_key" + ScopeWritePublicKey Scope = "write:public_key" + ScopeAdminPublicKey Scope = "admin:public_key" + ScopeReadGPGKey Scope = "read:gpg_key" + ScopeWriteGPGKey Scope = "write:gpg_key" + ScopeAdminGPGKey Scope = "admin:gpg_key" +) + +// AuthorizationsService handles communication with the authorization related +// methods of the GitHub API. +// +// This service requires HTTP Basic Authentication; it cannot be accessed using +// an OAuth token. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/ +type AuthorizationsService service + +// Authorization represents an individual GitHub authorization. +type Authorization struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Scopes []Scope `json:"scopes,omitempty"` + Token *string `json:"token,omitempty"` + TokenLastEight *string `json:"token_last_eight,omitempty"` + HashedToken *string `json:"hashed_token,omitempty"` + App *AuthorizationApp `json:"app,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` + + // User is only populated by the Check and Reset methods. + User *User `json:"user,omitempty"` +} + +func (a Authorization) String() string { + return Stringify(a) +} + +// AuthorizationApp represents an individual GitHub app (in the context of authorization). +type AuthorizationApp struct { + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + ClientID *string `json:"client_id,omitempty"` +} + +func (a AuthorizationApp) String() string { + return Stringify(a) +} + +// Grant represents an OAuth application that has been granted access to an account. +type Grant struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + App *AuthorizationApp `json:"app,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Scopes []string `json:"scopes,omitempty"` +} + +func (g Grant) String() string { + return Stringify(g) +} + +// AuthorizationRequest represents a request to create an authorization. +type AuthorizationRequest struct { + Scopes []Scope `json:"scopes,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + ClientID *string `json:"client_id,omitempty"` + ClientSecret *string `json:"client_secret,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +func (a AuthorizationRequest) String() string { + return Stringify(a) +} + +// AuthorizationUpdateRequest represents a request to update an authorization. +// +// Note that for any one update, you must only provide one of the "scopes" +// fields. That is, you may provide only one of "Scopes", or "AddScopes", or +// "RemoveScopes". +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization +type AuthorizationUpdateRequest struct { + Scopes []string `json:"scopes,omitempty"` + AddScopes []string `json:"add_scopes,omitempty"` + RemoveScopes []string `json:"remove_scopes,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +func (a AuthorizationUpdateRequest) String() string { + return Stringify(a) +} + +// List the authorizations for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations +func (s *AuthorizationsService) List(ctx context.Context, opt *ListOptions) ([]*Authorization, *Response, error) { + u := "authorizations" + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var auths []*Authorization + resp, err := s.client.Do(ctx, req, &auths) + if err != nil { + return nil, resp, err + } + return auths, resp, nil +} + +// Get a single authorization. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-authorization +func (s *AuthorizationsService) Get(ctx context.Context, id int64) (*Authorization, *Response, error) { + u := fmt.Sprintf("authorizations/%d", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + return a, resp, nil +} + +// Create a new authorization for the specified OAuth application. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization +func (s *AuthorizationsService) Create(ctx context.Context, auth *AuthorizationRequest) (*Authorization, *Response, error) { + u := "authorizations" + + req, err := s.client.NewRequest("POST", u, auth) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + return a, resp, nil +} + +// GetOrCreateForApp creates a new authorization for the specified OAuth +// application, only if an authorization for that application doesn’t already +// exist for the user. +// +// If a new token is created, the HTTP status code will be "201 Created", and +// the returned Authorization.Token field will be populated. If an existing +// token is returned, the status code will be "200 OK" and the +// Authorization.Token field will be empty. +// +// clientID is the OAuth Client ID with which to create the token. +// +// GitHub API docs: +// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app +// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app-and-fingerprint +func (s *AuthorizationsService) GetOrCreateForApp(ctx context.Context, clientID string, auth *AuthorizationRequest) (*Authorization, *Response, error) { + var u string + if auth.Fingerprint == nil || *auth.Fingerprint == "" { + u = fmt.Sprintf("authorizations/clients/%v", clientID) + } else { + u = fmt.Sprintf("authorizations/clients/%v/%v", clientID, *auth.Fingerprint) + } + + req, err := s.client.NewRequest("PUT", u, auth) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// Edit a single authorization. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization +func (s *AuthorizationsService) Edit(ctx context.Context, id int64, auth *AuthorizationUpdateRequest) (*Authorization, *Response, error) { + u := fmt.Sprintf("authorizations/%d", id) + + req, err := s.client.NewRequest("PATCH", u, auth) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// Delete a single authorization. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-an-authorization +func (s *AuthorizationsService) Delete(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("authorizations/%d", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Check if an OAuth token is valid for a specific app. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// The returned Authorization.User field will be populated. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#check-an-authorization +func (s *AuthorizationsService) Check(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) { + u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// Reset is used to reset a valid OAuth token without end user involvement. +// Applications must save the "token" property in the response, because changes +// take effect immediately. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// The returned Authorization.User field will be populated. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization +func (s *AuthorizationsService) Reset(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) { + u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// Revoke an authorization for an application. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application +func (s *AuthorizationsService) Revoke(ctx context.Context, clientID string, token string) (*Response, error) { + u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListGrants lists the set of OAuth applications that have been granted +// access to a user's account. This will return one entry for each application +// that has been granted access to the account, regardless of the number of +// tokens an application has generated for the user. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-grants +func (s *AuthorizationsService) ListGrants(ctx context.Context, opt *ListOptions) ([]*Grant, *Response, error) { + u, err := addOptions("applications/grants", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + grants := []*Grant{} + resp, err := s.client.Do(ctx, req, &grants) + if err != nil { + return nil, resp, err + } + + return grants, resp, nil +} + +// GetGrant gets a single OAuth application grant. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-grant +func (s *AuthorizationsService) GetGrant(ctx context.Context, id int64) (*Grant, *Response, error) { + u := fmt.Sprintf("applications/grants/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + grant := new(Grant) + resp, err := s.client.Do(ctx, req, grant) + if err != nil { + return nil, resp, err + } + + return grant, resp, nil +} + +// DeleteGrant deletes an OAuth application grant. Deleting an application's +// grant will also delete all OAuth tokens associated with the application for +// the user. +// +// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-a-grant +func (s *AuthorizationsService) DeleteGrant(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("applications/grants/%d", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateImpersonation creates an impersonation OAuth token. +// +// This requires admin permissions. With the returned Authorization.Token +// you can e.g. create or delete a user's public SSH key. NOTE: creating a +// new token automatically revokes an existing one. +// +// GitHub API docs: https://developer.github.com/enterprise/2.5/v3/users/administration/#create-an-impersonation-oauth-token +func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, username string, authReq *AuthorizationRequest) (*Authorization, *Response, error) { + u := fmt.Sprintf("admin/users/%v/authorizations", username) + req, err := s.client.NewRequest("POST", u, authReq) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + return a, resp, nil +} + +// DeleteImpersonation deletes an impersonation OAuth token. +// +// NOTE: there can be only one at a time. +// +// GitHub API docs: https://developer.github.com/enterprise/2.5/v3/users/administration/#delete-an-impersonation-oauth-token +func (s *AuthorizationsService) DeleteImpersonation(ctx context.Context, username string) (*Response, error) { + u := fmt.Sprintf("admin/users/%v/authorizations", username) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/doc.go b/vendor/github.com/google/go-github/github/doc.go new file mode 100644 index 00000000..96445d26 --- /dev/null +++ b/vendor/github.com/google/go-github/github/doc.go @@ -0,0 +1,187 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package github provides a client for using the GitHub API. + +Usage: + + import "github.com/google/go-github/github" + +Construct a new GitHub client, then use the various services on the client to +access different parts of the GitHub API. For example: + + client := github.NewClient(nil) + + // list all organizations for user "willnorris" + orgs, _, err := client.Organizations.List(ctx, "willnorris", nil) + +Some API methods have optional parameters that can be passed. For example: + + client := github.NewClient(nil) + + // list public repositories for org "github" + opt := &github.RepositoryListByOrgOptions{Type: "public"} + repos, _, err := client.Repositories.ListByOrg(ctx, "github", opt) + +The services of a client divide the API into logical chunks and correspond to +the structure of the GitHub API documentation at +https://developer.github.com/v3/. + +NOTE: Using the https://godoc.org/context package, one can easily +pass cancelation signals and deadlines to various services of the client for +handling a request. In case there is no context available, then context.Background() +can be used as a starting point. + +For more sample code snippets, head over to the https://github.com/google/go-github/tree/master/example directory. + +Authentication + +The go-github library does not directly handle authentication. Instead, when +creating a new client, pass an http.Client that can handle authentication for +you. The easiest and recommended way to do this is using the golang.org/x/oauth2 +library, but you can always use any other library that provides an http.Client. +If you have an OAuth2 access token (for example, a personal API token), you can +use it with the oauth2 library using: + + import "golang.org/x/oauth2" + + func main() { + ctx := context.Background() + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: "... your access token ..."}, + ) + tc := oauth2.NewClient(ctx, ts) + + client := github.NewClient(tc) + + // list all repositories for the authenticated user + repos, _, err := client.Repositories.List(ctx, "", nil) + } + +Note that when using an authenticated Client, all calls made by the client will +include the specified OAuth token. Therefore, authenticated clients should +almost never be shared between different users. + +See the oauth2 docs for complete instructions on using that library. + +For API methods that require HTTP Basic Authentication, use the +BasicAuthTransport. + +GitHub Apps authentication can be provided by the +https://github.com/bradleyfalzon/ghinstallation package. + + import "github.com/bradleyfalzon/ghinstallation" + + func main() { + // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99. + itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem") + if err != nil { + // Handle error. + } + + // Use installation transport with client + client := github.NewClient(&http.Client{Transport: itr}) + + // Use client... + } + +Rate Limiting + +GitHub imposes a rate limit on all API clients. Unauthenticated clients are +limited to 60 requests per hour, while authenticated clients can make up to +5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated +clients are limited to 10 requests per minute, while authenticated clients +can make up to 30 requests per minute. To receive the higher rate limit when +making calls that are not issued on behalf of a user, +use UnauthenticatedRateLimitedTransport. + +The returned Response.Rate value contains the rate limit information +from the most recent API call. If a recent enough response isn't +available, you can use RateLimits to fetch the most up-to-date rate +limit data for the client. + +To detect an API rate limit error, you can check if its type is *github.RateLimitError: + + repos, _, err := client.Repositories.List(ctx, "", nil) + if _, ok := err.(*github.RateLimitError); ok { + log.Println("hit rate limit") + } + +Learn more about GitHub rate limiting at +https://developer.github.com/v3/#rate-limiting. + +Accepted Status + +Some endpoints may return a 202 Accepted status code, meaning that the +information required is not yet ready and was scheduled to be gathered on +the GitHub side. Methods known to behave like this are documented specifying +this behavior. + +To detect this condition of error, you can check if its type is +*github.AcceptedError: + + stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo) + if _, ok := err.(*github.AcceptedError); ok { + log.Println("scheduled on GitHub side") + } + +Conditional Requests + +The GitHub API has good support for conditional requests which will help +prevent you from burning through your rate limit, as well as help speed up your +application. go-github does not handle conditional requests directly, but is +instead designed to work with a caching http.Transport. We recommend using +https://github.com/gregjones/httpcache for that. + +Learn more about GitHub conditional requests at +https://developer.github.com/v3/#conditional-requests. + +Creating and Updating Resources + +All structs for GitHub resources use pointer values for all non-repeated fields. +This allows distinguishing between unset fields and those set to a zero-value. +Helper functions have been provided to easily create these pointers for string, +bool, and int values. For example: + + // create a new private repository named "foo" + repo := &github.Repository{ + Name: github.String("foo"), + Private: github.Bool(true), + } + client.Repositories.Create(ctx, "", repo) + +Users who have worked with protocol buffers should find this pattern familiar. + +Pagination + +All requests for resource collections (repos, pull requests, issues, etc.) +support pagination. Pagination options are described in the +github.ListOptions struct and passed to the list methods directly or as an +embedded type of a more specific list options struct (for example +github.PullRequestListOptions). Pages information is available via the +github.Response struct. + + client := github.NewClient(nil) + + opt := &github.RepositoryListByOrgOptions{ + ListOptions: github.ListOptions{PerPage: 10}, + } + // get all pages of results + var allRepos []*github.Repository + for { + repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt) + if err != nil { + return err + } + allRepos = append(allRepos, repos...) + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + +*/ +package github diff --git a/vendor/github.com/google/go-github/github/event_types.go b/vendor/github.com/google/go-github/github/event_types.go new file mode 100644 index 00000000..17c2b102 --- /dev/null +++ b/vendor/github.com/google/go-github/github/event_types.go @@ -0,0 +1,752 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// These event types are shared between the Events API and used as Webhook payloads. + +package github + +// CommitCommentEvent is triggered when a commit comment is created. +// The Webhook event name is "commit_comment". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#commitcommentevent +type CommitCommentEvent struct { + Comment *RepositoryComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CreateEvent represents a created repository, branch, or tag. +// The Webhook event name is "create". +// +// Note: webhooks will not receive this event for created repositories. +// Additionally, webhooks will not receive this event for tags if more +// than three tags are pushed at once. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#createevent +type CreateEvent struct { + Ref *string `json:"ref,omitempty"` + // RefType is the object that was created. Possible values are: "repository", "branch", "tag". + RefType *string `json:"ref_type,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + Description *string `json:"description,omitempty"` + + // The following fields are only populated by Webhook events. + PusherType *string `json:"pusher_type,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeleteEvent represents a deleted branch or tag. +// The Webhook event name is "delete". +// +// Note: webhooks will not receive this event for tags if more than three tags +// are deleted at once. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deleteevent +type DeleteEvent struct { + Ref *string `json:"ref,omitempty"` + // RefType is the object that was deleted. Possible values are: "branch", "tag". + RefType *string `json:"ref_type,omitempty"` + + // The following fields are only populated by Webhook events. + PusherType *string `json:"pusher_type,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeploymentEvent represents a deployment. +// The Webhook event name is "deployment". +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentevent +type DeploymentEvent struct { + Deployment *Deployment `json:"deployment,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeploymentStatusEvent represents a deployment status. +// The Webhook event name is "deployment_status". +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentstatusevent +type DeploymentStatusEvent struct { + Deployment *Deployment `json:"deployment,omitempty"` + DeploymentStatus *DeploymentStatus `json:"deployment_status,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ForkEvent is triggered when a user forks a repository. +// The Webhook event name is "fork". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#forkevent +type ForkEvent struct { + // Forkee is the created repository. + Forkee *Repository `json:"forkee,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// Page represents a single Wiki page. +type Page struct { + PageName *string `json:"page_name,omitempty"` + Title *string `json:"title,omitempty"` + Summary *string `json:"summary,omitempty"` + Action *string `json:"action,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// GollumEvent is triggered when a Wiki page is created or updated. +// The Webhook event name is "gollum". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#gollumevent +type GollumEvent struct { + Pages []*Page `json:"pages,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// EditChange represents the changes when an issue, pull request, or comment has +// been edited. +type EditChange struct { + Title *struct { + From *string `json:"from,omitempty"` + } `json:"title,omitempty"` + Body *struct { + From *string `json:"from,omitempty"` + } `json:"body,omitempty"` +} + +// ProjectChange represents the changes when a project has been edited. +type ProjectChange struct { + Name *struct { + From *string `json:"from,omitempty"` + } `json:"name,omitempty"` + Body *struct { + From *string `json:"from,omitempty"` + } `json:"body,omitempty"` +} + +// ProjectCardChange represents the changes when a project card has been edited. +type ProjectCardChange struct { + Note *struct { + From *string `json:"from,omitempty"` + } `json:"note,omitempty"` +} + +// ProjectColumnChange represents the changes when a project column has been edited. +type ProjectColumnChange struct { + Name *struct { + From *string `json:"from,omitempty"` + } `json:"name,omitempty"` +} + +// TeamChange represents the changes when a team has been edited. +type TeamChange struct { + Description *struct { + From *string `json:"from,omitempty"` + } `json:"description,omitempty"` + Name *struct { + From *string `json:"from,omitempty"` + } `json:"name,omitempty"` + Privacy *struct { + From *string `json:"from,omitempty"` + } `json:"privacy,omitempty"` + Repository *struct { + Permissions *struct { + From *struct { + Admin *bool `json:"admin,omitempty"` + Pull *bool `json:"pull,omitempty"` + Push *bool `json:"push,omitempty"` + } `json:"from,omitempty"` + } `json:"permissions,omitempty"` + } `json:"repository,omitempty"` +} + +// InstallationEvent is triggered when a GitHub App has been installed or uninstalled. +// The Webhook event name is "installation". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationevent +type InstallationEvent struct { + // The action that was performed. Can be either "created" or "deleted". + Action *string `json:"action,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// InstallationRepositoriesEvent is triggered when a repository is added or +// removed from an installation. The Webhook event name is "installation_repositories". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationrepositoriesevent +type InstallationRepositoriesEvent struct { + // The action that was performed. Can be either "added" or "removed". + Action *string `json:"action,omitempty"` + RepositoriesAdded []*Repository `json:"repositories_added,omitempty"` + RepositoriesRemoved []*Repository `json:"repositories_removed,omitempty"` + RepositorySelection *string `json:"repository_selection,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// IssueCommentEvent is triggered when an issue comment is created on an issue +// or pull request. +// The Webhook event name is "issue_comment". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuecommentevent +type IssueCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". + Action *string `json:"action,omitempty"` + Issue *Issue `json:"issue,omitempty"` + Comment *IssueComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// IssuesEvent is triggered when an issue is assigned, unassigned, labeled, +// unlabeled, opened, closed, or reopened. +// The Webhook event name is "issues". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuesevent +type IssuesEvent struct { + // Action is the action that was performed. Possible values are: "assigned", + // "unassigned", "labeled", "unlabeled", "opened", "closed", "reopened", "edited". + Action *string `json:"action,omitempty"` + Issue *Issue `json:"issue,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Label *Label `json:"label,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// LabelEvent is triggered when a repository's label is created, edited, or deleted. +// The Webhook event name is "label" +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#labelevent +type LabelEvent struct { + // Action is the action that was performed. Possible values are: + // "created", "edited", "deleted" + Action *string `json:"action,omitempty"` + Label *Label `json:"label,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MarketplacePurchaseEvent is triggered when a user purchases, cancels, or changes +// their GitHub Marketplace plan. +// Webhook event name "marketplace_purchase". +// +// Github API docs: https://developer.github.com/v3/activity/events/types/#marketplacepurchaseevent +type MarketplacePurchaseEvent struct { + // Action is the action that was performed. Possible values are: + // "purchased", "cancelled", "changed". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + EffectiveDate *Timestamp `json:"effective_date,omitempty"` + MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` + PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MemberEvent is triggered when a user is added as a collaborator to a repository. +// The Webhook event name is "member". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#memberevent +type MemberEvent struct { + // Action is the action that was performed. Possible value is: "added". + Action *string `json:"action,omitempty"` + Member *User `json:"member,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MembershipEvent is triggered when a user is added or removed from a team. +// The Webhook event name is "membership". +// +// Events of this type are not visible in timelines, they are only used to +// trigger organization webhooks. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#membershipevent +type MembershipEvent struct { + // Action is the action that was performed. Possible values are: "added", "removed". + Action *string `json:"action,omitempty"` + // Scope is the scope of the membership. Possible value is: "team". + Scope *string `json:"scope,omitempty"` + Member *User `json:"member,omitempty"` + Team *Team `json:"team,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted. +// The Webhook event name is "milestone". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#milestoneevent +type MilestoneEvent struct { + // Action is the action that was performed. Possible values are: + // "created", "closed", "opened", "edited", "deleted" + Action *string `json:"action,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Org *Organization `json:"organization,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// OrganizationEvent is triggered when a user is added, removed, or invited to an organization. +// Events of this type are not visible in timelines. These events are only used to trigger organization hooks. +// Webhook event name is "organization". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#organizationevent +type OrganizationEvent struct { + // Action is the action that was performed. + // Can be one of "member_added", "member_removed", or "member_invited". + Action *string `json:"action,omitempty"` + + // Invitaion is the invitation for the user or email if the action is "member_invited". + Invitation *Invitation `json:"invitation,omitempty"` + + // Membership is the membership between the user and the organization. + // Not present when the action is "member_invited". + Membership *Membership `json:"membership,omitempty"` + + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// OrgBlockEvent is triggered when an organization blocks or unblocks a user. +// The Webhook event name is "org_block". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#orgblockevent +type OrgBlockEvent struct { + // Action is the action that was performed. + // Can be "blocked" or "unblocked". + Action *string `json:"action,omitempty"` + BlockedUser *User `json:"blocked_user,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// PageBuildEvent represents an attempted build of a GitHub Pages site, whether +// successful or not. +// The Webhook event name is "page_build". +// +// This event is triggered on push to a GitHub Pages enabled branch (gh-pages +// for project pages, master for user and organization pages). +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pagebuildevent +type PageBuildEvent struct { + Build *PagesBuild `json:"build,omitempty"` + + // The following fields are only populated by Webhook events. + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PingEvent is triggered when a Webhook is added to GitHub. +// +// GitHub API docs: https://developer.github.com/webhooks/#ping-event +type PingEvent struct { + // Random string of GitHub zen. + Zen *string `json:"zen,omitempty"` + // The ID of the webhook that triggered the ping. + HookID *int64 `json:"hook_id,omitempty"` + // The webhook configuration. + Hook *Hook `json:"hook,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ProjectEvent is triggered when project is created, modified or deleted. +// The webhook event name is "project". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectevent +type ProjectEvent struct { + Action *string `json:"action,omitempty"` + Changes *ProjectChange `json:"changes,omitempty"` + Project *Project `json:"project,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ProjectCardEvent is triggered when a project card is created, updated, moved, converted to an issue, or deleted. +// The webhook event name is "project_card". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcardevent +type ProjectCardEvent struct { + Action *string `json:"action,omitempty"` + Changes *ProjectCardChange `json:"changes,omitempty"` + AfterID *int64 `json:"after_id,omitempty"` + ProjectCard *ProjectCard `json:"project_card,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ProjectColumnEvent is triggered when a project column is created, updated, moved, or deleted. +// The webhook event name is "project_column". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcolumnevent +type ProjectColumnEvent struct { + Action *string `json:"action,omitempty"` + Changes *ProjectColumnChange `json:"changes,omitempty"` + AfterID *int64 `json:"after_id,omitempty"` + ProjectColumn *ProjectColumn `json:"project_column,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PublicEvent is triggered when a private repository is open sourced. +// According to GitHub: "Without a doubt: the best GitHub event." +// The Webhook event name is "public". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#publicevent +type PublicEvent struct { + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PullRequestEvent is triggered when a pull request is assigned, unassigned, +// labeled, unlabeled, opened, closed, reopened, or synchronized. +// The Webhook event name is "pull_request". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestevent +type PullRequestEvent struct { + // Action is the action that was performed. Possible values are: + // "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled", + // "opened", "closed", "reopened", "synchronize", "edited". + // If the action is "closed" and the merged key is false, + // the pull request was closed with unmerged commits. If the action is "closed" + // and the merged key is true, the pull request was merged. + Action *string `json:"action,omitempty"` + Number *int `json:"number,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. + // A request affecting multiple reviewers at once is split into multiple + // such event deliveries, each with a single, different RequestedReviewer. + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. +} + +// PullRequestReviewEvent is triggered when a review is submitted on a pull +// request. +// The Webhook event name is "pull_request_review". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent +type PullRequestReviewEvent struct { + // Action is always "submitted". + Action *string `json:"action,omitempty"` + Review *PullRequestReview `json:"review,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// PullRequestReviewCommentEvent is triggered when a comment is created on a +// portion of the unified diff of a pull request. +// The Webhook event name is "pull_request_review_comment". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewcommentevent +type PullRequestReviewCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". + Action *string `json:"action,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + Comment *PullRequestComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PushEvent represents a git push to a GitHub repository. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pushevent +type PushEvent struct { + PushID *int64 `json:"push_id,omitempty"` + Head *string `json:"head,omitempty"` + Ref *string `json:"ref,omitempty"` + Size *int `json:"size,omitempty"` + Commits []PushEventCommit `json:"commits,omitempty"` + Before *string `json:"before,omitempty"` + DistinctSize *int `json:"distinct_size,omitempty"` + + // The following fields are only populated by Webhook events. + After *string `json:"after,omitempty"` + Created *bool `json:"created,omitempty"` + Deleted *bool `json:"deleted,omitempty"` + Forced *bool `json:"forced,omitempty"` + BaseRef *string `json:"base_ref,omitempty"` + Compare *string `json:"compare,omitempty"` + Repo *PushEventRepository `json:"repository,omitempty"` + HeadCommit *PushEventCommit `json:"head_commit,omitempty"` + Pusher *User `json:"pusher,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +func (p PushEvent) String() string { + return Stringify(p) +} + +// PushEventCommit represents a git commit in a GitHub PushEvent. +type PushEventCommit struct { + Message *string `json:"message,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + URL *string `json:"url,omitempty"` + Distinct *bool `json:"distinct,omitempty"` + + // The following fields are only populated by Events API. + SHA *string `json:"sha,omitempty"` + + // The following fields are only populated by Webhook events. + ID *string `json:"id,omitempty"` + TreeID *string `json:"tree_id,omitempty"` + Timestamp *Timestamp `json:"timestamp,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Added []string `json:"added,omitempty"` + Removed []string `json:"removed,omitempty"` + Modified []string `json:"modified,omitempty"` +} + +func (p PushEventCommit) String() string { + return Stringify(p) +} + +// PushEventRepository represents the repo object in a PushEvent payload. +type PushEventRepository struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + FullName *string `json:"full_name,omitempty"` + Owner *PushEventRepoOwner `json:"owner,omitempty"` + Private *bool `json:"private,omitempty"` + Description *string `json:"description,omitempty"` + Fork *bool `json:"fork,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PushedAt *Timestamp `json:"pushed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Homepage *string `json:"homepage,omitempty"` + Size *int `json:"size,omitempty"` + StargazersCount *int `json:"stargazers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` + Language *string `json:"language,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasDownloads *bool `json:"has_downloads,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasPages *bool `json:"has_pages,omitempty"` + ForksCount *int `json:"forks_count,omitempty"` + OpenIssuesCount *int `json:"open_issues_count,omitempty"` + DefaultBranch *string `json:"default_branch,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + Organization *string `json:"organization,omitempty"` + URL *string `json:"url,omitempty"` + ArchiveURL *string `json:"archive_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + SSHURL *string `json:"ssh_url,omitempty"` + CloneURL *string `json:"clone_url,omitempty"` + SVNURL *string `json:"svn_url,omitempty"` +} + +// PushEventRepoOwner is a basic representation of user/org in a PushEvent payload. +type PushEventRepoOwner struct { + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` +} + +// ReleaseEvent is triggered when a release is published. +// The Webhook event name is "release". +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#releaseevent +type ReleaseEvent struct { + // Action is the action that was performed. Possible value is: "published". + Action *string `json:"action,omitempty"` + Release *RepositoryRelease `json:"release,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// RepositoryEvent is triggered when a repository is created. +// The Webhook event name is "repository". +// +// Events of this type are not visible in timelines, they are only used to +// trigger organization webhooks. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryevent +type RepositoryEvent struct { + // Action is the action that was performed. Possible values are: "created", "deleted", + // "publicized", "privatized". + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// StatusEvent is triggered when the status of a Git commit changes. +// The Webhook event name is "status". +// +// Events of this type are not visible in timelines, they are only used to +// trigger hooks. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#statusevent +type StatusEvent struct { + SHA *string `json:"sha,omitempty"` + // State is the new state. Possible values are: "pending", "success", "failure", "error". + State *string `json:"state,omitempty"` + Description *string `json:"description,omitempty"` + TargetURL *string `json:"target_url,omitempty"` + Branches []*Branch `json:"branches,omitempty"` + + // The following fields are only populated by Webhook events. + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Context *string `json:"context,omitempty"` + Commit *RepositoryCommit `json:"commit,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// TeamEvent is triggered when an organization's team is created, modified or deleted. +// The Webhook event name is "team". +// +// Events of this type are not visible in timelines. These events are only used +// to trigger hooks. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamevent +type TeamEvent struct { + Action *string `json:"action,omitempty"` + Team *Team `json:"team,omitempty"` + Changes *TeamChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// TeamAddEvent is triggered when a repository is added to a team. +// The Webhook event name is "team_add". +// +// Events of this type are not visible in timelines. These events are only used +// to trigger hooks. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamaddevent +type TeamAddEvent struct { + Team *Team `json:"team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// WatchEvent is related to starring a repository, not watching. See this API +// blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/ +// +// The event’s actor is the user who starred a repository, and the event’s +// repository is the repository that was starred. +// +// GitHub API docs: https://developer.github.com/v3/activity/events/types/#watchevent +type WatchEvent struct { + // Action is the action that was performed. Possible value is: "started". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} diff --git a/vendor/github.com/google/go-github/github/gen-accessors.go b/vendor/github.com/google/go-github/github/gen-accessors.go new file mode 100644 index 00000000..fe92206f --- /dev/null +++ b/vendor/github.com/google/go-github/github/gen-accessors.go @@ -0,0 +1,332 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// gen-accessors generates accessor methods for structs with pointer fields. +// +// It is meant to be used by the go-github authors in conjunction with the +// go generate tool before sending a commit to GitHub. +package main + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "io/ioutil" + "log" + "os" + "sort" + "strings" + "text/template" +) + +const ( + fileSuffix = "-accessors.go" +) + +var ( + verbose = flag.Bool("v", false, "Print verbose log messages") + + sourceTmpl = template.Must(template.New("source").Parse(source)) + + // blacklistStructMethod lists "struct.method" combos to skip. + blacklistStructMethod = map[string]bool{ + "RepositoryContent.GetContent": true, + "Client.GetBaseURL": true, + "Client.GetUploadURL": true, + "ErrorResponse.GetResponse": true, + "RateLimitError.GetResponse": true, + "AbuseRateLimitError.GetResponse": true, + } + // blacklistStruct lists structs to skip. + blacklistStruct = map[string]bool{ + "Client": true, + } +) + +func logf(fmt string, args ...interface{}) { + if *verbose { + log.Printf(fmt, args...) + } +} + +func main() { + flag.Parse() + fset := token.NewFileSet() + + pkgs, err := parser.ParseDir(fset, ".", sourceFilter, 0) + if err != nil { + log.Fatal(err) + return + } + + for pkgName, pkg := range pkgs { + t := &templateData{ + filename: pkgName + fileSuffix, + Year: 2017, + Package: pkgName, + Imports: map[string]string{}, + } + for filename, f := range pkg.Files { + logf("Processing %v...", filename) + if err := t.processAST(f); err != nil { + log.Fatal(err) + } + } + if err := t.dump(); err != nil { + log.Fatal(err) + } + } + logf("Done.") +} + +func (t *templateData) processAST(f *ast.File) error { + for _, decl := range f.Decls { + gd, ok := decl.(*ast.GenDecl) + if !ok { + continue + } + for _, spec := range gd.Specs { + ts, ok := spec.(*ast.TypeSpec) + if !ok { + continue + } + // Skip unexported identifiers. + if !ts.Name.IsExported() { + logf("Struct %v is unexported; skipping.", ts.Name) + continue + } + // Check if the struct is blacklisted. + if blacklistStruct[ts.Name.Name] { + logf("Struct %v is blacklisted; skipping.", ts.Name) + continue + } + st, ok := ts.Type.(*ast.StructType) + if !ok { + continue + } + for _, field := range st.Fields.List { + se, ok := field.Type.(*ast.StarExpr) + if len(field.Names) == 0 || !ok { + continue + } + + fieldName := field.Names[0] + // Skip unexported identifiers. + if !fieldName.IsExported() { + logf("Field %v is unexported; skipping.", fieldName) + continue + } + // Check if "struct.method" is blacklisted. + if key := fmt.Sprintf("%v.Get%v", ts.Name, fieldName); blacklistStructMethod[key] { + logf("Method %v is blacklisted; skipping.", key) + continue + } + + switch x := se.X.(type) { + case *ast.ArrayType: + t.addArrayType(x, ts.Name.String(), fieldName.String()) + case *ast.Ident: + t.addIdent(x, ts.Name.String(), fieldName.String()) + case *ast.MapType: + t.addMapType(x, ts.Name.String(), fieldName.String()) + case *ast.SelectorExpr: + t.addSelectorExpr(x, ts.Name.String(), fieldName.String()) + default: + logf("processAST: type %q, field %q, unknown %T: %+v", ts.Name, fieldName, x, x) + } + } + } + } + return nil +} + +func sourceFilter(fi os.FileInfo) bool { + return !strings.HasSuffix(fi.Name(), "_test.go") && !strings.HasSuffix(fi.Name(), fileSuffix) +} + +func (t *templateData) dump() error { + if len(t.Getters) == 0 { + logf("No getters for %v; skipping.", t.filename) + return nil + } + + // Sort getters by ReceiverType.FieldName. + sort.Sort(byName(t.Getters)) + + var buf bytes.Buffer + if err := sourceTmpl.Execute(&buf, t); err != nil { + return err + } + clean, err := format.Source(buf.Bytes()) + if err != nil { + return err + } + + logf("Writing %v...", t.filename) + return ioutil.WriteFile(t.filename, clean, 0644) +} + +func newGetter(receiverType, fieldName, fieldType, zeroValue string, namedStruct bool) *getter { + return &getter{ + sortVal: strings.ToLower(receiverType) + "." + strings.ToLower(fieldName), + ReceiverVar: strings.ToLower(receiverType[:1]), + ReceiverType: receiverType, + FieldName: fieldName, + FieldType: fieldType, + ZeroValue: zeroValue, + NamedStruct: namedStruct, + } +} + +func (t *templateData) addArrayType(x *ast.ArrayType, receiverType, fieldName string) { + var eltType string + switch elt := x.Elt.(type) { + case *ast.Ident: + eltType = elt.String() + default: + logf("addArrayType: type %q, field %q: unknown elt type: %T %+v; skipping.", receiverType, fieldName, elt, elt) + return + } + + t.Getters = append(t.Getters, newGetter(receiverType, fieldName, "[]"+eltType, "nil", false)) +} + +func (t *templateData) addIdent(x *ast.Ident, receiverType, fieldName string) { + var zeroValue string + var namedStruct = false + switch x.String() { + case "int", "int64": + zeroValue = "0" + case "string": + zeroValue = `""` + case "bool": + zeroValue = "false" + case "Timestamp": + zeroValue = "Timestamp{}" + default: + zeroValue = "nil" + namedStruct = true + } + + t.Getters = append(t.Getters, newGetter(receiverType, fieldName, x.String(), zeroValue, namedStruct)) +} + +func (t *templateData) addMapType(x *ast.MapType, receiverType, fieldName string) { + var keyType string + switch key := x.Key.(type) { + case *ast.Ident: + keyType = key.String() + default: + logf("addMapType: type %q, field %q: unknown key type: %T %+v; skipping.", receiverType, fieldName, key, key) + return + } + + var valueType string + switch value := x.Value.(type) { + case *ast.Ident: + valueType = value.String() + default: + logf("addMapType: type %q, field %q: unknown value type: %T %+v; skipping.", receiverType, fieldName, value, value) + return + } + + fieldType := fmt.Sprintf("map[%v]%v", keyType, valueType) + zeroValue := fmt.Sprintf("map[%v]%v{}", keyType, valueType) + t.Getters = append(t.Getters, newGetter(receiverType, fieldName, fieldType, zeroValue, false)) +} + +func (t *templateData) addSelectorExpr(x *ast.SelectorExpr, receiverType, fieldName string) { + if strings.ToLower(fieldName[:1]) == fieldName[:1] { // Non-exported field. + return + } + + var xX string + if xx, ok := x.X.(*ast.Ident); ok { + xX = xx.String() + } + + switch xX { + case "time", "json": + if xX == "json" { + t.Imports["encoding/json"] = "encoding/json" + } else { + t.Imports[xX] = xX + } + fieldType := fmt.Sprintf("%v.%v", xX, x.Sel.Name) + zeroValue := fmt.Sprintf("%v.%v{}", xX, x.Sel.Name) + if xX == "time" && x.Sel.Name == "Duration" { + zeroValue = "0" + } + t.Getters = append(t.Getters, newGetter(receiverType, fieldName, fieldType, zeroValue, false)) + default: + logf("addSelectorExpr: xX %q, type %q, field %q: unknown x=%+v; skipping.", xX, receiverType, fieldName, x) + } +} + +type templateData struct { + filename string + Year int + Package string + Imports map[string]string + Getters []*getter +} + +type getter struct { + sortVal string // Lower-case version of "ReceiverType.FieldName". + ReceiverVar string // The one-letter variable name to match the ReceiverType. + ReceiverType string + FieldName string + FieldType string + ZeroValue string + NamedStruct bool // Getter for named struct. +} + +type byName []*getter + +func (b byName) Len() int { return len(b) } +func (b byName) Less(i, j int) bool { return b[i].sortVal < b[j].sortVal } +func (b byName) Swap(i, j int) { b[i], b[j] = b[j], b[i] } + +const source = `// Copyright {{.Year}} The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by gen-accessors; DO NOT EDIT. + +package {{.Package}} +{{with .Imports}} +import ( + {{- range . -}} + "{{.}}" + {{end -}} +) +{{end}} +{{range .Getters}} +{{if .NamedStruct}} +// Get{{.FieldName}} returns the {{.FieldName}} field. +func ({{.ReceiverVar}} *{{.ReceiverType}}) Get{{.FieldName}}() *{{.FieldType}} { + if {{.ReceiverVar}} == nil { + return {{.ZeroValue}} + } + return {{.ReceiverVar}}.{{.FieldName}} +} +{{else}} +// Get{{.FieldName}} returns the {{.FieldName}} field if it's non-nil, zero value otherwise. +func ({{.ReceiverVar}} *{{.ReceiverType}}) Get{{.FieldName}}() {{.FieldType}} { + if {{.ReceiverVar}} == nil || {{.ReceiverVar}}.{{.FieldName}} == nil { + return {{.ZeroValue}} + } + return *{{.ReceiverVar}}.{{.FieldName}} +} +{{end}} +{{end}} +` diff --git a/vendor/github.com/google/go-github/github/gists.go b/vendor/github.com/google/go-github/github/gists.go new file mode 100644 index 00000000..9108b642 --- /dev/null +++ b/vendor/github.com/google/go-github/github/gists.go @@ -0,0 +1,388 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// GistsService handles communication with the Gist related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/gists/ +type GistsService service + +// Gist represents a GitHub's gist. +type Gist struct { + ID *string `json:"id,omitempty"` + Description *string `json:"description,omitempty"` + Public *bool `json:"public,omitempty"` + Owner *User `json:"owner,omitempty"` + Files map[GistFilename]GistFile `json:"files,omitempty"` + Comments *int `json:"comments,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GitPullURL *string `json:"git_pull_url,omitempty"` + GitPushURL *string `json:"git_push_url,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (g Gist) String() string { + return Stringify(g) +} + +// GistFilename represents filename on a gist. +type GistFilename string + +// GistFile represents a file on a gist. +type GistFile struct { + Size *int `json:"size,omitempty"` + Filename *string `json:"filename,omitempty"` + Language *string `json:"language,omitempty"` + Type *string `json:"type,omitempty"` + RawURL *string `json:"raw_url,omitempty"` + Content *string `json:"content,omitempty"` +} + +func (g GistFile) String() string { + return Stringify(g) +} + +// GistCommit represents a commit on a gist. +type GistCommit struct { + URL *string `json:"url,omitempty"` + Version *string `json:"version,omitempty"` + User *User `json:"user,omitempty"` + ChangeStatus *CommitStats `json:"change_status,omitempty"` + CommittedAt *Timestamp `json:"committed_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (gc GistCommit) String() string { + return Stringify(gc) +} + +// GistFork represents a fork of a gist. +type GistFork struct { + URL *string `json:"url,omitempty"` + User *User `json:"user,omitempty"` + ID *string `json:"id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (gf GistFork) String() string { + return Stringify(gf) +} + +// GistListOptions specifies the optional parameters to the +// GistsService.List, GistsService.ListAll, and GistsService.ListStarred methods. +type GistListOptions struct { + // Since filters Gists by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// List gists for a user. Passing the empty string will list +// all public gists if called anonymously. However, if the call +// is authenticated, it will returns all gists for the authenticated +// user. +// +// GitHub API docs: https://developer.github.com/v3/gists/#list-gists +func (s *GistsService) List(ctx context.Context, user string, opt *GistListOptions) ([]*Gist, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/gists", user) + } else { + u = "gists" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// ListAll lists all public gists. +// +// GitHub API docs: https://developer.github.com/v3/gists/#list-gists +func (s *GistsService) ListAll(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) { + u, err := addOptions("gists/public", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// ListStarred lists starred gists of authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/gists/#list-gists +func (s *GistsService) ListStarred(ctx context.Context, opt *GistListOptions) ([]*Gist, *Response, error) { + u, err := addOptions("gists/starred", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// Get a single gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/#get-a-single-gist +func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + gist := new(Gist) + resp, err := s.client.Do(ctx, req, gist) + if err != nil { + return nil, resp, err + } + + return gist, resp, nil +} + +// GetRevision gets a specific revision of a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/#get-a-specific-revision-of-a-gist +func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v/%v", id, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + gist := new(Gist) + resp, err := s.client.Do(ctx, req, gist) + if err != nil { + return nil, resp, err + } + + return gist, resp, nil +} + +// Create a gist for authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/gists/#create-a-gist +func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response, error) { + u := "gists" + req, err := s.client.NewRequest("POST", u, gist) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// Edit a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/#edit-a-gist +func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("PATCH", u, gist) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// ListCommits lists commits of a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-commits +func (s *GistsService) ListCommits(ctx context.Context, id string, opt *ListOptions) ([]*GistCommit, *Response, error) { + u := fmt.Sprintf("gists/%v/commits", id) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var gistCommits []*GistCommit + resp, err := s.client.Do(ctx, req, &gistCommits) + if err != nil { + return nil, resp, err + } + + return gistCommits, resp, nil +} + +// Delete a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/#delete-a-gist +func (s *GistsService) Delete(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// Star a gist on behalf of authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/gists/#star-a-gist +func (s *GistsService) Star(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// Unstar a gist on a behalf of authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/gists/#unstar-a-gist +func (s *GistsService) Unstar(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// IsStarred checks if a gist is starred by authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/gists/#check-if-a-gist-is-starred +func (s *GistsService) IsStarred(ctx context.Context, id string) (bool, *Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + resp, err := s.client.Do(ctx, req, nil) + starred, err := parseBoolResponse(err) + return starred, resp, err +} + +// Fork a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/#fork-a-gist +func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v/forks", id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// ListForks lists forks of a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-forks +func (s *GistsService) ListForks(ctx context.Context, id string) ([]*GistFork, *Response, error) { + u := fmt.Sprintf("gists/%v/forks", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var gistForks []*GistFork + resp, err := s.client.Do(ctx, req, &gistForks) + if err != nil { + return nil, resp, err + } + + return gistForks, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/gists_comments.go b/vendor/github.com/google/go-github/github/gists_comments.go new file mode 100644 index 00000000..d5322e3d --- /dev/null +++ b/vendor/github.com/google/go-github/github/gists_comments.go @@ -0,0 +1,119 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// GistComment represents a Gist comment. +type GistComment struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Body *string `json:"body,omitempty"` + User *User `json:"user,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` +} + +func (g GistComment) String() string { + return Stringify(g) +} + +// ListComments lists all comments for a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/comments/#list-comments-on-a-gist +func (s *GistsService) ListComments(ctx context.Context, gistID string, opt *ListOptions) ([]*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments", gistID) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*GistComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment retrieves a single comment from a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/comments/#get-a-single-comment +func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// CreateComment creates a comment for a gist. +// +// GitHub API docs: https://developer.github.com/v3/gists/comments/#create-a-comment +func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments", gistID) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment edits an existing gist comment. +// +// GitHub API docs: https://developer.github.com/v3/gists/comments/#edit-a-comment +func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a gist comment. +// +// GitHub API docs: https://developer.github.com/v3/gists/comments/#delete-a-comment +func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/git.go b/vendor/github.com/google/go-github/github/git.go new file mode 100644 index 00000000..1ce47437 --- /dev/null +++ b/vendor/github.com/google/go-github/github/git.go @@ -0,0 +1,12 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// GitService handles communication with the git data related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/git/ +type GitService service diff --git a/vendor/github.com/google/go-github/github/git_blobs.go b/vendor/github.com/google/go-github/github/git_blobs.go new file mode 100644 index 00000000..5290c553 --- /dev/null +++ b/vendor/github.com/google/go-github/github/git_blobs.go @@ -0,0 +1,75 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" +) + +// Blob represents a blob object. +type Blob struct { + Content *string `json:"content,omitempty"` + Encoding *string `json:"encoding,omitempty"` + SHA *string `json:"sha,omitempty"` + Size *int `json:"size,omitempty"` + URL *string `json:"url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// GetBlob fetches a blob from a repo given a SHA. +// +// GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob +func (s *GitService) GetBlob(ctx context.Context, owner string, repo string, sha string) (*Blob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + blob := new(Blob) + resp, err := s.client.Do(ctx, req, blob) + return blob, resp, err +} + +// GetBlobRaw fetches a blob's contents from a repo. +// Unlike GetBlob, it returns the raw bytes rather than the base64-encoded data. +// +// GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob +func (s *GitService) GetBlobRaw(ctx context.Context, owner, repo, sha string) ([]byte, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + req.Header.Set("Accept", "application/vnd.github.v3.raw") + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + return buf.Bytes(), resp, err +} + +// CreateBlob creates a blob object. +// +// GitHub API docs: https://developer.github.com/v3/git/blobs/#create-a-blob +func (s *GitService) CreateBlob(ctx context.Context, owner string, repo string, blob *Blob) (*Blob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs", owner, repo) + req, err := s.client.NewRequest("POST", u, blob) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + t := new(Blob) + resp, err := s.client.Do(ctx, req, t) + return t, resp, err +} diff --git a/vendor/github.com/google/go-github/github/git_commits.go b/vendor/github.com/google/go-github/github/git_commits.go new file mode 100644 index 00000000..29882569 --- /dev/null +++ b/vendor/github.com/google/go-github/github/git_commits.go @@ -0,0 +1,139 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" + "time" +) + +// SignatureVerification represents GPG signature verification. +type SignatureVerification struct { + Verified *bool `json:"verified,omitempty"` + Reason *string `json:"reason,omitempty"` + Signature *string `json:"signature,omitempty"` + Payload *string `json:"payload,omitempty"` +} + +// Commit represents a GitHub commit. +type Commit struct { + SHA *string `json:"sha,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Message *string `json:"message,omitempty"` + Tree *Tree `json:"tree,omitempty"` + Parents []Commit `json:"parents,omitempty"` + Stats *CommitStats `json:"stats,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + Verification *SignatureVerification `json:"verification,omitempty"` + NodeID *string `json:"node_id,omitempty"` + + // CommentCount is the number of GitHub comments on the commit. This + // is only populated for requests that fetch GitHub data like + // Pulls.ListCommits, Repositories.ListCommits, etc. + CommentCount *int `json:"comment_count,omitempty"` +} + +func (c Commit) String() string { + return Stringify(c) +} + +// CommitAuthor represents the author or committer of a commit. The commit +// author may not correspond to a GitHub User. +type CommitAuthor struct { + Date *time.Time `json:"date,omitempty"` + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` + + // The following fields are only populated by Webhook events. + Login *string `json:"username,omitempty"` // Renamed for go-github consistency. +} + +func (c CommitAuthor) String() string { + return Stringify(c) +} + +// GetCommit fetchs the Commit object for a given SHA. +// +// GitHub API docs: https://developer.github.com/v3/git/commits/#get-a-commit +func (s *GitService) GetCommit(ctx context.Context, owner string, repo string, sha string) (*Commit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeGitSigningPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + c := new(Commit) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// createCommit represents the body of a CreateCommit request. +type createCommit struct { + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Message *string `json:"message,omitempty"` + Tree *string `json:"tree,omitempty"` + Parents []string `json:"parents,omitempty"` +} + +// CreateCommit creates a new commit in a repository. +// commit must not be nil. +// +// The commit.Committer is optional and will be filled with the commit.Author +// data if omitted. If the commit.Author is omitted, it will be filled in with +// the authenticated user’s information and the current date. +// +// GitHub API docs: https://developer.github.com/v3/git/commits/#create-a-commit +func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string, commit *Commit) (*Commit, *Response, error) { + if commit == nil { + return nil, nil, fmt.Errorf("commit must be provided") + } + + u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo) + + parents := make([]string, len(commit.Parents)) + for i, parent := range commit.Parents { + parents[i] = *parent.SHA + } + + body := &createCommit{ + Author: commit.Author, + Committer: commit.Committer, + Message: commit.Message, + Parents: parents, + } + if commit.Tree != nil { + body.Tree = commit.Tree.SHA + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + c := new(Commit) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/git_refs.go b/vendor/github.com/google/go-github/github/git_refs.go new file mode 100644 index 00000000..0947d866 --- /dev/null +++ b/vendor/github.com/google/go-github/github/git_refs.go @@ -0,0 +1,233 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strings" +) + +// Reference represents a GitHub reference. +type Reference struct { + Ref *string `json:"ref"` + URL *string `json:"url"` + Object *GitObject `json:"object"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r Reference) String() string { + return Stringify(r) +} + +// GitObject represents a Git object. +type GitObject struct { + Type *string `json:"type"` + SHA *string `json:"sha"` + URL *string `json:"url"` +} + +func (o GitObject) String() string { + return Stringify(o) +} + +// createRefRequest represents the payload for creating a reference. +type createRefRequest struct { + Ref *string `json:"ref"` + SHA *string `json:"sha"` +} + +// updateRefRequest represents the payload for updating a reference. +type updateRefRequest struct { + SHA *string `json:"sha"` + Force *bool `json:"force"` +} + +// GetRef fetches a single Reference object for a given Git ref. +// If there is no exact match, GetRef will return an error. +// +// Note: The GitHub API can return multiple matches. +// If you wish to use this functionality please use the GetRefs() method. +// +// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference +func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if _, ok := err.(*json.UnmarshalTypeError); ok { + // Multiple refs, means there wasn't an exact match. + return nil, resp, errors.New("no exact match found for this ref") + } else if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// GetRefs fetches a slice of Reference objects for a given Git ref. +// If there is an exact match, only that ref is returned. +// If there is no exact match, GitHub returns all refs that start with ref. +// If returned error is nil, there will be at least 1 ref returned. +// For example: +// +// "heads/featureA" -> ["refs/heads/featureA"] // Exact match, single ref is returned. +// "heads/feature" -> ["refs/heads/featureA", "refs/heads/featureB"] // All refs that start with ref. +// "heads/notexist" -> [] // Returns an error. +// +// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference +func (s *GitService) GetRefs(ctx context.Context, owner string, repo string, ref string) ([]*Reference, *Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var rawJSON json.RawMessage + resp, err := s.client.Do(ctx, req, &rawJSON) + if err != nil { + return nil, resp, err + } + + // Prioritize the most common case: a single returned ref. + r := new(Reference) + singleUnmarshalError := json.Unmarshal(rawJSON, r) + if singleUnmarshalError == nil { + return []*Reference{r}, resp, nil + } + + // Attempt to unmarshal multiple refs. + var rs []*Reference + multipleUnmarshalError := json.Unmarshal(rawJSON, &rs) + if multipleUnmarshalError == nil { + if len(rs) == 0 { + return nil, resp, fmt.Errorf("unexpected response from GitHub API: an array of refs with length 0") + } + return rs, resp, nil + } + + return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", singleUnmarshalError, multipleUnmarshalError) +} + +// ReferenceListOptions specifies optional parameters to the +// GitService.ListRefs method. +type ReferenceListOptions struct { + Type string `url:"-"` + + ListOptions +} + +// ListRefs lists all refs in a repository. +// +// GitHub API docs: https://developer.github.com/v3/git/refs/#get-all-references +func (s *GitService) ListRefs(ctx context.Context, owner, repo string, opt *ReferenceListOptions) ([]*Reference, *Response, error) { + var u string + if opt != nil && opt.Type != "" { + u = fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, opt.Type) + } else { + u = fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var rs []*Reference + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// CreateRef creates a new ref in a repository. +// +// GitHub API docs: https://developer.github.com/v3/git/refs/#create-a-reference +func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) + req, err := s.client.NewRequest("POST", u, &createRefRequest{ + // back-compat with previous behavior that didn't require 'refs/' prefix + Ref: String("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")), + SHA: ref.Object.SHA, + }) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdateRef updates an existing ref in a repository. +// +// GitHub API docs: https://developer.github.com/v3/git/refs/#update-a-reference +func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) { + refPath := strings.TrimPrefix(*ref.Ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refPath) + req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{ + SHA: ref.Object.SHA, + Force: &force, + }) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DeleteRef deletes a ref from a repository. +// +// GitHub API docs: https://developer.github.com/v3/git/refs/#delete-a-reference +func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, ref) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/git_tags.go b/vendor/github.com/google/go-github/github/git_tags.go new file mode 100644 index 00000000..f3822ffa --- /dev/null +++ b/vendor/github.com/google/go-github/github/git_tags.go @@ -0,0 +1,84 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// Tag represents a tag object. +type Tag struct { + Tag *string `json:"tag,omitempty"` + SHA *string `json:"sha,omitempty"` + URL *string `json:"url,omitempty"` + Message *string `json:"message,omitempty"` + Tagger *CommitAuthor `json:"tagger,omitempty"` + Object *GitObject `json:"object,omitempty"` + Verification *SignatureVerification `json:"verification,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// createTagRequest represents the body of a CreateTag request. This is mostly +// identical to Tag with the exception that the object SHA and Type are +// top-level fields, rather than being nested inside a JSON object. +type createTagRequest struct { + Tag *string `json:"tag,omitempty"` + Message *string `json:"message,omitempty"` + Object *string `json:"object,omitempty"` + Type *string `json:"type,omitempty"` + Tagger *CommitAuthor `json:"tagger,omitempty"` +} + +// GetTag fetchs a tag from a repo given a SHA. +// +// GitHub API docs: https://developer.github.com/v3/git/tags/#get-a-tag +func (s *GitService) GetTag(ctx context.Context, owner string, repo string, sha string) (*Tag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/tags/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeGitSigningPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + tag := new(Tag) + resp, err := s.client.Do(ctx, req, tag) + return tag, resp, err +} + +// CreateTag creates a tag object. +// +// GitHub API docs: https://developer.github.com/v3/git/tags/#create-a-tag-object +func (s *GitService) CreateTag(ctx context.Context, owner string, repo string, tag *Tag) (*Tag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/tags", owner, repo) + + // convert Tag into a createTagRequest + tagRequest := &createTagRequest{ + Tag: tag.Tag, + Message: tag.Message, + Tagger: tag.Tagger, + } + if tag.Object != nil { + tagRequest.Object = tag.Object.SHA + tagRequest.Type = tag.Object.Type + } + + req, err := s.client.NewRequest("POST", u, tagRequest) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + t := new(Tag) + resp, err := s.client.Do(ctx, req, t) + return t, resp, err +} diff --git a/vendor/github.com/google/go-github/github/git_trees.go b/vendor/github.com/google/go-github/github/git_trees.go new file mode 100644 index 00000000..4d6809a8 --- /dev/null +++ b/vendor/github.com/google/go-github/github/git_trees.go @@ -0,0 +1,93 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Tree represents a GitHub tree. +type Tree struct { + SHA *string `json:"sha,omitempty"` + Entries []TreeEntry `json:"tree,omitempty"` +} + +func (t Tree) String() string { + return Stringify(t) +} + +// TreeEntry represents the contents of a tree structure. TreeEntry can +// represent either a blob, a commit (in the case of a submodule), or another +// tree. +type TreeEntry struct { + SHA *string `json:"sha,omitempty"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (t TreeEntry) String() string { + return Stringify(t) +} + +// GetTree fetches the Tree object for a given sha hash from a repository. +// +// GitHub API docs: https://developer.github.com/v3/git/trees/#get-a-tree +func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha) + if recursive { + u += "?recursive=1" + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Tree) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// createTree represents the body of a CreateTree request. +type createTree struct { + BaseTree string `json:"base_tree,omitempty"` + Entries []TreeEntry `json:"tree"` +} + +// CreateTree creates a new tree in a repository. If both a tree and a nested +// path modifying that tree are specified, it will overwrite the contents of +// that tree with the new path contents and write a new tree out. +// +// GitHub API docs: https://developer.github.com/v3/git/trees/#create-a-tree +func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []TreeEntry) (*Tree, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo) + + body := &createTree{ + BaseTree: baseTree, + Entries: entries, + } + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + t := new(Tree) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/github-accessors.go b/vendor/github.com/google/go-github/github/github-accessors.go new file mode 100644 index 00000000..d9939c20 --- /dev/null +++ b/vendor/github.com/google/go-github/github/github-accessors.go @@ -0,0 +1,10989 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by gen-accessors; DO NOT EDIT. + +package github + +import ( + "encoding/json" + "time" +) + +// GetRetryAfter returns the RetryAfter field if it's non-nil, zero value otherwise. +func (a *AbuseRateLimitError) GetRetryAfter() time.Duration { + if a == nil || a.RetryAfter == nil { + return 0 + } + return *a.RetryAfter +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AdminEnforcement) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetComments returns the Comments field. +func (a *AdminStats) GetComments() *CommentStats { + if a == nil { + return nil + } + return a.Comments +} + +// GetGists returns the Gists field. +func (a *AdminStats) GetGists() *GistStats { + if a == nil { + return nil + } + return a.Gists +} + +// GetHooks returns the Hooks field. +func (a *AdminStats) GetHooks() *HookStats { + if a == nil { + return nil + } + return a.Hooks +} + +// GetIssues returns the Issues field. +func (a *AdminStats) GetIssues() *IssueStats { + if a == nil { + return nil + } + return a.Issues +} + +// GetMilestones returns the Milestones field. +func (a *AdminStats) GetMilestones() *MilestoneStats { + if a == nil { + return nil + } + return a.Milestones +} + +// GetOrgs returns the Orgs field. +func (a *AdminStats) GetOrgs() *OrgStats { + if a == nil { + return nil + } + return a.Orgs +} + +// GetPages returns the Pages field. +func (a *AdminStats) GetPages() *PageStats { + if a == nil { + return nil + } + return a.Pages +} + +// GetPulls returns the Pulls field. +func (a *AdminStats) GetPulls() *PullStats { + if a == nil { + return nil + } + return a.Pulls +} + +// GetRepos returns the Repos field. +func (a *AdminStats) GetRepos() *RepoStats { + if a == nil { + return nil + } + return a.Repos +} + +// GetUsers returns the Users field. +func (a *AdminStats) GetUsers() *UserStats { + if a == nil { + return nil + } + return a.Users +} + +// GetVerifiablePasswordAuthentication returns the VerifiablePasswordAuthentication field if it's non-nil, zero value otherwise. +func (a *APIMeta) GetVerifiablePasswordAuthentication() bool { + if a == nil || a.VerifiablePasswordAuthentication == nil { + return false + } + return *a.VerifiablePasswordAuthentication +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *App) GetCreatedAt() time.Time { + if a == nil || a.CreatedAt == nil { + return time.Time{} + } + return *a.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (a *App) GetDescription() string { + if a == nil || a.Description == nil { + return "" + } + return *a.Description +} + +// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. +func (a *App) GetExternalURL() string { + if a == nil || a.ExternalURL == nil { + return "" + } + return *a.ExternalURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *App) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *App) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *App) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetOwner returns the Owner field. +func (a *App) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *App) GetUpdatedAt() time.Time { + if a == nil || a.UpdatedAt == nil { + return time.Time{} + } + return *a.UpdatedAt +} + +// GetApp returns the App field. +func (a *Authorization) GetApp() *AuthorizationApp { + if a == nil { + return nil + } + return a.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Authorization) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *Authorization) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (a *Authorization) GetHashedToken() string { + if a == nil || a.HashedToken == nil { + return "" + } + return *a.HashedToken +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Authorization) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *Authorization) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *Authorization) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (a *Authorization) GetToken() string { + if a == nil || a.Token == nil { + return "" + } + return *a.Token +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (a *Authorization) GetTokenLastEight() string { + if a == nil || a.TokenLastEight == nil { + return "" + } + return *a.TokenLastEight +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Authorization) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Authorization) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetUser returns the User field. +func (a *Authorization) GetUser() *User { + if a == nil { + return nil + } + return a.User +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetClientSecret() string { + if a == nil || a.ClientSecret == nil { + return "" + } + return *a.ClientSecret +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (b *Blob) GetContent() string { + if b == nil || b.Content == nil { + return "" + } + return *b.Content +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (b *Blob) GetEncoding() string { + if b == nil || b.Encoding == nil { + return "" + } + return *b.Encoding +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (b *Blob) GetNodeID() string { + if b == nil || b.NodeID == nil { + return "" + } + return *b.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (b *Blob) GetSHA() string { + if b == nil || b.SHA == nil { + return "" + } + return *b.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (b *Blob) GetSize() int { + if b == nil || b.Size == nil { + return 0 + } + return *b.Size +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (b *Blob) GetURL() string { + if b == nil || b.URL == nil { + return "" + } + return *b.URL +} + +// GetCommit returns the Commit field. +func (b *Branch) GetCommit() *RepositoryCommit { + if b == nil { + return nil + } + return b.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *Branch) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *Branch) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetBody() string { + if c == nil || c.Body == nil { + return "" + } + return *c.Body +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetKey() string { + if c == nil || c.Key == nil { + return "" + } + return *c.Key +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetPath() string { + if c == nil || c.Path == nil { + return "" + } + return *c.Path +} + +// GetRepository returns the Repository field. +func (c *CodeResult) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (c *CodeSearchResult) GetIncompleteResults() bool { + if c == nil || c.IncompleteResults == nil { + return false + } + return *c.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CodeSearchResult) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetCommitURL() string { + if c == nil || c.CommitURL == nil { + return "" + } + return *c.CommitURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetRepositoryURL() string { + if c == nil || c.RepositoryURL == nil { + return "" + } + return *c.RepositoryURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetState() string { + if c == nil || c.State == nil { + return "" + } + return *c.State +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetTotalCount() int { + if c == nil || c.TotalCount == nil { + return 0 + } + return *c.TotalCount +} + +// GetTotalCommitComments returns the TotalCommitComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalCommitComments() int { + if c == nil || c.TotalCommitComments == nil { + return 0 + } + return *c.TotalCommitComments +} + +// GetTotalGistComments returns the TotalGistComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalGistComments() int { + if c == nil || c.TotalGistComments == nil { + return 0 + } + return *c.TotalGistComments +} + +// GetTotalIssueComments returns the TotalIssueComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalIssueComments() int { + if c == nil || c.TotalIssueComments == nil { + return 0 + } + return *c.TotalIssueComments +} + +// GetTotalPullRequestComments returns the TotalPullRequestComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalPullRequestComments() int { + if c == nil || c.TotalPullRequestComments == nil { + return 0 + } + return *c.TotalPullRequestComments +} + +// GetAuthor returns the Author field. +func (c *Commit) GetAuthor() *CommitAuthor { + if c == nil { + return nil + } + return c.Author +} + +// GetCommentCount returns the CommentCount field if it's non-nil, zero value otherwise. +func (c *Commit) GetCommentCount() int { + if c == nil || c.CommentCount == nil { + return 0 + } + return *c.CommentCount +} + +// GetCommitter returns the Committer field. +func (c *Commit) GetCommitter() *CommitAuthor { + if c == nil { + return nil + } + return c.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Commit) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (c *Commit) GetMessage() string { + if c == nil || c.Message == nil { + return "" + } + return *c.Message +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *Commit) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *Commit) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetStats returns the Stats field. +func (c *Commit) GetStats() *CommitStats { + if c == nil { + return nil + } + return c.Stats +} + +// GetTree returns the Tree field. +func (c *Commit) GetTree() *Tree { + if c == nil { + return nil + } + return c.Tree +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Commit) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetVerification returns the Verification field. +func (c *Commit) GetVerification() *SignatureVerification { + if c == nil { + return nil + } + return c.Verification +} + +// GetDate returns the Date field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetDate() time.Time { + if c == nil || c.Date == nil { + return time.Time{} + } + return *c.Date +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CommitCommentEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetComment returns the Comment field. +func (c *CommitCommentEvent) GetComment() *RepositoryComment { + if c == nil { + return nil + } + return c.Comment +} + +// GetInstallation returns the Installation field. +func (c *CommitCommentEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetRepo returns the Repo field. +func (c *CommitCommentEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CommitCommentEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetAdditions() int { + if c == nil || c.Additions == nil { + return 0 + } + return *c.Additions +} + +// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetBlobURL() string { + if c == nil || c.BlobURL == nil { + return "" + } + return *c.BlobURL +} + +// GetChanges returns the Changes field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetChanges() int { + if c == nil || c.Changes == nil { + return 0 + } + return *c.Changes +} + +// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetContentsURL() string { + if c == nil || c.ContentsURL == nil { + return "" + } + return *c.ContentsURL +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetDeletions() int { + if c == nil || c.Deletions == nil { + return 0 + } + return *c.Deletions +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetFilename() string { + if c == nil || c.Filename == nil { + return "" + } + return *c.Filename +} + +// GetPatch returns the Patch field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetPatch() string { + if c == nil || c.Patch == nil { + return "" + } + return *c.Patch +} + +// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetRawURL() string { + if c == nil || c.RawURL == nil { + return "" + } + return *c.RawURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetAuthor returns the Author field. +func (c *CommitResult) GetAuthor() *User { + if c == nil { + return nil + } + return c.Author +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetCommentsURL() string { + if c == nil || c.CommentsURL == nil { + return "" + } + return *c.CommentsURL +} + +// GetCommit returns the Commit field. +func (c *CommitResult) GetCommit() *Commit { + if c == nil { + return nil + } + return c.Commit +} + +// GetCommitter returns the Committer field. +func (c *CommitResult) GetCommitter() *User { + if c == nil { + return nil + } + return c.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetRepository returns the Repository field. +func (c *CommitResult) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetScore returns the Score field. +func (c *CommitResult) GetScore() *float64 { + if c == nil { + return nil + } + return c.Score +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAheadBy returns the AheadBy field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetAheadBy() int { + if c == nil || c.AheadBy == nil { + return 0 + } + return *c.AheadBy +} + +// GetBaseCommit returns the BaseCommit field. +func (c *CommitsComparison) GetBaseCommit() *RepositoryCommit { + if c == nil { + return nil + } + return c.BaseCommit +} + +// GetBehindBy returns the BehindBy field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetBehindBy() int { + if c == nil || c.BehindBy == nil { + return 0 + } + return *c.BehindBy +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetDiffURL() string { + if c == nil || c.DiffURL == nil { + return "" + } + return *c.DiffURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetMergeBaseCommit returns the MergeBaseCommit field. +func (c *CommitsComparison) GetMergeBaseCommit() *RepositoryCommit { + if c == nil { + return nil + } + return c.MergeBaseCommit +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetPatchURL() string { + if c == nil || c.PatchURL == nil { + return "" + } + return *c.PatchURL +} + +// GetPermalinkURL returns the PermalinkURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetPermalinkURL() string { + if c == nil || c.PermalinkURL == nil { + return "" + } + return *c.PermalinkURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetTotalCommits returns the TotalCommits field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetTotalCommits() int { + if c == nil || c.TotalCommits == nil { + return 0 + } + return *c.TotalCommits +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (c *CommitsSearchResult) GetIncompleteResults() bool { + if c == nil || c.IncompleteResults == nil { + return false + } + return *c.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CommitsSearchResult) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetAdditions() int { + if c == nil || c.Additions == nil { + return 0 + } + return *c.Additions +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetDeletions() int { + if c == nil || c.Deletions == nil { + return 0 + } + return *c.Deletions +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCodeOfConduct returns the CodeOfConduct field. +func (c *CommunityHealthFiles) GetCodeOfConduct() *Metric { + if c == nil { + return nil + } + return c.CodeOfConduct +} + +// GetContributing returns the Contributing field. +func (c *CommunityHealthFiles) GetContributing() *Metric { + if c == nil { + return nil + } + return c.Contributing +} + +// GetLicense returns the License field. +func (c *CommunityHealthFiles) GetLicense() *Metric { + if c == nil { + return nil + } + return c.License +} + +// GetReadme returns the Readme field. +func (c *CommunityHealthFiles) GetReadme() *Metric { + if c == nil { + return nil + } + return c.Readme +} + +// GetFiles returns the Files field. +func (c *CommunityHealthMetrics) GetFiles() *CommunityHealthFiles { + if c == nil { + return nil + } + return c.Files +} + +// GetHealthPercentage returns the HealthPercentage field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetHealthPercentage() int { + if c == nil || c.HealthPercentage == nil { + return 0 + } + return *c.HealthPercentage +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetUpdatedAt() time.Time { + if c == nil || c.UpdatedAt == nil { + return time.Time{} + } + return *c.UpdatedAt +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetAvatarURL() string { + if c == nil || c.AvatarURL == nil { + return "" + } + return *c.AvatarURL +} + +// GetContributions returns the Contributions field if it's non-nil, zero value otherwise. +func (c *Contributor) GetContributions() int { + if c == nil || c.Contributions == nil { + return 0 + } + return *c.Contributions +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEventsURL() string { + if c == nil || c.EventsURL == nil { + return "" + } + return *c.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowersURL() string { + if c == nil || c.FollowersURL == nil { + return "" + } + return *c.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowingURL() string { + if c == nil || c.FollowingURL == nil { + return "" + } + return *c.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGistsURL() string { + if c == nil || c.GistsURL == nil { + return "" + } + return *c.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGravatarID() string { + if c == nil || c.GravatarID == nil { + return "" + } + return *c.GravatarID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *Contributor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetOrganizationsURL() string { + if c == nil || c.OrganizationsURL == nil { + return "" + } + return *c.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReceivedEventsURL() string { + if c == nil || c.ReceivedEventsURL == nil { + return "" + } + return *c.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReposURL() string { + if c == nil || c.ReposURL == nil { + return "" + } + return *c.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSiteAdmin() bool { + if c == nil || c.SiteAdmin == nil { + return false + } + return *c.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetStarredURL() string { + if c == nil || c.StarredURL == nil { + return "" + } + return *c.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSubscriptionsURL() string { + if c == nil || c.SubscriptionsURL == nil { + return "" + } + return *c.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (c *Contributor) GetType() string { + if c == nil || c.Type == nil { + return "" + } + return *c.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAuthor returns the Author field. +func (c *ContributorStats) GetAuthor() *Contributor { + if c == nil { + return nil + } + return c.Author +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *ContributorStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetInstallation returns the Installation field. +func (c *CreateEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetMasterBranch() string { + if c == nil || c.MasterBranch == nil { + return "" + } + return *c.MasterBranch +} + +// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetPusherType() string { + if c == nil || c.PusherType == nil { + return "" + } + return *c.PusherType +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRefType returns the RefType field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetRefType() string { + if c == nil || c.RefType == nil { + return "" + } + return *c.RefType +} + +// GetRepo returns the Repo field. +func (c *CreateEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CreateEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetInviteeID returns the InviteeID field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetInviteeID() int64 { + if c == nil || c.InviteeID == nil { + return 0 + } + return *c.InviteeID +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetRole() string { + if c == nil || c.Role == nil { + return "" + } + return *c.Role +} + +// GetInstallation returns the Installation field. +func (d *DeleteEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetPusherType() string { + if d == nil || d.PusherType == nil { + return "" + } + return *d.PusherType +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRefType returns the RefType field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetRefType() string { + if d == nil || d.RefType == nil { + return "" + } + return *d.RefType +} + +// GetRepo returns the Repo field. +func (d *DeleteEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeleteEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *Deployment) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetCreator returns the Creator field. +func (d *Deployment) GetCreator() *User { + if d == nil { + return nil + } + return d.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *Deployment) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *Deployment) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *Deployment) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *Deployment) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *Deployment) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (d *Deployment) GetSHA() string { + if d == nil || d.SHA == nil { + return "" + } + return *d.SHA +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetStatusesURL() string { + if d == nil || d.StatusesURL == nil { + return "" + } + return *d.StatusesURL +} + +// GetTask returns the Task field if it's non-nil, zero value otherwise. +func (d *Deployment) GetTask() string { + if d == nil || d.Task == nil { + return "" + } + return *d.Task +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *Deployment) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetInstallation returns the Installation field. +func (d *DeploymentEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetRepo returns the Repo field. +func (d *DeploymentEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoMerge returns the AutoMerge field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetAutoMerge() bool { + if d == nil || d.AutoMerge == nil { + return false + } + return *d.AutoMerge +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetPayload returns the Payload field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetPayload() string { + if d == nil || d.Payload == nil { + return "" + } + return *d.Payload +} + +// GetProductionEnvironment returns the ProductionEnvironment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetProductionEnvironment() bool { + if d == nil || d.ProductionEnvironment == nil { + return false + } + return *d.ProductionEnvironment +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRequiredContexts returns the RequiredContexts field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetRequiredContexts() []string { + if d == nil || d.RequiredContexts == nil { + return nil + } + return *d.RequiredContexts +} + +// GetTask returns the Task field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetTask() string { + if d == nil || d.Task == nil { + return "" + } + return *d.Task +} + +// GetTransientEnvironment returns the TransientEnvironment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetTransientEnvironment() bool { + if d == nil || d.TransientEnvironment == nil { + return false + } + return *d.TransientEnvironment +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetCreator returns the Creator field. +func (d *DeploymentStatus) GetCreator() *User { + if d == nil { + return nil + } + return d.Creator +} + +// GetDeploymentURL returns the DeploymentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetDeploymentURL() string { + if d == nil || d.DeploymentURL == nil { + return "" + } + return *d.DeploymentURL +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetTargetURL() string { + if d == nil || d.TargetURL == nil { + return "" + } + return *d.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentStatusEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetDeploymentStatus returns the DeploymentStatus field. +func (d *DeploymentStatusEvent) GetDeploymentStatus() *DeploymentStatus { + if d == nil { + return nil + } + return d.DeploymentStatus +} + +// GetInstallation returns the Installation field. +func (d *DeploymentStatusEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetRepo returns the Repo field. +func (d *DeploymentStatusEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentStatusEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoInactive returns the AutoInactive field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetAutoInactive() bool { + if d == nil || d.AutoInactive == nil { + return false + } + return *d.AutoInactive +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetEnvironmentURL() string { + if d == nil || d.EnvironmentURL == nil { + return "" + } + return *d.EnvironmentURL +} + +// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetLogURL() string { + if d == nil || d.LogURL == nil { + return "" + } + return *d.LogURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetAuthor returns the Author field. +func (d *DiscussionComment) GetAuthor() *User { + if d == nil { + return nil + } + return d.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBodyHTML() string { + if d == nil || d.BodyHTML == nil { + return "" + } + return *d.BodyHTML +} + +// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBodyVersion() string { + if d == nil || d.BodyVersion == nil { + return "" + } + return *d.BodyVersion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDiscussionURL returns the DiscussionURL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetDiscussionURL() string { + if d == nil || d.DiscussionURL == nil { + return "" + } + return *d.DiscussionURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetLastEditedAt() Timestamp { + if d == nil || d.LastEditedAt == nil { + return Timestamp{} + } + return *d.LastEditedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetNumber() int64 { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetTeams returns the Teams field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetTeams() []string { + if d == nil || d.Teams == nil { + return nil + } + return *d.Teams +} + +// GetUsers returns the Users field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetUsers() []string { + if d == nil || d.Users == nil { + return nil + } + return *d.Users +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetPath() string { + if d == nil || d.Path == nil { + return "" + } + return *d.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetPosition() int { + if d == nil || d.Position == nil { + return 0 + } + return *d.Position +} + +// GetActor returns the Actor field. +func (e *Event) GetActor() *User { + if e == nil { + return nil + } + return e.Actor +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Event) GetCreatedAt() time.Time { + if e == nil || e.CreatedAt == nil { + return time.Time{} + } + return *e.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Event) GetID() string { + if e == nil || e.ID == nil { + return "" + } + return *e.ID +} + +// GetOrg returns the Org field. +func (e *Event) GetOrg() *Organization { + if e == nil { + return nil + } + return e.Org +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (e *Event) GetPublic() bool { + if e == nil || e.Public == nil { + return false + } + return *e.Public +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (e *Event) GetRawPayload() json.RawMessage { + if e == nil || e.RawPayload == nil { + return json.RawMessage{} + } + return *e.RawPayload +} + +// GetRepo returns the Repo field. +func (e *Event) GetRepo() *Repository { + if e == nil { + return nil + } + return e.Repo +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (e *Event) GetType() string { + if e == nil || e.Type == nil { + return "" + } + return *e.Type +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (f *FeedLink) GetHRef() string { + if f == nil || f.HRef == nil { + return "" + } + return *f.HRef +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (f *FeedLink) GetType() string { + if f == nil || f.Type == nil { + return "" + } + return *f.Type +} + +// GetCurrentUserActorURL returns the CurrentUserActorURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserActorURL() string { + if f == nil || f.CurrentUserActorURL == nil { + return "" + } + return *f.CurrentUserActorURL +} + +// GetCurrentUserOrganizationURL returns the CurrentUserOrganizationURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserOrganizationURL() string { + if f == nil || f.CurrentUserOrganizationURL == nil { + return "" + } + return *f.CurrentUserOrganizationURL +} + +// GetCurrentUserPublicURL returns the CurrentUserPublicURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserPublicURL() string { + if f == nil || f.CurrentUserPublicURL == nil { + return "" + } + return *f.CurrentUserPublicURL +} + +// GetCurrentUserURL returns the CurrentUserURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserURL() string { + if f == nil || f.CurrentUserURL == nil { + return "" + } + return *f.CurrentUserURL +} + +// GetTimelineURL returns the TimelineURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetTimelineURL() string { + if f == nil || f.TimelineURL == nil { + return "" + } + return *f.TimelineURL +} + +// GetUserURL returns the UserURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetUserURL() string { + if f == nil || f.UserURL == nil { + return "" + } + return *f.UserURL +} + +// GetForkee returns the Forkee field. +func (f *ForkEvent) GetForkee() *Repository { + if f == nil { + return nil + } + return f.Forkee +} + +// GetInstallation returns the Installation field. +func (f *ForkEvent) GetInstallation() *Installation { + if f == nil { + return nil + } + return f.Installation +} + +// GetRepo returns the Repo field. +func (f *ForkEvent) GetRepo() *Repository { + if f == nil { + return nil + } + return f.Repo +} + +// GetSender returns the Sender field. +func (f *ForkEvent) GetSender() *User { + if f == nil { + return nil + } + return f.Sender +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (g *Gist) GetComments() int { + if g == nil || g.Comments == nil { + return 0 + } + return *g.Comments +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *Gist) GetCreatedAt() time.Time { + if g == nil || g.CreatedAt == nil { + return time.Time{} + } + return *g.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (g *Gist) GetDescription() string { + if g == nil || g.Description == nil { + return "" + } + return *g.Description +} + +// GetGitPullURL returns the GitPullURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetGitPullURL() string { + if g == nil || g.GitPullURL == nil { + return "" + } + return *g.GitPullURL +} + +// GetGitPushURL returns the GitPushURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetGitPushURL() string { + if g == nil || g.GitPushURL == nil { + return "" + } + return *g.GitPushURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetHTMLURL() string { + if g == nil || g.HTMLURL == nil { + return "" + } + return *g.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *Gist) GetID() string { + if g == nil || g.ID == nil { + return "" + } + return *g.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *Gist) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetOwner returns the Owner field. +func (g *Gist) GetOwner() *User { + if g == nil { + return nil + } + return g.Owner +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (g *Gist) GetPublic() bool { + if g == nil || g.Public == nil { + return false + } + return *g.Public +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *Gist) GetUpdatedAt() time.Time { + if g == nil || g.UpdatedAt == nil { + return time.Time{} + } + return *g.UpdatedAt +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (g *GistComment) GetBody() string { + if g == nil || g.Body == nil { + return "" + } + return *g.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GistComment) GetCreatedAt() time.Time { + if g == nil || g.CreatedAt == nil { + return time.Time{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GistComment) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistComment) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistComment) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetChangeStatus returns the ChangeStatus field. +func (g *GistCommit) GetChangeStatus() *CommitStats { + if g == nil { + return nil + } + return g.ChangeStatus +} + +// GetCommittedAt returns the CommittedAt field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetCommittedAt() Timestamp { + if g == nil || g.CommittedAt == nil { + return Timestamp{} + } + return *g.CommittedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistCommit) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetVersion() string { + if g == nil || g.Version == nil { + return "" + } + return *g.Version +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (g *GistFile) GetContent() string { + if g == nil || g.Content == nil { + return "" + } + return *g.Content +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (g *GistFile) GetFilename() string { + if g == nil || g.Filename == nil { + return "" + } + return *g.Filename +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (g *GistFile) GetLanguage() string { + if g == nil || g.Language == nil { + return "" + } + return *g.Language +} + +// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. +func (g *GistFile) GetRawURL() string { + if g == nil || g.RawURL == nil { + return "" + } + return *g.RawURL +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (g *GistFile) GetSize() int { + if g == nil || g.Size == nil { + return 0 + } + return *g.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GistFile) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GistFork) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GistFork) GetID() string { + if g == nil || g.ID == nil { + return "" + } + return *g.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *GistFork) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *GistFork) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistFork) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistFork) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetPrivateGists() int { + if g == nil || g.PrivateGists == nil { + return 0 + } + return *g.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetPublicGists() int { + if g == nil || g.PublicGists == nil { + return 0 + } + return *g.PublicGists +} + +// GetTotalGists returns the TotalGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetTotalGists() int { + if g == nil || g.TotalGists == nil { + return 0 + } + return *g.TotalGists +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (g *Gitignore) GetName() string { + if g == nil || g.Name == nil { + return "" + } + return *g.Name +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (g *Gitignore) GetSource() string { + if g == nil || g.Source == nil { + return "" + } + return *g.Source +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (g *GitObject) GetSHA() string { + if g == nil || g.SHA == nil { + return "" + } + return *g.SHA +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GitObject) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GitObject) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetInstallation returns the Installation field. +func (g *GollumEvent) GetInstallation() *Installation { + if g == nil { + return nil + } + return g.Installation +} + +// GetRepo returns the Repo field. +func (g *GollumEvent) GetRepo() *Repository { + if g == nil { + return nil + } + return g.Repo +} + +// GetSender returns the Sender field. +func (g *GollumEvent) GetSender() *User { + if g == nil { + return nil + } + return g.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (g *GPGEmail) GetEmail() string { + if g == nil || g.Email == nil { + return "" + } + return *g.Email +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (g *GPGEmail) GetVerified() bool { + if g == nil || g.Verified == nil { + return false + } + return *g.Verified +} + +// GetCanCertify returns the CanCertify field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanCertify() bool { + if g == nil || g.CanCertify == nil { + return false + } + return *g.CanCertify +} + +// GetCanEncryptComms returns the CanEncryptComms field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanEncryptComms() bool { + if g == nil || g.CanEncryptComms == nil { + return false + } + return *g.CanEncryptComms +} + +// GetCanEncryptStorage returns the CanEncryptStorage field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanEncryptStorage() bool { + if g == nil || g.CanEncryptStorage == nil { + return false + } + return *g.CanEncryptStorage +} + +// GetCanSign returns the CanSign field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanSign() bool { + if g == nil || g.CanSign == nil { + return false + } + return *g.CanSign +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCreatedAt() time.Time { + if g == nil || g.CreatedAt == nil { + return time.Time{} + } + return *g.CreatedAt +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetExpiresAt() time.Time { + if g == nil || g.ExpiresAt == nil { + return time.Time{} + } + return *g.ExpiresAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetKeyID() string { + if g == nil || g.KeyID == nil { + return "" + } + return *g.KeyID +} + +// GetPrimaryKeyID returns the PrimaryKeyID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetPrimaryKeyID() int64 { + if g == nil || g.PrimaryKeyID == nil { + return 0 + } + return *g.PrimaryKeyID +} + +// GetPublicKey returns the PublicKey field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetPublicKey() string { + if g == nil || g.PublicKey == nil { + return "" + } + return *g.PublicKey +} + +// GetApp returns the App field. +func (g *Grant) GetApp() *AuthorizationApp { + if g == nil { + return nil + } + return g.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *Grant) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *Grant) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *Grant) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *Grant) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetActive returns the Active field if it's non-nil, zero value otherwise. +func (h *Hook) GetActive() bool { + if h == nil || h.Active == nil { + return false + } + return *h.Active +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (h *Hook) GetCreatedAt() time.Time { + if h == nil || h.CreatedAt == nil { + return time.Time{} + } + return *h.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *Hook) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (h *Hook) GetName() string { + if h == nil || h.Name == nil { + return "" + } + return *h.Name +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (h *Hook) GetUpdatedAt() time.Time { + if h == nil || h.UpdatedAt == nil { + return time.Time{} + } + return *h.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *Hook) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetActiveHooks returns the ActiveHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetActiveHooks() int { + if h == nil || h.ActiveHooks == nil { + return 0 + } + return *h.ActiveHooks +} + +// GetInactiveHooks returns the InactiveHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetInactiveHooks() int { + if h == nil || h.InactiveHooks == nil { + return 0 + } + return *h.InactiveHooks +} + +// GetTotalHooks returns the TotalHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetTotalHooks() int { + if h == nil || h.TotalHooks == nil { + return 0 + } + return *h.TotalHooks +} + +// GetAuthorsCount returns the AuthorsCount field if it's non-nil, zero value otherwise. +func (i *Import) GetAuthorsCount() int { + if i == nil || i.AuthorsCount == nil { + return 0 + } + return *i.AuthorsCount +} + +// GetAuthorsURL returns the AuthorsURL field if it's non-nil, zero value otherwise. +func (i *Import) GetAuthorsURL() string { + if i == nil || i.AuthorsURL == nil { + return "" + } + return *i.AuthorsURL +} + +// GetCommitCount returns the CommitCount field if it's non-nil, zero value otherwise. +func (i *Import) GetCommitCount() int { + if i == nil || i.CommitCount == nil { + return 0 + } + return *i.CommitCount +} + +// GetFailedStep returns the FailedStep field if it's non-nil, zero value otherwise. +func (i *Import) GetFailedStep() string { + if i == nil || i.FailedStep == nil { + return "" + } + return *i.FailedStep +} + +// GetHasLargeFiles returns the HasLargeFiles field if it's non-nil, zero value otherwise. +func (i *Import) GetHasLargeFiles() bool { + if i == nil || i.HasLargeFiles == nil { + return false + } + return *i.HasLargeFiles +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Import) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetHumanName returns the HumanName field if it's non-nil, zero value otherwise. +func (i *Import) GetHumanName() string { + if i == nil || i.HumanName == nil { + return "" + } + return *i.HumanName +} + +// GetLargeFilesCount returns the LargeFilesCount field if it's non-nil, zero value otherwise. +func (i *Import) GetLargeFilesCount() int { + if i == nil || i.LargeFilesCount == nil { + return 0 + } + return *i.LargeFilesCount +} + +// GetLargeFilesSize returns the LargeFilesSize field if it's non-nil, zero value otherwise. +func (i *Import) GetLargeFilesSize() int { + if i == nil || i.LargeFilesSize == nil { + return 0 + } + return *i.LargeFilesSize +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (i *Import) GetMessage() string { + if i == nil || i.Message == nil { + return "" + } + return *i.Message +} + +// GetPercent returns the Percent field if it's non-nil, zero value otherwise. +func (i *Import) GetPercent() int { + if i == nil || i.Percent == nil { + return 0 + } + return *i.Percent +} + +// GetPushPercent returns the PushPercent field if it's non-nil, zero value otherwise. +func (i *Import) GetPushPercent() int { + if i == nil || i.PushPercent == nil { + return 0 + } + return *i.PushPercent +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *Import) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (i *Import) GetStatus() string { + if i == nil || i.Status == nil { + return "" + } + return *i.Status +} + +// GetStatusText returns the StatusText field if it's non-nil, zero value otherwise. +func (i *Import) GetStatusText() string { + if i == nil || i.StatusText == nil { + return "" + } + return *i.StatusText +} + +// GetTFVCProject returns the TFVCProject field if it's non-nil, zero value otherwise. +func (i *Import) GetTFVCProject() string { + if i == nil || i.TFVCProject == nil { + return "" + } + return *i.TFVCProject +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *Import) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUseLFS returns the UseLFS field if it's non-nil, zero value otherwise. +func (i *Import) GetUseLFS() string { + if i == nil || i.UseLFS == nil { + return "" + } + return *i.UseLFS +} + +// GetVCS returns the VCS field if it's non-nil, zero value otherwise. +func (i *Import) GetVCS() string { + if i == nil || i.VCS == nil { + return "" + } + return *i.VCS +} + +// GetVCSPassword returns the VCSPassword field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSPassword() string { + if i == nil || i.VCSPassword == nil { + return "" + } + return *i.VCSPassword +} + +// GetVCSURL returns the VCSURL field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSURL() string { + if i == nil || i.VCSURL == nil { + return "" + } + return *i.VCSURL +} + +// GetVCSUsername returns the VCSUsername field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSUsername() string { + if i == nil || i.VCSUsername == nil { + return "" + } + return *i.VCSUsername +} + +// GetAccessTokensURL returns the AccessTokensURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetAccessTokensURL() string { + if i == nil || i.AccessTokensURL == nil { + return "" + } + return *i.AccessTokensURL +} + +// GetAccount returns the Account field. +func (i *Installation) GetAccount() *User { + if i == nil { + return nil + } + return i.Account +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (i *Installation) GetAppID() int64 { + if i == nil || i.AppID == nil { + return 0 + } + return *i.AppID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Installation) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetPermissions returns the Permissions field. +func (i *Installation) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetRepositoriesURL() string { + if i == nil || i.RepositoriesURL == nil { + return "" + } + return *i.RepositoriesURL +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (i *Installation) GetRepositorySelection() string { + if i == nil || i.RepositorySelection == nil { + return "" + } + return *i.RepositorySelection +} + +// GetSingleFileName returns the SingleFileName field if it's non-nil, zero value otherwise. +func (i *Installation) GetSingleFileName() string { + if i == nil || i.SingleFileName == nil { + return "" + } + return *i.SingleFileName +} + +// GetTargetID returns the TargetID field if it's non-nil, zero value otherwise. +func (i *Installation) GetTargetID() int64 { + if i == nil || i.TargetID == nil { + return 0 + } + return *i.TargetID +} + +// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. +func (i *Installation) GetTargetType() string { + if i == nil || i.TargetType == nil { + return "" + } + return *i.TargetType +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetInstallation returns the Installation field. +func (i *InstallationEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetSender returns the Sender field. +func (i *InstallationEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetContents returns the Contents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetContents() string { + if i == nil || i.Contents == nil { + return "" + } + return *i.Contents +} + +// GetIssues returns the Issues field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetIssues() string { + if i == nil || i.Issues == nil { + return "" + } + return *i.Issues +} + +// GetMetadata returns the Metadata field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMetadata() string { + if i == nil || i.Metadata == nil { + return "" + } + return *i.Metadata +} + +// GetSingleFile returns the SingleFile field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSingleFile() string { + if i == nil || i.SingleFile == nil { + return "" + } + return *i.SingleFile +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationRepositoriesEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetInstallation returns the Installation field. +func (i *InstallationRepositoriesEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (i *InstallationRepositoriesEvent) GetRepositorySelection() string { + if i == nil || i.RepositorySelection == nil { + return "" + } + return *i.RepositorySelection +} + +// GetSender returns the Sender field. +func (i *InstallationRepositoriesEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (i *InstallationToken) GetExpiresAt() time.Time { + if i == nil || i.ExpiresAt == nil { + return time.Time{} + } + return *i.ExpiresAt +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (i *InstallationToken) GetToken() string { + if i == nil || i.Token == nil { + return "" + } + return *i.Token +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Invitation) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (i *Invitation) GetEmail() string { + if i == nil || i.Email == nil { + return "" + } + return *i.Email +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Invitation) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetInvitationTeamURL returns the InvitationTeamURL field if it's non-nil, zero value otherwise. +func (i *Invitation) GetInvitationTeamURL() string { + if i == nil || i.InvitationTeamURL == nil { + return "" + } + return *i.InvitationTeamURL +} + +// GetInviter returns the Inviter field. +func (i *Invitation) GetInviter() *User { + if i == nil { + return nil + } + return i.Inviter +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (i *Invitation) GetLogin() string { + if i == nil || i.Login == nil { + return "" + } + return *i.Login +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (i *Invitation) GetRole() string { + if i == nil || i.Role == nil { + return "" + } + return *i.Role +} + +// GetTeamCount returns the TeamCount field if it's non-nil, zero value otherwise. +func (i *Invitation) GetTeamCount() int { + if i == nil || i.TeamCount == nil { + return 0 + } + return *i.TeamCount +} + +// GetAssignee returns the Assignee field. +func (i *Issue) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *Issue) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetClosedAt() time.Time { + if i == nil || i.ClosedAt == nil { + return time.Time{} + } + return *i.ClosedAt +} + +// GetClosedBy returns the ClosedBy field. +func (i *Issue) GetClosedBy() *User { + if i == nil { + return nil + } + return i.ClosedBy +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (i *Issue) GetComments() int { + if i == nil || i.Comments == nil { + return 0 + } + return *i.Comments +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetCommentsURL() string { + if i == nil || i.CommentsURL == nil { + return "" + } + return *i.CommentsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetEventsURL() string { + if i == nil || i.EventsURL == nil { + return "" + } + return *i.EventsURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Issue) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetLabelsURL() string { + if i == nil || i.LabelsURL == nil { + return "" + } + return *i.LabelsURL +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (i *Issue) GetLocked() bool { + if i == nil || i.Locked == nil { + return false + } + return *i.Locked +} + +// GetMilestone returns the Milestone field. +func (i *Issue) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Issue) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (i *Issue) GetNumber() int { + if i == nil || i.Number == nil { + return 0 + } + return *i.Number +} + +// GetPullRequestLinks returns the PullRequestLinks field. +func (i *Issue) GetPullRequestLinks() *PullRequestLinks { + if i == nil { + return nil + } + return i.PullRequestLinks +} + +// GetReactions returns the Reactions field. +func (i *Issue) GetReactions() *Reactions { + if i == nil { + return nil + } + return i.Reactions +} + +// GetRepository returns the Repository field. +func (i *Issue) GetRepository() *Repository { + if i == nil { + return nil + } + return i.Repository +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (i *Issue) GetState() string { + if i == nil || i.State == nil { + return "" + } + return *i.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (i *Issue) GetTitle() string { + if i == nil || i.Title == nil { + return "" + } + return *i.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetUpdatedAt() time.Time { + if i == nil || i.UpdatedAt == nil { + return time.Time{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *Issue) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUser returns the User field. +func (i *Issue) GetUser() *User { + if i == nil { + return nil + } + return i.User +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetAuthorAssociation() string { + if i == nil || i.AuthorAssociation == nil { + return "" + } + return *i.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetIssueURL() string { + if i == nil || i.IssueURL == nil { + return "" + } + return *i.IssueURL +} + +// GetReactions returns the Reactions field. +func (i *IssueComment) GetReactions() *Reactions { + if i == nil { + return nil + } + return i.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetUpdatedAt() time.Time { + if i == nil || i.UpdatedAt == nil { + return time.Time{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUser returns the User field. +func (i *IssueComment) GetUser() *User { + if i == nil { + return nil + } + return i.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssueCommentEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetChanges returns the Changes field. +func (i *IssueCommentEvent) GetChanges() *EditChange { + if i == nil { + return nil + } + return i.Changes +} + +// GetComment returns the Comment field. +func (i *IssueCommentEvent) GetComment() *IssueComment { + if i == nil { + return nil + } + return i.Comment +} + +// GetInstallation returns the Installation field. +func (i *IssueCommentEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetIssue returns the Issue field. +func (i *IssueCommentEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetRepo returns the Repo field. +func (i *IssueCommentEvent) GetRepo() *Repository { + if i == nil { + return nil + } + return i.Repo +} + +// GetSender returns the Sender field. +func (i *IssueCommentEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetActor returns the Actor field. +func (i *IssueEvent) GetActor() *User { + if i == nil { + return nil + } + return i.Actor +} + +// GetAssignee returns the Assignee field. +func (i *IssueEvent) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetAssigner returns the Assigner field. +func (i *IssueEvent) GetAssigner() *User { + if i == nil { + return nil + } + return i.Assigner +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetCommitID() string { + if i == nil || i.CommitID == nil { + return "" + } + return *i.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetEvent() string { + if i == nil || i.Event == nil { + return "" + } + return *i.Event +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetIssue returns the Issue field. +func (i *IssueEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetLabel returns the Label field. +func (i *IssueEvent) GetLabel() *Label { + if i == nil { + return nil + } + return i.Label +} + +// GetMilestone returns the Milestone field. +func (i *IssueEvent) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetRename returns the Rename field. +func (i *IssueEvent) GetRename() *Rename { + if i == nil { + return nil + } + return i.Rename +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetAssignee() string { + if i == nil || i.Assignee == nil { + return "" + } + return *i.Assignee +} + +// GetAssignees returns the Assignees field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetAssignees() []string { + if i == nil || i.Assignees == nil { + return nil + } + return *i.Assignees +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetLabels returns the Labels field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetLabels() []string { + if i == nil || i.Labels == nil { + return nil + } + return *i.Labels +} + +// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetMilestone() int { + if i == nil || i.Milestone == nil { + return 0 + } + return *i.Milestone +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetState() string { + if i == nil || i.State == nil { + return "" + } + return *i.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetTitle() string { + if i == nil || i.Title == nil { + return "" + } + return *i.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssuesEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetAssignee returns the Assignee field. +func (i *IssuesEvent) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetChanges returns the Changes field. +func (i *IssuesEvent) GetChanges() *EditChange { + if i == nil { + return nil + } + return i.Changes +} + +// GetInstallation returns the Installation field. +func (i *IssuesEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetIssue returns the Issue field. +func (i *IssuesEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetLabel returns the Label field. +func (i *IssuesEvent) GetLabel() *Label { + if i == nil { + return nil + } + return i.Label +} + +// GetRepo returns the Repo field. +func (i *IssuesEvent) GetRepo() *Repository { + if i == nil { + return nil + } + return i.Repo +} + +// GetSender returns the Sender field. +func (i *IssuesEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (i *IssuesSearchResult) GetIncompleteResults() bool { + if i == nil || i.IncompleteResults == nil { + return false + } + return *i.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (i *IssuesSearchResult) GetTotal() int { + if i == nil || i.Total == nil { + return 0 + } + return *i.Total +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetClosedIssues() int { + if i == nil || i.ClosedIssues == nil { + return 0 + } + return *i.ClosedIssues +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetOpenIssues() int { + if i == nil || i.OpenIssues == nil { + return 0 + } + return *i.OpenIssues +} + +// GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetTotalIssues() int { + if i == nil || i.TotalIssues == nil { + return 0 + } + return *i.TotalIssues +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (k *Key) GetID() int64 { + if k == nil || k.ID == nil { + return 0 + } + return *k.ID +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (k *Key) GetKey() string { + if k == nil || k.Key == nil { + return "" + } + return *k.Key +} + +// GetReadOnly returns the ReadOnly field if it's non-nil, zero value otherwise. +func (k *Key) GetReadOnly() bool { + if k == nil || k.ReadOnly == nil { + return false + } + return *k.ReadOnly +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (k *Key) GetTitle() string { + if k == nil || k.Title == nil { + return "" + } + return *k.Title +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (k *Key) GetURL() string { + if k == nil || k.URL == nil { + return "" + } + return *k.URL +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (l *Label) GetColor() string { + if l == nil || l.Color == nil { + return "" + } + return *l.Color +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (l *Label) GetDefault() bool { + if l == nil || l.Default == nil { + return false + } + return *l.Default +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *Label) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (l *Label) GetID() int64 { + if l == nil || l.ID == nil { + return 0 + } + return *l.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *Label) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (l *Label) GetNodeID() string { + if l == nil || l.NodeID == nil { + return "" + } + return *l.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *Label) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (l *LabelEvent) GetAction() string { + if l == nil || l.Action == nil { + return "" + } + return *l.Action +} + +// GetChanges returns the Changes field. +func (l *LabelEvent) GetChanges() *EditChange { + if l == nil { + return nil + } + return l.Changes +} + +// GetInstallation returns the Installation field. +func (l *LabelEvent) GetInstallation() *Installation { + if l == nil { + return nil + } + return l.Installation +} + +// GetLabel returns the Label field. +func (l *LabelEvent) GetLabel() *Label { + if l == nil { + return nil + } + return l.Label +} + +// GetOrg returns the Org field. +func (l *LabelEvent) GetOrg() *Organization { + if l == nil { + return nil + } + return l.Org +} + +// GetRepo returns the Repo field. +func (l *LabelEvent) GetRepo() *Repository { + if l == nil { + return nil + } + return l.Repo +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetColor() string { + if l == nil || l.Color == nil { + return "" + } + return *l.Color +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetDefault() bool { + if l == nil || l.Default == nil { + return false + } + return *l.Default +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetID() int64 { + if l == nil || l.ID == nil { + return 0 + } + return *l.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetScore returns the Score field. +func (l *LabelResult) GetScore() *float64 { + if l == nil { + return nil + } + return l.Score +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (l *LabelsSearchResult) GetIncompleteResults() bool { + if l == nil || l.IncompleteResults == nil { + return false + } + return *l.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *LabelsSearchResult) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetOID returns the OID field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetOID() string { + if l == nil || l.OID == nil { + return "" + } + return *l.OID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetPath() string { + if l == nil || l.Path == nil { + return "" + } + return *l.Path +} + +// GetRefName returns the RefName field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetRefName() string { + if l == nil || l.RefName == nil { + return "" + } + return *l.RefName +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetSize() int { + if l == nil || l.Size == nil { + return 0 + } + return *l.Size +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (l *License) GetBody() string { + if l == nil || l.Body == nil { + return "" + } + return *l.Body +} + +// GetConditions returns the Conditions field if it's non-nil, zero value otherwise. +func (l *License) GetConditions() []string { + if l == nil || l.Conditions == nil { + return nil + } + return *l.Conditions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *License) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetFeatured returns the Featured field if it's non-nil, zero value otherwise. +func (l *License) GetFeatured() bool { + if l == nil || l.Featured == nil { + return false + } + return *l.Featured +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (l *License) GetHTMLURL() string { + if l == nil || l.HTMLURL == nil { + return "" + } + return *l.HTMLURL +} + +// GetImplementation returns the Implementation field if it's non-nil, zero value otherwise. +func (l *License) GetImplementation() string { + if l == nil || l.Implementation == nil { + return "" + } + return *l.Implementation +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (l *License) GetKey() string { + if l == nil || l.Key == nil { + return "" + } + return *l.Key +} + +// GetLimitations returns the Limitations field if it's non-nil, zero value otherwise. +func (l *License) GetLimitations() []string { + if l == nil || l.Limitations == nil { + return nil + } + return *l.Limitations +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *License) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (l *License) GetPermissions() []string { + if l == nil || l.Permissions == nil { + return nil + } + return *l.Permissions +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (l *License) GetSPDXID() string { + if l == nil || l.SPDXID == nil { + return "" + } + return *l.SPDXID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *License) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetAccountsURL returns the AccountsURL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetAccountsURL() string { + if m == nil || m.AccountsURL == nil { + return "" + } + return *m.AccountsURL +} + +// GetBullets returns the Bullets field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetBullets() []string { + if m == nil || m.Bullets == nil { + return nil + } + return *m.Bullets +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetDescription() string { + if m == nil || m.Description == nil { + return "" + } + return *m.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetMonthlyPriceInCents returns the MonthlyPriceInCents field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetMonthlyPriceInCents() int { + if m == nil || m.MonthlyPriceInCents == nil { + return 0 + } + return *m.MonthlyPriceInCents +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetName() string { + if m == nil || m.Name == nil { + return "" + } + return *m.Name +} + +// GetPriceModel returns the PriceModel field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetPriceModel() string { + if m == nil || m.PriceModel == nil { + return "" + } + return *m.PriceModel +} + +// GetUnitName returns the UnitName field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetUnitName() string { + if m == nil || m.UnitName == nil { + return "" + } + return *m.UnitName +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetYearlyPriceInCents returns the YearlyPriceInCents field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetYearlyPriceInCents() int { + if m == nil || m.YearlyPriceInCents == nil { + return 0 + } + return *m.YearlyPriceInCents +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetEmail() string { + if m == nil || m.Email == nil { + return "" + } + return *m.Email +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetLogin() string { + if m == nil || m.Login == nil { + return "" + } + return *m.Login +} + +// GetMarketplacePurchase returns the MarketplacePurchase field. +func (m *MarketplacePlanAccount) GetMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.MarketplacePurchase +} + +// GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetOrganizationBillingEmail() string { + if m == nil || m.OrganizationBillingEmail == nil { + return "" + } + return *m.OrganizationBillingEmail +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetType() string { + if m == nil || m.Type == nil { + return "" + } + return *m.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAccount returns the Account field. +func (m *MarketplacePurchase) GetAccount() *MarketplacePlanAccount { + if m == nil { + return nil + } + return m.Account +} + +// GetBillingCycle returns the BillingCycle field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetBillingCycle() string { + if m == nil || m.BillingCycle == nil { + return "" + } + return *m.BillingCycle +} + +// GetNextBillingDate returns the NextBillingDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetNextBillingDate() string { + if m == nil || m.NextBillingDate == nil { + return "" + } + return *m.NextBillingDate +} + +// GetPlan returns the Plan field. +func (m *MarketplacePurchase) GetPlan() *MarketplacePlan { + if m == nil { + return nil + } + return m.Plan +} + +// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetUnitCount() int { + if m == nil || m.UnitCount == nil { + return 0 + } + return *m.UnitCount +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseEvent) GetEffectiveDate() Timestamp { + if m == nil || m.EffectiveDate == nil { + return Timestamp{} + } + return *m.EffectiveDate +} + +// GetInstallation returns the Installation field. +func (m *MarketplacePurchaseEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMarketplacePurchase returns the MarketplacePurchase field. +func (m *MarketplacePurchaseEvent) GetMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.MarketplacePurchase +} + +// GetPreviousMarketplacePurchase returns the PreviousMarketplacePurchase field. +func (m *MarketplacePurchaseEvent) GetPreviousMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.PreviousMarketplacePurchase +} + +// GetSender returns the Sender field. +func (m *MarketplacePurchaseEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (m *Match) GetText() string { + if m == nil || m.Text == nil { + return "" + } + return *m.Text +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MemberEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetInstallation returns the Installation field. +func (m *MemberEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMember returns the Member field. +func (m *MemberEvent) GetMember() *User { + if m == nil { + return nil + } + return m.Member +} + +// GetRepo returns the Repo field. +func (m *MemberEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MemberEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetOrganization returns the Organization field. +func (m *Membership) GetOrganization() *Organization { + if m == nil { + return nil + } + return m.Organization +} + +// GetOrganizationURL returns the OrganizationURL field if it's non-nil, zero value otherwise. +func (m *Membership) GetOrganizationURL() string { + if m == nil || m.OrganizationURL == nil { + return "" + } + return *m.OrganizationURL +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (m *Membership) GetRole() string { + if m == nil || m.Role == nil { + return "" + } + return *m.Role +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Membership) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Membership) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetUser returns the User field. +func (m *Membership) GetUser() *User { + if m == nil { + return nil + } + return m.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MembershipEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetInstallation returns the Installation field. +func (m *MembershipEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMember returns the Member field. +func (m *MembershipEvent) GetMember() *User { + if m == nil { + return nil + } + return m.Member +} + +// GetOrg returns the Org field. +func (m *MembershipEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (m *MembershipEvent) GetScope() string { + if m == nil || m.Scope == nil { + return "" + } + return *m.Scope +} + +// GetSender returns the Sender field. +func (m *MembershipEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetTeam returns the Team field. +func (m *MembershipEvent) GetTeam() *Team { + if m == nil { + return nil + } + return m.Team +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *Metric) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (m *Metric) GetKey() string { + if m == nil || m.Key == nil { + return "" + } + return *m.Key +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (m *Metric) GetName() string { + if m == nil || m.Name == nil { + return "" + } + return *m.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Metric) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (m *Migration) GetCreatedAt() string { + if m == nil || m.CreatedAt == nil { + return "" + } + return *m.CreatedAt +} + +// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. +func (m *Migration) GetExcludeAttachments() bool { + if m == nil || m.ExcludeAttachments == nil { + return false + } + return *m.ExcludeAttachments +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (m *Migration) GetGUID() string { + if m == nil || m.GUID == nil { + return "" + } + return *m.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *Migration) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. +func (m *Migration) GetLockRepositories() bool { + if m == nil || m.LockRepositories == nil { + return false + } + return *m.LockRepositories +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Migration) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *Migration) GetUpdatedAt() string { + if m == nil || m.UpdatedAt == nil { + return "" + } + return *m.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Migration) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetClosedAt() time.Time { + if m == nil || m.ClosedAt == nil { + return time.Time{} + } + return *m.ClosedAt +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (m *Milestone) GetClosedIssues() int { + if m == nil || m.ClosedIssues == nil { + return 0 + } + return *m.ClosedIssues +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetCreatedAt() time.Time { + if m == nil || m.CreatedAt == nil { + return time.Time{} + } + return *m.CreatedAt +} + +// GetCreator returns the Creator field. +func (m *Milestone) GetCreator() *User { + if m == nil { + return nil + } + return m.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (m *Milestone) GetDescription() string { + if m == nil || m.Description == nil { + return "" + } + return *m.Description +} + +// GetDueOn returns the DueOn field if it's non-nil, zero value otherwise. +func (m *Milestone) GetDueOn() time.Time { + if m == nil || m.DueOn == nil { + return time.Time{} + } + return *m.DueOn +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *Milestone) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetLabelsURL() string { + if m == nil || m.LabelsURL == nil { + return "" + } + return *m.LabelsURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *Milestone) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (m *Milestone) GetNumber() int { + if m == nil || m.Number == nil { + return 0 + } + return *m.Number +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (m *Milestone) GetOpenIssues() int { + if m == nil || m.OpenIssues == nil { + return 0 + } + return *m.OpenIssues +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Milestone) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (m *Milestone) GetTitle() string { + if m == nil || m.Title == nil { + return "" + } + return *m.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetUpdatedAt() time.Time { + if m == nil || m.UpdatedAt == nil { + return time.Time{} + } + return *m.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MilestoneEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetChanges returns the Changes field. +func (m *MilestoneEvent) GetChanges() *EditChange { + if m == nil { + return nil + } + return m.Changes +} + +// GetInstallation returns the Installation field. +func (m *MilestoneEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMilestone returns the Milestone field. +func (m *MilestoneEvent) GetMilestone() *Milestone { + if m == nil { + return nil + } + return m.Milestone +} + +// GetOrg returns the Org field. +func (m *MilestoneEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MilestoneEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MilestoneEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetClosedMilestones returns the ClosedMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetClosedMilestones() int { + if m == nil || m.ClosedMilestones == nil { + return 0 + } + return *m.ClosedMilestones +} + +// GetOpenMilestones returns the OpenMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetOpenMilestones() int { + if m == nil || m.OpenMilestones == nil { + return 0 + } + return *m.OpenMilestones +} + +// GetTotalMilestones returns the TotalMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetTotalMilestones() int { + if m == nil || m.TotalMilestones == nil { + return 0 + } + return *m.TotalMilestones +} + +// GetBase returns the Base field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetBase() string { + if n == nil || n.Base == nil { + return "" + } + return *n.Base +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetBody() string { + if n == nil || n.Body == nil { + return "" + } + return *n.Body +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetHead() string { + if n == nil || n.Head == nil { + return "" + } + return *n.Head +} + +// GetIssue returns the Issue field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetIssue() int { + if n == nil || n.Issue == nil { + return 0 + } + return *n.Issue +} + +// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetMaintainerCanModify() bool { + if n == nil || n.MaintainerCanModify == nil { + return false + } + return *n.MaintainerCanModify +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetTitle() string { + if n == nil || n.Title == nil { + return "" + } + return *n.Title +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetDescription() string { + if n == nil || n.Description == nil { + return "" + } + return *n.Description +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetLDAPDN() string { + if n == nil || n.LDAPDN == nil { + return "" + } + return *n.LDAPDN +} + +// GetParentTeamID returns the ParentTeamID field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetParentTeamID() int64 { + if n == nil || n.ParentTeamID == nil { + return 0 + } + return *n.ParentTeamID +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPermission() string { + if n == nil || n.Permission == nil { + return "" + } + return *n.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPrivacy() string { + if n == nil || n.Privacy == nil { + return "" + } + return *n.Privacy +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (n *Notification) GetID() string { + if n == nil || n.ID == nil { + return "" + } + return *n.ID +} + +// GetLastReadAt returns the LastReadAt field if it's non-nil, zero value otherwise. +func (n *Notification) GetLastReadAt() time.Time { + if n == nil || n.LastReadAt == nil { + return time.Time{} + } + return *n.LastReadAt +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (n *Notification) GetReason() string { + if n == nil || n.Reason == nil { + return "" + } + return *n.Reason +} + +// GetRepository returns the Repository field. +func (n *Notification) GetRepository() *Repository { + if n == nil { + return nil + } + return n.Repository +} + +// GetSubject returns the Subject field. +func (n *Notification) GetSubject() *NotificationSubject { + if n == nil { + return nil + } + return n.Subject +} + +// GetUnread returns the Unread field if it's non-nil, zero value otherwise. +func (n *Notification) GetUnread() bool { + if n == nil || n.Unread == nil { + return false + } + return *n.Unread +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (n *Notification) GetUpdatedAt() time.Time { + if n == nil || n.UpdatedAt == nil { + return time.Time{} + } + return *n.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (n *Notification) GetURL() string { + if n == nil || n.URL == nil { + return "" + } + return *n.URL +} + +// GetLatestCommentURL returns the LatestCommentURL field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetLatestCommentURL() string { + if n == nil || n.LatestCommentURL == nil { + return "" + } + return *n.LatestCommentURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetTitle() string { + if n == nil || n.Title == nil { + return "" + } + return *n.Title +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetType() string { + if n == nil || n.Type == nil { + return "" + } + return *n.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetURL() string { + if n == nil || n.URL == nil { + return "" + } + return *n.URL +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetAvatarURL() string { + if o == nil || o.AvatarURL == nil { + return "" + } + return *o.AvatarURL +} + +// GetBillingEmail returns the BillingEmail field if it's non-nil, zero value otherwise. +func (o *Organization) GetBillingEmail() string { + if o == nil || o.BillingEmail == nil { + return "" + } + return *o.BillingEmail +} + +// GetBlog returns the Blog field if it's non-nil, zero value otherwise. +func (o *Organization) GetBlog() string { + if o == nil || o.Blog == nil { + return "" + } + return *o.Blog +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (o *Organization) GetCollaborators() int { + if o == nil || o.Collaborators == nil { + return 0 + } + return *o.Collaborators +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (o *Organization) GetCompany() string { + if o == nil || o.Company == nil { + return "" + } + return *o.Company +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (o *Organization) GetCreatedAt() time.Time { + if o == nil || o.CreatedAt == nil { + return time.Time{} + } + return *o.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (o *Organization) GetDescription() string { + if o == nil || o.Description == nil { + return "" + } + return *o.Description +} + +// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. +func (o *Organization) GetDiskUsage() int { + if o == nil || o.DiskUsage == nil { + return 0 + } + return *o.DiskUsage +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (o *Organization) GetEmail() string { + if o == nil || o.Email == nil { + return "" + } + return *o.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetEventsURL() string { + if o == nil || o.EventsURL == nil { + return "" + } + return *o.EventsURL +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (o *Organization) GetFollowers() int { + if o == nil || o.Followers == nil { + return 0 + } + return *o.Followers +} + +// GetFollowing returns the Following field if it's non-nil, zero value otherwise. +func (o *Organization) GetFollowing() int { + if o == nil || o.Following == nil { + return 0 + } + return *o.Following +} + +// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetHooksURL() string { + if o == nil || o.HooksURL == nil { + return "" + } + return *o.HooksURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetHTMLURL() string { + if o == nil || o.HTMLURL == nil { + return "" + } + return *o.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (o *Organization) GetID() int64 { + if o == nil || o.ID == nil { + return 0 + } + return *o.ID +} + +// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetIssuesURL() string { + if o == nil || o.IssuesURL == nil { + return "" + } + return *o.IssuesURL +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (o *Organization) GetLocation() string { + if o == nil || o.Location == nil { + return "" + } + return *o.Location +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (o *Organization) GetLogin() string { + if o == nil || o.Login == nil { + return "" + } + return *o.Login +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersURL() string { + if o == nil || o.MembersURL == nil { + return "" + } + return *o.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *Organization) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (o *Organization) GetNodeID() string { + if o == nil || o.NodeID == nil { + return "" + } + return *o.NodeID +} + +// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetOwnedPrivateRepos() int { + if o == nil || o.OwnedPrivateRepos == nil { + return 0 + } + return *o.OwnedPrivateRepos +} + +// GetPlan returns the Plan field. +func (o *Organization) GetPlan() *Plan { + if o == nil { + return nil + } + return o.Plan +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (o *Organization) GetPrivateGists() int { + if o == nil || o.PrivateGists == nil { + return 0 + } + return *o.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicGists() int { + if o == nil || o.PublicGists == nil { + return 0 + } + return *o.PublicGists +} + +// GetPublicMembersURL returns the PublicMembersURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicMembersURL() string { + if o == nil || o.PublicMembersURL == nil { + return "" + } + return *o.PublicMembersURL +} + +// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicRepos() int { + if o == nil || o.PublicRepos == nil { + return 0 + } + return *o.PublicRepos +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetReposURL() string { + if o == nil || o.ReposURL == nil { + return "" + } + return *o.ReposURL +} + +// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetTotalPrivateRepos() int { + if o == nil || o.TotalPrivateRepos == nil { + return 0 + } + return *o.TotalPrivateRepos +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (o *Organization) GetType() string { + if o == nil || o.Type == nil { + return "" + } + return *o.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (o *Organization) GetUpdatedAt() time.Time { + if o == nil || o.UpdatedAt == nil { + return time.Time{} + } + return *o.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (o *Organization) GetURL() string { + if o == nil || o.URL == nil { + return "" + } + return *o.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (o *OrganizationEvent) GetAction() string { + if o == nil || o.Action == nil { + return "" + } + return *o.Action +} + +// GetInstallation returns the Installation field. +func (o *OrganizationEvent) GetInstallation() *Installation { + if o == nil { + return nil + } + return o.Installation +} + +// GetInvitation returns the Invitation field. +func (o *OrganizationEvent) GetInvitation() *Invitation { + if o == nil { + return nil + } + return o.Invitation +} + +// GetMembership returns the Membership field. +func (o *OrganizationEvent) GetMembership() *Membership { + if o == nil { + return nil + } + return o.Membership +} + +// GetOrganization returns the Organization field. +func (o *OrganizationEvent) GetOrganization() *Organization { + if o == nil { + return nil + } + return o.Organization +} + +// GetSender returns the Sender field. +func (o *OrganizationEvent) GetSender() *User { + if o == nil { + return nil + } + return o.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (o *OrgBlockEvent) GetAction() string { + if o == nil || o.Action == nil { + return "" + } + return *o.Action +} + +// GetBlockedUser returns the BlockedUser field. +func (o *OrgBlockEvent) GetBlockedUser() *User { + if o == nil { + return nil + } + return o.BlockedUser +} + +// GetInstallation returns the Installation field. +func (o *OrgBlockEvent) GetInstallation() *Installation { + if o == nil { + return nil + } + return o.Installation +} + +// GetOrganization returns the Organization field. +func (o *OrgBlockEvent) GetOrganization() *Organization { + if o == nil { + return nil + } + return o.Organization +} + +// GetSender returns the Sender field. +func (o *OrgBlockEvent) GetSender() *User { + if o == nil { + return nil + } + return o.Sender +} + +// GetDisabledOrgs returns the DisabledOrgs field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetDisabledOrgs() int { + if o == nil || o.DisabledOrgs == nil { + return 0 + } + return *o.DisabledOrgs +} + +// GetTotalOrgs returns the TotalOrgs field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalOrgs() int { + if o == nil || o.TotalOrgs == nil { + return 0 + } + return *o.TotalOrgs +} + +// GetTotalTeamMembers returns the TotalTeamMembers field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalTeamMembers() int { + if o == nil || o.TotalTeamMembers == nil { + return 0 + } + return *o.TotalTeamMembers +} + +// GetTotalTeams returns the TotalTeams field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalTeams() int { + if o == nil || o.TotalTeams == nil { + return 0 + } + return *o.TotalTeams +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *Page) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Page) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetPageName returns the PageName field if it's non-nil, zero value otherwise. +func (p *Page) GetPageName() string { + if p == nil || p.PageName == nil { + return "" + } + return *p.PageName +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *Page) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (p *Page) GetSummary() string { + if p == nil || p.Summary == nil { + return "" + } + return *p.Summary +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *Page) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetBuild returns the Build field. +func (p *PageBuildEvent) GetBuild() *PagesBuild { + if p == nil { + return nil + } + return p.Build +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PageBuildEvent) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInstallation returns the Installation field. +func (p *PageBuildEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetRepo returns the Repo field. +func (p *PageBuildEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PageBuildEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. +func (p *Pages) GetCNAME() string { + if p == nil || p.CNAME == nil { + return "" + } + return *p.CNAME +} + +// GetCustom404 returns the Custom404 field if it's non-nil, zero value otherwise. +func (p *Pages) GetCustom404() bool { + if p == nil || p.Custom404 == nil { + return false + } + return *p.Custom404 +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Pages) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (p *Pages) GetStatus() string { + if p == nil || p.Status == nil { + return "" + } + return *p.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Pages) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetCommit returns the Commit field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetCommit() string { + if p == nil || p.Commit == nil { + return "" + } + return *p.Commit +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDuration returns the Duration field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetDuration() int { + if p == nil || p.Duration == nil { + return 0 + } + return *p.Duration +} + +// GetError returns the Error field. +func (p *PagesBuild) GetError() *PagesError { + if p == nil { + return nil + } + return p.Error +} + +// GetPusher returns the Pusher field. +func (p *PagesBuild) GetPusher() *User { + if p == nil { + return nil + } + return p.Pusher +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetStatus() string { + if p == nil || p.Status == nil { + return "" + } + return *p.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PagesError) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetTotalPages returns the TotalPages field if it's non-nil, zero value otherwise. +func (p *PageStats) GetTotalPages() int { + if p == nil || p.TotalPages == nil { + return 0 + } + return *p.TotalPages +} + +// GetHook returns the Hook field. +func (p *PingEvent) GetHook() *Hook { + if p == nil { + return nil + } + return p.Hook +} + +// GetHookID returns the HookID field if it's non-nil, zero value otherwise. +func (p *PingEvent) GetHookID() int64 { + if p == nil || p.HookID == nil { + return 0 + } + return *p.HookID +} + +// GetInstallation returns the Installation field. +func (p *PingEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetZen returns the Zen field if it's non-nil, zero value otherwise. +func (p *PingEvent) GetZen() string { + if p == nil || p.Zen == nil { + return "" + } + return *p.Zen +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (p *Plan) GetCollaborators() int { + if p == nil || p.Collaborators == nil { + return 0 + } + return *p.Collaborators +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Plan) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPrivateRepos returns the PrivateRepos field if it's non-nil, zero value otherwise. +func (p *Plan) GetPrivateRepos() int { + if p == nil || p.PrivateRepos == nil { + return 0 + } + return *p.PrivateRepos +} + +// GetSpace returns the Space field if it's non-nil, zero value otherwise. +func (p *Plan) GetSpace() int { + if p == nil || p.Space == nil { + return 0 + } + return *p.Space +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *Project) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *Project) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetCreator returns the Creator field. +func (p *Project) GetCreator() *User { + if p == nil { + return nil + } + return p.Creator +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *Project) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Project) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *Project) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *Project) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOwnerURL returns the OwnerURL field if it's non-nil, zero value otherwise. +func (p *Project) GetOwnerURL() string { + if p == nil || p.OwnerURL == nil { + return "" + } + return *p.OwnerURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *Project) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Project) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetColumnID returns the ColumnID field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetColumnID() int64 { + if p == nil || p.ColumnID == nil { + return 0 + } + return *p.ColumnID +} + +// GetColumnURL returns the ColumnURL field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetColumnURL() string { + if p == nil || p.ColumnURL == nil { + return "" + } + return *p.ColumnURL +} + +// GetContentURL returns the ContentURL field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetContentURL() string { + if p == nil || p.ContentURL == nil { + return "" + } + return *p.ContentURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetCreator returns the Creator field. +func (p *ProjectCard) GetCreator() *User { + if p == nil { + return nil + } + return p.Creator +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetNote() string { + if p == nil || p.Note == nil { + return "" + } + return *p.Note +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectCardEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfterID returns the AfterID field if it's non-nil, zero value otherwise. +func (p *ProjectCardEvent) GetAfterID() int64 { + if p == nil || p.AfterID == nil { + return 0 + } + return *p.AfterID +} + +// GetChanges returns the Changes field. +func (p *ProjectCardEvent) GetChanges() *ProjectCardChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *ProjectCardEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectCardEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProjectCard returns the ProjectCard field. +func (p *ProjectCardEvent) GetProjectCard() *ProjectCard { + if p == nil { + return nil + } + return p.ProjectCard +} + +// GetRepo returns the Repo field. +func (p *ProjectCardEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *ProjectCardEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetProjectURL returns the ProjectURL field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetProjectURL() string { + if p == nil || p.ProjectURL == nil { + return "" + } + return *p.ProjectURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectColumnEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfterID returns the AfterID field if it's non-nil, zero value otherwise. +func (p *ProjectColumnEvent) GetAfterID() int64 { + if p == nil || p.AfterID == nil { + return 0 + } + return *p.AfterID +} + +// GetChanges returns the Changes field. +func (p *ProjectColumnEvent) GetChanges() *ProjectColumnChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *ProjectColumnEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectColumnEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProjectColumn returns the ProjectColumn field. +func (p *ProjectColumnEvent) GetProjectColumn() *ProjectColumn { + if p == nil { + return nil + } + return p.ProjectColumn +} + +// GetRepo returns the Repo field. +func (p *ProjectColumnEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *ProjectColumnEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *ProjectEvent) GetChanges() *ProjectChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *ProjectEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProject returns the Project field. +func (p *ProjectEvent) GetProject() *Project { + if p == nil { + return nil + } + return p.Project +} + +// GetRepo returns the Repo field. +func (p *ProjectEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *ProjectEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetEnforceAdmins returns the EnforceAdmins field. +func (p *Protection) GetEnforceAdmins() *AdminEnforcement { + if p == nil { + return nil + } + return p.EnforceAdmins +} + +// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. +func (p *Protection) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcement { + if p == nil { + return nil + } + return p.RequiredPullRequestReviews +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *Protection) GetRequiredStatusChecks() *RequiredStatusChecks { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRestrictions returns the Restrictions field. +func (p *Protection) GetRestrictions() *BranchRestrictions { + if p == nil { + return nil + } + return p.Restrictions +} + +// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. +func (p *ProtectionRequest) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcementRequest { + if p == nil { + return nil + } + return p.RequiredPullRequestReviews +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *ProtectionRequest) GetRequiredStatusChecks() *RequiredStatusChecks { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRestrictions returns the Restrictions field. +func (p *ProtectionRequest) GetRestrictions() *BranchRestrictionsRequest { + if p == nil { + return nil + } + return p.Restrictions +} + +// GetInstallation returns the Installation field. +func (p *PublicEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetRepo returns the Repo field. +func (p *PublicEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PublicEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetAdditions() int { + if p == nil || p.Additions == nil { + return 0 + } + return *p.Additions +} + +// GetAssignee returns the Assignee field. +func (p *PullRequest) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetBase returns the Base field. +func (p *PullRequest) GetBase() *PullRequestBranch { + if p == nil { + return nil + } + return p.Base +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetChangedFiles returns the ChangedFiles field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetChangedFiles() int { + if p == nil || p.ChangedFiles == nil { + return 0 + } + return *p.ChangedFiles +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetClosedAt() time.Time { + if p == nil || p.ClosedAt == nil { + return time.Time{} + } + return *p.ClosedAt +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetComments() int { + if p == nil || p.Comments == nil { + return 0 + } + return *p.Comments +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommentsURL() string { + if p == nil || p.CommentsURL == nil { + return "" + } + return *p.CommentsURL +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommits() int { + if p == nil || p.Commits == nil { + return 0 + } + return *p.Commits +} + +// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommitsURL() string { + if p == nil || p.CommitsURL == nil { + return "" + } + return *p.CommitsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCreatedAt() time.Time { + if p == nil || p.CreatedAt == nil { + return time.Time{} + } + return *p.CreatedAt +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDeletions() int { + if p == nil || p.Deletions == nil { + return 0 + } + return *p.Deletions +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDiffURL() string { + if p == nil || p.DiffURL == nil { + return "" + } + return *p.DiffURL +} + +// GetHead returns the Head field. +func (p *PullRequest) GetHead() *PullRequestBranch { + if p == nil { + return nil + } + return p.Head +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetIssueURL() string { + if p == nil || p.IssueURL == nil { + return "" + } + return *p.IssueURL +} + +// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMaintainerCanModify() bool { + if p == nil || p.MaintainerCanModify == nil { + return false + } + return *p.MaintainerCanModify +} + +// GetMergeable returns the Mergeable field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeable() bool { + if p == nil || p.Mergeable == nil { + return false + } + return *p.Mergeable +} + +// GetMergeableState returns the MergeableState field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeableState() string { + if p == nil || p.MergeableState == nil { + return "" + } + return *p.MergeableState +} + +// GetMergeCommitSHA returns the MergeCommitSHA field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeCommitSHA() string { + if p == nil || p.MergeCommitSHA == nil { + return "" + } + return *p.MergeCommitSHA +} + +// GetMerged returns the Merged field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMerged() bool { + if p == nil || p.Merged == nil { + return false + } + return *p.Merged +} + +// GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergedAt() time.Time { + if p == nil || p.MergedAt == nil { + return time.Time{} + } + return *p.MergedAt +} + +// GetMergedBy returns the MergedBy field. +func (p *PullRequest) GetMergedBy() *User { + if p == nil { + return nil + } + return p.MergedBy +} + +// GetMilestone returns the Milestone field. +func (p *PullRequest) GetMilestone() *Milestone { + if p == nil { + return nil + } + return p.Milestone +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetPatchURL() string { + if p == nil || p.PatchURL == nil { + return "" + } + return *p.PatchURL +} + +// GetReviewCommentsURL returns the ReviewCommentsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewCommentsURL() string { + if p == nil || p.ReviewCommentsURL == nil { + return "" + } + return *p.ReviewCommentsURL +} + +// GetReviewCommentURL returns the ReviewCommentURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewCommentURL() string { + if p == nil || p.ReviewCommentURL == nil { + return "" + } + return *p.ReviewCommentURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetStatusesURL() string { + if p == nil || p.StatusesURL == nil { + return "" + } + return *p.StatusesURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetUpdatedAt() time.Time { + if p == nil || p.UpdatedAt == nil { + return time.Time{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetUser returns the User field. +func (p *PullRequest) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetLabel returns the Label field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetLabel() string { + if p == nil || p.Label == nil { + return "" + } + return *p.Label +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetRef() string { + if p == nil || p.Ref == nil { + return "" + } + return *p.Ref +} + +// GetRepo returns the Repo field. +func (p *PullRequestBranch) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetUser returns the User field. +func (p *PullRequestBranch) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetCreatedAt() time.Time { + if p == nil || p.CreatedAt == nil { + return time.Time{} + } + return *p.CreatedAt +} + +// GetDiffHunk returns the DiffHunk field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetDiffHunk() string { + if p == nil || p.DiffHunk == nil { + return "" + } + return *p.DiffHunk +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInReplyTo returns the InReplyTo field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetInReplyTo() int64 { + if p == nil || p.InReplyTo == nil { + return 0 + } + return *p.InReplyTo +} + +// GetOriginalCommitID returns the OriginalCommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalCommitID() string { + if p == nil || p.OriginalCommitID == nil { + return "" + } + return *p.OriginalCommitID +} + +// GetOriginalPosition returns the OriginalPosition field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalPosition() int { + if p == nil || p.OriginalPosition == nil { + return 0 + } + return *p.OriginalPosition +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPath() string { + if p == nil || p.Path == nil { + return "" + } + return *p.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPosition() int { + if p == nil || p.Position == nil { + return 0 + } + return *p.Position +} + +// GetPullRequestReviewID returns the PullRequestReviewID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPullRequestReviewID() int64 { + if p == nil || p.PullRequestReviewID == nil { + return 0 + } + return *p.PullRequestReviewID +} + +// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPullRequestURL() string { + if p == nil || p.PullRequestURL == nil { + return "" + } + return *p.PullRequestURL +} + +// GetReactions returns the Reactions field. +func (p *PullRequestComment) GetReactions() *Reactions { + if p == nil { + return nil + } + return p.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetUpdatedAt() time.Time { + if p == nil || p.UpdatedAt == nil { + return time.Time{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetUser returns the User field. +func (p *PullRequestComment) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *PullRequestEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *PullRequestEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetLabel returns the Label field. +func (p *PullRequestEvent) GetLabel() *Label { + if p == nil { + return nil + } + return p.Label +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (p *PullRequestEvent) GetRequestedReviewer() *User { + if p == nil { + return nil + } + return p.RequestedReviewer +} + +// GetSender returns the Sender field. +func (p *PullRequestEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetDiffURL() string { + if p == nil || p.DiffURL == nil { + return "" + } + return *p.DiffURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetPatchURL() string { + if p == nil || p.PatchURL == nil { + return "" + } + return *p.PatchURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetMerged returns the Merged field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetMerged() bool { + if p == nil || p.Merged == nil { + return false + } + return *p.Merged +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetPullRequestURL() string { + if p == nil || p.PullRequestURL == nil { + return "" + } + return *p.PullRequestURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetSubmittedAt() time.Time { + if p == nil || p.SubmittedAt == nil { + return time.Time{} + } + return *p.SubmittedAt +} + +// GetUser returns the User field. +func (p *PullRequestReview) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewCommentEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *PullRequestReviewCommentEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetComment returns the Comment field. +func (p *PullRequestReviewCommentEvent) GetComment() *PullRequestComment { + if p == nil { + return nil + } + return p.Comment +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewCommentEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewCommentEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewCommentEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewCommentEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewDismissalRequest) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrganization returns the Organization field. +func (p *PullRequestReviewEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetReview returns the Review field. +func (p *PullRequestReviewEvent) GetReview() *PullRequestReview { + if p == nil { + return nil + } + return p.Review +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetEvent() string { + if p == nil || p.Event == nil { + return "" + } + return *p.Event +} + +// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. +func (p *PullRequestReviewsEnforcementRequest) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { + if p == nil { + return nil + } + return p.DismissalRestrictionsRequest +} + +// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. +func (p *PullRequestReviewsEnforcementUpdate) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { + if p == nil { + return nil + } + return p.DismissalRestrictionsRequest +} + +// GetDismissStaleReviews returns the DismissStaleReviews field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetDismissStaleReviews() bool { + if p == nil || p.DismissStaleReviews == nil { + return false + } + return *p.DismissStaleReviews +} + +// GetMergablePulls returns the MergablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergablePulls() int { + if p == nil || p.MergablePulls == nil { + return 0 + } + return *p.MergablePulls +} + +// GetMergedPulls returns the MergedPulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergedPulls() int { + if p == nil || p.MergedPulls == nil { + return 0 + } + return *p.MergedPulls +} + +// GetTotalPulls returns the TotalPulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetTotalPulls() int { + if p == nil || p.TotalPulls == nil { + return 0 + } + return *p.TotalPulls +} + +// GetUnmergablePulls returns the UnmergablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetUnmergablePulls() int { + if p == nil || p.UnmergablePulls == nil { + return 0 + } + return *p.UnmergablePulls +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetCommits() int { + if p == nil || p.Commits == nil { + return 0 + } + return *p.Commits +} + +// GetDay returns the Day field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetDay() int { + if p == nil || p.Day == nil { + return 0 + } + return *p.Day +} + +// GetHour returns the Hour field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetHour() int { + if p == nil || p.Hour == nil { + return 0 + } + return *p.Hour +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetBaseRef() string { + if p == nil || p.BaseRef == nil { + return "" + } + return *p.BaseRef +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetCompare returns the Compare field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetCompare() string { + if p == nil || p.Compare == nil { + return "" + } + return *p.Compare +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetCreated() bool { + if p == nil || p.Created == nil { + return false + } + return *p.Created +} + +// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetDeleted() bool { + if p == nil || p.Deleted == nil { + return false + } + return *p.Deleted +} + +// GetDistinctSize returns the DistinctSize field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetDistinctSize() int { + if p == nil || p.DistinctSize == nil { + return 0 + } + return *p.DistinctSize +} + +// GetForced returns the Forced field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetForced() bool { + if p == nil || p.Forced == nil { + return false + } + return *p.Forced +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetHead() string { + if p == nil || p.Head == nil { + return "" + } + return *p.Head +} + +// GetHeadCommit returns the HeadCommit field. +func (p *PushEvent) GetHeadCommit() *PushEventCommit { + if p == nil { + return nil + } + return p.HeadCommit +} + +// GetInstallation returns the Installation field. +func (p *PushEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetPusher returns the Pusher field. +func (p *PushEvent) GetPusher() *User { + if p == nil { + return nil + } + return p.Pusher +} + +// GetPushID returns the PushID field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetPushID() int64 { + if p == nil || p.PushID == nil { + return 0 + } + return *p.PushID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetRef() string { + if p == nil || p.Ref == nil { + return "" + } + return *p.Ref +} + +// GetRepo returns the Repo field. +func (p *PushEvent) GetRepo() *PushEventRepository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PushEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetSize() int { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetAuthor returns the Author field. +func (p *PushEventCommit) GetAuthor() *CommitAuthor { + if p == nil { + return nil + } + return p.Author +} + +// GetCommitter returns the Committer field. +func (p *PushEventCommit) GetCommitter() *CommitAuthor { + if p == nil { + return nil + } + return p.Committer +} + +// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. +func (p *PushEventCommit) GetDistinct() bool { + if p == nil || p.Distinct == nil { + return false + } + return *p.Distinct +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PushEventCommit) GetID() string { + if p == nil || p.ID == nil { + return "" + } + return *p.ID +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PushEventCommit) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PushEventCommit) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (p *PushEventCommit) GetTimestamp() Timestamp { + if p == nil || p.Timestamp == nil { + return Timestamp{} + } + return *p.Timestamp +} + +// GetTreeID returns the TreeID field if it's non-nil, zero value otherwise. +func (p *PushEventCommit) GetTreeID() string { + if p == nil || p.TreeID == nil { + return "" + } + return *p.TreeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PushEventCommit) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (p *PushEventRepoOwner) GetEmail() string { + if p == nil || p.Email == nil { + return "" + } + return *p.Email +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PushEventRepoOwner) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetArchiveURL() string { + if p == nil || p.ArchiveURL == nil { + return "" + } + return *p.ArchiveURL +} + +// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetCloneURL() string { + if p == nil || p.CloneURL == nil { + return "" + } + return *p.CloneURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDefaultBranch() string { + if p == nil || p.DefaultBranch == nil { + return "" + } + return *p.DefaultBranch +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetFork returns the Fork field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetFork() bool { + if p == nil || p.Fork == nil { + return false + } + return *p.Fork +} + +// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetForksCount() int { + if p == nil || p.ForksCount == nil { + return 0 + } + return *p.ForksCount +} + +// GetFullName returns the FullName field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetFullName() string { + if p == nil || p.FullName == nil { + return "" + } + return *p.FullName +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetGitURL() string { + if p == nil || p.GitURL == nil { + return "" + } + return *p.GitURL +} + +// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasDownloads() bool { + if p == nil || p.HasDownloads == nil { + return false + } + return *p.HasDownloads +} + +// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasIssues() bool { + if p == nil || p.HasIssues == nil { + return false + } + return *p.HasIssues +} + +// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasPages() bool { + if p == nil || p.HasPages == nil { + return false + } + return *p.HasPages +} + +// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasWiki() bool { + if p == nil || p.HasWiki == nil { + return false + } + return *p.HasWiki +} + +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHomepage() string { + if p == nil || p.Homepage == nil { + return "" + } + return *p.Homepage +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetLanguage() string { + if p == nil || p.Language == nil { + return "" + } + return *p.Language +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetMasterBranch() string { + if p == nil || p.MasterBranch == nil { + return "" + } + return *p.MasterBranch +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetOpenIssuesCount() int { + if p == nil || p.OpenIssuesCount == nil { + return 0 + } + return *p.OpenIssuesCount +} + +// GetOrganization returns the Organization field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetOrganization() string { + if p == nil || p.Organization == nil { + return "" + } + return *p.Organization +} + +// GetOwner returns the Owner field. +func (p *PushEventRepository) GetOwner() *PushEventRepoOwner { + if p == nil { + return nil + } + return p.Owner +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPrivate() bool { + if p == nil || p.Private == nil { + return false + } + return *p.Private +} + +// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPushedAt() Timestamp { + if p == nil || p.PushedAt == nil { + return Timestamp{} + } + return *p.PushedAt +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSize() int { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSSHURL() string { + if p == nil || p.SSHURL == nil { + return "" + } + return *p.SSHURL +} + +// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetStargazersCount() int { + if p == nil || p.StargazersCount == nil { + return 0 + } + return *p.StargazersCount +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetStatusesURL() string { + if p == nil || p.StatusesURL == nil { + return "" + } + return *p.StatusesURL +} + +// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSVNURL() string { + if p == nil || p.SVNURL == nil { + return "" + } + return *p.SVNURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetWatchersCount() int { + if p == nil || p.WatchersCount == nil { + return 0 + } + return *p.WatchersCount +} + +// GetCore returns the Core field. +func (r *RateLimits) GetCore() *Rate { + if r == nil { + return nil + } + return r.Core +} + +// GetSearch returns the Search field. +func (r *RateLimits) GetSearch() *Rate { + if r == nil { + return nil + } + return r.Search +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (r *Reaction) GetContent() string { + if r == nil || r.Content == nil { + return "" + } + return *r.Content +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Reaction) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Reaction) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetUser returns the User field. +func (r *Reaction) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetConfused returns the Confused field if it's non-nil, zero value otherwise. +func (r *Reactions) GetConfused() int { + if r == nil || r.Confused == nil { + return 0 + } + return *r.Confused +} + +// GetHeart returns the Heart field if it's non-nil, zero value otherwise. +func (r *Reactions) GetHeart() int { + if r == nil || r.Heart == nil { + return 0 + } + return *r.Heart +} + +// GetHooray returns the Hooray field if it's non-nil, zero value otherwise. +func (r *Reactions) GetHooray() int { + if r == nil || r.Hooray == nil { + return 0 + } + return *r.Hooray +} + +// GetLaugh returns the Laugh field if it's non-nil, zero value otherwise. +func (r *Reactions) GetLaugh() int { + if r == nil || r.Laugh == nil { + return 0 + } + return *r.Laugh +} + +// GetMinusOne returns the MinusOne field if it's non-nil, zero value otherwise. +func (r *Reactions) GetMinusOne() int { + if r == nil || r.MinusOne == nil { + return 0 + } + return *r.MinusOne +} + +// GetPlusOne returns the PlusOne field if it's non-nil, zero value otherwise. +func (r *Reactions) GetPlusOne() int { + if r == nil || r.PlusOne == nil { + return 0 + } + return *r.PlusOne +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (r *Reactions) GetTotalCount() int { + if r == nil || r.TotalCount == nil { + return 0 + } + return *r.TotalCount +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Reactions) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Reference) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetObject returns the Object field. +func (r *Reference) GetObject() *GitObject { + if r == nil { + return nil + } + return r.Object +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (r *Reference) GetRef() string { + if r == nil || r.Ref == nil { + return "" + } + return *r.Ref +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Reference) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetBrowserDownloadURL returns the BrowserDownloadURL field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetBrowserDownloadURL() string { + if r == nil || r.BrowserDownloadURL == nil { + return "" + } + return *r.BrowserDownloadURL +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetContentType() string { + if r == nil || r.ContentType == nil { + return "" + } + return *r.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDownloadCount returns the DownloadCount field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetDownloadCount() int { + if r == nil || r.DownloadCount == nil { + return 0 + } + return *r.DownloadCount +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetLabel returns the Label field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetLabel() string { + if r == nil || r.Label == nil { + return "" + } + return *r.Label +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetUploader returns the Uploader field. +func (r *ReleaseAsset) GetUploader() *User { + if r == nil { + return nil + } + return r.Uploader +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *ReleaseEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetInstallation returns the Installation field. +func (r *ReleaseEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetRelease returns the Release field. +func (r *ReleaseEvent) GetRelease() *RepositoryRelease { + if r == nil { + return nil + } + return r.Release +} + +// GetRepo returns the Repo field. +func (r *ReleaseEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *ReleaseEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *Rename) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (r *Rename) GetTo() string { + if r == nil || r.To == nil { + return "" + } + return *r.To +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (r *RepositoriesSearchResult) GetIncompleteResults() bool { + if r == nil || r.IncompleteResults == nil { + return false + } + return *r.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (r *RepositoriesSearchResult) GetTotal() int { + if r == nil || r.Total == nil { + return 0 + } + return *r.Total +} + +// GetAllowMergeCommit returns the AllowMergeCommit field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowMergeCommit() bool { + if r == nil || r.AllowMergeCommit == nil { + return false + } + return *r.AllowMergeCommit +} + +// GetAllowRebaseMerge returns the AllowRebaseMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowRebaseMerge() bool { + if r == nil || r.AllowRebaseMerge == nil { + return false + } + return *r.AllowRebaseMerge +} + +// GetAllowSquashMerge returns the AllowSquashMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowSquashMerge() bool { + if r == nil || r.AllowSquashMerge == nil { + return false + } + return *r.AllowSquashMerge +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (r *Repository) GetArchived() bool { + if r == nil || r.Archived == nil { + return false + } + return *r.Archived +} + +// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetArchiveURL() string { + if r == nil || r.ArchiveURL == nil { + return "" + } + return *r.ArchiveURL +} + +// GetAssigneesURL returns the AssigneesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetAssigneesURL() string { + if r == nil || r.AssigneesURL == nil { + return "" + } + return *r.AssigneesURL +} + +// GetAutoInit returns the AutoInit field if it's non-nil, zero value otherwise. +func (r *Repository) GetAutoInit() bool { + if r == nil || r.AutoInit == nil { + return false + } + return *r.AutoInit +} + +// GetBlobsURL returns the BlobsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetBlobsURL() string { + if r == nil || r.BlobsURL == nil { + return "" + } + return *r.BlobsURL +} + +// GetBranchesURL returns the BranchesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetBranchesURL() string { + if r == nil || r.BranchesURL == nil { + return "" + } + return *r.BranchesURL +} + +// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCloneURL() string { + if r == nil || r.CloneURL == nil { + return "" + } + return *r.CloneURL +} + +// GetCodeOfConduct returns the CodeOfConduct field. +func (r *Repository) GetCodeOfConduct() *CodeOfConduct { + if r == nil { + return nil + } + return r.CodeOfConduct +} + +// GetCollaboratorsURL returns the CollaboratorsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCollaboratorsURL() string { + if r == nil || r.CollaboratorsURL == nil { + return "" + } + return *r.CollaboratorsURL +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCommentsURL() string { + if r == nil || r.CommentsURL == nil { + return "" + } + return *r.CommentsURL +} + +// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCommitsURL() string { + if r == nil || r.CommitsURL == nil { + return "" + } + return *r.CommitsURL +} + +// GetCompareURL returns the CompareURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCompareURL() string { + if r == nil || r.CompareURL == nil { + return "" + } + return *r.CompareURL +} + +// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetContentsURL() string { + if r == nil || r.ContentsURL == nil { + return "" + } + return *r.ContentsURL +} + +// GetContributorsURL returns the ContributorsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetContributorsURL() string { + if r == nil || r.ContributorsURL == nil { + return "" + } + return *r.ContributorsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetDefaultBranch() string { + if r == nil || r.DefaultBranch == nil { + return "" + } + return *r.DefaultBranch +} + +// GetDeploymentsURL returns the DeploymentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetDeploymentsURL() string { + if r == nil || r.DeploymentsURL == nil { + return "" + } + return *r.DeploymentsURL +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *Repository) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetDownloadsURL returns the DownloadsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetDownloadsURL() string { + if r == nil || r.DownloadsURL == nil { + return "" + } + return *r.DownloadsURL +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetEventsURL() string { + if r == nil || r.EventsURL == nil { + return "" + } + return *r.EventsURL +} + +// GetFork returns the Fork field if it's non-nil, zero value otherwise. +func (r *Repository) GetFork() bool { + if r == nil || r.Fork == nil { + return false + } + return *r.Fork +} + +// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetForksCount() int { + if r == nil || r.ForksCount == nil { + return 0 + } + return *r.ForksCount +} + +// GetForksURL returns the ForksURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetForksURL() string { + if r == nil || r.ForksURL == nil { + return "" + } + return *r.ForksURL +} + +// GetFullName returns the FullName field if it's non-nil, zero value otherwise. +func (r *Repository) GetFullName() string { + if r == nil || r.FullName == nil { + return "" + } + return *r.FullName +} + +// GetGitCommitsURL returns the GitCommitsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitCommitsURL() string { + if r == nil || r.GitCommitsURL == nil { + return "" + } + return *r.GitCommitsURL +} + +// GetGitignoreTemplate returns the GitignoreTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitignoreTemplate() string { + if r == nil || r.GitignoreTemplate == nil { + return "" + } + return *r.GitignoreTemplate +} + +// GetGitRefsURL returns the GitRefsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitRefsURL() string { + if r == nil || r.GitRefsURL == nil { + return "" + } + return *r.GitRefsURL +} + +// GetGitTagsURL returns the GitTagsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitTagsURL() string { + if r == nil || r.GitTagsURL == nil { + return "" + } + return *r.GitTagsURL +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasDownloads() bool { + if r == nil || r.HasDownloads == nil { + return false + } + return *r.HasDownloads +} + +// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasIssues() bool { + if r == nil || r.HasIssues == nil { + return false + } + return *r.HasIssues +} + +// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasPages() bool { + if r == nil || r.HasPages == nil { + return false + } + return *r.HasPages +} + +// GetHasProjects returns the HasProjects field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasProjects() bool { + if r == nil || r.HasProjects == nil { + return false + } + return *r.HasProjects +} + +// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasWiki() bool { + if r == nil || r.HasWiki == nil { + return false + } + return *r.HasWiki +} + +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (r *Repository) GetHomepage() string { + if r == nil || r.Homepage == nil { + return "" + } + return *r.Homepage +} + +// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetHooksURL() string { + if r == nil || r.HooksURL == nil { + return "" + } + return *r.HooksURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Repository) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetIssueCommentURL returns the IssueCommentURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssueCommentURL() string { + if r == nil || r.IssueCommentURL == nil { + return "" + } + return *r.IssueCommentURL +} + +// GetIssueEventsURL returns the IssueEventsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssueEventsURL() string { + if r == nil || r.IssueEventsURL == nil { + return "" + } + return *r.IssueEventsURL +} + +// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssuesURL() string { + if r == nil || r.IssuesURL == nil { + return "" + } + return *r.IssuesURL +} + +// GetKeysURL returns the KeysURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetKeysURL() string { + if r == nil || r.KeysURL == nil { + return "" + } + return *r.KeysURL +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetLabelsURL() string { + if r == nil || r.LabelsURL == nil { + return "" + } + return *r.LabelsURL +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (r *Repository) GetLanguage() string { + if r == nil || r.Language == nil { + return "" + } + return *r.Language +} + +// GetLanguagesURL returns the LanguagesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetLanguagesURL() string { + if r == nil || r.LanguagesURL == nil { + return "" + } + return *r.LanguagesURL +} + +// GetLicense returns the License field. +func (r *Repository) GetLicense() *License { + if r == nil { + return nil + } + return r.License +} + +// GetLicenseTemplate returns the LicenseTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetLicenseTemplate() string { + if r == nil || r.LicenseTemplate == nil { + return "" + } + return *r.LicenseTemplate +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetMasterBranch() string { + if r == nil || r.MasterBranch == nil { + return "" + } + return *r.MasterBranch +} + +// GetMergesURL returns the MergesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMergesURL() string { + if r == nil || r.MergesURL == nil { + return "" + } + return *r.MergesURL +} + +// GetMilestonesURL returns the MilestonesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMilestonesURL() string { + if r == nil || r.MilestonesURL == nil { + return "" + } + return *r.MilestonesURL +} + +// GetMirrorURL returns the MirrorURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMirrorURL() string { + if r == nil || r.MirrorURL == nil { + return "" + } + return *r.MirrorURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Repository) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNetworkCount returns the NetworkCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetNetworkCount() int { + if r == nil || r.NetworkCount == nil { + return 0 + } + return *r.NetworkCount +} + +// GetNotificationsURL returns the NotificationsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetNotificationsURL() string { + if r == nil || r.NotificationsURL == nil { + return "" + } + return *r.NotificationsURL +} + +// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetOpenIssuesCount() int { + if r == nil || r.OpenIssuesCount == nil { + return 0 + } + return *r.OpenIssuesCount +} + +// GetOrganization returns the Organization field. +func (r *Repository) GetOrganization() *Organization { + if r == nil { + return nil + } + return r.Organization +} + +// GetOwner returns the Owner field. +func (r *Repository) GetOwner() *User { + if r == nil { + return nil + } + return r.Owner +} + +// GetParent returns the Parent field. +func (r *Repository) GetParent() *Repository { + if r == nil { + return nil + } + return r.Parent +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (r *Repository) GetPermissions() map[string]bool { + if r == nil || r.Permissions == nil { + return map[string]bool{} + } + return *r.Permissions +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (r *Repository) GetPrivate() bool { + if r == nil || r.Private == nil { + return false + } + return *r.Private +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetPullsURL() string { + if r == nil || r.PullsURL == nil { + return "" + } + return *r.PullsURL +} + +// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetPushedAt() Timestamp { + if r == nil || r.PushedAt == nil { + return Timestamp{} + } + return *r.PushedAt +} + +// GetReleasesURL returns the ReleasesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetReleasesURL() string { + if r == nil || r.ReleasesURL == nil { + return "" + } + return *r.ReleasesURL +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *Repository) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetSource returns the Source field. +func (r *Repository) GetSource() *Repository { + if r == nil { + return nil + } + return r.Source +} + +// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSSHURL() string { + if r == nil || r.SSHURL == nil { + return "" + } + return *r.SSHURL +} + +// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetStargazersCount() int { + if r == nil || r.StargazersCount == nil { + return 0 + } + return *r.StargazersCount +} + +// GetStargazersURL returns the StargazersURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetStargazersURL() string { + if r == nil || r.StargazersURL == nil { + return "" + } + return *r.StargazersURL +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetStatusesURL() string { + if r == nil || r.StatusesURL == nil { + return "" + } + return *r.StatusesURL +} + +// GetSubscribersCount returns the SubscribersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscribersCount() int { + if r == nil || r.SubscribersCount == nil { + return 0 + } + return *r.SubscribersCount +} + +// GetSubscribersURL returns the SubscribersURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscribersURL() string { + if r == nil || r.SubscribersURL == nil { + return "" + } + return *r.SubscribersURL +} + +// GetSubscriptionURL returns the SubscriptionURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscriptionURL() string { + if r == nil || r.SubscriptionURL == nil { + return "" + } + return *r.SubscriptionURL +} + +// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSVNURL() string { + if r == nil || r.SVNURL == nil { + return "" + } + return *r.SVNURL +} + +// GetTagsURL returns the TagsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTagsURL() string { + if r == nil || r.TagsURL == nil { + return "" + } + return *r.TagsURL +} + +// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. +func (r *Repository) GetTeamID() int64 { + if r == nil || r.TeamID == nil { + return 0 + } + return *r.TeamID +} + +// GetTeamsURL returns the TeamsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTeamsURL() string { + if r == nil || r.TeamsURL == nil { + return "" + } + return *r.TeamsURL +} + +// GetTreesURL returns the TreesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTreesURL() string { + if r == nil || r.TreesURL == nil { + return "" + } + return *r.TreesURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Repository) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetWatchersCount() int { + if r == nil || r.WatchersCount == nil { + return 0 + } + return *r.WatchersCount +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetBody() string { + if r == nil || r.Body == nil { + return "" + } + return *r.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetCommitID() string { + if r == nil || r.CommitID == nil { + return "" + } + return *r.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetCreatedAt() time.Time { + if r == nil || r.CreatedAt == nil { + return time.Time{} + } + return *r.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetPosition() int { + if r == nil || r.Position == nil { + return 0 + } + return *r.Position +} + +// GetReactions returns the Reactions field. +func (r *RepositoryComment) GetReactions() *Reactions { + if r == nil { + return nil + } + return r.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetUpdatedAt() time.Time { + if r == nil || r.UpdatedAt == nil { + return time.Time{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetUser returns the User field. +func (r *RepositoryComment) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetAuthor returns the Author field. +func (r *RepositoryCommit) GetAuthor() *User { + if r == nil { + return nil + } + return r.Author +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetCommentsURL() string { + if r == nil || r.CommentsURL == nil { + return "" + } + return *r.CommentsURL +} + +// GetCommit returns the Commit field. +func (r *RepositoryCommit) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + +// GetCommitter returns the Committer field. +func (r *RepositoryCommit) GetCommitter() *User { + if r == nil { + return nil + } + return r.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetStats returns the Stats field. +func (r *RepositoryCommit) GetStats() *CommitStats { + if r == nil { + return nil + } + return r.Stats +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetEncoding() string { + if r == nil || r.Encoding == nil { + return "" + } + return *r.Encoding +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetAuthor returns the Author field. +func (r *RepositoryContentFileOptions) GetAuthor() *CommitAuthor { + if r == nil { + return nil + } + return r.Author +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetCommitter returns the Committer field. +func (r *RepositoryContentFileOptions) GetCommitter() *CommitAuthor { + if r == nil { + return nil + } + return r.Committer +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetContent returns the Content field. +func (r *RepositoryContentResponse) GetContent() *RepositoryContent { + if r == nil { + return nil + } + return r.Content +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetInstallation returns the Installation field. +func (r *RepositoryEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetInvitee returns the Invitee field. +func (r *RepositoryInvitation) GetInvitee() *User { + if r == nil { + return nil + } + return r.Invitee +} + +// GetInviter returns the Inviter field. +func (r *RepositoryInvitation) GetInviter() *User { + if r == nil { + return nil + } + return r.Inviter +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetPermissions() string { + if r == nil || r.Permissions == nil { + return "" + } + return *r.Permissions +} + +// GetRepo returns the Repo field. +func (r *RepositoryInvitation) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetContent() string { + if r == nil || r.Content == nil { + return "" + } + return *r.Content +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetEncoding() string { + if r == nil || r.Encoding == nil { + return "" + } + return *r.Encoding +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetLicense returns the License field. +func (r *RepositoryLicense) GetLicense() *License { + if r == nil { + return nil + } + return r.License +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetBase returns the Base field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetBase() string { + if r == nil || r.Base == nil { + return "" + } + return *r.Base +} + +// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetCommitMessage() string { + if r == nil || r.CommitMessage == nil { + return "" + } + return *r.CommitMessage +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetHead() string { + if r == nil || r.Head == nil { + return "" + } + return *r.Head +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (r *RepositoryPermissionLevel) GetPermission() string { + if r == nil || r.Permission == nil { + return "" + } + return *r.Permission +} + +// GetUser returns the User field. +func (r *RepositoryPermissionLevel) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetAssetsURL returns the AssetsURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetAssetsURL() string { + if r == nil || r.AssetsURL == nil { + return "" + } + return *r.AssetsURL +} + +// GetAuthor returns the Author field. +func (r *RepositoryRelease) GetAuthor() *User { + if r == nil { + return nil + } + return r.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetBody() string { + if r == nil || r.Body == nil { + return "" + } + return *r.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetDraft() bool { + if r == nil || r.Draft == nil { + return false + } + return *r.Draft +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetPrerelease() bool { + if r == nil || r.Prerelease == nil { + return false + } + return *r.Prerelease +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetPublishedAt() Timestamp { + if r == nil || r.PublishedAt == nil { + return Timestamp{} + } + return *r.PublishedAt +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTagName() string { + if r == nil || r.TagName == nil { + return "" + } + return *r.TagName +} + +// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTarballURL() string { + if r == nil || r.TarballURL == nil { + return "" + } + return *r.TarballURL +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTargetCommitish() string { + if r == nil || r.TargetCommitish == nil { + return "" + } + return *r.TargetCommitish +} + +// GetUploadURL returns the UploadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetUploadURL() string { + if r == nil || r.UploadURL == nil { + return "" + } + return *r.UploadURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetZipballURL() string { + if r == nil || r.ZipballURL == nil { + return "" + } + return *r.ZipballURL +} + +// GetCommit returns the Commit field. +func (r *RepositoryTag) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetTarballURL() string { + if r == nil || r.TarballURL == nil { + return "" + } + return *r.TarballURL +} + +// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetZipballURL() string { + if r == nil || r.ZipballURL == nil { + return "" + } + return *r.ZipballURL +} + +// GetForkRepos returns the ForkRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetForkRepos() int { + if r == nil || r.ForkRepos == nil { + return 0 + } + return *r.ForkRepos +} + +// GetOrgRepos returns the OrgRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetOrgRepos() int { + if r == nil || r.OrgRepos == nil { + return 0 + } + return *r.OrgRepos +} + +// GetRootRepos returns the RootRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetRootRepos() int { + if r == nil || r.RootRepos == nil { + return 0 + } + return *r.RootRepos +} + +// GetTotalPushes returns the TotalPushes field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalPushes() int { + if r == nil || r.TotalPushes == nil { + return 0 + } + return *r.TotalPushes +} + +// GetTotalRepos returns the TotalRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalRepos() int { + if r == nil || r.TotalRepos == nil { + return 0 + } + return *r.TotalRepos +} + +// GetTotalWikis returns the TotalWikis field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalWikis() int { + if r == nil || r.TotalWikis == nil { + return 0 + } + return *r.TotalWikis +} + +// GetContext returns the Context field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetContext() string { + if r == nil || r.Context == nil { + return "" + } + return *r.Context +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetCreatedAt() time.Time { + if r == nil || r.CreatedAt == nil { + return time.Time{} + } + return *r.CreatedAt +} + +// GetCreator returns the Creator field. +func (r *RepoStatus) GetCreator() *User { + if r == nil { + return nil + } + return r.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetTargetURL() string { + if r == nil || r.TargetURL == nil { + return "" + } + return *r.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetUpdatedAt() time.Time { + if r == nil || r.UpdatedAt == nil { + return time.Time{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *ServiceHook) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetPayload returns the Payload field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetPayload() string { + if s == nil || s.Payload == nil { + return "" + } + return *s.Payload +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetReason() string { + if s == nil || s.Reason == nil { + return "" + } + return *s.Reason +} + +// GetSignature returns the Signature field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetSignature() string { + if s == nil || s.Signature == nil { + return "" + } + return *s.Signature +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetVerified() bool { + if s == nil || s.Verified == nil { + return false + } + return *s.Verified +} + +// GetActor returns the Actor field. +func (s *Source) GetActor() *User { + if s == nil { + return nil + } + return s.Actor +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *Source) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *Source) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetEmail() string { + if s == nil || s.Email == nil { + return "" + } + return *s.Email +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetImportURL returns the ImportURL field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetImportURL() string { + if s == nil || s.ImportURL == nil { + return "" + } + return *s.ImportURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetRemoteID returns the RemoteID field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetRemoteID() string { + if s == nil || s.RemoteID == nil { + return "" + } + return *s.RemoteID +} + +// GetRemoteName returns the RemoteName field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetRemoteName() string { + if s == nil || s.RemoteName == nil { + return "" + } + return *s.RemoteName +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *Stargazer) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetUser returns the User field. +func (s *Stargazer) GetUser() *User { + if s == nil { + return nil + } + return s.User +} + +// GetRepository returns the Repository field. +func (s *StarredRepository) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *StarredRepository) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetCommit returns the Commit field. +func (s *StatusEvent) GetCommit() *RepositoryCommit { + if s == nil { + return nil + } + return s.Commit +} + +// GetContext returns the Context field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetContext() string { + if s == nil || s.Context == nil { + return "" + } + return *s.Context +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetDescription() string { + if s == nil || s.Description == nil { + return "" + } + return *s.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetInstallation returns the Installation field. +func (s *StatusEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetRepo returns the Repo field. +func (s *StatusEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *StatusEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetSHA() string { + if s == nil || s.SHA == nil { + return "" + } + return *s.SHA +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetTargetURL() string { + if s == nil || s.TargetURL == nil { + return "" + } + return *s.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *Subscription) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetIgnored returns the Ignored field if it's non-nil, zero value otherwise. +func (s *Subscription) GetIgnored() bool { + if s == nil || s.Ignored == nil { + return false + } + return *s.Ignored +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (s *Subscription) GetReason() string { + if s == nil || s.Reason == nil { + return "" + } + return *s.Reason +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetRepositoryURL() string { + if s == nil || s.RepositoryURL == nil { + return "" + } + return *s.RepositoryURL +} + +// GetSubscribed returns the Subscribed field if it's non-nil, zero value otherwise. +func (s *Subscription) GetSubscribed() bool { + if s == nil || s.Subscribed == nil { + return false + } + return *s.Subscribed +} + +// GetThreadURL returns the ThreadURL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetThreadURL() string { + if s == nil || s.ThreadURL == nil { + return "" + } + return *s.ThreadURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (t *Tag) GetMessage() string { + if t == nil || t.Message == nil { + return "" + } + return *t.Message +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *Tag) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetObject returns the Object field. +func (t *Tag) GetObject() *GitObject { + if t == nil { + return nil + } + return t.Object +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Tag) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetTag returns the Tag field if it's non-nil, zero value otherwise. +func (t *Tag) GetTag() string { + if t == nil || t.Tag == nil { + return "" + } + return *t.Tag +} + +// GetTagger returns the Tagger field. +func (t *Tag) GetTagger() *CommitAuthor { + if t == nil { + return nil + } + return t.Tagger +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Tag) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetVerification returns the Verification field. +func (t *Tag) GetVerification() *SignatureVerification { + if t == nil { + return nil + } + return t.Verification +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *Team) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *Team) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (t *Team) GetLDAPDN() string { + if t == nil || t.LDAPDN == nil { + return "" + } + return *t.LDAPDN +} + +// GetMembersCount returns the MembersCount field if it's non-nil, zero value otherwise. +func (t *Team) GetMembersCount() int { + if t == nil || t.MembersCount == nil { + return 0 + } + return *t.MembersCount +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (t *Team) GetMembersURL() string { + if t == nil || t.MembersURL == nil { + return "" + } + return *t.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *Team) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetOrganization returns the Organization field. +func (t *Team) GetOrganization() *Organization { + if t == nil { + return nil + } + return t.Organization +} + +// GetParent returns the Parent field. +func (t *Team) GetParent() *Team { + if t == nil { + return nil + } + return t.Parent +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *Team) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (t *Team) GetPrivacy() string { + if t == nil || t.Privacy == nil { + return "" + } + return *t.Privacy +} + +// GetReposCount returns the ReposCount field if it's non-nil, zero value otherwise. +func (t *Team) GetReposCount() int { + if t == nil || t.ReposCount == nil { + return 0 + } + return *t.ReposCount +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (t *Team) GetRepositoriesURL() string { + if t == nil || t.RepositoriesURL == nil { + return "" + } + return *t.RepositoriesURL +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (t *Team) GetSlug() string { + if t == nil || t.Slug == nil { + return "" + } + return *t.Slug +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Team) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetInstallation returns the Installation field. +func (t *TeamAddEvent) GetInstallation() *Installation { + if t == nil { + return nil + } + return t.Installation +} + +// GetOrg returns the Org field. +func (t *TeamAddEvent) GetOrg() *Organization { + if t == nil { + return nil + } + return t.Org +} + +// GetRepo returns the Repo field. +func (t *TeamAddEvent) GetRepo() *Repository { + if t == nil { + return nil + } + return t.Repo +} + +// GetSender returns the Sender field. +func (t *TeamAddEvent) GetSender() *User { + if t == nil { + return nil + } + return t.Sender +} + +// GetTeam returns the Team field. +func (t *TeamAddEvent) GetTeam() *Team { + if t == nil { + return nil + } + return t.Team +} + +// GetAuthor returns the Author field. +func (t *TeamDiscussion) GetAuthor() *User { + if t == nil { + return nil + } + return t.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBody() string { + if t == nil || t.Body == nil { + return "" + } + return *t.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBodyHTML() string { + if t == nil || t.BodyHTML == nil { + return "" + } + return *t.BodyHTML +} + +// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBodyVersion() string { + if t == nil || t.BodyVersion == nil { + return "" + } + return *t.BodyVersion +} + +// GetCommentsCount returns the CommentsCount field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCommentsCount() int64 { + if t == nil || t.CommentsCount == nil { + return 0 + } + return *t.CommentsCount +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCommentsURL() string { + if t == nil || t.CommentsURL == nil { + return "" + } + return *t.CommentsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetHTMLURL() string { + if t == nil || t.HTMLURL == nil { + return "" + } + return *t.HTMLURL +} + +// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetLastEditedAt() Timestamp { + if t == nil || t.LastEditedAt == nil { + return Timestamp{} + } + return *t.LastEditedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetNumber() int64 { + if t == nil || t.Number == nil { + return 0 + } + return *t.Number +} + +// GetPinned returns the Pinned field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetPinned() bool { + if t == nil || t.Pinned == nil { + return false + } + return *t.Pinned +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetPrivate() bool { + if t == nil || t.Private == nil { + return false + } + return *t.Private +} + +// GetTeamURL returns the TeamURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetTeamURL() string { + if t == nil || t.TeamURL == nil { + return "" + } + return *t.TeamURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetTitle() string { + if t == nil || t.Title == nil { + return "" + } + return *t.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetUpdatedAt() Timestamp { + if t == nil || t.UpdatedAt == nil { + return Timestamp{} + } + return *t.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (t *TeamEvent) GetAction() string { + if t == nil || t.Action == nil { + return "" + } + return *t.Action +} + +// GetChanges returns the Changes field. +func (t *TeamEvent) GetChanges() *TeamChange { + if t == nil { + return nil + } + return t.Changes +} + +// GetInstallation returns the Installation field. +func (t *TeamEvent) GetInstallation() *Installation { + if t == nil { + return nil + } + return t.Installation +} + +// GetOrg returns the Org field. +func (t *TeamEvent) GetOrg() *Organization { + if t == nil { + return nil + } + return t.Org +} + +// GetRepo returns the Repo field. +func (t *TeamEvent) GetRepo() *Repository { + if t == nil { + return nil + } + return t.Repo +} + +// GetSender returns the Sender field. +func (t *TeamEvent) GetSender() *User { + if t == nil { + return nil + } + return t.Sender +} + +// GetTeam returns the Team field. +func (t *TeamEvent) GetTeam() *Team { + if t == nil { + return nil + } + return t.Team +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetLDAPDN() string { + if t == nil || t.LDAPDN == nil { + return "" + } + return *t.LDAPDN +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetMembersURL() string { + if t == nil || t.MembersURL == nil { + return "" + } + return *t.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetPrivacy() string { + if t == nil || t.Privacy == nil { + return "" + } + return *t.Privacy +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetRepositoriesURL() string { + if t == nil || t.RepositoriesURL == nil { + return "" + } + return *t.RepositoriesURL +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetSlug() string { + if t == nil || t.Slug == nil { + return "" + } + return *t.Slug +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetFragment returns the Fragment field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetFragment() string { + if t == nil || t.Fragment == nil { + return "" + } + return *t.Fragment +} + +// GetObjectType returns the ObjectType field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetObjectType() string { + if t == nil || t.ObjectType == nil { + return "" + } + return *t.ObjectType +} + +// GetObjectURL returns the ObjectURL field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetObjectURL() string { + if t == nil || t.ObjectURL == nil { + return "" + } + return *t.ObjectURL +} + +// GetProperty returns the Property field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetProperty() string { + if t == nil || t.Property == nil { + return "" + } + return *t.Property +} + +// GetActor returns the Actor field. +func (t *Timeline) GetActor() *User { + if t == nil { + return nil + } + return t.Actor +} + +// GetAssignee returns the Assignee field. +func (t *Timeline) GetAssignee() *User { + if t == nil { + return nil + } + return t.Assignee +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCommitID() string { + if t == nil || t.CommitID == nil { + return "" + } + return *t.CommitID +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCommitURL() string { + if t == nil || t.CommitURL == nil { + return "" + } + return *t.CommitURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCreatedAt() time.Time { + if t == nil || t.CreatedAt == nil { + return time.Time{} + } + return *t.CreatedAt +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (t *Timeline) GetEvent() string { + if t == nil || t.Event == nil { + return "" + } + return *t.Event +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *Timeline) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLabel returns the Label field. +func (t *Timeline) GetLabel() *Label { + if t == nil { + return nil + } + return t.Label +} + +// GetMilestone returns the Milestone field. +func (t *Timeline) GetMilestone() *Milestone { + if t == nil { + return nil + } + return t.Milestone +} + +// GetRename returns the Rename field. +func (t *Timeline) GetRename() *Rename { + if t == nil { + return nil + } + return t.Rename +} + +// GetSource returns the Source field. +func (t *Timeline) GetSource() *Source { + if t == nil { + return nil + } + return t.Source +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Timeline) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficClones) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficClones) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetTimestamp() Timestamp { + if t == nil || t.Timestamp == nil { + return Timestamp{} + } + return *t.Timestamp +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetPath() string { + if t == nil || t.Path == nil { + return "" + } + return *t.Path +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetTitle() string { + if t == nil || t.Title == nil { + return "" + } + return *t.Title +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetReferrer returns the Referrer field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetReferrer() string { + if t == nil || t.Referrer == nil { + return "" + } + return *t.Referrer +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficViews) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficViews) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Tree) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetContent() string { + if t == nil || t.Content == nil { + return "" + } + return *t.Content +} + +// GetMode returns the Mode field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetMode() string { + if t == nil || t.Mode == nil { + return "" + } + return *t.Mode +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetPath() string { + if t == nil || t.Path == nil { + return "" + } + return *t.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetSize() int { + if t == nil || t.Size == nil { + return 0 + } + return *t.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetType() string { + if t == nil || t.Type == nil { + return "" + } + return *t.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (u *User) GetAvatarURL() string { + if u == nil || u.AvatarURL == nil { + return "" + } + return *u.AvatarURL +} + +// GetBio returns the Bio field if it's non-nil, zero value otherwise. +func (u *User) GetBio() string { + if u == nil || u.Bio == nil { + return "" + } + return *u.Bio +} + +// GetBlog returns the Blog field if it's non-nil, zero value otherwise. +func (u *User) GetBlog() string { + if u == nil || u.Blog == nil { + return "" + } + return *u.Blog +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (u *User) GetCollaborators() int { + if u == nil || u.Collaborators == nil { + return 0 + } + return *u.Collaborators +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (u *User) GetCompany() string { + if u == nil || u.Company == nil { + return "" + } + return *u.Company +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *User) GetCreatedAt() Timestamp { + if u == nil || u.CreatedAt == nil { + return Timestamp{} + } + return *u.CreatedAt +} + +// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. +func (u *User) GetDiskUsage() int { + if u == nil || u.DiskUsage == nil { + return 0 + } + return *u.DiskUsage +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (u *User) GetEmail() string { + if u == nil || u.Email == nil { + return "" + } + return *u.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (u *User) GetEventsURL() string { + if u == nil || u.EventsURL == nil { + return "" + } + return *u.EventsURL +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (u *User) GetFollowers() int { + if u == nil || u.Followers == nil { + return 0 + } + return *u.Followers +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (u *User) GetFollowersURL() string { + if u == nil || u.FollowersURL == nil { + return "" + } + return *u.FollowersURL +} + +// GetFollowing returns the Following field if it's non-nil, zero value otherwise. +func (u *User) GetFollowing() int { + if u == nil || u.Following == nil { + return 0 + } + return *u.Following +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (u *User) GetFollowingURL() string { + if u == nil || u.FollowingURL == nil { + return "" + } + return *u.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (u *User) GetGistsURL() string { + if u == nil || u.GistsURL == nil { + return "" + } + return *u.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (u *User) GetGravatarID() string { + if u == nil || u.GravatarID == nil { + return "" + } + return *u.GravatarID +} + +// GetHireable returns the Hireable field if it's non-nil, zero value otherwise. +func (u *User) GetHireable() bool { + if u == nil || u.Hireable == nil { + return false + } + return *u.Hireable +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (u *User) GetHTMLURL() string { + if u == nil || u.HTMLURL == nil { + return "" + } + return *u.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *User) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (u *User) GetLocation() string { + if u == nil || u.Location == nil { + return "" + } + return *u.Location +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (u *User) GetLogin() string { + if u == nil || u.Login == nil { + return "" + } + return *u.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *User) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (u *User) GetOrganizationsURL() string { + if u == nil || u.OrganizationsURL == nil { + return "" + } + return *u.OrganizationsURL +} + +// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. +func (u *User) GetOwnedPrivateRepos() int { + if u == nil || u.OwnedPrivateRepos == nil { + return 0 + } + return *u.OwnedPrivateRepos +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (u *User) GetPermissions() map[string]bool { + if u == nil || u.Permissions == nil { + return map[string]bool{} + } + return *u.Permissions +} + +// GetPlan returns the Plan field. +func (u *User) GetPlan() *Plan { + if u == nil { + return nil + } + return u.Plan +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (u *User) GetPrivateGists() int { + if u == nil || u.PrivateGists == nil { + return 0 + } + return *u.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (u *User) GetPublicGists() int { + if u == nil || u.PublicGists == nil { + return 0 + } + return *u.PublicGists +} + +// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. +func (u *User) GetPublicRepos() int { + if u == nil || u.PublicRepos == nil { + return 0 + } + return *u.PublicRepos +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (u *User) GetReceivedEventsURL() string { + if u == nil || u.ReceivedEventsURL == nil { + return "" + } + return *u.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (u *User) GetReposURL() string { + if u == nil || u.ReposURL == nil { + return "" + } + return *u.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (u *User) GetSiteAdmin() bool { + if u == nil || u.SiteAdmin == nil { + return false + } + return *u.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (u *User) GetStarredURL() string { + if u == nil || u.StarredURL == nil { + return "" + } + return *u.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (u *User) GetSubscriptionsURL() string { + if u == nil || u.SubscriptionsURL == nil { + return "" + } + return *u.SubscriptionsURL +} + +// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. +func (u *User) GetSuspendedAt() Timestamp { + if u == nil || u.SuspendedAt == nil { + return Timestamp{} + } + return *u.SuspendedAt +} + +// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. +func (u *User) GetTotalPrivateRepos() int { + if u == nil || u.TotalPrivateRepos == nil { + return 0 + } + return *u.TotalPrivateRepos +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *User) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *User) GetUpdatedAt() Timestamp { + if u == nil || u.UpdatedAt == nil { + return Timestamp{} + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *User) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetEmail() string { + if u == nil || u.Email == nil { + return "" + } + return *u.Email +} + +// GetPrimary returns the Primary field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetPrimary() bool { + if u == nil || u.Primary == nil { + return false + } + return *u.Primary +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetVerified() bool { + if u == nil || u.Verified == nil { + return false + } + return *u.Verified +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetAvatarURL() string { + if u == nil || u.AvatarURL == nil { + return "" + } + return *u.AvatarURL +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetEventsURL() string { + if u == nil || u.EventsURL == nil { + return "" + } + return *u.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetFollowersURL() string { + if u == nil || u.FollowersURL == nil { + return "" + } + return *u.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetFollowingURL() string { + if u == nil || u.FollowingURL == nil { + return "" + } + return *u.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetGistsURL() string { + if u == nil || u.GistsURL == nil { + return "" + } + return *u.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetGravatarID() string { + if u == nil || u.GravatarID == nil { + return "" + } + return *u.GravatarID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetLDAPDN() string { + if u == nil || u.LDAPDN == nil { + return "" + } + return *u.LDAPDN +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetLogin() string { + if u == nil || u.Login == nil { + return "" + } + return *u.Login +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetOrganizationsURL() string { + if u == nil || u.OrganizationsURL == nil { + return "" + } + return *u.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetReceivedEventsURL() string { + if u == nil || u.ReceivedEventsURL == nil { + return "" + } + return *u.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetReposURL() string { + if u == nil || u.ReposURL == nil { + return "" + } + return *u.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetSiteAdmin() bool { + if u == nil || u.SiteAdmin == nil { + return false + } + return *u.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetStarredURL() string { + if u == nil || u.StarredURL == nil { + return "" + } + return *u.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetSubscriptionsURL() string { + if u == nil || u.SubscriptionsURL == nil { + return "" + } + return *u.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (u *UsersSearchResult) GetIncompleteResults() bool { + if u == nil || u.IncompleteResults == nil { + return false + } + return *u.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (u *UsersSearchResult) GetTotal() int { + if u == nil || u.Total == nil { + return 0 + } + return *u.Total +} + +// GetAdminUsers returns the AdminUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetAdminUsers() int { + if u == nil || u.AdminUsers == nil { + return 0 + } + return *u.AdminUsers +} + +// GetSuspendedUsers returns the SuspendedUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetSuspendedUsers() int { + if u == nil || u.SuspendedUsers == nil { + return 0 + } + return *u.SuspendedUsers +} + +// GetTotalUsers returns the TotalUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetTotalUsers() int { + if u == nil || u.TotalUsers == nil { + return 0 + } + return *u.TotalUsers +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WatchEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetInstallation returns the Installation field. +func (w *WatchEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetRepo returns the Repo field. +func (w *WatchEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WatchEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (w *WebHookAuthor) GetEmail() string { + if w == nil || w.Email == nil { + return "" + } + return *w.Email +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WebHookAuthor) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetUsername returns the Username field if it's non-nil, zero value otherwise. +func (w *WebHookAuthor) GetUsername() string { + if w == nil || w.Username == nil { + return "" + } + return *w.Username +} + +// GetAuthor returns the Author field. +func (w *WebHookCommit) GetAuthor() *WebHookAuthor { + if w == nil { + return nil + } + return w.Author +} + +// GetCommitter returns the Committer field. +func (w *WebHookCommit) GetCommitter() *WebHookAuthor { + if w == nil { + return nil + } + return w.Committer +} + +// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. +func (w *WebHookCommit) GetDistinct() bool { + if w == nil || w.Distinct == nil { + return false + } + return *w.Distinct +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WebHookCommit) GetID() string { + if w == nil || w.ID == nil { + return "" + } + return *w.ID +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (w *WebHookCommit) GetMessage() string { + if w == nil || w.Message == nil { + return "" + } + return *w.Message +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (w *WebHookCommit) GetTimestamp() time.Time { + if w == nil || w.Timestamp == nil { + return time.Time{} + } + return *w.Timestamp +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (w *WebHookPayload) GetAfter() string { + if w == nil || w.After == nil { + return "" + } + return *w.After +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (w *WebHookPayload) GetBefore() string { + if w == nil || w.Before == nil { + return "" + } + return *w.Before +} + +// GetCompare returns the Compare field if it's non-nil, zero value otherwise. +func (w *WebHookPayload) GetCompare() string { + if w == nil || w.Compare == nil { + return "" + } + return *w.Compare +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (w *WebHookPayload) GetCreated() bool { + if w == nil || w.Created == nil { + return false + } + return *w.Created +} + +// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. +func (w *WebHookPayload) GetDeleted() bool { + if w == nil || w.Deleted == nil { + return false + } + return *w.Deleted +} + +// GetForced returns the Forced field if it's non-nil, zero value otherwise. +func (w *WebHookPayload) GetForced() bool { + if w == nil || w.Forced == nil { + return false + } + return *w.Forced +} + +// GetHeadCommit returns the HeadCommit field. +func (w *WebHookPayload) GetHeadCommit() *WebHookCommit { + if w == nil { + return nil + } + return w.HeadCommit +} + +// GetPusher returns the Pusher field. +func (w *WebHookPayload) GetPusher() *User { + if w == nil { + return nil + } + return w.Pusher +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (w *WebHookPayload) GetRef() string { + if w == nil || w.Ref == nil { + return "" + } + return *w.Ref +} + +// GetRepo returns the Repo field. +func (w *WebHookPayload) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WebHookPayload) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (w *WeeklyCommitActivity) GetTotal() int { + if w == nil || w.Total == nil { + return 0 + } + return *w.Total +} + +// GetWeek returns the Week field if it's non-nil, zero value otherwise. +func (w *WeeklyCommitActivity) GetWeek() Timestamp { + if w == nil || w.Week == nil { + return Timestamp{} + } + return *w.Week +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetAdditions() int { + if w == nil || w.Additions == nil { + return 0 + } + return *w.Additions +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetCommits() int { + if w == nil || w.Commits == nil { + return 0 + } + return *w.Commits +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetDeletions() int { + if w == nil || w.Deletions == nil { + return 0 + } + return *w.Deletions +} + +// GetWeek returns the Week field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetWeek() Timestamp { + if w == nil || w.Week == nil { + return Timestamp{} + } + return *w.Week +} diff --git a/vendor/github.com/google/go-github/github/github.go b/vendor/github.com/google/go-github/github/github.go new file mode 100644 index 00000000..a0c78aae --- /dev/null +++ b/vendor/github.com/google/go-github/github/github.go @@ -0,0 +1,989 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen-accessors.go + +package github + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/google/go-querystring/query" +) + +const ( + defaultBaseURL = "https://api.github.com/" + uploadBaseURL = "https://uploads.github.com/" + userAgent = "go-github" + + headerRateLimit = "X-RateLimit-Limit" + headerRateRemaining = "X-RateLimit-Remaining" + headerRateReset = "X-RateLimit-Reset" + headerOTP = "X-GitHub-OTP" + + mediaTypeV3 = "application/vnd.github.v3+json" + defaultMediaType = "application/octet-stream" + mediaTypeV3SHA = "application/vnd.github.v3.sha" + mediaTypeV3Diff = "application/vnd.github.v3.diff" + mediaTypeV3Patch = "application/vnd.github.v3.patch" + mediaTypeOrgPermissionRepo = "application/vnd.github.v3.repository+json" + + // Media Type values to access preview APIs + + // https://developer.github.com/changes/2015-03-09-licenses-api/ + mediaTypeLicensesPreview = "application/vnd.github.drax-preview+json" + + // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/ + mediaTypeStarringPreview = "application/vnd.github.v3.star+json" + + // https://developer.github.com/changes/2015-11-11-protected-branches-api/ + mediaTypeProtectedBranchesPreview = "application/vnd.github.loki-preview+json" + + // https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-github-com-organization-s-repositories/ + mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json" + + // https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/ + mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json" + + // https://developer.github.com/changes/2016-02-19-source-import-preview-api/ + mediaTypeImportPreview = "application/vnd.github.barred-rock-preview" + + // https://developer.github.com/changes/2016-05-12-reactions-api-preview/ + mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview" + + // https://developer.github.com/changes/2016-04-04-git-signing-api-preview/ + mediaTypeGitSigningPreview = "application/vnd.github.cryptographer-preview+json" + + // https://developer.github.com/changes/2016-05-23-timeline-preview-api/ + mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json" + + // https://developer.github.com/changes/2016-06-14-repository-invitations/ + mediaTypeRepositoryInvitationsPreview = "application/vnd.github.swamp-thing-preview+json" + + // https://developer.github.com/changes/2016-07-06-github-pages-preiew-api/ + mediaTypePagesPreview = "application/vnd.github.mister-fantastic-preview+json" + + // https://developer.github.com/changes/2016-09-14-projects-api/ + mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json" + + // https://developer.github.com/changes/2016-09-14-Integrations-Early-Access/ + mediaTypeIntegrationPreview = "application/vnd.github.machine-man-preview+json" + + // https://developer.github.com/changes/2017-01-05-commit-search-api/ + mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json" + + // https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/ + mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json" + + // https://developer.github.com/changes/2017-02-09-community-health/ + mediaTypeRepositoryCommunityHealthMetricsPreview = "application/vnd.github.black-panther-preview+json" + + // https://developer.github.com/changes/2017-05-23-coc-api/ + mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json" + + // https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/ + mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json" + + // https://developer.github.com/v3/apps/marketplace/ + mediaTypeMarketplacePreview = "application/vnd.github.valkyrie-preview+json" + + // https://developer.github.com/changes/2017-08-30-preview-nested-teams/ + mediaTypeNestedTeamsPreview = "application/vnd.github.hellcat-preview+json" + + // https://developer.github.com/changes/2017-11-09-repository-transfer-api-preview/ + mediaTypeRepositoryTransferPreview = "application/vnd.github.nightshade-preview+json" + + // https://developer.github.com/changes/2017-12-19-graphql-node-id/ + mediaTypeGraphQLNodeIDPreview = "application/vnd.github.jean-grey-preview+json" + + // https://developer.github.com/changes/2018-01-25-organization-invitation-api-preview/ + mediaTypeOrganizationInvitationPreview = "application/vnd.github.dazzler-preview+json" + + // https://developer.github.com/changes/2018-02-22-label-description-search-preview/ + mediaTypeLabelDescriptionSearchPreview = "application/vnd.github.symmetra-preview+json" + + // https://developer.github.com/changes/2018-02-07-team-discussions-api/ + mediaTypeTeamDiscussionsPreview = "application/vnd.github.echo-preview+json" +) + +// A Client manages communication with the GitHub API. +type Client struct { + clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func. + client *http.Client // HTTP client used to communicate with the API. + + // Base URL for API requests. Defaults to the public GitHub API, but can be + // set to a domain endpoint to use with GitHub Enterprise. BaseURL should + // always be specified with a trailing slash. + BaseURL *url.URL + + // Base URL for uploading files. + UploadURL *url.URL + + // User agent used when communicating with the GitHub API. + UserAgent string + + rateMu sync.Mutex + rateLimits [categories]Rate // Rate limits for the client as determined by the most recent API calls. + + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // Services used for talking to different parts of the GitHub API. + Activity *ActivityService + Admin *AdminService + Apps *AppsService + Authorizations *AuthorizationsService + Gists *GistsService + Git *GitService + Gitignores *GitignoresService + Issues *IssuesService + Licenses *LicensesService + Marketplace *MarketplaceService + Migrations *MigrationService + Organizations *OrganizationsService + Projects *ProjectsService + PullRequests *PullRequestsService + Reactions *ReactionsService + Repositories *RepositoriesService + Search *SearchService + Teams *TeamsService + Users *UsersService +} + +type service struct { + client *Client +} + +// ListOptions specifies the optional parameters to various List methods that +// support pagination. +type ListOptions struct { + // For paginated result sets, page of results to retrieve. + Page int `url:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty"` +} + +// UploadOptions specifies the parameters to methods that support uploads. +type UploadOptions struct { + Name string `url:"name,omitempty"` +} + +// RawType represents type of raw format of a request instead of JSON. +type RawType uint8 + +const ( + // Diff format. + Diff RawType = 1 + iota + // Patch format. + Patch +) + +// RawOptions specifies parameters when user wants to get raw format of +// a response instead of JSON. +type RawOptions struct { + Type RawType +} + +// addOptions adds the parameters in opt as URL query parameters to s. opt +// must be a struct whose fields may contain "url" tags. +func addOptions(s string, opt interface{}) (string, error) { + v := reflect.ValueOf(opt) + if v.Kind() == reflect.Ptr && v.IsNil() { + return s, nil + } + + u, err := url.Parse(s) + if err != nil { + return s, err + } + + qs, err := query.Values(opt) + if err != nil { + return s, err + } + + u.RawQuery = qs.Encode() + return u.String(), nil +} + +// NewClient returns a new GitHub API client. If a nil httpClient is +// provided, http.DefaultClient will be used. To use API methods which require +// authentication, provide an http.Client that will perform the authentication +// for you (such as that provided by the golang.org/x/oauth2 library). +func NewClient(httpClient *http.Client) *Client { + if httpClient == nil { + httpClient = http.DefaultClient + } + baseURL, _ := url.Parse(defaultBaseURL) + uploadURL, _ := url.Parse(uploadBaseURL) + + c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, UploadURL: uploadURL} + c.common.client = c + c.Activity = (*ActivityService)(&c.common) + c.Admin = (*AdminService)(&c.common) + c.Apps = (*AppsService)(&c.common) + c.Authorizations = (*AuthorizationsService)(&c.common) + c.Gists = (*GistsService)(&c.common) + c.Git = (*GitService)(&c.common) + c.Gitignores = (*GitignoresService)(&c.common) + c.Issues = (*IssuesService)(&c.common) + c.Licenses = (*LicensesService)(&c.common) + c.Marketplace = &MarketplaceService{client: c} + c.Migrations = (*MigrationService)(&c.common) + c.Organizations = (*OrganizationsService)(&c.common) + c.Projects = (*ProjectsService)(&c.common) + c.PullRequests = (*PullRequestsService)(&c.common) + c.Reactions = (*ReactionsService)(&c.common) + c.Repositories = (*RepositoriesService)(&c.common) + c.Search = (*SearchService)(&c.common) + c.Teams = (*TeamsService)(&c.common) + c.Users = (*UsersService)(&c.common) + return c +} + +// NewEnterpriseClient returns a new GitHub API client with provided +// base URL and upload URL (often the same URL). +// If either URL does not have a trailing slash, one is added automatically. +// If a nil httpClient is provided, http.DefaultClient will be used. +// +// Note that NewEnterpriseClient is a convenience helper only; +// its behavior is equivalent to using NewClient, followed by setting +// the BaseURL and UploadURL fields. +func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) { + baseEndpoint, err := url.Parse(baseURL) + if err != nil { + return nil, err + } + if !strings.HasSuffix(baseEndpoint.Path, "/") { + baseEndpoint.Path += "/" + } + + uploadEndpoint, err := url.Parse(uploadURL) + if err != nil { + return nil, err + } + if !strings.HasSuffix(uploadEndpoint.Path, "/") { + uploadEndpoint.Path += "/" + } + + c := NewClient(httpClient) + c.BaseURL = baseEndpoint + c.UploadURL = uploadEndpoint + return c, nil +} + +// NewRequest creates an API request. A relative URL can be provided in urlStr, +// in which case it is resolved relative to the BaseURL of the Client. +// Relative URLs should always be specified without a preceding slash. If +// specified, the value pointed to by body is JSON encoded and included as the +// request body. +func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) { + if !strings.HasSuffix(c.BaseURL.Path, "/") { + return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) + } + u, err := c.BaseURL.Parse(urlStr) + if err != nil { + return nil, err + } + + var buf io.ReadWriter + if body != nil { + buf = new(bytes.Buffer) + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + err := enc.Encode(body) + if err != nil { + return nil, err + } + } + + req, err := http.NewRequest(method, u.String(), buf) + if err != nil { + return nil, err + } + + if body != nil { + req.Header.Set("Content-Type", "application/json") + } + req.Header.Set("Accept", mediaTypeV3) + if c.UserAgent != "" { + req.Header.Set("User-Agent", c.UserAgent) + } + return req, nil +} + +// NewUploadRequest creates an upload request. A relative URL can be provided in +// urlStr, in which case it is resolved relative to the UploadURL of the Client. +// Relative URLs should always be specified without a preceding slash. +func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string) (*http.Request, error) { + if !strings.HasSuffix(c.UploadURL.Path, "/") { + return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", c.UploadURL) + } + u, err := c.UploadURL.Parse(urlStr) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", u.String(), reader) + if err != nil { + return nil, err + } + req.ContentLength = size + + if mediaType == "" { + mediaType = defaultMediaType + } + req.Header.Set("Content-Type", mediaType) + req.Header.Set("Accept", mediaTypeV3) + req.Header.Set("User-Agent", c.UserAgent) + return req, nil +} + +// Response is a GitHub API response. This wraps the standard http.Response +// returned from GitHub and provides convenient access to things like +// pagination links. +type Response struct { + *http.Response + + // These fields provide the page values for paginating through a set of + // results. Any or all of these may be set to the zero value for + // responses that are not part of a paginated set, or for which there + // are no additional pages. + + NextPage int + PrevPage int + FirstPage int + LastPage int + + Rate +} + +// newResponse creates a new Response for the provided http.Response. +// r must not be nil. +func newResponse(r *http.Response) *Response { + response := &Response{Response: r} + response.populatePageValues() + response.Rate = parseRate(r) + return response +} + +// populatePageValues parses the HTTP Link response headers and populates the +// various pagination link values in the Response. +func (r *Response) populatePageValues() { + if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 { + for _, link := range strings.Split(links[0], ",") { + segments := strings.Split(strings.TrimSpace(link), ";") + + // link must at least have href and rel + if len(segments) < 2 { + continue + } + + // ensure href is properly formatted + if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") { + continue + } + + // try to pull out page parameter + url, err := url.Parse(segments[0][1 : len(segments[0])-1]) + if err != nil { + continue + } + page := url.Query().Get("page") + if page == "" { + continue + } + + for _, segment := range segments[1:] { + switch strings.TrimSpace(segment) { + case `rel="next"`: + r.NextPage, _ = strconv.Atoi(page) + case `rel="prev"`: + r.PrevPage, _ = strconv.Atoi(page) + case `rel="first"`: + r.FirstPage, _ = strconv.Atoi(page) + case `rel="last"`: + r.LastPage, _ = strconv.Atoi(page) + } + + } + } + } +} + +// parseRate parses the rate related headers. +func parseRate(r *http.Response) Rate { + var rate Rate + if limit := r.Header.Get(headerRateLimit); limit != "" { + rate.Limit, _ = strconv.Atoi(limit) + } + if remaining := r.Header.Get(headerRateRemaining); remaining != "" { + rate.Remaining, _ = strconv.Atoi(remaining) + } + if reset := r.Header.Get(headerRateReset); reset != "" { + if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { + rate.Reset = Timestamp{time.Unix(v, 0)} + } + } + return rate +} + +// Do sends an API request and returns the API response. The API response is +// JSON decoded and stored in the value pointed to by v, or returned as an +// error if an API error has occurred. If v implements the io.Writer +// interface, the raw response body will be written to v, without attempting to +// first decode it. If rate limit is exceeded and reset time is in the future, +// Do returns *RateLimitError immediately without making a network API call. +// +// The provided ctx must be non-nil. If it is canceled or times out, +// ctx.Err() will be returned. +func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) { + req = withContext(ctx, req) + + rateLimitCategory := category(req.URL.Path) + + // If we've hit rate limit, don't make further requests before Reset time. + if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { + return &Response{ + Response: err.Response, + Rate: err.Rate, + }, err + } + + resp, err := c.client.Do(req) + if err != nil { + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + + // If the error type is *url.Error, sanitize its URL before returning. + if e, ok := err.(*url.Error); ok { + if url, err := url.Parse(e.URL); err == nil { + e.URL = sanitizeURL(url).String() + return nil, e + } + } + + return nil, err + } + defer resp.Body.Close() + + response := newResponse(resp) + + c.rateMu.Lock() + c.rateLimits[rateLimitCategory] = response.Rate + c.rateMu.Unlock() + + err = CheckResponse(resp) + if err != nil { + // Even though there was an error, we still return the response + // in case the caller wants to inspect it further. + // However, if the error is AcceptedError, decode it below before + // returning from this function and closing the response body. + if _, ok := err.(*AcceptedError); !ok { + return response, err + } + } + + if v != nil { + if w, ok := v.(io.Writer); ok { + io.Copy(w, resp.Body) + } else { + decErr := json.NewDecoder(resp.Body).Decode(v) + if decErr == io.EOF { + decErr = nil // ignore EOF errors caused by empty response body + } + if decErr != nil { + err = decErr + } + } + } + + return response, err +} + +// checkRateLimitBeforeDo does not make any network calls, but uses existing knowledge from +// current client state in order to quickly check if *RateLimitError can be immediately returned +// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily. +// Otherwise it returns nil, and Client.Do should proceed normally. +func (c *Client) checkRateLimitBeforeDo(req *http.Request, rateLimitCategory rateLimitCategory) *RateLimitError { + c.rateMu.Lock() + rate := c.rateLimits[rateLimitCategory] + c.rateMu.Unlock() + if !rate.Reset.Time.IsZero() && rate.Remaining == 0 && time.Now().Before(rate.Reset.Time) { + // Create a fake response. + resp := &http.Response{ + Status: http.StatusText(http.StatusForbidden), + StatusCode: http.StatusForbidden, + Request: req, + Header: make(http.Header), + Body: ioutil.NopCloser(strings.NewReader("")), + } + return &RateLimitError{ + Rate: rate, + Response: resp, + Message: fmt.Sprintf("API rate limit of %v still exceeded until %v, not making remote request.", rate.Limit, rate.Reset.Time), + } + } + + return nil +} + +/* +An ErrorResponse reports one or more errors caused by an API request. + +GitHub API docs: https://developer.github.com/v3/#client-errors +*/ +type ErrorResponse struct { + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message + Errors []Error `json:"errors"` // more detail on individual errors + // Block is only populated on certain types of errors such as code 451. + // See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ + // for more information. + Block *struct { + Reason string `json:"reason,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + } `json:"block,omitempty"` + // Most errors will also include a documentation_url field pointing + // to some content that might help you resolve the error, see + // https://developer.github.com/v3/#client-errors + DocumentationURL string `json:"documentation_url,omitempty"` +} + +func (r *ErrorResponse) Error() string { + return fmt.Sprintf("%v %v: %d %v %+v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message, r.Errors) +} + +// TwoFactorAuthError occurs when using HTTP Basic Authentication for a user +// that has two-factor authentication enabled. The request can be reattempted +// by providing a one-time password in the request. +type TwoFactorAuthError ErrorResponse + +func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() } + +// RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit +// remaining value of 0, and error message starts with "API rate limit exceeded for ". +type RateLimitError struct { + Rate Rate // Rate specifies last known rate limit for the client + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message +} + +func (r *RateLimitError) Error() string { + return fmt.Sprintf("%v %v: %d %v %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message, formatRateReset(r.Rate.Reset.Time.Sub(time.Now()))) +} + +// AcceptedError occurs when GitHub returns 202 Accepted response with an +// empty body, which means a job was scheduled on the GitHub side to process +// the information needed and cache it. +// Technically, 202 Accepted is not a real error, it's just used to +// indicate that results are not ready yet, but should be available soon. +// The request can be repeated after some time. +type AcceptedError struct{} + +func (*AcceptedError) Error() string { + return "job scheduled on GitHub side; try again later" +} + +// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the +// "documentation_url" field value equal to "https://developer.github.com/v3/#abuse-rate-limits". +type AbuseRateLimitError struct { + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message + + // RetryAfter is provided with some abuse rate limit errors. If present, + // it is the amount of time that the client should wait before retrying. + // Otherwise, the client should try again later (after an unspecified amount of time). + RetryAfter *time.Duration +} + +func (r *AbuseRateLimitError) Error() string { + return fmt.Sprintf("%v %v: %d %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message) +} + +// sanitizeURL redacts the client_secret parameter from the URL which may be +// exposed to the user. +func sanitizeURL(uri *url.URL) *url.URL { + if uri == nil { + return nil + } + params := uri.Query() + if len(params.Get("client_secret")) > 0 { + params.Set("client_secret", "REDACTED") + uri.RawQuery = params.Encode() + } + return uri +} + +/* +An Error reports more details on an individual error in an ErrorResponse. +These are the possible validation error codes: + + missing: + resource does not exist + missing_field: + a required field on a resource has not been set + invalid: + the formatting of a field is invalid + already_exists: + another resource has the same valid as this field + custom: + some resources return this (e.g. github.User.CreateKey()), additional + information is set in the Message field of the Error + +GitHub API docs: https://developer.github.com/v3/#client-errors +*/ +type Error struct { + Resource string `json:"resource"` // resource on which the error occurred + Field string `json:"field"` // field on which the error occurred + Code string `json:"code"` // validation error code + Message string `json:"message"` // Message describing the error. Errors with Code == "custom" will always have this set. +} + +func (e *Error) Error() string { + return fmt.Sprintf("%v error caused by %v field on %v resource", + e.Code, e.Field, e.Resource) +} + +// CheckResponse checks the API response for errors, and returns them if +// present. A response is considered an error if it has a status code outside +// the 200 range or equal to 202 Accepted. +// API error responses are expected to have either no response +// body, or a JSON response body that maps to ErrorResponse. Any other +// response body will be silently ignored. +// +// The error type will be *RateLimitError for rate limit exceeded errors, +// *AcceptedError for 202 Accepted status codes, +// and *TwoFactorAuthError for two-factor authentication errors. +func CheckResponse(r *http.Response) error { + if r.StatusCode == http.StatusAccepted { + return &AcceptedError{} + } + if c := r.StatusCode; 200 <= c && c <= 299 { + return nil + } + errorResponse := &ErrorResponse{Response: r} + data, err := ioutil.ReadAll(r.Body) + if err == nil && data != nil { + json.Unmarshal(data, errorResponse) + } + switch { + case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"): + return (*TwoFactorAuthError)(errorResponse) + case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0" && strings.HasPrefix(errorResponse.Message, "API rate limit exceeded for "): + return &RateLimitError{ + Rate: parseRate(r), + Response: errorResponse.Response, + Message: errorResponse.Message, + } + case r.StatusCode == http.StatusForbidden && strings.HasSuffix(errorResponse.DocumentationURL, "/v3/#abuse-rate-limits"): + abuseRateLimitError := &AbuseRateLimitError{ + Response: errorResponse.Response, + Message: errorResponse.Message, + } + if v := r.Header["Retry-After"]; len(v) > 0 { + // According to GitHub support, the "Retry-After" header value will be + // an integer which represents the number of seconds that one should + // wait before resuming making requests. + retryAfterSeconds, _ := strconv.ParseInt(v[0], 10, 64) // Error handling is noop. + retryAfter := time.Duration(retryAfterSeconds) * time.Second + abuseRateLimitError.RetryAfter = &retryAfter + } + return abuseRateLimitError + default: + return errorResponse + } +} + +// parseBoolResponse determines the boolean result from a GitHub API response. +// Several GitHub API methods return boolean responses indicated by the HTTP +// status code in the response (true indicated by a 204, false indicated by a +// 404). This helper function will determine that result and hide the 404 +// error if present. Any other error will be returned through as-is. +func parseBoolResponse(err error) (bool, error) { + if err == nil { + return true, nil + } + + if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound { + // Simply false. In this one case, we do not pass the error through. + return false, nil + } + + // some other real error occurred + return false, err +} + +// Rate represents the rate limit for the current client. +type Rate struct { + // The number of requests per hour the client is currently limited to. + Limit int `json:"limit"` + + // The number of remaining requests the client can make this hour. + Remaining int `json:"remaining"` + + // The time at which the current rate limit will reset. + Reset Timestamp `json:"reset"` +} + +func (r Rate) String() string { + return Stringify(r) +} + +// RateLimits represents the rate limits for the current client. +type RateLimits struct { + // The rate limit for non-search API requests. Unauthenticated + // requests are limited to 60 per hour. Authenticated requests are + // limited to 5,000 per hour. + // + // GitHub API docs: https://developer.github.com/v3/#rate-limiting + Core *Rate `json:"core"` + + // The rate limit for search API requests. Unauthenticated requests + // are limited to 10 requests per minutes. Authenticated requests are + // limited to 30 per minute. + // + // GitHub API docs: https://developer.github.com/v3/search/#rate-limit + Search *Rate `json:"search"` +} + +func (r RateLimits) String() string { + return Stringify(r) +} + +type rateLimitCategory uint8 + +const ( + coreCategory rateLimitCategory = iota + searchCategory + + categories // An array of this length will be able to contain all rate limit categories. +) + +// category returns the rate limit category of the endpoint, determined by Request.URL.Path. +func category(path string) rateLimitCategory { + switch { + default: + return coreCategory + case strings.HasPrefix(path, "/search/"): + return searchCategory + } +} + +// RateLimits returns the rate limits for the current client. +func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error) { + req, err := c.NewRequest("GET", "rate_limit", nil) + if err != nil { + return nil, nil, err + } + + response := new(struct { + Resources *RateLimits `json:"resources"` + }) + resp, err := c.Do(ctx, req, response) + if err != nil { + return nil, nil, err + } + + if response.Resources != nil { + c.rateMu.Lock() + if response.Resources.Core != nil { + c.rateLimits[coreCategory] = *response.Resources.Core + } + if response.Resources.Search != nil { + c.rateLimits[searchCategory] = *response.Resources.Search + } + c.rateMu.Unlock() + } + + return response.Resources, resp, nil +} + +/* +UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls +that need to use a higher rate limit associated with your OAuth application. + + t := &github.UnauthenticatedRateLimitedTransport{ + ClientID: "your app's client ID", + ClientSecret: "your app's client secret", + } + client := github.NewClient(t.Client()) + +This will append the querystring params client_id=xxx&client_secret=yyy to all +requests. + +See https://developer.github.com/v3/#unauthenticated-rate-limited-requests for +more information. +*/ +type UnauthenticatedRateLimitedTransport struct { + // ClientID is the GitHub OAuth client ID of the current application, which + // can be found by selecting its entry in the list at + // https://github.com/settings/applications. + ClientID string + + // ClientSecret is the GitHub OAuth client secret of the current + // application. + ClientSecret string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if t.ClientID == "" { + return nil, errors.New("t.ClientID is empty") + } + if t.ClientSecret == "" { + return nil, errors.New("t.ClientSecret is empty") + } + + // To set extra querystring params, we must make a copy of the Request so + // that we don't modify the Request we were given. This is required by the + // specification of http.RoundTripper. + // + // Since we are going to modify only req.URL here, we only need a deep copy + // of req.URL. + req2 := new(http.Request) + *req2 = *req + req2.URL = new(url.URL) + *req2.URL = *req.URL + + q := req2.URL.Query() + q.Set("client_id", t.ClientID) + q.Set("client_secret", t.ClientSecret) + req2.URL.RawQuery = q.Encode() + + // Make the HTTP request. + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests which are subject to the +// rate limit of your OAuth application. +func (t *UnauthenticatedRateLimitedTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *UnauthenticatedRateLimitedTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// BasicAuthTransport is an http.RoundTripper that authenticates all requests +// using HTTP Basic Authentication with the provided username and password. It +// additionally supports users who have two-factor authentication enabled on +// their GitHub account. +type BasicAuthTransport struct { + Username string // GitHub username + Password string // GitHub password + OTP string // one-time password for users with two-factor auth enabled + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + // To set extra headers, we must make a copy of the Request so + // that we don't modify the Request we were given. This is required by the + // specification of http.RoundTripper. + // + // Since we are going to modify only req.Header here, we only need a deep copy + // of req.Header. + req2 := new(http.Request) + *req2 = *req + req2.Header = make(http.Header, len(req.Header)) + for k, s := range req.Header { + req2.Header[k] = append([]string(nil), s...) + } + + req2.SetBasicAuth(t.Username, t.Password) + if t.OTP != "" { + req2.Header.Set(headerOTP, t.OTP) + } + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. +func (t *BasicAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *BasicAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// formatRateReset formats d to look like "[rate reset in 2s]" or +// "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]" +// for the negative cases. +func formatRateReset(d time.Duration) string { + isNegative := d < 0 + if isNegative { + d *= -1 + } + secondsTotal := int(0.5 + d.Seconds()) + minutes := secondsTotal / 60 + seconds := secondsTotal - minutes*60 + + var timeString string + if minutes > 0 { + timeString = fmt.Sprintf("%dm%02ds", minutes, seconds) + } else { + timeString = fmt.Sprintf("%ds", seconds) + } + + if isNegative { + return fmt.Sprintf("[rate limit was reset %v ago]", timeString) + } + return fmt.Sprintf("[rate reset in %v]", timeString) +} + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { return &v } + +// Int is a helper routine that allocates a new int value +// to store v and returns a pointer to it. +func Int(v int) *int { return &v } + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +func Int64(v int64) *int64 { return &v } + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { return &v } diff --git a/vendor/github.com/google/go-github/github/gitignore.go b/vendor/github.com/google/go-github/github/gitignore.go new file mode 100644 index 00000000..2f691bc3 --- /dev/null +++ b/vendor/github.com/google/go-github/github/gitignore.go @@ -0,0 +1,64 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GitignoresService provides access to the gitignore related functions in the +// GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/gitignore/ +type GitignoresService service + +// Gitignore represents a .gitignore file as returned by the GitHub API. +type Gitignore struct { + Name *string `json:"name,omitempty"` + Source *string `json:"source,omitempty"` +} + +func (g Gitignore) String() string { + return Stringify(g) +} + +// List all available Gitignore templates. +// +// GitHub API docs: https://developer.github.com/v3/gitignore/#listing-available-templates +func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error) { + req, err := s.client.NewRequest("GET", "gitignore/templates", nil) + if err != nil { + return nil, nil, err + } + + var availableTemplates []string + resp, err := s.client.Do(ctx, req, &availableTemplates) + if err != nil { + return nil, resp, err + } + + return availableTemplates, resp, nil +} + +// Get a Gitignore by name. +// +// GitHub API docs: https://developer.github.com/v3/gitignore/#get-a-single-template +func (s GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) { + u := fmt.Sprintf("gitignore/templates/%v", name) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + gitignore := new(Gitignore) + resp, err := s.client.Do(ctx, req, gitignore) + if err != nil { + return nil, resp, err + } + + return gitignore, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/issues.go b/vendor/github.com/google/go-github/github/issues.go new file mode 100644 index 00000000..ded07f0a --- /dev/null +++ b/vendor/github.com/google/go-github/github/issues.go @@ -0,0 +1,332 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" + "time" +) + +// IssuesService handles communication with the issue related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/issues/ +type IssuesService service + +// Issue represents a GitHub issue on a repository. +// +// Note: As far as the GitHub API is concerned, every pull request is an issue, +// but not every issue is a pull request. Some endpoints, events, and webhooks +// may also return pull requests via this struct. If PullRequestLinks is nil, +// this is an issue, and if PullRequestLinks is not nil, this is a pull request. +// The IsPullRequest helper method can be used to check that. +type Issue struct { + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + User *User `json:"user,omitempty"` + Labels []Label `json:"labels,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Comments *int `json:"comments,omitempty"` + ClosedAt *time.Time `json:"closed_at,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + ClosedBy *User `json:"closed_by,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + NodeID *string `json:"node_id,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://developer.github.com/v3/search/#text-match-metadata + TextMatches []TextMatch `json:"text_matches,omitempty"` +} + +func (i Issue) String() string { + return Stringify(i) +} + +// IsPullRequest reports whether the issue is also a pull request. It uses the +// method recommended by GitHub's API documentation, which is to check whether +// PullRequestLinks is non-nil. +func (i Issue) IsPullRequest() bool { + return i.PullRequestLinks != nil +} + +// IssueRequest represents a request to create/edit an issue. +// It is separate from Issue above because otherwise Labels +// and Assignee fail to serialize to the correct JSON. +type IssueRequest struct { + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + Labels *[]string `json:"labels,omitempty"` + Assignee *string `json:"assignee,omitempty"` + State *string `json:"state,omitempty"` + Milestone *int `json:"milestone,omitempty"` + Assignees *[]string `json:"assignees,omitempty"` +} + +// IssueListOptions specifies the optional parameters to the IssuesService.List +// and IssuesService.ListByOrg methods. +type IssueListOptions struct { + // Filter specifies which issues to list. Possible values are: assigned, + // created, mentioned, subscribed, all. Default is "assigned". + Filter string `url:"filter,omitempty"` + + // State filters issues based on their state. Possible values are: open, + // closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Labels filters issues based on their label. + Labels []string `url:"labels,comma,omitempty"` + + // Sort specifies how to sort issues. Possible values are: created, updated, + // and comments. Default value is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort issues. Possible values are: asc, desc. + // Default is "desc". + Direction string `url:"direction,omitempty"` + + // Since filters issues by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// PullRequestLinks object is added to the Issue object when it's an issue included +// in the IssueCommentEvent webhook payload, if the webhook is fired by a comment on a PR. +type PullRequestLinks struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` +} + +// List the issues for the authenticated user. If all is true, list issues +// across all the user's visible repositories including owned, member, and +// organization repositories; if false, list only owned and member +// repositories. +// +// GitHub API docs: https://developer.github.com/v3/issues/#list-issues +func (s *IssuesService) List(ctx context.Context, all bool, opt *IssueListOptions) ([]*Issue, *Response, error) { + var u string + if all { + u = "issues" + } else { + u = "user/issues" + } + return s.listIssues(ctx, u, opt) +} + +// ListByOrg fetches the issues in the specified organization for the +// authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/issues/#list-issues +func (s *IssuesService) ListByOrg(ctx context.Context, org string, opt *IssueListOptions) ([]*Issue, *Response, error) { + u := fmt.Sprintf("orgs/%v/issues", org) + return s.listIssues(ctx, u, opt) +} + +func (s *IssuesService) listIssues(ctx context.Context, u string, opt *IssueListOptions) ([]*Issue, *Response, error) { + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var issues []*Issue + resp, err := s.client.Do(ctx, req, &issues) + if err != nil { + return nil, resp, err + } + + return issues, resp, nil +} + +// IssueListByRepoOptions specifies the optional parameters to the +// IssuesService.ListByRepo method. +type IssueListByRepoOptions struct { + // Milestone limits issues for the specified milestone. Possible values are + // a milestone number, "none" for issues with no milestone, "*" for issues + // with any milestone. + Milestone string `url:"milestone,omitempty"` + + // State filters issues based on their state. Possible values are: open, + // closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Assignee filters issues based on their assignee. Possible values are a + // user name, "none" for issues that are not assigned, "*" for issues with + // any assigned user. + Assignee string `url:"assignee,omitempty"` + + // Creator filters issues based on their creator. + Creator string `url:"creator,omitempty"` + + // Mentioned filters issues to those mentioned a specific user. + Mentioned string `url:"mentioned,omitempty"` + + // Labels filters issues based on their label. + Labels []string `url:"labels,omitempty,comma"` + + // Sort specifies how to sort issues. Possible values are: created, updated, + // and comments. Default value is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort issues. Possible values are: asc, desc. + // Default is "desc". + Direction string `url:"direction,omitempty"` + + // Since filters issues by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListByRepo lists the issues for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/#list-issues-for-a-repository +func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opt *IssueListByRepoOptions) ([]*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var issues []*Issue + resp, err := s.client.Do(ctx, req, &issues) + if err != nil { + return nil, resp, err + } + + return issues, resp, nil +} + +// Get a single issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/#get-a-single-issue +func (s *IssuesService) Get(ctx context.Context, owner string, repo string, number int) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + issue := new(Issue) + resp, err := s.client.Do(ctx, req, issue) + if err != nil { + return nil, resp, err + } + + return issue, resp, nil +} + +// Create a new issue on the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/#create-an-issue +func (s *IssuesService) Create(ctx context.Context, owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) + req, err := s.client.NewRequest("POST", u, issue) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// Edit an issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/#edit-an-issue +func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) + req, err := s.client.NewRequest("PATCH", u, issue) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// Lock an issue's conversation. +// +// GitHub API docs: https://developer.github.com/v3/issues/#lock-an-issue +func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unlock an issue's conversation. +// +// GitHub API docs: https://developer.github.com/v3/issues/#unlock-an-issue +func (s *IssuesService) Unlock(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/issues_assignees.go b/vendor/github.com/google/go-github/github/issues_assignees.go new file mode 100644 index 00000000..9cb366f5 --- /dev/null +++ b/vendor/github.com/google/go-github/github/issues_assignees.go @@ -0,0 +1,85 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAssignees fetches all available assignees (owners and collaborators) to +// which issues may be assigned. +// +// GitHub API docs: https://developer.github.com/v3/issues/assignees/#list-assignees +func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + var assignees []*User + resp, err := s.client.Do(ctx, req, &assignees) + if err != nil { + return nil, resp, err + } + + return assignees, resp, nil +} + +// IsAssignee checks if a user is an assignee for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/assignees/#check-assignee +func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + resp, err := s.client.Do(ctx, req, nil) + assignee, err := parseBoolResponse(err) + return assignee, resp, err +} + +// AddAssignees adds the provided GitHub users as assignees to the issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/assignees/#add-assignees-to-an-issue +func (s *IssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { + users := &struct { + Assignees []string `json:"assignees,omitempty"` + }{Assignees: assignees} + u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) + req, err := s.client.NewRequest("POST", u, users) + if err != nil { + return nil, nil, err + } + + issue := &Issue{} + resp, err := s.client.Do(ctx, req, issue) + return issue, resp, err +} + +// RemoveAssignees removes the provided GitHub users as assignees from the issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/assignees/#remove-assignees-from-an-issue +func (s *IssuesService) RemoveAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { + users := &struct { + Assignees []string `json:"assignees,omitempty"` + }{Assignees: assignees} + u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, users) + if err != nil { + return nil, nil, err + } + + issue := &Issue{} + resp, err := s.client.Do(ctx, req, issue) + return issue, resp, err +} diff --git a/vendor/github.com/google/go-github/github/issues_comments.go b/vendor/github.com/google/go-github/github/issues_comments.go new file mode 100644 index 00000000..e6f6f219 --- /dev/null +++ b/vendor/github.com/google/go-github/github/issues_comments.go @@ -0,0 +1,152 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// IssueComment represents a comment left on an issue. +type IssueComment struct { + ID *int64 `json:"id,omitempty"` + Body *string `json:"body,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + // AuthorAssociation is the comment author's relationship to the issue's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` +} + +func (i IssueComment) String() string { + return Stringify(i) +} + +// IssueListCommentsOptions specifies the optional parameters to the +// IssuesService.ListComments method. +type IssueListCommentsOptions struct { + // Sort specifies how to sort comments. Possible values are: created, updated. + Sort string `url:"sort,omitempty"` + + // Direction in which to sort comments. Possible values are: asc, desc. + Direction string `url:"direction,omitempty"` + + // Since filters comments by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListComments lists all comments on the specified issue. Specifying an issue +// number of 0 will return all comments on all issues for the repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue +func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opt *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { + var u string + if number == 0 { + u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo) + } else { + u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*IssueComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment fetches the specified issue comment. +// +// GitHub API docs: https://developer.github.com/v3/issues/comments/#get-a-single-comment +func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + comment := new(IssueComment) + resp, err := s.client.Do(ctx, req, comment) + if err != nil { + return nil, resp, err + } + + return comment, resp, nil +} + +// CreateComment creates a new comment on the specified issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/comments/#create-a-comment +func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + c := new(IssueComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment updates an issue comment. +// A non-nil comment.Body must be provided. Other comment fields should be left nil. +// +// GitHub API docs: https://developer.github.com/v3/issues/comments/#edit-a-comment +func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + c := new(IssueComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes an issue comment. +// +// GitHub API docs: https://developer.github.com/v3/issues/comments/#delete-a-comment +func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/issues_events.go b/vendor/github.com/google/go-github/github/issues_events.go new file mode 100644 index 00000000..55e6d431 --- /dev/null +++ b/vendor/github.com/google/go-github/github/issues_events.go @@ -0,0 +1,151 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// IssueEvent represents an event that occurred around an Issue or Pull Request. +type IssueEvent struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + + // The User that generated this event. + Actor *User `json:"actor,omitempty"` + + // Event identifies the actual type of Event that occurred. Possible + // values are: + // + // closed + // The Actor closed the issue. + // If the issue was closed by commit message, CommitID holds the SHA1 hash of the commit. + // + // merged + // The Actor merged into master a branch containing a commit mentioning the issue. + // CommitID holds the SHA1 of the merge commit. + // + // referenced + // The Actor committed to master a commit mentioning the issue in its commit message. + // CommitID holds the SHA1 of the commit. + // + // reopened, locked, unlocked + // The Actor did that to the issue. + // + // renamed + // The Actor changed the issue title from Rename.From to Rename.To. + // + // mentioned + // Someone unspecified @mentioned the Actor [sic] in an issue comment body. + // + // assigned, unassigned + // The Assigner assigned the issue to or removed the assignment from the Assignee. + // + // labeled, unlabeled + // The Actor added or removed the Label from the issue. + // + // milestoned, demilestoned + // The Actor added or removed the issue from the Milestone. + // + // subscribed, unsubscribed + // The Actor subscribed to or unsubscribed from notifications for an issue. + // + // head_ref_deleted, head_ref_restored + // The pull request’s branch was deleted or restored. + // + Event *string `json:"event,omitempty"` + + CreatedAt *time.Time `json:"created_at,omitempty"` + Issue *Issue `json:"issue,omitempty"` + + // Only present on certain events; see above. + Assignee *User `json:"assignee,omitempty"` + Assigner *User `json:"assigner,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + Label *Label `json:"label,omitempty"` + Rename *Rename `json:"rename,omitempty"` +} + +// ListIssueEvents lists events for the specified issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-an-issue +func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-a-repository +func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// GetEvent returns the specified issue event. +// +// GitHub API docs: https://developer.github.com/v3/issues/events/#get-a-single-event +func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + event := new(IssueEvent) + resp, err := s.client.Do(ctx, req, event) + if err != nil { + return nil, resp, err + } + + return event, resp, nil +} + +// Rename contains details for 'renamed' events. +type Rename struct { + From *string `json:"from,omitempty"` + To *string `json:"to,omitempty"` +} + +func (r Rename) String() string { + return Stringify(r) +} diff --git a/vendor/github.com/google/go-github/github/issues_labels.go b/vendor/github.com/google/go-github/github/issues_labels.go new file mode 100644 index 00000000..4328997b --- /dev/null +++ b/vendor/github.com/google/go-github/github/issues_labels.go @@ -0,0 +1,270 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// Label represents a GitHub label on an Issue +type Label struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Color *string `json:"color,omitempty"` + Description *string `json:"description,omitempty"` + Default *bool `json:"default,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (l Label) String() string { + return Stringify(l) +} + +// ListLabels lists all labels for a repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository +func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} + +// GetLabel gets a single label. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-a-single-label +func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + label := new(Label) + resp, err := s.client.Do(ctx, req, label) + if err != nil { + return nil, resp, err + } + + return label, resp, nil +} + +// CreateLabel creates a new label on the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#create-a-label +func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo string, label *Label) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) + req, err := s.client.NewRequest("POST", u, label) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + l := new(Label) + resp, err := s.client.Do(ctx, req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// EditLabel edits a label. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#update-a-label +func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string, name string, label *Label) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("PATCH", u, label) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + l := new(Label) + resp, err := s.client.Do(ctx, req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// DeleteLabel deletes a label. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#delete-a-label +func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo string, name string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListLabelsByIssue lists all labels for an issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-on-an-issue +func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} + +// AddLabelsToIssue adds labels to an issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#add-labels-to-an-issue +func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("POST", u, labels) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var l []*Label + resp, err := s.client.Do(ctx, req, &l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// RemoveLabelForIssue removes a label for an issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-a-label-from-an-issue +func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels/%v", owner, repo, number, label) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) + + return s.client.Do(ctx, req, nil) +} + +// ReplaceLabelsForIssue replaces all labels for an issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#replace-all-labels-for-an-issue +func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("PUT", u, labels) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var l []*Label + resp, err := s.client.Do(ctx, req, &l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// RemoveLabelsForIssue removes all labels for an issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-all-labels-from-an-issue +func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) + + return s.client.Do(ctx, req, nil) +} + +// ListLabelsForMilestone lists labels for every issue in a milestone. +// +// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-labels-for-every-issue-in-a-milestone +func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/issues_milestones.go b/vendor/github.com/google/go-github/github/issues_milestones.go new file mode 100644 index 00000000..6af1cc03 --- /dev/null +++ b/vendor/github.com/google/go-github/github/issues_milestones.go @@ -0,0 +1,160 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// Milestone represents a GitHub repository milestone. +type Milestone struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Title *string `json:"title,omitempty"` + Description *string `json:"description,omitempty"` + Creator *User `json:"creator,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` + ClosedIssues *int `json:"closed_issues,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + ClosedAt *time.Time `json:"closed_at,omitempty"` + DueOn *time.Time `json:"due_on,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (m Milestone) String() string { + return Stringify(m) +} + +// MilestoneListOptions specifies the optional parameters to the +// IssuesService.ListMilestones method. +type MilestoneListOptions struct { + // State filters milestones based on their state. Possible values are: + // open, closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Sort specifies how to sort milestones. Possible values are: due_on, completeness. + // Default value is "due_on". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort milestones. Possible values are: asc, desc. + // Default is "asc". + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListMilestones lists all milestones for a repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository +func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opt *MilestoneListOptions) ([]*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var milestones []*Milestone + resp, err := s.client.Do(ctx, req, &milestones) + if err != nil { + return nil, resp, err + } + + return milestones, resp, nil +} + +// GetMilestone gets a single milestone. +// +// GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-single-milestone +func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + milestone := new(Milestone) + resp, err := s.client.Do(ctx, req, milestone) + if err != nil { + return nil, resp, err + } + + return milestone, resp, nil +} + +// CreateMilestone creates a new milestone on the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/issues/milestones/#create-a-milestone +func (s *IssuesService) CreateMilestone(ctx context.Context, owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) + req, err := s.client.NewRequest("POST", u, milestone) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + m := new(Milestone) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// EditMilestone edits a milestone. +// +// GitHub API docs: https://developer.github.com/v3/issues/milestones/#update-a-milestone +func (s *IssuesService) EditMilestone(ctx context.Context, owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("PATCH", u, milestone) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + m := new(Milestone) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteMilestone deletes a milestone. +// +// GitHub API docs: https://developer.github.com/v3/issues/milestones/#delete-a-milestone +func (s *IssuesService) DeleteMilestone(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/issues_timeline.go b/vendor/github.com/google/go-github/github/issues_timeline.go new file mode 100644 index 00000000..9cfda832 --- /dev/null +++ b/vendor/github.com/google/go-github/github/issues_timeline.go @@ -0,0 +1,149 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// Timeline represents an event that occurred around an Issue or Pull Request. +// +// It is similar to an IssueEvent but may contain more information. +// GitHub API docs: https://developer.github.com/v3/issues/timeline/ +type Timeline struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + CommitURL *string `json:"commit_url,omitempty"` + + // The User object that generated the event. + Actor *User `json:"actor,omitempty"` + + // Event identifies the actual type of Event that occurred. Possible values + // are: + // + // assigned + // The issue was assigned to the assignee. + // + // closed + // The issue was closed by the actor. When the commit_id is present, it + // identifies the commit that closed the issue using "closes / fixes #NN" + // syntax. + // + // commented + // A comment was added to the issue. + // + // committed + // A commit was added to the pull request's 'HEAD' branch. Only provided + // for pull requests. + // + // cross-referenced + // The issue was referenced from another issue. The 'source' attribute + // contains the 'id', 'actor', and 'url' of the reference's source. + // + // demilestoned + // The issue was removed from a milestone. + // + // head_ref_deleted + // The pull request's branch was deleted. + // + // head_ref_restored + // The pull request's branch was restored. + // + // labeled + // A label was added to the issue. + // + // locked + // The issue was locked by the actor. + // + // mentioned + // The actor was @mentioned in an issue body. + // + // merged + // The issue was merged by the actor. The 'commit_id' attribute is the + // SHA1 of the HEAD commit that was merged. + // + // milestoned + // The issue was added to a milestone. + // + // referenced + // The issue was referenced from a commit message. The 'commit_id' + // attribute is the commit SHA1 of where that happened. + // + // renamed + // The issue title was changed. + // + // reopened + // The issue was reopened by the actor. + // + // subscribed + // The actor subscribed to receive notifications for an issue. + // + // unassigned + // The assignee was unassigned from the issue. + // + // unlabeled + // A label was removed from the issue. + // + // unlocked + // The issue was unlocked by the actor. + // + // unsubscribed + // The actor unsubscribed to stop receiving notifications for an issue. + // + Event *string `json:"event,omitempty"` + + // The string SHA of a commit that referenced this Issue or Pull Request. + CommitID *string `json:"commit_id,omitempty"` + // The timestamp indicating when the event occurred. + CreatedAt *time.Time `json:"created_at,omitempty"` + // The Label object including `name` and `color` attributes. Only provided for + // 'labeled' and 'unlabeled' events. + Label *Label `json:"label,omitempty"` + // The User object which was assigned to (or unassigned from) this Issue or + // Pull Request. Only provided for 'assigned' and 'unassigned' events. + Assignee *User `json:"assignee,omitempty"` + // The Milestone object including a 'title' attribute. + // Only provided for 'milestoned' and 'demilestoned' events. + Milestone *Milestone `json:"milestone,omitempty"` + // The 'id', 'actor', and 'url' for the source of a reference from another issue. + // Only provided for 'cross-referenced' events. + Source *Source `json:"source,omitempty"` + // An object containing rename details including 'from' and 'to' attributes. + // Only provided for 'renamed' events. + Rename *Rename `json:"rename,omitempty"` +} + +// Source represents a reference's source. +type Source struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Actor *User `json:"actor,omitempty"` +} + +// ListIssueTimeline lists events for the specified issue. +// +// GitHub API docs: https://developer.github.com/v3/issues/timeline/#list-events-for-an-issue +func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Timeline, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTimelinePreview) + + var events []*Timeline + resp, err := s.client.Do(ctx, req, &events) + return events, resp, err +} diff --git a/vendor/github.com/google/go-github/github/licenses.go b/vendor/github.com/google/go-github/github/licenses.go new file mode 100644 index 00000000..e9cd1777 --- /dev/null +++ b/vendor/github.com/google/go-github/github/licenses.go @@ -0,0 +1,103 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// LicensesService handles communication with the license related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/licenses/ +type LicensesService service + +// RepositoryLicense represents the license for a repository. +type RepositoryLicense struct { + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + + SHA *string `json:"sha,omitempty"` + Size *int `json:"size,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` + Type *string `json:"type,omitempty"` + Content *string `json:"content,omitempty"` + Encoding *string `json:"encoding,omitempty"` + License *License `json:"license,omitempty"` +} + +func (l RepositoryLicense) String() string { + return Stringify(l) +} + +// License represents an open source license. +type License struct { + Key *string `json:"key,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + + SPDXID *string `json:"spdx_id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Featured *bool `json:"featured,omitempty"` + Description *string `json:"description,omitempty"` + Implementation *string `json:"implementation,omitempty"` + Permissions *[]string `json:"permissions,omitempty"` + Conditions *[]string `json:"conditions,omitempty"` + Limitations *[]string `json:"limitations,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (l License) String() string { + return Stringify(l) +} + +// List popular open source licenses. +// +// GitHub API docs: https://developer.github.com/v3/licenses/#list-all-licenses +func (s *LicensesService) List(ctx context.Context) ([]*License, *Response, error) { + req, err := s.client.NewRequest("GET", "licenses", nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeLicensesPreview) + + var licenses []*License + resp, err := s.client.Do(ctx, req, &licenses) + if err != nil { + return nil, resp, err + } + + return licenses, resp, nil +} + +// Get extended metadata for one license. +// +// GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license +func (s *LicensesService) Get(ctx context.Context, licenseName string) (*License, *Response, error) { + u := fmt.Sprintf("licenses/%s", licenseName) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeLicensesPreview) + + license := new(License) + resp, err := s.client.Do(ctx, req, license) + if err != nil { + return nil, resp, err + } + + return license, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/messages.go b/vendor/github.com/google/go-github/github/messages.go new file mode 100644 index 00000000..2396fd43 --- /dev/null +++ b/vendor/github.com/google/go-github/github/messages.go @@ -0,0 +1,245 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file provides functions for validating payloads from GitHub Webhooks. +// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github + +package github + +import ( + "crypto/hmac" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "hash" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + +const ( + // sha1Prefix is the prefix used by GitHub before the HMAC hexdigest. + sha1Prefix = "sha1" + // sha256Prefix and sha512Prefix are provided for future compatibility. + sha256Prefix = "sha256" + sha512Prefix = "sha512" + // signatureHeader is the GitHub header key used to pass the HMAC hexdigest. + signatureHeader = "X-Hub-Signature" + // eventTypeHeader is the GitHub header key used to pass the event type. + eventTypeHeader = "X-Github-Event" + // deliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event. + deliveryIDHeader = "X-Github-Delivery" +) + +var ( + // eventTypeMapping maps webhooks types to their corresponding go-github struct types. + eventTypeMapping = map[string]string{ + "commit_comment": "CommitCommentEvent", + "create": "CreateEvent", + "delete": "DeleteEvent", + "deployment": "DeploymentEvent", + "deployment_status": "DeploymentStatusEvent", + "fork": "ForkEvent", + "gollum": "GollumEvent", + "installation": "InstallationEvent", + "installation_repositories": "InstallationRepositoriesEvent", + "issue_comment": "IssueCommentEvent", + "issues": "IssuesEvent", + "label": "LabelEvent", + "marketplace_purchase": "MarketplacePurchaseEvent", + "member": "MemberEvent", + "membership": "MembershipEvent", + "milestone": "MilestoneEvent", + "organization": "OrganizationEvent", + "org_block": "OrgBlockEvent", + "page_build": "PageBuildEvent", + "ping": "PingEvent", + "project": "ProjectEvent", + "project_card": "ProjectCardEvent", + "project_column": "ProjectColumnEvent", + "public": "PublicEvent", + "pull_request_review": "PullRequestReviewEvent", + "pull_request_review_comment": "PullRequestReviewCommentEvent", + "pull_request": "PullRequestEvent", + "push": "PushEvent", + "repository": "RepositoryEvent", + "release": "ReleaseEvent", + "status": "StatusEvent", + "team": "TeamEvent", + "team_add": "TeamAddEvent", + "watch": "WatchEvent", + } +) + +// genMAC generates the HMAC signature for a message provided the secret key +// and hashFunc. +func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte { + mac := hmac.New(hashFunc, key) + mac.Write(message) + return mac.Sum(nil) +} + +// checkMAC reports whether messageMAC is a valid HMAC tag for message. +func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool { + expectedMAC := genMAC(message, key, hashFunc) + return hmac.Equal(messageMAC, expectedMAC) +} + +// messageMAC returns the hex-decoded HMAC tag from the signature and its +// corresponding hash function. +func messageMAC(signature string) ([]byte, func() hash.Hash, error) { + if signature == "" { + return nil, nil, errors.New("missing signature") + } + sigParts := strings.SplitN(signature, "=", 2) + if len(sigParts) != 2 { + return nil, nil, fmt.Errorf("error parsing signature %q", signature) + } + + var hashFunc func() hash.Hash + switch sigParts[0] { + case sha1Prefix: + hashFunc = sha1.New + case sha256Prefix: + hashFunc = sha256.New + case sha512Prefix: + hashFunc = sha512.New + default: + return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0]) + } + + buf, err := hex.DecodeString(sigParts[1]) + if err != nil { + return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err) + } + return buf, hashFunc, nil +} + +// ValidatePayload validates an incoming GitHub Webhook event request +// and returns the (JSON) payload. +// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". +// If the Content-Type is neither then an error is returned. +// secretKey is the GitHub Webhook secret message. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// payload, err := github.ValidatePayload(r, s.webhookSecretKey) +// if err != nil { ... } +// // Process payload... +// } +// +func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err error) { + var body []byte // Raw body that GitHub uses to calculate the signature. + + switch ct := r.Header.Get("Content-Type"); ct { + case "application/json": + var err error + if body, err = ioutil.ReadAll(r.Body); err != nil { + return nil, err + } + + // If the content type is application/json, + // the JSON payload is just the original body. + payload = body + + case "application/x-www-form-urlencoded": + // payloadFormParam is the name of the form parameter that the JSON payload + // will be in if a webhook has its content type set to application/x-www-form-urlencoded. + const payloadFormParam = "payload" + + var err error + if body, err = ioutil.ReadAll(r.Body); err != nil { + return nil, err + } + + // If the content type is application/x-www-form-urlencoded, + // the JSON payload will be under the "payload" form param. + form, err := url.ParseQuery(string(body)) + if err != nil { + return nil, err + } + payload = []byte(form.Get(payloadFormParam)) + + default: + return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", ct) + } + + sig := r.Header.Get(signatureHeader) + if err := validateSignature(sig, body, secretKey); err != nil { + return nil, err + } + return payload, nil +} + +// validateSignature validates the signature for the given payload. +// signature is the GitHub hash signature delivered in the X-Hub-Signature header. +// payload is the JSON payload sent by GitHub Webhooks. +// secretKey is the GitHub Webhook secret message. +// +// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github +func validateSignature(signature string, payload, secretKey []byte) error { + messageMAC, hashFunc, err := messageMAC(signature) + if err != nil { + return err + } + if !checkMAC(payload, messageMAC, secretKey, hashFunc) { + return errors.New("payload signature check failed") + } + return nil +} + +// WebHookType returns the event type of webhook request r. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers +func WebHookType(r *http.Request) string { + return r.Header.Get(eventTypeHeader) +} + +// DeliveryID returns the unique delivery ID of webhook request r. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers +func DeliveryID(r *http.Request) string { + return r.Header.Get(deliveryIDHeader) +} + +// ParseWebHook parses the event payload. For recognized event types, a +// value of the corresponding struct type will be returned (as returned +// by Event.ParsePayload()). An error will be returned for unrecognized event +// types. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// payload, err := github.ValidatePayload(r, s.webhookSecretKey) +// if err != nil { ... } +// event, err := github.ParseWebHook(github.WebHookType(r), payload) +// if err != nil { ... } +// switch event := event.(type) { +// case *github.CommitCommentEvent: +// processCommitCommentEvent(event) +// case *github.CreateEvent: +// processCreateEvent(event) +// ... +// } +// } +// +func ParseWebHook(messageType string, payload []byte) (interface{}, error) { + eventType, ok := eventTypeMapping[messageType] + if !ok { + return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType) + } + + event := Event{ + Type: &eventType, + RawPayload: (*json.RawMessage)(&payload), + } + return event.ParsePayload() +} diff --git a/vendor/github.com/google/go-github/github/migrations.go b/vendor/github.com/google/go-github/github/migrations.go new file mode 100644 index 00000000..90cc1fae --- /dev/null +++ b/vendor/github.com/google/go-github/github/migrations.go @@ -0,0 +1,224 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "net/http" + "strings" +) + +// MigrationService provides access to the migration related functions +// in the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/migration/ +type MigrationService service + +// Migration represents a GitHub migration (archival). +type Migration struct { + ID *int64 `json:"id,omitempty"` + GUID *string `json:"guid,omitempty"` + // State is the current state of a migration. + // Possible values are: + // "pending" which means the migration hasn't started yet, + // "exporting" which means the migration is in progress, + // "exported" which means the migration finished successfully, or + // "failed" which means the migration failed. + State *string `json:"state,omitempty"` + // LockRepositories indicates whether repositories are locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` + URL *string `json:"url,omitempty"` + CreatedAt *string `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +func (m Migration) String() string { + return Stringify(m) +} + +// MigrationOptions specifies the optional parameters to Migration methods. +type MigrationOptions struct { + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories bool + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments bool +} + +// startMigration represents the body of a StartMigration request. +type startMigration struct { + // Repositories is a slice of repository names to migrate. + Repositories []string `json:"repositories,omitempty"` + + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` +} + +// StartMigration starts the generation of a migration archive. +// repos is a slice of repository names to migrate. +// +// GitHub API docs: https://developer.github.com/v3/migration/migrations/#start-a-migration +func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opt *MigrationOptions) (*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations", org) + + body := &startMigration{Repositories: repos} + if opt != nil { + body.LockRepositories = Bool(opt.LockRepositories) + body.ExcludeAttachments = Bool(opt.ExcludeAttachments) + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &Migration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// ListMigrations lists the most recent migrations. +// +// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-a-list-of-migrations +func (s *MigrationService) ListMigrations(ctx context.Context, org string) ([]*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + var m []*Migration + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// MigrationStatus gets the status of a specific migration archive. +// id is the migration ID. +// +// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-the-status-of-a-migration +func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &Migration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// MigrationArchiveURL fetches a migration archive URL. +// id is the migration ID. +// +// GitHub API docs: https://developer.github.com/v3/migration/migrations/#download-a-migration-archive +func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + s.client.clientMu.Lock() + defer s.client.clientMu.Unlock() + + // Disable the redirect mechanism because AWS fails if the GitHub auth token is provided. + var loc string + saveRedirect := s.client.client.CheckRedirect + s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + loc = req.URL.String() + return errors.New("disable redirect") + } + defer func() { s.client.client.CheckRedirect = saveRedirect }() + + _, err = s.client.Do(ctx, req, nil) // expect error from disable redirect + if err == nil { + return "", errors.New("expected redirect, none provided") + } + if !strings.Contains(err.Error(), "disable redirect") { + return "", err + } + return loc, nil +} + +// DeleteMigration deletes a previous migration archive. +// id is the migration ID. +// +// GitHub API docs: https://developer.github.com/v3/migration/migrations/#delete-a-migration-archive +func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnlockRepo unlocks a repository that was locked for migration. +// id is the migration ID. +// You should unlock each migrated repository and delete them when the migration +// is complete and you no longer need the source data. +// +// GitHub API docs: https://developer.github.com/v3/migration/migrations/#unlock-a-repository +func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/migrations_source_import.go b/vendor/github.com/google/go-github/github/migrations_source_import.go new file mode 100644 index 00000000..fd45e780 --- /dev/null +++ b/vendor/github.com/google/go-github/github/migrations_source_import.go @@ -0,0 +1,329 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Import represents a repository import request. +type Import struct { + // The URL of the originating repository. + VCSURL *string `json:"vcs_url,omitempty"` + // The originating VCS type. Can be one of 'subversion', 'git', + // 'mercurial', or 'tfvc'. Without this parameter, the import job will + // take additional time to detect the VCS type before beginning the + // import. This detection step will be reflected in the response. + VCS *string `json:"vcs,omitempty"` + // VCSUsername and VCSPassword are only used for StartImport calls that + // are importing a password-protected repository. + VCSUsername *string `json:"vcs_username,omitempty"` + VCSPassword *string `json:"vcs_password,omitempty"` + // For a tfvc import, the name of the project that is being imported. + TFVCProject *string `json:"tfvc_project,omitempty"` + + // LFS related fields that may be preset in the Import Progress response + + // Describes whether the import has been opted in or out of using Git + // LFS. The value can be 'opt_in', 'opt_out', or 'undecided' if no + // action has been taken. + UseLFS *string `json:"use_lfs,omitempty"` + // Describes whether files larger than 100MB were found during the + // importing step. + HasLargeFiles *bool `json:"has_large_files,omitempty"` + // The total size in gigabytes of files larger than 100MB found in the + // originating repository. + LargeFilesSize *int `json:"large_files_size,omitempty"` + // The total number of files larger than 100MB found in the originating + // repository. To see a list of these files, call LargeFiles. + LargeFilesCount *int `json:"large_files_count,omitempty"` + + // Identifies the current status of an import. An import that does not + // have errors will progress through these steps: + // + // detecting - the "detection" step of the import is in progress + // because the request did not include a VCS parameter. The + // import is identifying the type of source control present at + // the URL. + // importing - the "raw" step of the import is in progress. This is + // where commit data is fetched from the original repository. + // The import progress response will include CommitCount (the + // total number of raw commits that will be imported) and + // Percent (0 - 100, the current progress through the import). + // mapping - the "rewrite" step of the import is in progress. This + // is where SVN branches are converted to Git branches, and + // where author updates are applied. The import progress + // response does not include progress information. + // pushing - the "push" step of the import is in progress. This is + // where the importer updates the repository on GitHub. The + // import progress response will include PushPercent, which is + // the percent value reported by git push when it is "Writing + // objects". + // complete - the import is complete, and the repository is ready + // on GitHub. + // + // If there are problems, you will see one of these in the status field: + // + // auth_failed - the import requires authentication in order to + // connect to the original repository. Make an UpdateImport + // request, and include VCSUsername and VCSPassword. + // error - the import encountered an error. The import progress + // response will include the FailedStep and an error message. + // Contact GitHub support for more information. + // detection_needs_auth - the importer requires authentication for + // the originating repository to continue detection. Make an + // UpdatImport request, and include VCSUsername and + // VCSPassword. + // detection_found_nothing - the importer didn't recognize any + // source control at the URL. + // detection_found_multiple - the importer found several projects + // or repositories at the provided URL. When this is the case, + // the Import Progress response will also include a + // ProjectChoices field with the possible project choices as + // values. Make an UpdateImport request, and include VCS and + // (if applicable) TFVCProject. + Status *string `json:"status,omitempty"` + CommitCount *int `json:"commit_count,omitempty"` + StatusText *string `json:"status_text,omitempty"` + AuthorsCount *int `json:"authors_count,omitempty"` + Percent *int `json:"percent,omitempty"` + PushPercent *int `json:"push_percent,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + AuthorsURL *string `json:"authors_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + Message *string `json:"message,omitempty"` + FailedStep *string `json:"failed_step,omitempty"` + + // Human readable display name, provided when the Import appears as + // part of ProjectChoices. + HumanName *string `json:"human_name,omitempty"` + + // When the importer finds several projects or repositories at the + // provided URLs, this will identify the available choices. Call + // UpdateImport with the selected Import value. + ProjectChoices []Import `json:"project_choices,omitempty"` +} + +func (i Import) String() string { + return Stringify(i) +} + +// SourceImportAuthor identifies an author imported from a source repository. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors +type SourceImportAuthor struct { + ID *int64 `json:"id,omitempty"` + RemoteID *string `json:"remote_id,omitempty"` + RemoteName *string `json:"remote_name,omitempty"` + Email *string `json:"email,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + ImportURL *string `json:"import_url,omitempty"` +} + +func (a SourceImportAuthor) String() string { + return Stringify(a) +} + +// LargeFile identifies a file larger than 100MB found during a repository import. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files +type LargeFile struct { + RefName *string `json:"ref_name,omitempty"` + Path *string `json:"path,omitempty"` + OID *string `json:"oid,omitempty"` + Size *int `json:"size,omitempty"` +} + +func (f LargeFile) String() string { + return Stringify(f) +} + +// StartImport initiates a repository import. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#start-an-import +func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("PUT", u, in) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeImportPreview) + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// ImportProgress queries for the status and progress of an ongoing repository import. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-import-progress +func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeImportPreview) + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// UpdateImport initiates a repository import. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#update-existing-import +func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("PATCH", u, in) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeImportPreview) + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// CommitAuthors gets the authors mapped from the original repository. +// +// Each type of source control system represents authors in a different way. +// For example, a Git commit author has a display name and an email address, +// but a Subversion commit author just has a username. The GitHub Importer will +// make the author information valid, but the author might not be correct. For +// example, it will change the bare Subversion username "hubot" into something +// like "hubot ". +// +// This method and MapCommitAuthor allow you to provide correct Git author +// information. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors +func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string) ([]*SourceImportAuthor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeImportPreview) + + var authors []*SourceImportAuthor + resp, err := s.client.Do(ctx, req, &authors) + if err != nil { + return nil, resp, err + } + + return authors, resp, nil +} + +// MapCommitAuthor updates an author's identity for the import. Your +// application can continue updating authors any time before you push new +// commits to the repository. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#map-a-commit-author +func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo string, id int64, author *SourceImportAuthor) (*SourceImportAuthor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, author) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeImportPreview) + + out := new(SourceImportAuthor) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// SetLFSPreference sets whether imported repositories should use Git LFS for +// files larger than 100MB. Only the UseLFS field on the provided Import is +// used. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#set-git-lfs-preference +func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/lfs", owner, repo) + req, err := s.client.NewRequest("PATCH", u, in) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeImportPreview) + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// LargeFiles lists files larger than 100MB found during the import. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files +func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ([]*LargeFile, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeImportPreview) + + var files []*LargeFile + resp, err := s.client.Do(ctx, req, &files) + if err != nil { + return nil, resp, err + } + + return files, resp, nil +} + +// CancelImport stops an import for a repository. +// +// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#cancel-an-import +func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeImportPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/misc.go b/vendor/github.com/google/go-github/github/misc.go new file mode 100644 index 00000000..e9b0ea22 --- /dev/null +++ b/vendor/github.com/google/go-github/github/misc.go @@ -0,0 +1,257 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "net/url" +) + +// MarkdownOptions specifies optional parameters to the Markdown method. +type MarkdownOptions struct { + // Mode identifies the rendering mode. Possible values are: + // markdown - render a document as plain Markdown, just like + // README files are rendered. + // + // gfm - to render a document as user-content, e.g. like user + // comments or issues are rendered. In GFM mode, hard line breaks are + // always taken into account, and issue and user mentions are linked + // accordingly. + // + // Default is "markdown". + Mode string + + // Context identifies the repository context. Only taken into account + // when rendering as "gfm". + Context string +} + +type markdownRequest struct { + Text *string `json:"text,omitempty"` + Mode *string `json:"mode,omitempty"` + Context *string `json:"context,omitempty"` +} + +// Markdown renders an arbitrary Markdown document. +// +// GitHub API docs: https://developer.github.com/v3/markdown/ +func (c *Client) Markdown(ctx context.Context, text string, opt *MarkdownOptions) (string, *Response, error) { + request := &markdownRequest{Text: String(text)} + if opt != nil { + if opt.Mode != "" { + request.Mode = String(opt.Mode) + } + if opt.Context != "" { + request.Context = String(opt.Context) + } + } + + req, err := c.NewRequest("POST", "markdown", request) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := c.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// ListEmojis returns the emojis available to use on GitHub. +// +// GitHub API docs: https://developer.github.com/v3/emojis/ +func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error) { + req, err := c.NewRequest("GET", "emojis", nil) + if err != nil { + return nil, nil, err + } + + var emoji map[string]string + resp, err := c.Do(ctx, req, &emoji) + if err != nil { + return nil, resp, err + } + + return emoji, resp, nil +} + +// CodeOfConduct represents a code of conduct. +type CodeOfConduct struct { + Name *string `json:"name,omitempty"` + Key *string `json:"key,omitempty"` + URL *string `json:"url,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (c *CodeOfConduct) String() string { + return Stringify(c) +} + +// ListCodesOfConduct returns all codes of conduct. +// +// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#list-all-codes-of-conduct +func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error) { + req, err := c.NewRequest("GET", "codes_of_conduct", nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + var cs []*CodeOfConduct + resp, err := c.Do(ctx, req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, nil +} + +// GetCodeOfConduct returns an individual code of conduct. +// +// https://developer.github.com/v3/codes_of_conduct/#get-an-individual-code-of-conduct +func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error) { + u := fmt.Sprintf("codes_of_conduct/%s", key) + req, err := c.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + coc := new(CodeOfConduct) + resp, err := c.Do(ctx, req, coc) + if err != nil { + return nil, resp, err + } + + return coc, resp, nil +} + +// APIMeta represents metadata about the GitHub API. +type APIMeta struct { + // An Array of IP addresses in CIDR format specifying the addresses + // that incoming service hooks will originate from on GitHub.com. + Hooks []string `json:"hooks,omitempty"` + + // An Array of IP addresses in CIDR format specifying the Git servers + // for GitHub.com. + Git []string `json:"git,omitempty"` + + // Whether authentication with username and password is supported. + // (GitHub Enterprise instances using CAS or OAuth for authentication + // will return false. Features like Basic Authentication with a + // username and password, sudo mode, and two-factor authentication are + // not supported on these servers.) + VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub Pages websites. + Pages []string `json:"pages,omitempty"` + + // An Array of IP addresses specifying the addresses that source imports + // will originate from on GitHub.com. + Importer []string `json:"importer,omitempty"` +} + +// APIMeta returns information about GitHub.com, the service. Or, if you access +// this endpoint on your organization’s GitHub Enterprise installation, this +// endpoint provides information about that installation. +// +// GitHub API docs: https://developer.github.com/v3/meta/ +func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error) { + req, err := c.NewRequest("GET", "meta", nil) + if err != nil { + return nil, nil, err + } + + meta := new(APIMeta) + resp, err := c.Do(ctx, req, meta) + if err != nil { + return nil, resp, err + } + + return meta, resp, nil +} + +// Octocat returns an ASCII art octocat with the specified message in a speech +// bubble. If message is empty, a random zen phrase is used. +func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error) { + u := "octocat" + if message != "" { + u = fmt.Sprintf("%s?s=%s", u, url.QueryEscape(message)) + } + + req, err := c.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := c.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// Zen returns a random line from The Zen of GitHub. +// +// see also: http://warpspire.com/posts/taste/ +func (c *Client) Zen(ctx context.Context) (string, *Response, error) { + req, err := c.NewRequest("GET", "zen", nil) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := c.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// ServiceHook represents a hook that has configuration settings, a list of +// available events, and default events. +type ServiceHook struct { + Name *string `json:"name,omitempty"` + Events []string `json:"events,omitempty"` + SupportedEvents []string `json:"supported_events,omitempty"` + Schema [][]string `json:"schema,omitempty"` +} + +func (s *ServiceHook) String() string { + return Stringify(s) +} + +// ListServiceHooks lists all of the available service hooks. +// +// GitHub API docs: https://developer.github.com/webhooks/#services +func (c *Client) ListServiceHooks(ctx context.Context) ([]*ServiceHook, *Response, error) { + u := "hooks" + req, err := c.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*ServiceHook + resp, err := c.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/orgs.go b/vendor/github.com/google/go-github/github/orgs.go new file mode 100644 index 00000000..78320535 --- /dev/null +++ b/vendor/github.com/google/go-github/github/orgs.go @@ -0,0 +1,212 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// OrganizationsService provides access to the organization related functions +// in the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/orgs/ +type OrganizationsService service + +// Organization represents a GitHub organization account. +type Organization struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Name *string `json:"name,omitempty"` + Company *string `json:"company,omitempty"` + Blog *string `json:"blog,omitempty"` + Location *string `json:"location,omitempty"` + Email *string `json:"email,omitempty"` + Description *string `json:"description,omitempty"` + PublicRepos *int `json:"public_repos,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` + Followers *int `json:"followers,omitempty"` + Following *int `json:"following,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + TotalPrivateRepos *int `json:"total_private_repos,omitempty"` + OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + DiskUsage *int `json:"disk_usage,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + BillingEmail *string `json:"billing_email,omitempty"` + Type *string `json:"type,omitempty"` + Plan *Plan `json:"plan,omitempty"` + NodeID *string `json:"node_id,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + HooksURL *string `json:"hooks_url,omitempty"` + IssuesURL *string `json:"issues_url,omitempty"` + MembersURL *string `json:"members_url,omitempty"` + PublicMembersURL *string `json:"public_members_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` +} + +func (o Organization) String() string { + return Stringify(o) +} + +// Plan represents the payment plan for an account. See plans at https://github.com/plans. +type Plan struct { + Name *string `json:"name,omitempty"` + Space *int `json:"space,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + PrivateRepos *int `json:"private_repos,omitempty"` +} + +func (p Plan) String() string { + return Stringify(p) +} + +// OrganizationsListOptions specifies the optional parameters to the +// OrganizationsService.ListAll method. +type OrganizationsListOptions struct { + // Since filters Organizations by ID. + Since int64 `url:"since,omitempty"` + + // Note: Pagination is powered exclusively by the Since parameter, + // ListOptions.Page has no effect. + // ListOptions.PerPage controls an undocumented GitHub API parameter. + ListOptions +} + +// ListAll lists all organizations, in the order that they were created on GitHub. +// +// Note: Pagination is powered exclusively by the since parameter. To continue +// listing the next set of organizations, use the ID of the last-returned organization +// as the opts.Since parameter for the next call. +// +// GitHub API docs: https://developer.github.com/v3/orgs/#list-all-organizations +func (s *OrganizationsService) ListAll(ctx context.Context, opt *OrganizationsListOptions) ([]*Organization, *Response, error) { + u, err := addOptions("organizations", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + orgs := []*Organization{} + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + return orgs, resp, nil +} + +// List the organizations for a user. Passing the empty string will list +// organizations for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/orgs/#list-user-organizations +func (s *OrganizationsService) List(ctx context.Context, user string, opt *ListOptions) ([]*Organization, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/orgs", user) + } else { + u = "user/orgs" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var orgs []*Organization + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + + return orgs, resp, nil +} + +// Get fetches an organization by name. +// +// GitHub API docs: https://developer.github.com/v3/orgs/#get-an-organization +func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organization, *Response, error) { + u := fmt.Sprintf("orgs/%v", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + organization := new(Organization) + resp, err := s.client.Do(ctx, req, organization) + if err != nil { + return nil, resp, err + } + + return organization, resp, nil +} + +// GetByID fetches an organization. +// +// Note: GetByID uses the undocumented GitHub API endpoint /organizations/:id. +func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organization, *Response, error) { + u := fmt.Sprintf("organizations/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + organization := new(Organization) + resp, err := s.client.Do(ctx, req, organization) + if err != nil { + return nil, resp, err + } + + return organization, resp, nil +} + +// Edit an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/#edit-an-organization +func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) { + u := fmt.Sprintf("orgs/%v", name) + req, err := s.client.NewRequest("PATCH", u, org) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + o := new(Organization) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/orgs_hooks.go b/vendor/github.com/google/go-github/github/orgs_hooks.go new file mode 100644 index 00000000..ab1d02da --- /dev/null +++ b/vendor/github.com/google/go-github/github/orgs_hooks.go @@ -0,0 +1,107 @@ +// Copyright 2015 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHooks lists all Hooks for the specified organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-hooks +func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opt *ListOptions) ([]*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*Hook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook +func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + hook := new(Hook) + resp, err := s.client.Do(ctx, req, hook) + return hook, resp, err +} + +// CreateHook creates a Hook for the specified org. +// Name and Config are required fields. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-a-hook +func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks", org) + req, err := s.client.NewRequest("POST", u, hook) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook +func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + return h, resp, err +} + +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-a-hook +func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook +func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/orgs_members.go b/vendor/github.com/google/go-github/github/orgs_members.go new file mode 100644 index 00000000..98e138e7 --- /dev/null +++ b/vendor/github.com/google/go-github/github/orgs_members.go @@ -0,0 +1,370 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Membership represents the status of a user's membership in an organization or team. +type Membership struct { + URL *string `json:"url,omitempty"` + + // State is the user's status within the organization or team. + // Possible values are: "active", "pending" + State *string `json:"state,omitempty"` + + // Role identifies the user's role within the organization or team. + // Possible values for organization membership: + // member - non-owner organization member + // admin - organization owner + // + // Possible values for team membership are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description + Role *string `json:"role,omitempty"` + + // For organization membership, the API URL of the organization. + OrganizationURL *string `json:"organization_url,omitempty"` + + // For organization membership, the organization the membership is for. + Organization *Organization `json:"organization,omitempty"` + + // For organization membership, the user the membership is for. + User *User `json:"user,omitempty"` +} + +func (m Membership) String() string { + return Stringify(m) +} + +// ListMembersOptions specifies optional parameters to the +// OrganizationsService.ListMembers method. +type ListMembersOptions struct { + // If true (or if the authenticated user is not an owner of the + // organization), list only publicly visible members. + PublicOnly bool `url:"-"` + + // Filter members returned in the list. Possible values are: + // 2fa_disabled, all. Default is "all". + Filter string `url:"filter,omitempty"` + + // Role filters members returned by their role in the organization. + // Possible values are: + // all - all members of the organization, regardless of role + // admin - organization owners + // member - non-organization members + // + // Default is "all". + Role string `url:"role,omitempty"` + + ListOptions +} + +// ListMembers lists the members for an organization. If the authenticated +// user is an owner of the organization, this will return both concealed and +// public members, otherwise it will only return public members. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#members-list +func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opt *ListMembersOptions) ([]*User, *Response, error) { + var u string + if opt != nil && opt.PublicOnly { + u = fmt.Sprintf("orgs/%v/public_members", org) + } else { + u = fmt.Sprintf("orgs/%v/members", org) + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// IsMember checks if a user is a member of an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-membership +func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/members/%v", org, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + member, err := parseBoolResponse(err) + return member, resp, err +} + +// IsPublicMember checks if a user is a public member of an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-public-membership +func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + member, err := parseBoolResponse(err) + return member, resp, err +} + +// RemoveMember removes a user from all teams of an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-a-member +func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/members/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PublicizeMembership publicizes a user's membership in an organization. (A +// user cannot publicize the membership for another user.) +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#publicize-a-users-membership +func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ConcealMembership conceals a user's membership in an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#conceal-a-users-membership +func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListOrgMembershipsOptions specifies optional parameters to the +// OrganizationsService.ListOrgMemberships method. +type ListOrgMembershipsOptions struct { + // Filter memberships to include only those with the specified state. + // Possible values are: "active", "pending". + State string `url:"state,omitempty"` + + ListOptions +} + +// ListOrgMemberships lists the organization memberships for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-your-organization-memberships +func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opt *ListOrgMembershipsOptions) ([]*Membership, *Response, error) { + u := "user/memberships/orgs" + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var memberships []*Membership + resp, err := s.client.Do(ctx, req, &memberships) + if err != nil { + return nil, resp, err + } + + return memberships, resp, nil +} + +// GetOrgMembership gets the membership for a user in a specified organization. +// Passing an empty string for user will get the membership for the +// authenticated user. +// +// GitHub API docs: +// https://developer.github.com/v3/orgs/members/#get-organization-membership +// https://developer.github.com/v3/orgs/members/#get-your-organization-membership +func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) + } else { + u = fmt.Sprintf("user/memberships/orgs/%v", org) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + membership := new(Membership) + resp, err := s.client.Do(ctx, req, membership) + if err != nil { + return nil, resp, err + } + + return membership, resp, nil +} + +// EditOrgMembership edits the membership for user in specified organization. +// Passing an empty string for user will edit the membership for the +// authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership +// GitHub API docs: https://developer.github.com/v3/orgs/members/#edit-your-organization-membership +func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) { + var u, method string + if user != "" { + u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) + method = "PUT" + } else { + u = fmt.Sprintf("user/memberships/orgs/%v", org) + method = "PATCH" + } + + req, err := s.client.NewRequest(method, u, membership) + if err != nil { + return nil, nil, err + } + + m := new(Membership) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// RemoveOrgMembership removes user from the specified organization. If the +// user has been invited to the organization, this will cancel their invitation. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-organization-membership +func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, org string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/memberships/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListPendingOrgInvitations returns a list of pending invitations. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations +func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opt *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + return pendingInvitations, resp, nil +} + +// CreateOrgInvitationOptions specifies the parameters to the OrganizationService.Invite +// method. +type CreateOrgInvitationOptions struct { + // GitHub user ID for the person you are inviting. Not required if you provide Email. + InviteeID *int64 `json:"invitee_id,omitempty"` + // Email address of the person you are inviting, which can be an existing GitHub user. + // Not required if you provide InviteeID + Email *string `json:"email,omitempty"` + // Specify role for new member. Can be one of: + // * admin - Organization owners with full administrative rights to the + // organization and complete access to all repositories and teams. + // * direct_member - Non-owner organization members with ability to see + // other members and join teams by invitation. + // * billing_manager - Non-owner organization members with ability to + // manage the billing settings of your organization. + // Default is "direct_member". + Role *string `json:"role"` + TeamID []int64 `json:"team_ids"` +} + +// CreateOrgInvitation invites people to an organization by using their GitHub user ID or their email address. +// In order to create invitations in an organization, +// the authenticated user must be an organization owner. +// +// https://developer.github.com/v3/orgs/members/#create-organization-invitation +func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opt *CreateOrgInvitationOptions) (*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations", org) + + req, err := s.client.NewRequest("POST", u, opt) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview) + + var invitation *Invitation + resp, err := s.client.Do(ctx, req, &invitation) + if err != nil { + return nil, resp, err + } + return invitation, resp, nil +} + +// ListOrgInvitationTeams lists all teams associated with an invitation. In order to see invitations in an organization, +// the authenticated user must be an organization owner. +// +// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-invitation-teams +func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opt *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview) + + var orgInvitationTeams []*Team + resp, err := s.client.Do(ctx, req, &orgInvitationTeams) + if err != nil { + return nil, resp, err + } + return orgInvitationTeams, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/orgs_outside_collaborators.go b/vendor/github.com/google/go-github/github/orgs_outside_collaborators.go new file mode 100644 index 00000000..85ffd05f --- /dev/null +++ b/vendor/github.com/google/go-github/github/orgs_outside_collaborators.go @@ -0,0 +1,81 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListOutsideCollaboratorsOptions specifies optional parameters to the +// OrganizationsService.ListOutsideCollaborators method. +type ListOutsideCollaboratorsOptions struct { + // Filter outside collaborators returned in the list. Possible values are: + // 2fa_disabled, all. Default is "all". + Filter string `url:"filter,omitempty"` + + ListOptions +} + +// ListOutsideCollaborators lists outside collaborators of organization's repositories. +// This will only work if the authenticated +// user is an owner of the organization. +// +// Warning: The API may change without advance notice during the preview period. +// Preview features are not supported for production use. +// +// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#list-outside-collaborators +func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opt *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// RemoveOutsideCollaborator removes a user from the list of outside collaborators; +// consequently, removing them from all the organization's repositories. +// +// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#remove-outside-collaborator +func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ConvertMemberToOutsideCollaborator reduces the permission level of a member of the +// organization to that of an outside collaborator. Therefore, they will only +// have access to the repositories that their current team membership allows. +// Responses for converting a non-member or the last owner to an outside collaborator +// are listed in GitHub API docs. +// +// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#convert-member-to-outside-collaborator +func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/orgs_projects.go b/vendor/github.com/google/go-github/github/orgs_projects.go new file mode 100644 index 00000000..e57cba97 --- /dev/null +++ b/vendor/github.com/google/go-github/github/orgs_projects.go @@ -0,0 +1,60 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListProjects lists the projects for an organization. +// +// GitHub API docs: https://developer.github.com/v3/projects/#list-organization-projects +func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opt *ProjectListOptions) ([]*Project, *Response, error) { + u := fmt.Sprintf("orgs/%v/projects", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var projects []*Project + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// CreateProject creates a GitHub Project for the specified organization. +// +// GitHub API docs: https://developer.github.com/v3/projects/#create-an-organization-project +func (s *OrganizationsService) CreateProject(ctx context.Context, org string, opt *ProjectOptions) (*Project, *Response, error) { + u := fmt.Sprintf("orgs/%v/projects", org) + req, err := s.client.NewRequest("POST", u, opt) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/orgs_teams.go b/vendor/github.com/google/go-github/github/orgs_teams.go new file mode 100644 index 00000000..b3cc9f07 --- /dev/null +++ b/vendor/github.com/google/go-github/github/orgs_teams.go @@ -0,0 +1,514 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" + "time" +) + +// Team represents a team within a GitHub organization. Teams are used to +// manage access to an organization's repositories. +type Team struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + URL *string `json:"url,omitempty"` + Slug *string `json:"slug,omitempty"` + + // Permission specifies the default permission for repositories owned by the team. + Permission *string `json:"permission,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + + MembersCount *int `json:"members_count,omitempty"` + ReposCount *int `json:"repos_count,omitempty"` + Organization *Organization `json:"organization,omitempty"` + MembersURL *string `json:"members_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` + Parent *Team `json:"parent,omitempty"` + + // LDAPDN is only available in GitHub Enterprise and when the team + // membership is synchronized with LDAP. + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +func (t Team) String() string { + return Stringify(t) +} + +// Invitation represents a team member's invitation status. +type Invitation struct { + ID *int64 `json:"id,omitempty"` + Login *string `json:"login,omitempty"` + Email *string `json:"email,omitempty"` + // Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'. + Role *string `json:"role,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + Inviter *User `json:"inviter,omitempty"` + TeamCount *int `json:"team_count,omitempty"` + InvitationTeamURL *string `json:"invitation_team_url,omitempty"` +} + +func (i Invitation) String() string { + return Stringify(i) +} + +// ListTeams lists all of the teams for an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#list-teams +func (s *OrganizationsService) ListTeams(ctx context.Context, org string, opt *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// GetTeam fetches a team by ID. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#get-team +func (s *OrganizationsService) GetTeam(ctx context.Context, team int64) (*Team, *Response, error) { + u := fmt.Sprintf("teams/%v", team) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// NewTeam represents a team to be created or modified. +type NewTeam struct { + Name string `json:"name"` // Name of the team. (Required.) + Description *string `json:"description,omitempty"` + Maintainers []string `json:"maintainers,omitempty"` + RepoNames []string `json:"repo_names,omitempty"` + ParentTeamID *int64 `json:"parent_team_id,omitempty"` + + // Deprecated: Permission is deprecated when creating or editing a team in an org + // using the new GitHub permission model. It no longer identifies the + // permission a team has on its repos, but only specifies the default + // permission a repo is initially added with. Avoid confusion by + // specifying a permission value when calling AddTeamRepo. + Permission *string `json:"permission,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + + // LDAPDN may be used in GitHub Enterprise when the team membership + // is synchronized with LDAP. + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +func (s NewTeam) String() string { + return Stringify(s) +} + +// CreateTeam creates a new team within an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#create-team +func (s *OrganizationsService) CreateTeam(ctx context.Context, org string, team *NewTeam) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams", org) + req, err := s.client.NewRequest("POST", u, team) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// EditTeam edits a team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#edit-team +func (s *OrganizationsService) EditTeam(ctx context.Context, id int64, team *NewTeam) (*Team, *Response, error) { + u := fmt.Sprintf("teams/%v", id) + req, err := s.client.NewRequest("PATCH", u, team) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// DeleteTeam deletes a team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#delete-team +func (s *OrganizationsService) DeleteTeam(ctx context.Context, team int64) (*Response, error) { + u := fmt.Sprintf("teams/%v", team) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + return s.client.Do(ctx, req, nil) +} + +// OrganizationListTeamMembersOptions specifies the optional parameters to the +// OrganizationsService.ListTeamMembers method. +type OrganizationListTeamMembersOptions struct { + // Role filters members returned by their role in the team. Possible + // values are "all", "member", "maintainer". Default is "all". + Role string `url:"role,omitempty"` + + ListOptions +} + +// ListChildTeams lists child teams for a team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#list-child-teams +func (s *OrganizationsService) ListChildTeams(ctx context.Context, teamID int64, opt *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("teams/%v/teams", teamID) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListTeamMembers lists all of the users who are members of the specified +// team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#list-team-members +func (s *OrganizationsService) ListTeamMembers(ctx context.Context, team int64, opt *OrganizationListTeamMembersOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("teams/%v/members", team) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// IsTeamMember checks if a user is a member of the specified team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#get-team-member +// +// Deprecated: This API has been marked as deprecated in the Github API docs, +// OrganizationsService.GetTeamMembership method should be used instead. +func (s *OrganizationsService) IsTeamMember(ctx context.Context, team int64, user string) (bool, *Response, error) { + u := fmt.Sprintf("teams/%v/members/%v", team, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + member, err := parseBoolResponse(err) + return member, resp, err +} + +// ListTeamRepos lists the repositories that the specified team has access to. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#list-team-repos +func (s *OrganizationsService) ListTeamRepos(ctx context.Context, team int64, opt *ListOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("teams/%v/repos", team) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + headers := []string{mediaTypeTopicsPreview, mediaTypeNestedTeamsPreview} + req.Header.Set("Accept", strings.Join(headers, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// IsTeamRepo checks if a team manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#check-if-a-team-manages-a-repository +func (s *OrganizationsService) IsTeamRepo(ctx context.Context, team int64, owner string, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + headers := []string{mediaTypeOrgPermissionRepo, mediaTypeNestedTeamsPreview} + req.Header.Set("Accept", strings.Join(headers, ", ")) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// OrganizationAddTeamRepoOptions specifies the optional parameters to the +// OrganizationsService.AddTeamRepo method. +type OrganizationAddTeamRepoOptions struct { + // Permission specifies the permission to grant the team on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // + // If not specified, the team's permission attribute will be used. + Permission string `json:"permission,omitempty"` +} + +// AddTeamRepo adds a repository to be managed by the specified team. The +// specified repository must be owned by the organization to which the team +// belongs, or a direct fork of a repository owned by the organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#add-team-repo +func (s *OrganizationsService) AddTeamRepo(ctx context.Context, team int64, owner string, repo string, opt *OrganizationAddTeamRepoOptions) (*Response, error) { + u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) + req, err := s.client.NewRequest("PUT", u, opt) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamRepo removes a repository from being managed by the specified +// team. Note that this does not delete the repository, it just removes it +// from the team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#remove-team-repo +func (s *OrganizationsService) RemoveTeamRepo(ctx context.Context, team int64, owner string, repo string) (*Response, error) { + u := fmt.Sprintf("teams/%v/repos/%v/%v", team, owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListUserTeams lists a user's teams +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#list-user-teams +func (s *OrganizationsService) ListUserTeams(ctx context.Context, opt *ListOptions) ([]*Team, *Response, error) { + u := "user/teams" + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// GetTeamMembership returns the membership status for a user in a team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#get-team-membership +func (s *OrganizationsService) GetTeamMembership(ctx context.Context, team int64, user string) (*Membership, *Response, error) { + u := fmt.Sprintf("teams/%v/memberships/%v", team, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// OrganizationAddTeamMembershipOptions does stuff specifies the optional +// parameters to the OrganizationsService.AddTeamMembership method. +type OrganizationAddTeamMembershipOptions struct { + // Role specifies the role the user should have in the team. Possible + // values are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description + // + // Default value is "member". + Role string `json:"role,omitempty"` +} + +// AddTeamMembership adds or invites a user to a team. +// +// In order to add a membership between a user and a team, the authenticated +// user must have 'admin' permissions to the team or be an owner of the +// organization that the team is associated with. +// +// If the user is already a part of the team's organization (meaning they're on +// at least one other team in the organization), this endpoint will add the +// user to the team. +// +// If the user is completely unaffiliated with the team's organization (meaning +// they're on none of the organization's teams), this endpoint will send an +// invitation to the user via email. This newly-created membership will be in +// the "pending" state until the user accepts the invitation, at which point +// the membership will transition to the "active" state and the user will be +// added as a member of the team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#add-team-membership +func (s *OrganizationsService) AddTeamMembership(ctx context.Context, team int64, user string, opt *OrganizationAddTeamMembershipOptions) (*Membership, *Response, error) { + u := fmt.Sprintf("teams/%v/memberships/%v", team, user) + req, err := s.client.NewRequest("PUT", u, opt) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// RemoveTeamMembership removes a user from a team. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#remove-team-membership +func (s *OrganizationsService) RemoveTeamMembership(ctx context.Context, team int64, user string) (*Response, error) { + u := fmt.Sprintf("teams/%v/memberships/%v", team, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListPendingTeamInvitations get pending invitaion list in team. +// Warning: The API may change without advance notice during the preview period. +// Preview features are not supported for production use. +// +// GitHub API docs: https://developer.github.com/v3/orgs/teams/#list-pending-team-invitations +func (s *OrganizationsService) ListPendingTeamInvitations(ctx context.Context, team int64, opt *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("teams/%v/invitations", team) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/orgs_users_blocking.go b/vendor/github.com/google/go-github/github/orgs_users_blocking.go new file mode 100644 index 00000000..b1aecf44 --- /dev/null +++ b/vendor/github.com/google/go-github/github/orgs_users_blocking.go @@ -0,0 +1,91 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListBlockedUsers lists all the users blocked by an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#list-blocked-users +func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opt *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/blocks", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + var blockedUsers []*User + resp, err := s.client.Do(ctx, req, &blockedUsers) + if err != nil { + return nil, resp, err + } + + return blockedUsers, resp, nil +} + +// IsBlocked reports whether specified user is blocked from an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#check-whether-a-user-is-blocked-from-an-organization +func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + resp, err := s.client.Do(ctx, req, nil) + isBlocked, err := parseBoolResponse(err) + return isBlocked, resp, err +} + +// BlockUser blocks specified user from an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#block-a-user +func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnblockUser unblocks specified user from an organization. +// +// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#unblock-a-user +func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/projects.go b/vendor/github.com/google/go-github/github/projects.go new file mode 100644 index 00000000..409ed4a2 --- /dev/null +++ b/vendor/github.com/google/go-github/github/projects.go @@ -0,0 +1,445 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// ProjectsService provides access to the projects functions in the +// GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/projects/ +type ProjectsService service + +// Project represents a GitHub Project. +type Project struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + OwnerURL *string `json:"owner_url,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Number *int `json:"number,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` + + // The User object that generated the project. + Creator *User `json:"creator,omitempty"` +} + +func (p Project) String() string { + return Stringify(p) +} + +// GetProject gets a GitHub Project for a repo. +// +// GitHub API docs: https://developer.github.com/v3/projects/#get-a-project +func (s *ProjectsService) GetProject(ctx context.Context, id int64) (*Project, *Response, error) { + u := fmt.Sprintf("projects/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} + +// ProjectOptions specifies the parameters to the +// RepositoriesService.CreateProject and +// ProjectsService.UpdateProject methods. +type ProjectOptions struct { + // The name of the project. (Required for creation; optional for update.) + Name string `json:"name,omitempty"` + // The body of the project. (Optional.) + Body string `json:"body,omitempty"` + + // The following field(s) are only applicable for update. + // They should be left with zero values for creation. + + // State of the project. Either "open" or "closed". (Optional.) + State string `json:"state,omitempty"` +} + +// UpdateProject updates a repository project. +// +// GitHub API docs: https://developer.github.com/v3/projects/#update-a-project +func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opt *ProjectOptions) (*Project, *Response, error) { + u := fmt.Sprintf("projects/%v", id) + req, err := s.client.NewRequest("PATCH", u, opt) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} + +// DeleteProject deletes a GitHub Project from a repository. +// +// GitHub API docs: https://developer.github.com/v3/projects/#delete-a-project +func (s *ProjectsService) DeleteProject(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("projects/%v", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectColumn represents a column of a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/repos/projects/ +type ProjectColumn struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + ProjectURL *string `json:"project_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// ListProjectColumns lists the columns of a GitHub Project for a repo. +// +// GitHub API docs: https://developer.github.com/v3/projects/columns/#list-project-columns +func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opt *ListOptions) ([]*ProjectColumn, *Response, error) { + u := fmt.Sprintf("projects/%v/columns", projectID) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + columns := []*ProjectColumn{} + resp, err := s.client.Do(ctx, req, &columns) + if err != nil { + return nil, resp, err + } + + return columns, resp, nil +} + +// GetProjectColumn gets a column of a GitHub Project for a repo. +// +// GitHub API docs: https://developer.github.com/v3/projects/columns/#get-a-project-column +func (s *ProjectsService) GetProjectColumn(ctx context.Context, id int64) (*ProjectColumn, *Response, error) { + u := fmt.Sprintf("projects/columns/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + column := &ProjectColumn{} + resp, err := s.client.Do(ctx, req, column) + if err != nil { + return nil, resp, err + } + + return column, resp, nil +} + +// ProjectColumnOptions specifies the parameters to the +// ProjectsService.CreateProjectColumn and +// ProjectsService.UpdateProjectColumn methods. +type ProjectColumnOptions struct { + // The name of the project column. (Required for creation and update.) + Name string `json:"name"` +} + +// CreateProjectColumn creates a column for the specified (by number) project. +// +// GitHub API docs: https://developer.github.com/v3/projects/columns/#create-a-project-column +func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) { + u := fmt.Sprintf("projects/%v/columns", projectID) + req, err := s.client.NewRequest("POST", u, opt) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + column := &ProjectColumn{} + resp, err := s.client.Do(ctx, req, column) + if err != nil { + return nil, resp, err + } + + return column, resp, nil +} + +// UpdateProjectColumn updates a column of a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/columns/#update-a-project-column +func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnOptions) (*ProjectColumn, *Response, error) { + u := fmt.Sprintf("projects/columns/%v", columnID) + req, err := s.client.NewRequest("PATCH", u, opt) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + column := &ProjectColumn{} + resp, err := s.client.Do(ctx, req, column) + if err != nil { + return nil, resp, err + } + + return column, resp, nil +} + +// DeleteProjectColumn deletes a column from a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/columns/#delete-a-project-column +func (s *ProjectsService) DeleteProjectColumn(ctx context.Context, columnID int64) (*Response, error) { + u := fmt.Sprintf("projects/columns/%v", columnID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectColumnMoveOptions specifies the parameters to the +// ProjectsService.MoveProjectColumn method. +type ProjectColumnMoveOptions struct { + // Position can be one of "first", "last", or "after:", where + // is the ID of a column in the same project. (Required.) + Position string `json:"position"` +} + +// MoveProjectColumn moves a column within a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/columns/#move-a-project-column +func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opt *ProjectColumnMoveOptions) (*Response, error) { + u := fmt.Sprintf("projects/columns/%v/moves", columnID) + req, err := s.client.NewRequest("POST", u, opt) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectCard represents a card in a column of a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card +type ProjectCard struct { + URL *string `json:"url,omitempty"` + ColumnURL *string `json:"column_url,omitempty"` + ContentURL *string `json:"content_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Note *string `json:"note,omitempty"` + Creator *User `json:"creator,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` + + // The following fields are only populated by Webhook events. + ColumnID *int64 `json:"column_id,omitempty"` +} + +// ListProjectCards lists the cards in a column of a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/cards/#list-project-cards +func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opt *ListOptions) ([]*ProjectCard, *Response, error) { + u := fmt.Sprintf("projects/columns/%v/cards", columnID) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + cards := []*ProjectCard{} + resp, err := s.client.Do(ctx, req, &cards) + if err != nil { + return nil, resp, err + } + + return cards, resp, nil +} + +// GetProjectCard gets a card in a column of a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card +func (s *ProjectsService) GetProjectCard(ctx context.Context, columnID int64) (*ProjectCard, *Response, error) { + u := fmt.Sprintf("projects/columns/cards/%v", columnID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + card := &ProjectCard{} + resp, err := s.client.Do(ctx, req, card) + if err != nil { + return nil, resp, err + } + + return card, resp, nil +} + +// ProjectCardOptions specifies the parameters to the +// ProjectsService.CreateProjectCard and +// ProjectsService.UpdateProjectCard methods. +type ProjectCardOptions struct { + // The note of the card. Note and ContentID are mutually exclusive. + Note string `json:"note,omitempty"` + // The ID (not Number) of the Issue to associate with this card. + // Note and ContentID are mutually exclusive. + ContentID int64 `json:"content_id,omitempty"` + // The type of content to associate with this card. Possible values are: "Issue". + ContentType string `json:"content_type,omitempty"` +} + +// CreateProjectCard creates a card in the specified column of a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/cards/#create-a-project-card +func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) { + u := fmt.Sprintf("projects/columns/%v/cards", columnID) + req, err := s.client.NewRequest("POST", u, opt) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + card := &ProjectCard{} + resp, err := s.client.Do(ctx, req, card) + if err != nil { + return nil, resp, err + } + + return card, resp, nil +} + +// UpdateProjectCard updates a card of a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/cards/#update-a-project-card +func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opt *ProjectCardOptions) (*ProjectCard, *Response, error) { + u := fmt.Sprintf("projects/columns/cards/%v", cardID) + req, err := s.client.NewRequest("PATCH", u, opt) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + card := &ProjectCard{} + resp, err := s.client.Do(ctx, req, card) + if err != nil { + return nil, resp, err + } + + return card, resp, nil +} + +// DeleteProjectCard deletes a card from a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/cards/#delete-a-project-card +func (s *ProjectsService) DeleteProjectCard(ctx context.Context, cardID int64) (*Response, error) { + u := fmt.Sprintf("projects/columns/cards/%v", cardID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectCardMoveOptions specifies the parameters to the +// ProjectsService.MoveProjectCard method. +type ProjectCardMoveOptions struct { + // Position can be one of "top", "bottom", or "after:", where + // is the ID of a card in the same project. + Position string `json:"position"` + // ColumnID is the ID of a column in the same project. Note that ColumnID + // is required when using Position "after:" when that card is in + // another column; otherwise it is optional. + ColumnID int64 `json:"column_id,omitempty"` +} + +// MoveProjectCard moves a card within a GitHub Project. +// +// GitHub API docs: https://developer.github.com/v3/projects/cards/#move-a-project-card +func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opt *ProjectCardMoveOptions) (*Response, error) { + u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID) + req, err := s.client.NewRequest("POST", u, opt) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/pulls.go b/vendor/github.com/google/go-github/github/pulls.go new file mode 100644 index 00000000..1f344690 --- /dev/null +++ b/vendor/github.com/google/go-github/github/pulls.go @@ -0,0 +1,380 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "strings" + "time" +) + +// PullRequestsService handles communication with the pull request related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/pulls/ +type PullRequestsService service + +// PullRequest represents a GitHub pull request on a repository. +type PullRequest struct { + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + ClosedAt *time.Time `json:"closed_at,omitempty"` + MergedAt *time.Time `json:"merged_at,omitempty"` + Labels []*Label `json:"labels,omitempty"` + User *User `json:"user,omitempty"` + Merged *bool `json:"merged,omitempty"` + Mergeable *bool `json:"mergeable,omitempty"` + MergeableState *string `json:"mergeable_state,omitempty"` + MergedBy *User `json:"merged_by,omitempty"` + MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` + Comments *int `json:"comments,omitempty"` + Commits *int `json:"commits,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + ChangedFiles *int `json:"changed_files,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + ReviewCommentsURL *string `json:"review_comments_url,omitempty"` + ReviewCommentURL *string `json:"review_comment_url,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RequestedReviewers []*User `json:"requested_reviewers,omitempty"` + + Head *PullRequestBranch `json:"head,omitempty"` + Base *PullRequestBranch `json:"base,omitempty"` +} + +func (p PullRequest) String() string { + return Stringify(p) +} + +// PullRequestBranch represents a base or head branch in a GitHub pull request. +type PullRequestBranch struct { + Label *string `json:"label,omitempty"` + Ref *string `json:"ref,omitempty"` + SHA *string `json:"sha,omitempty"` + Repo *Repository `json:"repo,omitempty"` + User *User `json:"user,omitempty"` +} + +// PullRequestListOptions specifies the optional parameters to the +// PullRequestsService.List method. +type PullRequestListOptions struct { + // State filters pull requests based on their state. Possible values are: + // open, closed. Default is "open". + State string `url:"state,omitempty"` + + // Head filters pull requests by head user and branch name in the format of: + // "user:ref-name". + Head string `url:"head,omitempty"` + + // Base filters pull requests by base branch name. + Base string `url:"base,omitempty"` + + // Sort specifies how to sort pull requests. Possible values are: created, + // updated, popularity, long-running. Default is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort pull requests. Possible values are: asc, desc. + // If Sort is "created" or not specified, Default is "desc", otherwise Default + // is "asc" + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// List the pull requests for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests +func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opt *PullRequestListOptions) ([]*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var pulls []*PullRequest + resp, err := s.client.Do(ctx, req, &pulls) + if err != nil { + return nil, resp, err + } + + return pulls, resp, nil +} + +// Get a single pull request. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#get-a-single-pull-request +func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + pull := new(PullRequest) + resp, err := s.client.Do(ctx, req, pull) + if err != nil { + return nil, resp, err + } + + return pull, resp, nil +} + +// GetRaw gets a single pull request in raw (diff or patch) format. +func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opt RawOptions) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opt.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// NewPullRequest represents a new pull request to be created. +type NewPullRequest struct { + Title *string `json:"title,omitempty"` + Head *string `json:"head,omitempty"` + Base *string `json:"base,omitempty"` + Body *string `json:"body,omitempty"` + Issue *int `json:"issue,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` +} + +// Create a new pull request on the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#create-a-pull-request +func (s *PullRequestsService) Create(ctx context.Context, owner string, repo string, pull *NewPullRequest) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) + req, err := s.client.NewRequest("POST", u, pull) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + p := new(PullRequest) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +type pullRequestUpdate struct { + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + State *string `json:"state,omitempty"` + Base *string `json:"base,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` +} + +// Edit a pull request. +// pull must not be nil. +// +// The following fields are editable: Title, Body, State, Base.Ref and MaintainerCanModify. +// Base.Ref updates the base branch of the pull request. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request +func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo string, number int, pull *PullRequest) (*PullRequest, *Response, error) { + if pull == nil { + return nil, nil, fmt.Errorf("pull must be provided") + } + + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + + update := &pullRequestUpdate{ + Title: pull.Title, + Body: pull.Body, + State: pull.State, + MaintainerCanModify: pull.MaintainerCanModify, + } + if pull.Base != nil { + update.Base = pull.Base.Ref + } + + req, err := s.client.NewRequest("PATCH", u, update) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeGraphQLNodeIDPreview, mediaTypeLabelDescriptionSearchPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + p := new(PullRequest) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListCommits lists the commits in a pull request. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request +func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGitSigningPreview) + + var commits []*RepositoryCommit + resp, err := s.client.Do(ctx, req, &commits) + if err != nil { + return nil, resp, err + } + + return commits, resp, nil +} + +// ListFiles lists the files in a pull request. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests-files +func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opt *ListOptions) ([]*CommitFile, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commitFiles []*CommitFile + resp, err := s.client.Do(ctx, req, &commitFiles) + if err != nil { + return nil, resp, err + } + + return commitFiles, resp, nil +} + +// IsMerged checks if a pull request has been merged. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged +func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + merged, err := parseBoolResponse(err) + return merged, resp, err +} + +// PullRequestMergeResult represents the result of merging a pull request. +type PullRequestMergeResult struct { + SHA *string `json:"sha,omitempty"` + Merged *bool `json:"merged,omitempty"` + Message *string `json:"message,omitempty"` +} + +// PullRequestOptions lets you define how a pull request will be merged. +type PullRequestOptions struct { + CommitTitle string // Extra detail to append to automatic commit message. (Optional.) + SHA string // SHA that pull request head must match to allow merge. (Optional.) + + // The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.) + MergeMethod string +} + +type pullRequestMergeRequest struct { + CommitMessage string `json:"commit_message"` + CommitTitle string `json:"commit_title,omitempty"` + MergeMethod string `json:"merge_method,omitempty"` + SHA string `json:"sha,omitempty"` +} + +// Merge a pull request (Merge Button™). +// commitMessage is the title for the automatic commit message. +// +// GitHub API docs: https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-buttontrade +func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) + + pullRequestBody := &pullRequestMergeRequest{CommitMessage: commitMessage} + if options != nil { + pullRequestBody.CommitTitle = options.CommitTitle + pullRequestBody.MergeMethod = options.MergeMethod + pullRequestBody.SHA = options.SHA + } + req, err := s.client.NewRequest("PUT", u, pullRequestBody) + if err != nil { + return nil, nil, err + } + + mergeResult := new(PullRequestMergeResult) + resp, err := s.client.Do(ctx, req, mergeResult) + if err != nil { + return nil, resp, err + } + + return mergeResult, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/pulls_comments.go b/vendor/github.com/google/go-github/github/pulls_comments.go new file mode 100644 index 00000000..a7f8ac30 --- /dev/null +++ b/vendor/github.com/google/go-github/github/pulls_comments.go @@ -0,0 +1,162 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// PullRequestComment represents a comment left on a pull request. +type PullRequestComment struct { + ID *int64 `json:"id,omitempty"` + InReplyTo *int64 `json:"in_reply_to,omitempty"` + Body *string `json:"body,omitempty"` + Path *string `json:"path,omitempty"` + DiffHunk *string `json:"diff_hunk,omitempty"` + PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"` + Position *int `json:"position,omitempty"` + OriginalPosition *int `json:"original_position,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + OriginalCommitID *string `json:"original_commit_id,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + // AuthorAssociation is the comment author's relationship to the pull request's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequestURL *string `json:"pull_request_url,omitempty"` +} + +func (p PullRequestComment) String() string { + return Stringify(p) +} + +// PullRequestListCommentsOptions specifies the optional parameters to the +// PullRequestsService.ListComments method. +type PullRequestListCommentsOptions struct { + // Sort specifies how to sort comments. Possible values are: created, updated. + Sort string `url:"sort,omitempty"` + + // Direction in which to sort comments. Possible values are: asc, desc. + Direction string `url:"direction,omitempty"` + + // Since filters comments by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListComments lists all comments on the specified pull request. Specifying a +// pull request number of 0 will return all comments on all pull requests for +// the repository. +// +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request +func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opt *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { + var u string + if number == 0 { + u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo) + } else { + u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*PullRequestComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment fetches the specified pull request comment. +// +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-single-comment +func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + comment := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, comment) + if err != nil { + return nil, resp, err + } + + return comment, resp, nil +} + +// CreateComment creates a new comment on the specified pull request. +// +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment +func (s *PullRequestsService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment updates a pull request comment. +// A non-nil comment.Body must be provided. Other comment fields should be left nil. +// +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#edit-a-comment +func (s *PullRequestsService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a pull request comment. +// +// GitHub API docs: https://developer.github.com/v3/pulls/comments/#delete-a-comment +func (s *PullRequestsService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/pulls_reviewers.go b/vendor/github.com/google/go-github/github/pulls_reviewers.go new file mode 100644 index 00000000..a1d78531 --- /dev/null +++ b/vendor/github.com/google/go-github/github/pulls_reviewers.go @@ -0,0 +1,79 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ReviewersRequest specifies users and teams for a pull request review request. +type ReviewersRequest struct { + Reviewers []string `json:"reviewers,omitempty"` + TeamReviewers []string `json:"team_reviewers,omitempty"` +} + +// Reviewers represents reviewers of a pull request. +type Reviewers struct { + Users []*User `json:"users,omitempty"` + Teams []*Team `json:"teams,omitempty"` +} + +// RequestReviewers creates a review request for the provided reviewers for the specified pull request. +// +// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#create-a-review-request +func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) + req, err := s.client.NewRequest("POST", u, &reviewers) + if err != nil { + return nil, nil, err + } + + r := new(PullRequest) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// ListReviewers lists reviewers whose reviews have been requested on the specified pull request. +// +// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#list-review-requests +func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opt *ListOptions) (*Reviewers, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + reviewers := new(Reviewers) + resp, err := s.client.Do(ctx, req, reviewers) + if err != nil { + return nil, resp, err + } + + return reviewers, resp, nil +} + +// RemoveReviewers removes the review request for the provided reviewers for the specified pull request. +// +// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#delete-a-review-request +func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, &reviewers) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/pulls_reviews.go b/vendor/github.com/google/go-github/github/pulls_reviews.go new file mode 100644 index 00000000..57d3c635 --- /dev/null +++ b/vendor/github.com/google/go-github/github/pulls_reviews.go @@ -0,0 +1,236 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// PullRequestReview represents a review of a pull request. +type PullRequestReview struct { + ID *int64 `json:"id,omitempty"` + User *User `json:"user,omitempty"` + Body *string `json:"body,omitempty"` + SubmittedAt *time.Time `json:"submitted_at,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequestURL *string `json:"pull_request_url,omitempty"` + State *string `json:"state,omitempty"` +} + +func (p PullRequestReview) String() string { + return Stringify(p) +} + +// DraftReviewComment represents a comment part of the review. +type DraftReviewComment struct { + Path *string `json:"path,omitempty"` + Position *int `json:"position,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (c DraftReviewComment) String() string { + return Stringify(c) +} + +// PullRequestReviewRequest represents a request to create a review. +type PullRequestReviewRequest struct { + CommitID *string `json:"commit_id,omitempty"` + Body *string `json:"body,omitempty"` + Event *string `json:"event,omitempty"` + Comments []*DraftReviewComment `json:"comments,omitempty"` +} + +func (r PullRequestReviewRequest) String() string { + return Stringify(r) +} + +// PullRequestReviewDismissalRequest represents a request to dismiss a review. +type PullRequestReviewDismissalRequest struct { + Message *string `json:"message,omitempty"` +} + +func (r PullRequestReviewDismissalRequest) String() string { + return Stringify(r) +} + +// ListReviews lists all reviews on the specified pull request. +// +// TODO: Follow up with GitHub support about an issue with this method's +// returned error format and remove this comment once it's fixed. +// Read more about it here - https://github.com/google/go-github/issues/540 +// +// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request +func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var reviews []*PullRequestReview + resp, err := s.client.Do(ctx, req, &reviews) + if err != nil { + return nil, resp, err + } + + return reviews, resp, nil +} + +// GetReview fetches the specified pull request review. +// +// TODO: Follow up with GitHub support about an issue with this method's +// returned error format and remove this comment once it's fixed. +// Read more about it here - https://github.com/google/go-github/issues/540 +// +// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-a-single-review +func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + review := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + +// DeletePendingReview deletes the specified pull request pending review. +// +// TODO: Follow up with GitHub support about an issue with this method's +// returned error format and remove this comment once it's fixed. +// Read more about it here - https://github.com/google/go-github/issues/540 +// +// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review +func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, nil, err + } + + review := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + +// ListReviewComments lists all the comments for the specified review. +// +// TODO: Follow up with GitHub support about an issue with this method's +// returned error format and remove this comment once it's fixed. +// Read more about it here - https://github.com/google/go-github/issues/540 +// +// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review +func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opt *ListOptions) ([]*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*PullRequestComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// CreateReview creates a new review on the specified pull request. +// +// TODO: Follow up with GitHub support about an issue with this method's +// returned error format and remove this comment once it's fixed. +// Read more about it here - https://github.com/google/go-github/issues/540 +// +// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review +func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) + + req, err := s.client.NewRequest("POST", u, review) + if err != nil { + return nil, nil, err + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// SubmitReview submits a specified review on the specified pull request. +// +// TODO: Follow up with GitHub support about an issue with this method's +// returned error format and remove this comment once it's fixed. +// Read more about it here - https://github.com/google/go-github/issues/540 +// +// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review +func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("POST", u, review) + if err != nil { + return nil, nil, err + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DismissReview dismisses a specified review on the specified pull request. +// +// TODO: Follow up with GitHub support about an issue with this method's +// returned error format and remove this comment once it's fixed. +// Read more about it here - https://github.com/google/go-github/issues/540 +// +// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review +func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("PUT", u, review) + if err != nil { + return nil, nil, err + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/reactions.go b/vendor/github.com/google/go-github/github/reactions.go new file mode 100644 index 00000000..19b533f3 --- /dev/null +++ b/vendor/github.com/google/go-github/github/reactions.go @@ -0,0 +1,283 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// ReactionsService provides access to the reactions-related functions in the +// GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/reactions/ +type ReactionsService service + +// Reaction represents a GitHub reaction. +type Reaction struct { + // ID is the Reaction ID. + ID *int64 `json:"id,omitempty"` + User *User `json:"user,omitempty"` + NodeID *string `json:"node_id,omitempty"` + // Content is the type of reaction. + // Possible values are: + // "+1", "-1", "laugh", "confused", "heart", "hooray". + Content *string `json:"content,omitempty"` +} + +// Reactions represents a summary of GitHub reactions. +type Reactions struct { + TotalCount *int `json:"total_count,omitempty"` + PlusOne *int `json:"+1,omitempty"` + MinusOne *int `json:"-1,omitempty"` + Laugh *int `json:"laugh,omitempty"` + Confused *int `json:"confused,omitempty"` + Heart *int `json:"heart,omitempty"` + Hooray *int `json:"hooray,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (r Reaction) String() string { + return Stringify(r) +} + +// ListCommentReactions lists the reactions for a commit comment. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment +func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateCommentReaction creates a reaction for a commit comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-commit-comment +func (s ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// ListIssueReactions lists the reactions for an issue. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue +func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueReaction creates a reaction for an issue. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue +func (s ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// ListIssueCommentReactions lists the reactions for an issue comment. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment +func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueCommentReaction creates a reaction for an issue comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment +func (s ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// ListPullRequestCommentReactions lists the reactions for a pull request review comment. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment +func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreatePullRequestCommentReaction creates a reaction for a pull request review comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// +// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment +func (s ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteReaction deletes a reaction. +// +// GitHub API docs: https://developer.github.com/v3/reaction/reactions/#delete-a-reaction-archive +func (s *ReactionsService) DeleteReaction(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("reactions/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos.go b/vendor/github.com/google/go-github/github/repos.go new file mode 100644 index 00000000..aa9b6ace --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos.go @@ -0,0 +1,1051 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// RepositoriesService handles communication with the repository related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/repos/ +type RepositoriesService service + +// Repository represents a GitHub repository. +type Repository struct { + ID *int64 `json:"id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + FullName *string `json:"full_name,omitempty"` + Description *string `json:"description,omitempty"` + Homepage *string `json:"homepage,omitempty"` + CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` + DefaultBranch *string `json:"default_branch,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PushedAt *Timestamp `json:"pushed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CloneURL *string `json:"clone_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + MirrorURL *string `json:"mirror_url,omitempty"` + SSHURL *string `json:"ssh_url,omitempty"` + SVNURL *string `json:"svn_url,omitempty"` + Language *string `json:"language,omitempty"` + Fork *bool `json:"fork,omitempty"` + ForksCount *int `json:"forks_count,omitempty"` + NetworkCount *int `json:"network_count,omitempty"` + OpenIssuesCount *int `json:"open_issues_count,omitempty"` + StargazersCount *int `json:"stargazers_count,omitempty"` + SubscribersCount *int `json:"subscribers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` + Size *int `json:"size,omitempty"` + AutoInit *bool `json:"auto_init,omitempty"` + Parent *Repository `json:"parent,omitempty"` + Source *Repository `json:"source,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Permissions *map[string]bool `json:"permissions,omitempty"` + AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` + AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` + AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` + Topics []string `json:"topics,omitempty"` + + // Only provided when using RepositoriesService.Get while in preview + License *License `json:"license,omitempty"` + + // Additional mutable fields when creating and editing a repository + Private *bool `json:"private,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasPages *bool `json:"has_pages,omitempty"` + HasProjects *bool `json:"has_projects,omitempty"` + HasDownloads *bool `json:"has_downloads,omitempty"` + LicenseTemplate *string `json:"license_template,omitempty"` + GitignoreTemplate *string `json:"gitignore_template,omitempty"` + Archived *bool `json:"archived,omitempty"` + + // Creating an organization repository. Required for non-owners. + TeamID *int64 `json:"team_id,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + ArchiveURL *string `json:"archive_url,omitempty"` + AssigneesURL *string `json:"assignees_url,omitempty"` + BlobsURL *string `json:"blobs_url,omitempty"` + BranchesURL *string `json:"branches_url,omitempty"` + CollaboratorsURL *string `json:"collaborators_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CompareURL *string `json:"compare_url,omitempty"` + ContentsURL *string `json:"contents_url,omitempty"` + ContributorsURL *string `json:"contributors_url,omitempty"` + DeploymentsURL *string `json:"deployments_url,omitempty"` + DownloadsURL *string `json:"downloads_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + ForksURL *string `json:"forks_url,omitempty"` + GitCommitsURL *string `json:"git_commits_url,omitempty"` + GitRefsURL *string `json:"git_refs_url,omitempty"` + GitTagsURL *string `json:"git_tags_url,omitempty"` + HooksURL *string `json:"hooks_url,omitempty"` + IssueCommentURL *string `json:"issue_comment_url,omitempty"` + IssueEventsURL *string `json:"issue_events_url,omitempty"` + IssuesURL *string `json:"issues_url,omitempty"` + KeysURL *string `json:"keys_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + LanguagesURL *string `json:"languages_url,omitempty"` + MergesURL *string `json:"merges_url,omitempty"` + MilestonesURL *string `json:"milestones_url,omitempty"` + NotificationsURL *string `json:"notifications_url,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + ReleasesURL *string `json:"releases_url,omitempty"` + StargazersURL *string `json:"stargazers_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + SubscribersURL *string `json:"subscribers_url,omitempty"` + SubscriptionURL *string `json:"subscription_url,omitempty"` + TagsURL *string `json:"tags_url,omitempty"` + TreesURL *string `json:"trees_url,omitempty"` + TeamsURL *string `json:"teams_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://developer.github.com/v3/search/#text-match-metadata + TextMatches []TextMatch `json:"text_matches,omitempty"` +} + +func (r Repository) String() string { + return Stringify(r) +} + +// RepositoryListOptions specifies the optional parameters to the +// RepositoriesService.List method. +type RepositoryListOptions struct { + // Visibility of repositories to list. Can be one of all, public, or private. + // Default: all + Visibility string `url:"visibility,omitempty"` + + // List repos of given affiliation[s]. + // Comma-separated list of values. Can include: + // * owner: Repositories that are owned by the authenticated user. + // * collaborator: Repositories that the user has been added to as a + // collaborator. + // * organization_member: Repositories that the user has access to through + // being a member of an organization. This includes every repository on + // every team that the user is on. + // Default: owner,collaborator,organization_member + Affiliation string `url:"affiliation,omitempty"` + + // Type of repositories to list. + // Can be one of all, owner, public, private, member. Default: all + // Will cause a 422 error if used in the same request as visibility or + // affiliation. + Type string `url:"type,omitempty"` + + // How to sort the repository list. Can be one of created, updated, pushed, + // full_name. Default: full_name + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Can be one of asc or desc. + // Default: when using full_name: asc; otherwise desc + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// List the repositories for a user. Passing the empty string will list +// repositories for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-user-repositories +func (s *RepositoriesService) List(ctx context.Context, user string, opt *RepositoryListOptions) ([]*Repository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/repos", user) + } else { + u = "user/repos" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeLicensesPreview, mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListByOrgOptions specifies the optional parameters to the +// RepositoriesService.ListByOrg method. +type RepositoryListByOrgOptions struct { + // Type of repositories to list. Possible values are: all, public, private, + // forks, sources, member. Default is "all". + Type string `url:"type,omitempty"` + + ListOptions +} + +// ListByOrg lists the repositories for an organization. +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-organization-repositories +func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opt *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/repos", org) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeLicensesPreview, mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListAllOptions specifies the optional parameters to the +// RepositoriesService.ListAll method. +type RepositoryListAllOptions struct { + // ID of the last repository seen + Since int64 `url:"since,omitempty"` +} + +// ListAll lists all GitHub repositories in the order that they were created. +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-all-public-repositories +func (s *RepositoriesService) ListAll(ctx context.Context, opt *RepositoryListAllOptions) ([]*Repository, *Response, error) { + u, err := addOptions("repositories", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// Create a new repository. If an organization is specified, the new +// repository will be created under that org. If the empty string is +// specified, it will be created for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/repos/#create +func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { + var u string + if org != "" { + u = fmt.Sprintf("orgs/%v/repos", org) + } else { + u = "user/repos" + } + + req, err := s.client.NewRequest("POST", u, repo) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// Get fetches a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#get +func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when the license support fully launches + // https://developer.github.com/v3/licenses/#get-a-repositorys-license + acceptHeaders := []string{mediaTypeLicensesPreview, mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// GetCodeOfConduct gets the contents of a repository's code of conduct. +// +// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#get-the-contents-of-a-repositorys-code-of-conduct +func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/community/code_of_conduct", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + coc := new(CodeOfConduct) + resp, err := s.client.Do(ctx, req, coc) + if err != nil { + return nil, resp, err + } + + return coc, resp, nil +} + +// GetByID fetches a repository. +// +// Note: GetByID uses the undocumented GitHub API endpoint /repositories/:id. +func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) { + u := fmt.Sprintf("repositories/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when the license support fully launches + // https://developer.github.com/v3/licenses/#get-a-repositorys-license + req.Header.Set("Accept", mediaTypeLicensesPreview) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// Edit updates a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#edit +func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("PATCH", u, repository) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// Delete a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#delete-a-repository +func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Contributor represents a repository contributor +type Contributor struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + Contributions *int `json:"contributions,omitempty"` +} + +// ListContributorsOptions specifies the optional parameters to the +// RepositoriesService.ListContributors method. +type ListContributorsOptions struct { + // Include anonymous contributors in results or not + Anon string `url:"anon,omitempty"` + + ListOptions +} + +// ListContributors lists contributors for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-contributors +func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opt *ListContributorsOptions) ([]*Contributor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var contributor []*Contributor + resp, err := s.client.Do(ctx, req, &contributor) + if err != nil { + return nil, nil, err + } + + return contributor, resp, nil +} + +// ListLanguages lists languages for the specified repository. The returned map +// specifies the languages and the number of bytes of code written in that +// language. For example: +// +// { +// "C": 78769, +// "Python": 7769 +// } +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-languages +func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + languages := make(map[string]int) + resp, err := s.client.Do(ctx, req, &languages) + if err != nil { + return nil, resp, err + } + + return languages, resp, nil +} + +// ListTeams lists the teams for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-teams +func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// RepositoryTag represents a repository tag. +type RepositoryTag struct { + Name *string `json:"name,omitempty"` + Commit *Commit `json:"commit,omitempty"` + ZipballURL *string `json:"zipball_url,omitempty"` + TarballURL *string `json:"tarball_url,omitempty"` +} + +// ListTags lists tags for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-tags +func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*RepositoryTag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var tags []*RepositoryTag + resp, err := s.client.Do(ctx, req, &tags) + if err != nil { + return nil, resp, err + } + + return tags, resp, nil +} + +// Branch represents a repository branch +type Branch struct { + Name *string `json:"name,omitempty"` + Commit *RepositoryCommit `json:"commit,omitempty"` + Protected *bool `json:"protected,omitempty"` +} + +// Protection represents a repository branch's protection. +type Protection struct { + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` + EnforceAdmins *AdminEnforcement `json:"enforce_admins"` + Restrictions *BranchRestrictions `json:"restrictions"` +} + +// ProtectionRequest represents a request to create/edit a branch's protection. +type ProtectionRequest struct { + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` + EnforceAdmins bool `json:"enforce_admins"` + Restrictions *BranchRestrictionsRequest `json:"restrictions"` +} + +// RequiredStatusChecks represents the protection status of a individual branch. +type RequiredStatusChecks struct { + // Require branches to be up to date before merging. (Required.) + Strict bool `json:"strict"` + // The list of status checks to require in order to merge into this + // branch. (Required; use []string{} instead of nil for empty list.) + Contexts []string `json:"contexts"` +} + +// PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. +type PullRequestReviewsEnforcement struct { + // Specifies which users and teams can dismiss pull request reviews. + DismissalRestrictions DismissalRestrictions `json:"dismissal_restrictions"` + // Specifies if approved reviews are dismissed automatically, when a new commit is pushed. + DismissStaleReviews bool `json:"dismiss_stale_reviews"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` +} + +// PullRequestReviewsEnforcementRequest represents request to set the pull request review +// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above +// because the request structure is different from the response structure. +type PullRequestReviewsEnforcementRequest struct { + // Specifies which users and teams should be allowed to dismiss pull request reviews. + // User and team dismissal restrictions are only available for + // organization-owned repositories. Must be nil for personal repositories. + DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required) + DismissStaleReviews bool `json:"dismiss_stale_reviews"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` +} + +// PullRequestReviewsEnforcementUpdate represents request to patch the pull request review +// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above +// because the patch request does not require all fields to be initialized. +type PullRequestReviewsEnforcementUpdate struct { + // Specifies which users and teams can dismiss pull request reviews. Can be omitted. + DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted. + DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews,omitempty"` +} + +// AdminEnforcement represents the configuration to enforce required status checks for repository administrators. +type AdminEnforcement struct { + URL *string `json:"url,omitempty"` + Enabled bool `json:"enabled"` +} + +// BranchRestrictions represents the restriction that only certain users or +// teams may push to a branch. +type BranchRestrictions struct { + // The list of user logins with push access. + Users []*User `json:"users"` + // The list of team slugs with push access. + Teams []*Team `json:"teams"` +} + +// BranchRestrictionsRequest represents the request to create/edit the +// restriction that only certain users or teams may push to a branch. It is +// separate from BranchRestrictions above because the request structure is +// different from the response structure. +type BranchRestrictionsRequest struct { + // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.) + Users []string `json:"users"` + // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) + Teams []string `json:"teams"` +} + +// DismissalRestrictions specifies which users and teams can dismiss pull request reviews. +type DismissalRestrictions struct { + // The list of users who can dimiss pull request reviews. + Users []*User `json:"users"` + // The list of teams which can dismiss pull request reviews. + Teams []*Team `json:"teams"` +} + +// DismissalRestrictionsRequest represents the request to create/edit the +// restriction to allows only specific users or teams to dimiss pull request reviews. It is +// separate from DismissalRestrictions above because the request structure is +// different from the response structure. +// Note: Both Users and Teams must be nil, or both must be non-nil. +type DismissalRestrictionsRequest struct { + // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Users *[]string `json:"users,omitempty"` + // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Teams *[]string `json:"teams,omitempty"` +} + +// ListBranches lists branches for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-branches +func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + var branches []*Branch + resp, err := s.client.Do(ctx, req, &branches) + if err != nil { + return nil, resp, err + } + + return branches, resp, nil +} + +// GetBranch gets the specified branch for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#get-branch +func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string) (*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + b := new(Branch) + resp, err := s.client.Do(ctx, req, b) + if err != nil { + return nil, resp, err + } + + return b, resp, nil +} + +// GetBranchProtection gets the protection of a given branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-branch-protection +func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + p := new(Protection) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// GetRequiredStatusChecks gets the required status checks for a given protected branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-status-checks-of-protected-branch +func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + p := new(RequiredStatusChecks) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#list-required-status-checks-contexts-of-protected-branch +func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + resp, err = s.client.Do(ctx, req, &contexts) + if err != nil { + return nil, resp, err + } + + return contexts, resp, nil +} + +// UpdateBranchProtection updates the protection of a given branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-branch-protection +func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) + req, err := s.client.NewRequest("PUT", u, preq) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + p := new(Protection) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// RemoveBranchProtection removes the protection of a given branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-branch-protection +func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + return s.client.Do(ctx, req, nil) +} + +// License gets the contents of a repository's license if one is detected. +// +// GitHub API docs: https://developer.github.com/v3/licenses/#get-the-contents-of-a-repositorys-license +func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/license", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := &RepositoryLicense{} + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-pull-request-review-enforcement-of-protected-branch +func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. +// It requires admin access and branch protection to be enabled. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch +func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) + req, err := s.client.NewRequest("PATCH", u, patch) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} + +// DisableDismissalRestrictions disables dismissal restrictions of a protected branch. +// It requires admin access and branch protection to be enabled. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch +func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) + + data := struct { + R []interface{} `json:"dismissal_restrictions"` + }{[]interface{}{}} + + req, err := s.client.NewRequest("PATCH", u, data) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} + +// RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-pull-request-review-enforcement-of-protected-branch +func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + return s.client.Do(ctx, req, nil) +} + +// GetAdminEnforcement gets admin enforcement information of a protected branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-admin-enforcement-of-protected-branch +func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + r := new(AdminEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// AddAdminEnforcement adds admin enforcement to a protected branch. +// It requires admin access and branch protection to be enabled. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#add-admin-enforcement-of-protected-branch +func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + r := new(AdminEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} + +// RemoveAdminEnforcement removes admin enforcement from a protected branch. +// +// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-admin-enforcement-of-protected-branch +func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeProtectedBranchesPreview) + + return s.client.Do(ctx, req, nil) +} + +// repositoryTopics represents a collection of repository topics. +type repositoryTopics struct { + Names []string `json:"names"` +} + +// ListAllTopics lists topics for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#list-all-topics-for-a-repository +func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + topics := new(repositoryTopics) + resp, err := s.client.Do(ctx, req, topics) + if err != nil { + return nil, resp, err + } + + return topics.Names, resp, nil +} + +// ReplaceAllTopics replaces topics for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository +func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) + t := &repositoryTopics{ + Names: topics, + } + if t.Names == nil { + t.Names = []string{} + } + req, err := s.client.NewRequest("PUT", u, t) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + t = new(repositoryTopics) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t.Names, resp, nil +} + +// TransferRequest represents a request to transfer a repository. +type TransferRequest struct { + NewOwner string `json:"new_owner"` + TeamID []int64 `json:"team_id,omitempty"` +} + +// Transfer transfers a repository from one account or organization to another. +// +// This method might return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it has now scheduled the transfer of the repository in a background task. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://developer.github.com/v3/repos/#transfer-a-repository +func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo) + + req, err := s.client.NewRequest("POST", u, &transfer) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryTransferPreview) + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_collaborators.go b/vendor/github.com/google/go-github/github/repos_collaborators.go new file mode 100644 index 00000000..61ee9d39 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_collaborators.go @@ -0,0 +1,140 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListCollaboratorsOptions specifies the optional parameters to the +// RepositoriesService.ListCollaborators method. +type ListCollaboratorsOptions struct { + // Affiliation specifies how collaborators should be filtered by their affiliation. + // Possible values are: + // outside - All outside collaborators of an organization-owned repository + // direct - All collaborators with permissions to an organization-owned repository, + // regardless of organization membership status + // all - All collaborators the authenticated user can see + // + // Default value is "all". + Affiliation string `url:"affiliation,omitempty"` + + ListOptions +} + +// ListCollaborators lists the GitHub users that have access to the repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#list-collaborators +func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opt *ListCollaboratorsOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeNestedTeamsPreview) + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// IsCollaborator checks whether the specified GitHub user has collaborator +// access to the given repo. +// Note: This will return false if the user is not a collaborator OR the user +// is not a GitHub user. +// +// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#get +func (s *RepositoriesService) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + isCollab, err := parseBoolResponse(err) + return isCollab, resp, err +} + +// RepositoryPermissionLevel represents the permission level an organization +// member has for a given repository. +type RepositoryPermissionLevel struct { + // Possible values: "admin", "write", "read", "none" + Permission *string `json:"permission,omitempty"` + + User *User `json:"user,omitempty"` +} + +// GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository. +// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level +func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + rpl := new(RepositoryPermissionLevel) + resp, err := s.client.Do(ctx, req, rpl) + if err != nil { + return nil, resp, err + } + return rpl, resp, nil +} + +// RepositoryAddCollaboratorOptions specifies the optional parameters to the +// RepositoriesService.AddCollaborator method. +type RepositoryAddCollaboratorOptions struct { + // Permission specifies the permission to grant the user on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // + // Default value is "push". This option is only valid for organization-owned repositories. + Permission string `json:"permission,omitempty"` +} + +// AddCollaborator sends an invitation to the specified GitHub user +// to become a collaborator to the given repo. +// +// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator +func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opt *RepositoryAddCollaboratorOptions) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("PUT", u, opt) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) + + return s.client.Do(ctx, req, nil) +} + +// RemoveCollaborator removes the specified GitHub user as collaborator from the given repo. +// Note: Does not return error if a valid user that is not a collaborator is removed. +// +// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#remove-collaborator +func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos_comments.go b/vendor/github.com/google/go-github/github/repos_comments.go new file mode 100644 index 00000000..fa2377d4 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_comments.go @@ -0,0 +1,161 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// RepositoryComment represents a comment for a commit, file, or line in a repository. +type RepositoryComment struct { + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + + // User-mutable fields + Body *string `json:"body"` + // User-initialized fields + Path *string `json:"path,omitempty"` + Position *int `json:"position,omitempty"` +} + +func (r RepositoryComment) String() string { + return Stringify(r) +} + +// ListComments lists all the comments for the repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-commit-comments-for-a-repository +func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*RepositoryComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// ListCommitComments lists all the comments for a given commit SHA. +// +// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-comments-for-a-single-commit +func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opt *ListOptions) ([]*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*RepositoryComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// CreateComment creates a comment for the given commit. +// Note: GitHub allows for comments to be created for non-existing files and positions. +// +// GitHub API docs: https://developer.github.com/v3/repos/comments/#create-a-commit-comment +func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sha string, comment *RepositoryComment) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// GetComment gets a single comment from a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/comments/#get-a-single-commit-comment +func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// UpdateComment updates the body of a single comment. +// +// GitHub API docs: https://developer.github.com/v3/repos/comments/#update-a-commit-comment +func (s *RepositoriesService) UpdateComment(ctx context.Context, owner, repo string, id int64, comment *RepositoryComment) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a single comment from a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/comments/#delete-a-commit-comment +func (s *RepositoriesService) DeleteComment(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos_commits.go b/vendor/github.com/google/go-github/github/repos_commits.go new file mode 100644 index 00000000..04847373 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_commits.go @@ -0,0 +1,237 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "time" +) + +// RepositoryCommit represents a commit in a repo. +// Note that it's wrapping a Commit, so author/committer information is in two places, +// but contain different details about them: in RepositoryCommit "github details", in Commit - "git details". +type RepositoryCommit struct { + SHA *string `json:"sha,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Author *User `json:"author,omitempty"` + Committer *User `json:"committer,omitempty"` + Parents []Commit `json:"parents,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + + // Details about how many changes were made in this commit. Only filled in during GetCommit! + Stats *CommitStats `json:"stats,omitempty"` + // Details about which files, and how this commit touched. Only filled in during GetCommit! + Files []CommitFile `json:"files,omitempty"` +} + +func (r RepositoryCommit) String() string { + return Stringify(r) +} + +// CommitStats represents the number of additions / deletions from a file in a given RepositoryCommit or GistCommit. +type CommitStats struct { + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + Total *int `json:"total,omitempty"` +} + +func (c CommitStats) String() string { + return Stringify(c) +} + +// CommitFile represents a file modified in a commit. +type CommitFile struct { + SHA *string `json:"sha,omitempty"` + Filename *string `json:"filename,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + Changes *int `json:"changes,omitempty"` + Status *string `json:"status,omitempty"` + Patch *string `json:"patch,omitempty"` + BlobURL *string `json:"blob_url,omitempty"` + RawURL *string `json:"raw_url,omitempty"` + ContentsURL *string `json:"contents_url,omitempty"` +} + +func (c CommitFile) String() string { + return Stringify(c) +} + +// CommitsComparison is the result of comparing two commits. +// See CompareCommits() for details. +type CommitsComparison struct { + BaseCommit *RepositoryCommit `json:"base_commit,omitempty"` + MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"` + + // Head can be 'behind' or 'ahead' + Status *string `json:"status,omitempty"` + AheadBy *int `json:"ahead_by,omitempty"` + BehindBy *int `json:"behind_by,omitempty"` + TotalCommits *int `json:"total_commits,omitempty"` + + Commits []RepositoryCommit `json:"commits,omitempty"` + + Files []CommitFile `json:"files,omitempty"` + + HTMLURL *string `json:"html_url,omitempty"` + PermalinkURL *string `json:"permalink_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + URL *string `json:"url,omitempty"` // API URL. +} + +func (c CommitsComparison) String() string { + return Stringify(c) +} + +// CommitsListOptions specifies the optional parameters to the +// RepositoriesService.ListCommits method. +type CommitsListOptions struct { + // SHA or branch to start listing Commits from. + SHA string `url:"sha,omitempty"` + + // Path that should be touched by the returned Commits. + Path string `url:"path,omitempty"` + + // Author of by which to filter Commits. + Author string `url:"author,omitempty"` + + // Since when should Commits be included in the response. + Since time.Time `url:"since,omitempty"` + + // Until when should Commits be included in the response. + Until time.Time `url:"until,omitempty"` + + ListOptions +} + +// ListCommits lists the commits of a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/commits/#list +func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opt *CommitsListOptions) ([]*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGitSigningPreview) + + var commits []*RepositoryCommit + resp, err := s.client.Do(ctx, req, &commits) + if err != nil { + return nil, resp, err + } + + return commits, resp, nil +} + +// GetCommit fetches the specified commit, including all details about it. +// +// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-single-commit +// See also: https://developer.github.com/v3/git/commits/#get-a-single-commit provides the same functionality +func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string) (*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGitSigningPreview) + + commit := new(RepositoryCommit) + resp, err := s.client.Do(ctx, req, commit) + if err != nil { + return nil, resp, err + } + + return commit, resp, nil +} + +// GetCommitRaw fetches the specified commit in raw (diff or patch) format. +func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opt RawOptions) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opt.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opt.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is +// supplied and no new commits have occurred, a 304 Unmodified response is returned. +// +// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference +func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, ref) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + if lastSHA != "" { + req.Header.Set("If-None-Match", `"`+lastSHA+`"`) + } + + req.Header.Set("Accept", mediaTypeV3SHA) + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// CompareCommits compares a range of commits with each other. +// todo: support media formats - https://github.com/google/go-github/issues/6 +// +// GitHub API docs: https://developer.github.com/v3/repos/commits/index.html#compare-two-commits +func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string) (*CommitsComparison, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, base, head) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + comp := new(CommitsComparison) + resp, err := s.client.Do(ctx, req, comp) + if err != nil { + return nil, resp, err + } + + return comp, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_community_health.go b/vendor/github.com/google/go-github/github/repos_community_health.go new file mode 100644 index 00000000..b5c75d6f --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_community_health.go @@ -0,0 +1,57 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// Metric represents the different fields for one file in community health files. +type Metric struct { + Name *string `json:"name"` + Key *string `json:"key"` + URL *string `json:"url"` + HTMLURL *string `json:"html_url"` +} + +// CommunityHealthFiles represents the different files in the community health metrics response. +type CommunityHealthFiles struct { + CodeOfConduct *Metric `json:"code_of_conduct"` + Contributing *Metric `json:"contributing"` + License *Metric `json:"license"` + Readme *Metric `json:"readme"` +} + +// CommunityHealthMetrics represents a response containing the community metrics of a repository. +type CommunityHealthMetrics struct { + HealthPercentage *int `json:"health_percentage"` + Files *CommunityHealthFiles `json:"files"` + UpdatedAt *time.Time `json:"updated_at"` +} + +// GetCommunityHealthMetrics retrieves all the community health metrics for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/community/#retrieve-community-health-metrics +func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryCommunityHealthMetricsPreview) + + metrics := &CommunityHealthMetrics{} + resp, err := s.client.Do(ctx, req, metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_contents.go b/vendor/github.com/google/go-github/github/repos_contents.go new file mode 100644 index 00000000..ffb56b90 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_contents.go @@ -0,0 +1,266 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Repository contents API methods. +// GitHub API docs: https://developer.github.com/v3/repos/contents/ + +package github + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "path" +) + +// RepositoryContent represents a file or directory in a github repository. +type RepositoryContent struct { + Type *string `json:"type,omitempty"` + Encoding *string `json:"encoding,omitempty"` + Size *int `json:"size,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + // Content contains the actual file content, which may be encoded. + // Callers should call GetContent which will decode the content if + // necessary. + Content *string `json:"content,omitempty"` + SHA *string `json:"sha,omitempty"` + URL *string `json:"url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` +} + +// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile. +type RepositoryContentResponse struct { + Content *RepositoryContent `json:"content,omitempty"` + Commit `json:"commit,omitempty"` +} + +// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile. +type RepositoryContentFileOptions struct { + Message *string `json:"message,omitempty"` + Content []byte `json:"content,omitempty"` // unencoded + SHA *string `json:"sha,omitempty"` + Branch *string `json:"branch,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` +} + +// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA, +// branch, or tag +type RepositoryContentGetOptions struct { + Ref string `url:"ref,omitempty"` +} + +// String converts RepositoryContent to a string. It's primarily for testing. +func (r RepositoryContent) String() string { + return Stringify(r) +} + +// GetContent returns the content of r, decoding it if necessary. +func (r *RepositoryContent) GetContent() (string, error) { + var encoding string + if r.Encoding != nil { + encoding = *r.Encoding + } + + switch encoding { + case "base64": + c, err := base64.StdEncoding.DecodeString(*r.Content) + return string(c), err + case "": + if r.Content == nil { + return "", nil + } + return *r.Content, nil + default: + return "", fmt.Errorf("unsupported content encoding: %v", encoding) + } +} + +// GetReadme gets the Readme file for the repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-the-readme +func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opt *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/readme", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + readme := new(RepositoryContent) + resp, err := s.client.Do(ctx, req, readme) + if err != nil { + return nil, resp, err + } + return readme, resp, nil +} + +// DownloadContents returns an io.ReadCloser that reads the contents of the +// specified file. This function will work with files of any size, as opposed +// to GetContents which is limited to 1 Mb files. It is the caller's +// responsibility to close the ReadCloser. +func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) { + dir := path.Dir(filepath) + filename := path.Base(filepath) + _, dirContents, _, err := s.GetContents(ctx, owner, repo, dir, opt) + if err != nil { + return nil, err + } + for _, contents := range dirContents { + if *contents.Name == filename { + if contents.DownloadURL == nil || *contents.DownloadURL == "" { + return nil, fmt.Errorf("No download link found for %s", filepath) + } + resp, err := s.client.client.Get(*contents.DownloadURL) + if err != nil { + return nil, err + } + return resp.Body, nil + } + } + return nil, fmt.Errorf("No file named %s found in %s", filename, dir) +} + +// GetContents can return either the metadata and content of a single file +// (when path references a file) or the metadata of all the files and/or +// subdirectories of a directory (when path references a directory). To make it +// easy to distinguish between both result types and to mimic the API as much +// as possible, both result types will be returned but only one will contain a +// value and the other will be nil. +// +// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-contents +func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opt *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) { + escapedPath := (&url.URL{Path: path}).String() + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath) + u, err = addOptions(u, opt) + if err != nil { + return nil, nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, nil, err + } + var rawJSON json.RawMessage + resp, err = s.client.Do(ctx, req, &rawJSON) + if err != nil { + return nil, nil, resp, err + } + fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent) + if fileUnmarshalError == nil { + return fileContent, nil, resp, nil + } + directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent) + if directoryUnmarshalError == nil { + return nil, directoryContent, resp, nil + } + return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError) +} + +// CreateFile creates a new file in a repository at the given path and returns +// the commit and file metadata. +// +// GitHub API docs: https://developer.github.com/v3/repos/contents/#create-a-file +func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("PUT", u, opt) + if err != nil { + return nil, nil, err + } + createResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, createResponse) + if err != nil { + return nil, resp, err + } + return createResponse, resp, nil +} + +// UpdateFile updates a file in a repository at the given path and returns the +// commit and file metadata. Requires the blob SHA of the file being updated. +// +// GitHub API docs: https://developer.github.com/v3/repos/contents/#update-a-file +func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("PUT", u, opt) + if err != nil { + return nil, nil, err + } + updateResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, updateResponse) + if err != nil { + return nil, resp, err + } + return updateResponse, resp, nil +} + +// DeleteFile deletes a file from a repository and returns the commit. +// Requires the blob SHA of the file to be deleted. +// +// GitHub API docs: https://developer.github.com/v3/repos/contents/#delete-a-file +func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("DELETE", u, opt) + if err != nil { + return nil, nil, err + } + deleteResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, deleteResponse) + if err != nil { + return nil, resp, err + } + return deleteResponse, resp, nil +} + +// archiveFormat is used to define the archive type when calling GetArchiveLink. +type archiveFormat string + +const ( + // Tarball specifies an archive in gzipped tar format. + Tarball archiveFormat = "tarball" + + // Zipball specifies an archive in zip format. + Zipball archiveFormat = "zipball" +) + +// GetArchiveLink returns an URL to download a tarball or zipball archive for a +// repository. The archiveFormat can be specified by either the github.Tarball +// or github.Zipball constant. +// +// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-archive-link +func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat archiveFormat, opt *RepositoryContentGetOptions) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat) + if opt != nil && opt.Ref != "" { + u += fmt.Sprintf("/%s", opt.Ref) + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + var resp *http.Response + // Use http.DefaultTransport if no custom Transport is configured + req = withContext(ctx, req) + if s.client.client.Transport == nil { + resp, err = http.DefaultTransport.RoundTrip(req) + } else { + resp, err = s.client.client.Transport.RoundTrip(req) + } + if err != nil { + return nil, nil, err + } + resp.Body.Close() + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} diff --git a/vendor/github.com/google/go-github/github/repos_deployments.go b/vendor/github.com/google/go-github/github/repos_deployments.go new file mode 100644 index 00000000..1300f05e --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_deployments.go @@ -0,0 +1,237 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "strings" +) + +// Deployment represents a deployment in a repo +type Deployment struct { + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + SHA *string `json:"sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Task *string `json:"task,omitempty"` + Payload json.RawMessage `json:"payload,omitempty"` + Environment *string `json:"environment,omitempty"` + Description *string `json:"description,omitempty"` + Creator *User `json:"creator,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// DeploymentRequest represents a deployment request +type DeploymentRequest struct { + Ref *string `json:"ref,omitempty"` + Task *string `json:"task,omitempty"` + AutoMerge *bool `json:"auto_merge,omitempty"` + RequiredContexts *[]string `json:"required_contexts,omitempty"` + Payload *string `json:"payload,omitempty"` + Environment *string `json:"environment,omitempty"` + Description *string `json:"description,omitempty"` + TransientEnvironment *bool `json:"transient_environment,omitempty"` + ProductionEnvironment *bool `json:"production_environment,omitempty"` +} + +// DeploymentsListOptions specifies the optional parameters to the +// RepositoriesService.ListDeployments method. +type DeploymentsListOptions struct { + // SHA of the Deployment. + SHA string `url:"sha,omitempty"` + + // List deployments for a given ref. + Ref string `url:"ref,omitempty"` + + // List deployments for a given task. + Task string `url:"task,omitempty"` + + // List deployments for a given environment. + Environment string `url:"environment,omitempty"` + + ListOptions +} + +// ListDeployments lists the deployments of a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployments +func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opt *DeploymentsListOptions) ([]*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var deployments []*Deployment + resp, err := s.client.Do(ctx, req, &deployments) + if err != nil { + return nil, resp, err + } + + return deployments, resp, nil +} + +// GetDeployment returns a single deployment of a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment +func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + deployment := new(Deployment) + resp, err := s.client.Do(ctx, req, deployment) + if err != nil { + return nil, resp, err + } + + return deployment, resp, nil +} + +// CreateDeployment creates a new deployment for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment +func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo string, request *DeploymentRequest) (*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(Deployment) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} + +// DeploymentStatus represents the status of a +// particular deployment. +type DeploymentStatus struct { + ID *int64 `json:"id,omitempty"` + // State is the deployment state. + // Possible values are: "pending", "success", "failure", "error", "inactive". + State *string `json:"state,omitempty"` + Creator *User `json:"creator,omitempty"` + Description *string `json:"description,omitempty"` + TargetURL *string `json:"target_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + DeploymentURL *string `json:"deployment_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// DeploymentStatusRequest represents a deployment request +type DeploymentStatusRequest struct { + State *string `json:"state,omitempty"` + LogURL *string `json:"log_url,omitempty"` + Description *string `json:"description,omitempty"` + EnvironmentURL *string `json:"environment_url,omitempty"` + AutoInactive *bool `json:"auto_inactive,omitempty"` +} + +// ListDeploymentStatuses lists the statuses of a given deployment of a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployment-statuses +func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opt *ListOptions) ([]*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var statuses []*DeploymentStatus + resp, err := s.client.Do(ctx, req, &statuses) + if err != nil { + return nil, resp, err + } + + return statuses, resp, nil +} + +// GetDeploymentStatus returns a single deployment status of a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment-status +func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(DeploymentStatus) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} + +// CreateDeploymentStatus creates a new status for a deployment. +// +// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment-status +func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, repo string, deployment int64, request *DeploymentStatusRequest) (*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(DeploymentStatus) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_forks.go b/vendor/github.com/google/go-github/github/repos_forks.go new file mode 100644 index 00000000..d0bff544 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_forks.go @@ -0,0 +1,89 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryListForksOptions specifies the optional parameters to the +// RepositoriesService.ListForks method. +type RepositoryListForksOptions struct { + // How to sort the forks list. Possible values are: newest, oldest, + // watchers. Default is "newest". + Sort string `url:"sort,omitempty"` + + ListOptions +} + +// ListForks lists the forks of the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/forks/#list-forks +func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opt *RepositoryListForksOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryCreateForkOptions specifies the optional parameters to the +// RepositoriesService.CreateFork method. +type RepositoryCreateForkOptions struct { + // The organization to fork the repository into. + Organization string `url:"organization,omitempty"` +} + +// CreateFork creates a fork of the specified repository. +// +// This method might return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing creating the fork in a background task. In this event, +// the Repository value will be returned, which includes the details about the pending fork. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://developer.github.com/v3/repos/forks/#create-a-fork +func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opt *RepositoryCreateForkOptions) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + fork := new(Repository) + resp, err := s.client.Do(ctx, req, fork) + if _, ok := err.(*AcceptedError); ok { + return fork, resp, err + } + if err != nil { + return nil, resp, err + } + + return fork, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_hooks.go b/vendor/github.com/google/go-github/github/repos_hooks.go new file mode 100644 index 00000000..f7ab3a13 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_hooks.go @@ -0,0 +1,192 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// WebHookPayload represents the data that is received from GitHub when a push +// event hook is triggered. The format of these payloads pre-date most of the +// GitHub v3 API, so there are lots of minor incompatibilities with the types +// defined in the rest of the API. Therefore, several types are duplicated +// here to account for these differences. +// +// GitHub API docs: https://help.github.com/articles/post-receive-hooks +type WebHookPayload struct { + After *string `json:"after,omitempty"` + Before *string `json:"before,omitempty"` + Commits []WebHookCommit `json:"commits,omitempty"` + Compare *string `json:"compare,omitempty"` + Created *bool `json:"created,omitempty"` + Deleted *bool `json:"deleted,omitempty"` + Forced *bool `json:"forced,omitempty"` + HeadCommit *WebHookCommit `json:"head_commit,omitempty"` + Pusher *User `json:"pusher,omitempty"` + Ref *string `json:"ref,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +func (w WebHookPayload) String() string { + return Stringify(w) +} + +// WebHookCommit represents the commit variant we receive from GitHub in a +// WebHookPayload. +type WebHookCommit struct { + Added []string `json:"added,omitempty"` + Author *WebHookAuthor `json:"author,omitempty"` + Committer *WebHookAuthor `json:"committer,omitempty"` + Distinct *bool `json:"distinct,omitempty"` + ID *string `json:"id,omitempty"` + Message *string `json:"message,omitempty"` + Modified []string `json:"modified,omitempty"` + Removed []string `json:"removed,omitempty"` + Timestamp *time.Time `json:"timestamp,omitempty"` +} + +func (w WebHookCommit) String() string { + return Stringify(w) +} + +// WebHookAuthor represents the author or committer of a commit, as specified +// in a WebHookCommit. The commit author may not correspond to a GitHub User. +type WebHookAuthor struct { + Email *string `json:"email,omitempty"` + Name *string `json:"name,omitempty"` + Username *string `json:"username,omitempty"` +} + +func (w WebHookAuthor) String() string { + return Stringify(w) +} + +// Hook represents a GitHub (web and service) hook for a repository. +type Hook struct { + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + Events []string `json:"events,omitempty"` + Active *bool `json:"active,omitempty"` + Config map[string]interface{} `json:"config,omitempty"` + ID *int64 `json:"id,omitempty"` +} + +func (h Hook) String() string { + return Stringify(h) +} + +// CreateHook creates a Hook for the specified repository. +// Name and Config are required fields. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#create-a-hook +func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + req, err := s.client.NewRequest("POST", u, hook) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// ListHooks lists all Hooks for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#list +func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*Hook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#get-single-hook +func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + hook := new(Hook) + resp, err := s.client.Do(ctx, req, hook) + return hook, resp, err +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#edit-a-hook +func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + return h, resp, err +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#delete-a-hook +func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#ping-a-hook +func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// TestHook triggers a test Hook by github. +// +// GitHub API docs: https://developer.github.com/v3/repos/hooks/#test-a-push-hook +func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos_invitations.go b/vendor/github.com/google/go-github/github/repos_invitations.go new file mode 100644 index 00000000..34bf3830 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_invitations.go @@ -0,0 +1,98 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryInvitation represents an invitation to collaborate on a repo. +type RepositoryInvitation struct { + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Invitee *User `json:"invitee,omitempty"` + Inviter *User `json:"inviter,omitempty"` + + // Permissions represents the permissions that the associated user will have + // on the repository. Possible values are: "read", "write", "admin". + Permissions *string `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// ListInvitations lists all currently-open repository invitations. +// +// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository +func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) + + invites := []*RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, &invites) + if err != nil { + return nil, resp, err + } + + return invites, resp, nil +} + +// DeleteInvitation deletes a repository invitation. +// +// GitHub API docs: https://developer.github.com/v3/repos/invitations/#delete-a-repository-invitation +func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo string, invitationID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) + + return s.client.Do(ctx, req, nil) +} + +// UpdateInvitation updates the permissions associated with a repository +// invitation. +// +// permissions represents the permissions that the associated user will have +// on the repository. Possible values are: "read", "write", "admin". +// +// GitHub API docs: https://developer.github.com/v3/repos/invitations/#update-a-repository-invitation +func (s *RepositoriesService) UpdateInvitation(ctx context.Context, owner, repo string, invitationID int64, permissions string) (*RepositoryInvitation, *Response, error) { + opts := &struct { + Permissions string `json:"permissions"` + }{Permissions: permissions} + u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) + + invite := &RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, invite) + if err != nil { + return nil, resp, err + } + + return invite, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_keys.go b/vendor/github.com/google/go-github/github/repos_keys.go new file mode 100644 index 00000000..b484f844 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_keys.go @@ -0,0 +1,111 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// The Key type is defined in users_keys.go + +// ListKeys lists the deploy keys for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/keys/#list +func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*Key + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetKey fetches a single deploy key. +// +// GitHub API docs: https://developer.github.com/v3/repos/keys/#get +func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo string, id int64) (*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := new(Key) + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateKey adds a deploy key for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/keys/#create +func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo string, key *Key) (*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) + + req, err := s.client.NewRequest("POST", u, key) + if err != nil { + return nil, nil, err + } + + k := new(Key) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// EditKey edits a deploy key. +// +// GitHub API docs: https://developer.github.com/v3/repos/keys/#edit +func (s *RepositoriesService) EditKey(ctx context.Context, owner string, repo string, id int64, key *Key) (*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) + + req, err := s.client.NewRequest("PATCH", u, key) + if err != nil { + return nil, nil, err + } + + k := new(Key) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// DeleteKey deletes a deploy key. +// +// GitHub API docs: https://developer.github.com/v3/repos/keys/#delete +func (s *RepositoriesService) DeleteKey(ctx context.Context, owner string, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/repos_merging.go b/vendor/github.com/google/go-github/github/repos_merging.go new file mode 100644 index 00000000..04383c1a --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_merging.go @@ -0,0 +1,38 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryMergeRequest represents a request to merge a branch in a +// repository. +type RepositoryMergeRequest struct { + Base *string `json:"base,omitempty"` + Head *string `json:"head,omitempty"` + CommitMessage *string `json:"commit_message,omitempty"` +} + +// Merge a branch in the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/merging/#perform-a-merge +func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/merges", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + commit := new(RepositoryCommit) + resp, err := s.client.Do(ctx, req, commit) + if err != nil { + return nil, resp, err + } + + return commit, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_pages.go b/vendor/github.com/google/go-github/github/repos_pages.go new file mode 100644 index 00000000..94a95f2b --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_pages.go @@ -0,0 +1,143 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Pages represents a GitHub Pages site configuration. +type Pages struct { + URL *string `json:"url,omitempty"` + Status *string `json:"status,omitempty"` + CNAME *string `json:"cname,omitempty"` + Custom404 *bool `json:"custom_404,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// PagesError represents a build error for a GitHub Pages site. +type PagesError struct { + Message *string `json:"message,omitempty"` +} + +// PagesBuild represents the build information for a GitHub Pages site. +type PagesBuild struct { + URL *string `json:"url,omitempty"` + Status *string `json:"status,omitempty"` + Error *PagesError `json:"error,omitempty"` + Pusher *User `json:"pusher,omitempty"` + Commit *string `json:"commit,omitempty"` + Duration *int `json:"duration,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// GetPagesInfo fetches information about a GitHub Pages site. +// +// GitHub API docs: https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site +func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePagesPreview) + + site := new(Pages) + resp, err := s.client.Do(ctx, req, site) + if err != nil { + return nil, resp, err + } + + return site, resp, nil +} + +// ListPagesBuilds lists the builds for a GitHub Pages site. +// +// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-pages-builds +func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opt *ListOptions) ([]*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pages []*PagesBuild + resp, err := s.client.Do(ctx, req, &pages) + if err != nil { + return nil, resp, err + } + + return pages, resp, nil +} + +// GetLatestPagesBuild fetches the latest build information for a GitHub pages site. +// +// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-latest-pages-build +func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// GetPageBuild fetches the specific build information for a GitHub pages site. +// +// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-a-specific-pages-build +func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit. +// +// GitHub API docs: https://developer.github.com/v3/repos/pages/#request-a-page-build +func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePagesPreview) + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_projects.go b/vendor/github.com/google/go-github/github/repos_projects.go new file mode 100644 index 00000000..97a045f6 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_projects.go @@ -0,0 +1,72 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// ProjectListOptions specifies the optional parameters to the +// OrganizationsService.ListProjects and RepositoriesService.ListProjects methods. +type ProjectListOptions struct { + // Indicates the state of the projects to return. Can be either open, closed, or all. Default: open + State string `url:"state,omitempty"` + + ListOptions +} + +// ListProjects lists the projects for a repo. +// +// GitHub API docs: https://developer.github.com/v3/projects/#list-repository-projects +func (s *RepositoriesService) ListProjects(ctx context.Context, owner, repo string, opt *ProjectListOptions) ([]*Project, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var projects []*Project + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// CreateProject creates a GitHub Project for the specified repository. +// +// GitHub API docs: https://developer.github.com/v3/projects/#create-a-repository-project +func (s *RepositoriesService) CreateProject(ctx context.Context, owner, repo string, opt *ProjectOptions) (*Project, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) + req, err := s.client.NewRequest("POST", u, opt) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeProjectsPreview, mediaTypeGraphQLNodeIDPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_releases.go b/vendor/github.com/google/go-github/github/repos_releases.go new file mode 100644 index 00000000..d5dfc702 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_releases.go @@ -0,0 +1,353 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "io" + "mime" + "net/http" + "os" + "path/filepath" + "strings" +) + +// RepositoryRelease represents a GitHub release in a repository. +type RepositoryRelease struct { + ID *int64 `json:"id,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + AssetsURL *string `json:"assets_url,omitempty"` + Assets []ReleaseAsset `json:"assets,omitempty"` + UploadURL *string `json:"upload_url,omitempty"` + ZipballURL *string `json:"zipball_url,omitempty"` + TarballURL *string `json:"tarball_url,omitempty"` + Author *User `json:"author,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r RepositoryRelease) String() string { + return Stringify(r) +} + +// ReleaseAsset represents a GitHub release asset in a repository. +type ReleaseAsset struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Label *string `json:"label,omitempty"` + State *string `json:"state,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Size *int `json:"size,omitempty"` + DownloadCount *int `json:"download_count,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + BrowserDownloadURL *string `json:"browser_download_url,omitempty"` + Uploader *User `json:"uploader,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r ReleaseAsset) String() string { + return Stringify(r) +} + +// ListReleases lists the releases for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository +func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opt *ListOptions) ([]*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var releases []*RepositoryRelease + resp, err := s.client.Do(ctx, req, &releases) + if err != nil { + return nil, resp, err + } + return releases, resp, nil +} + +// GetRelease fetches a single release. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release +func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string, id int64) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + return s.getSingleRelease(ctx, u) +} + +// GetLatestRelease fetches the latest published release for the repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-the-latest-release +func (s *RepositoriesService) GetLatestRelease(ctx context.Context, owner, repo string) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/latest", owner, repo) + return s.getSingleRelease(ctx, u) +} + +// GetReleaseByTag fetches a release with the specified tag. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-release-by-tag-name +func (s *RepositoriesService) GetReleaseByTag(ctx context.Context, owner, repo, tag string) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/tags/%s", owner, repo, tag) + return s.getSingleRelease(ctx, u) +} + +func (s *RepositoriesService) getSingleRelease(ctx context.Context, url string) (*RepositoryRelease, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + release := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, release) + if err != nil { + return nil, resp, err + } + return release, resp, nil +} + +// CreateRelease adds a new release for a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#create-a-release +func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo string, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) + + req, err := s.client.NewRequest("POST", u, release) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + r := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + return r, resp, nil +} + +// EditRelease edits a repository release. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release +func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + + req, err := s.client.NewRequest("PATCH", u, release) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + r := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + return r, resp, nil +} + +// DeleteRelease delete a single release from a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#delete-a-release +func (s *RepositoriesService) DeleteRelease(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListReleaseAssets lists the release's assets. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#list-assets-for-a-release +func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opt *ListOptions) ([]*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + var assets []*ReleaseAsset + resp, err := s.client.Do(ctx, req, &assets) + if err != nil { + return nil, resp, err + } + return assets, resp, nil +} + +// GetReleaseAsset fetches a single release asset. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset +func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo string, id int64) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} + +// DownloadReleaseAsset downloads a release asset or returns a redirect URL. +// +// DownloadReleaseAsset returns an io.ReadCloser that reads the contents of the +// specified release asset. It is the caller's responsibility to close the ReadCloser. +// If a redirect is returned, the redirect URL will be returned as a string instead +// of the io.ReadCloser. Exactly one of rc and redirectURL will be zero. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#get-a-single-release-asset +func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64) (rc io.ReadCloser, redirectURL string, err error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, "", err + } + req.Header.Set("Accept", defaultMediaType) + + s.client.clientMu.Lock() + defer s.client.clientMu.Unlock() + + var loc string + saveRedirect := s.client.client.CheckRedirect + s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + loc = req.URL.String() + return errors.New("disable redirect") + } + defer func() { s.client.client.CheckRedirect = saveRedirect }() + + req = withContext(ctx, req) + resp, err := s.client.client.Do(req) + if err != nil { + if !strings.Contains(err.Error(), "disable redirect") { + return nil, "", err + } + return nil, loc, nil // Intentionally return no error with valid redirect URL. + } + + if err := CheckResponse(resp); err != nil { + resp.Body.Close() + return nil, "", err + } + + return resp.Body, "", nil +} + +// EditReleaseAsset edits a repository release asset. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release-asset +func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo string, id int64, release *ReleaseAsset) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("PATCH", u, release) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} + +// DeleteReleaseAsset delete a single release asset from a repository. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#delete-a-release-asset +func (s *RepositoriesService) DeleteReleaseAsset(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// UploadReleaseAsset creates an asset by uploading a file into a release repository. +// To upload assets that cannot be represented by an os.File, call NewUploadRequest directly. +// +// GitHub API docs: https://developer.github.com/v3/repos/releases/#upload-a-release-asset +func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opt *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + stat, err := file.Stat() + if err != nil { + return nil, nil, err + } + if stat.IsDir() { + return nil, nil, errors.New("the asset to upload can't be a directory") + } + + mediaType := mime.TypeByExtension(filepath.Ext(file.Name())) + req, err := s.client.NewUploadRequest(u, file, stat.Size(), mediaType) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGraphQLNodeIDPreview) + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_stats.go b/vendor/github.com/google/go-github/github/repos_stats.go new file mode 100644 index 00000000..bb355aea --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_stats.go @@ -0,0 +1,226 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// ContributorStats represents a contributor to a repository and their +// weekly contributions to a given repo. +type ContributorStats struct { + Author *Contributor `json:"author,omitempty"` + Total *int `json:"total,omitempty"` + Weeks []WeeklyStats `json:"weeks,omitempty"` +} + +func (c ContributorStats) String() string { + return Stringify(c) +} + +// WeeklyStats represents the number of additions, deletions and commits +// a Contributor made in a given week. +type WeeklyStats struct { + Week *Timestamp `json:"w,omitempty"` + Additions *int `json:"a,omitempty"` + Deletions *int `json:"d,omitempty"` + Commits *int `json:"c,omitempty"` +} + +func (w WeeklyStats) String() string { + return Stringify(w) +} + +// ListContributorsStats gets a repo's contributor list with additions, +// deletions and commit counts. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://developer.github.com/v3/repos/statistics/#contributors +func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var contributorStats []*ContributorStats + resp, err := s.client.Do(ctx, req, &contributorStats) + if err != nil { + return nil, resp, err + } + + return contributorStats, resp, nil +} + +// WeeklyCommitActivity represents the weekly commit activity for a repository. +// The days array is a group of commits per day, starting on Sunday. +type WeeklyCommitActivity struct { + Days []int `json:"days,omitempty"` + Total *int `json:"total,omitempty"` + Week *Timestamp `json:"week,omitempty"` +} + +func (w WeeklyCommitActivity) String() string { + return Stringify(w) +} + +// ListCommitActivity returns the last year of commit activity +// grouped by week. The days array is a group of commits per day, +// starting on Sunday. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://developer.github.com/v3/repos/statistics/#commit-activity +func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var weeklyCommitActivity []*WeeklyCommitActivity + resp, err := s.client.Do(ctx, req, &weeklyCommitActivity) + if err != nil { + return nil, resp, err + } + + return weeklyCommitActivity, resp, nil +} + +// ListCodeFrequency returns a weekly aggregate of the number of additions and +// deletions pushed to a repository. Returned WeeklyStats will contain +// additions and deletions, but not total commits. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://developer.github.com/v3/repos/statistics/#code-frequency +func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var weeks [][]int + resp, err := s.client.Do(ctx, req, &weeks) + + // convert int slices into WeeklyStats + var stats []*WeeklyStats + for _, week := range weeks { + if len(week) != 3 { + continue + } + stat := &WeeklyStats{ + Week: &Timestamp{time.Unix(int64(week[0]), 0)}, + Additions: Int(week[1]), + Deletions: Int(week[2]), + } + stats = append(stats, stat) + } + + return stats, resp, err +} + +// RepositoryParticipation is the number of commits by everyone +// who has contributed to the repository (including the owner) +// as well as the number of commits by the owner themself. +type RepositoryParticipation struct { + All []int `json:"all,omitempty"` + Owner []int `json:"owner,omitempty"` +} + +func (r RepositoryParticipation) String() string { + return Stringify(r) +} + +// ListParticipation returns the total commit counts for the 'owner' +// and total commit counts in 'all'. 'all' is everyone combined, +// including the 'owner' in the last 52 weeks. If you’d like to get +// the commit counts for non-owners, you can subtract 'all' from 'owner'. +// +// The array order is oldest week (index 0) to most recent week. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://developer.github.com/v3/repos/statistics/#participation +func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + participation := new(RepositoryParticipation) + resp, err := s.client.Do(ctx, req, participation) + if err != nil { + return nil, resp, err + } + + return participation, resp, nil +} + +// PunchCard represents the number of commits made during a given hour of a +// day of the week. +type PunchCard struct { + Day *int // Day of the week (0-6: =Sunday - Saturday). + Hour *int // Hour of day (0-23). + Commits *int // Number of commits. +} + +// ListPunchCard returns the number of commits per hour in each day. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://developer.github.com/v3/repos/statistics/#punch-card +func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var results [][]int + resp, err := s.client.Do(ctx, req, &results) + + // convert int slices into Punchcards + var cards []*PunchCard + for _, result := range results { + if len(result) != 3 { + continue + } + card := &PunchCard{ + Day: Int(result[0]), + Hour: Int(result[1]), + Commits: Int(result[2]), + } + cards = append(cards, card) + } + + return cards, resp, err +} diff --git a/vendor/github.com/google/go-github/github/repos_statuses.go b/vendor/github.com/google/go-github/github/repos_statuses.go new file mode 100644 index 00000000..f94fdc85 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_statuses.go @@ -0,0 +1,129 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// RepoStatus represents the status of a repository at a particular reference. +type RepoStatus struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + + // State is the current state of the repository. Possible values are: + // pending, success, error, or failure. + State *string `json:"state,omitempty"` + + // TargetURL is the URL of the page representing this status. It will be + // linked from the GitHub UI to allow users to see the source of the status. + TargetURL *string `json:"target_url,omitempty"` + + // Description is a short high level summary of the status. + Description *string `json:"description,omitempty"` + + // A string label to differentiate this status from the statuses of other systems. + Context *string `json:"context,omitempty"` + + Creator *User `json:"creator,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +func (r RepoStatus) String() string { + return Stringify(r) +} + +// ListStatuses lists the statuses of a repository at the specified +// reference. ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref +func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opt *ListOptions) ([]*RepoStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, ref) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var statuses []*RepoStatus + resp, err := s.client.Do(ctx, req, &statuses) + if err != nil { + return nil, resp, err + } + + return statuses, resp, nil +} + +// CreateStatus creates a new status for a repository at the specified +// reference. Ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://developer.github.com/v3/repos/statuses/#create-a-status +func (s *RepositoriesService) CreateStatus(ctx context.Context, owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, ref) + req, err := s.client.NewRequest("POST", u, status) + if err != nil { + return nil, nil, err + } + + repoStatus := new(RepoStatus) + resp, err := s.client.Do(ctx, req, repoStatus) + if err != nil { + return nil, resp, err + } + + return repoStatus, resp, nil +} + +// CombinedStatus represents the combined status of a repository at a particular reference. +type CombinedStatus struct { + // State is the combined state of the repository. Possible values are: + // failure, pending, or success. + State *string `json:"state,omitempty"` + + Name *string `json:"name,omitempty"` + SHA *string `json:"sha,omitempty"` + TotalCount *int `json:"total_count,omitempty"` + Statuses []RepoStatus `json:"statuses,omitempty"` + + CommitURL *string `json:"commit_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` +} + +func (s CombinedStatus) String() string { + return Stringify(s) +} + +// GetCombinedStatus returns the combined status of a repository at the specified +// reference. ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref +func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opt *ListOptions) (*CombinedStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, ref) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + status := new(CombinedStatus) + resp, err := s.client.Do(ctx, req, status) + if err != nil { + return nil, resp, err + } + + return status, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/repos_traffic.go b/vendor/github.com/google/go-github/github/repos_traffic.go new file mode 100644 index 00000000..fb1c9764 --- /dev/null +++ b/vendor/github.com/google/go-github/github/repos_traffic.go @@ -0,0 +1,141 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TrafficReferrer represent information about traffic from a referrer . +type TrafficReferrer struct { + Referrer *string `json:"referrer,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficPath represent information about the traffic on a path of the repo. +type TrafficPath struct { + Path *string `json:"path,omitempty"` + Title *string `json:"title,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficData represent information about a specific timestamp in views or clones list. +type TrafficData struct { + Timestamp *Timestamp `json:"timestamp,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficViews represent information about the number of views in the last 14 days. +type TrafficViews struct { + Views []*TrafficData `json:"views,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficClones represent information about the number of clones in the last 14 days. +type TrafficClones struct { + Clones []*TrafficData `json:"clones,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficBreakdownOptions specifies the parameters to methods that support breakdown per day or week. +// Can be one of: day, week. Default: day. +type TrafficBreakdownOptions struct { + Per string `url:"per,omitempty"` +} + +// ListTrafficReferrers list the top 10 referrers over the last 14 days. +// +// GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-referrers +func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, repo string) ([]*TrafficReferrer, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/popular/referrers", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var trafficReferrers []*TrafficReferrer + resp, err := s.client.Do(ctx, req, &trafficReferrers) + if err != nil { + return nil, resp, err + } + + return trafficReferrers, resp, nil +} + +// ListTrafficPaths list the top 10 popular content over the last 14 days. +// +// GitHub API docs: https://developer.github.com/v3/repos/traffic/#list-paths +func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo string) ([]*TrafficPath, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/popular/paths", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var paths []*TrafficPath + resp, err := s.client.Do(ctx, req, &paths) + if err != nil { + return nil, resp, err + } + + return paths, resp, nil +} + +// ListTrafficViews get total number of views for the last 14 days and breaks it down either per day or week. +// +// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views +func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficViews, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/views", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + trafficViews := new(TrafficViews) + resp, err := s.client.Do(ctx, req, &trafficViews) + if err != nil { + return nil, resp, err + } + + return trafficViews, resp, nil +} + +// ListTrafficClones get total number of clones for the last 14 days and breaks it down either per day or week for the last 14 days. +// +// GitHub API docs: https://developer.github.com/v3/repos/traffic/#views +func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opt *TrafficBreakdownOptions) (*TrafficClones, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/clones", owner, repo) + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + trafficClones := new(TrafficClones) + resp, err := s.client.Do(ctx, req, &trafficClones) + if err != nil { + return nil, resp, err + } + + return trafficClones, resp, nil +} diff --git a/vendor/github.com/google/go-github/github/search.go b/vendor/github.com/google/go-github/github/search.go new file mode 100644 index 00000000..6e0000df --- /dev/null +++ b/vendor/github.com/google/go-github/github/search.go @@ -0,0 +1,255 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strconv" + + qs "github.com/google/go-querystring/query" +) + +// SearchService provides access to the search related functions +// in the GitHub API. +// +// Each method takes a query string defining the search keywords and any search qualifiers. +// For example, when searching issues, the query "gopher is:issue language:go" will search +// for issues containing the word "gopher" in Go repositories. The method call +// opts := &github.SearchOptions{Sort: "created", Order: "asc"} +// cl.Search.Issues(ctx, "gopher is:issue language:go", opts) +// will search for such issues, sorting by creation date in ascending order +// (i.e., oldest first). +// +// GitHub API docs: https://developer.github.com/v3/search/ +type SearchService service + +// SearchOptions specifies optional parameters to the SearchService methods. +type SearchOptions struct { + // How to sort the search results. Possible values are: + // - for repositories: stars, fork, updated + // - for commits: author-date, committer-date + // - for code: indexed + // - for issues: comments, created, updated + // - for users: followers, repositories, joined + // + // Default is to sort by best match. + Sort string `url:"sort,omitempty"` + + // Sort order if sort parameter is provided. Possible values are: asc, + // desc. Default is desc. + Order string `url:"order,omitempty"` + + // Whether to retrieve text match metadata with a query + TextMatch bool `url:"-"` + + ListOptions +} + +// Common search parameters. +type searchParameters struct { + Query string + RepositoryID *int64 // Sent if non-nil. +} + +// RepositoriesSearchResult represents the result of a repositories search. +type RepositoriesSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Repositories []Repository `json:"items,omitempty"` +} + +// Repositories searches repositories via various criteria. +// +// GitHub API docs: https://developer.github.com/v3/search/#search-repositories +func (s *SearchService) Repositories(ctx context.Context, query string, opt *SearchOptions) (*RepositoriesSearchResult, *Response, error) { + result := new(RepositoriesSearchResult) + resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opt, result) + return result, resp, err +} + +// CommitsSearchResult represents the result of a commits search. +type CommitsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Commits []*CommitResult `json:"items,omitempty"` +} + +// CommitResult represents a commit object as returned in commit search endpoint response. +type CommitResult struct { + SHA *string `json:"sha,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Author *User `json:"author,omitempty"` + Committer *User `json:"committer,omitempty"` + Parents []*Commit `json:"parents,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + + Repository *Repository `json:"repository,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +// Commits searches commits via various criteria. +// +// GitHub API docs: https://developer.github.com/v3/search/#search-commits +func (s *SearchService) Commits(ctx context.Context, query string, opt *SearchOptions) (*CommitsSearchResult, *Response, error) { + result := new(CommitsSearchResult) + resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opt, result) + return result, resp, err +} + +// IssuesSearchResult represents the result of an issues search. +type IssuesSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Issues []Issue `json:"items,omitempty"` +} + +// Issues searches issues via various criteria. +// +// GitHub API docs: https://developer.github.com/v3/search/#search-issues +func (s *SearchService) Issues(ctx context.Context, query string, opt *SearchOptions) (*IssuesSearchResult, *Response, error) { + result := new(IssuesSearchResult) + resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opt, result) + return result, resp, err +} + +// UsersSearchResult represents the result of a users search. +type UsersSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Users []User `json:"items,omitempty"` +} + +// Users searches users via various criteria. +// +// GitHub API docs: https://developer.github.com/v3/search/#search-users +func (s *SearchService) Users(ctx context.Context, query string, opt *SearchOptions) (*UsersSearchResult, *Response, error) { + result := new(UsersSearchResult) + resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opt, result) + return result, resp, err +} + +// Match represents a single text match. +type Match struct { + Text *string `json:"text,omitempty"` + Indices []int `json:"indices,omitempty"` +} + +// TextMatch represents a text match for a SearchResult +type TextMatch struct { + ObjectURL *string `json:"object_url,omitempty"` + ObjectType *string `json:"object_type,omitempty"` + Property *string `json:"property,omitempty"` + Fragment *string `json:"fragment,omitempty"` + Matches []Match `json:"matches,omitempty"` +} + +func (tm TextMatch) String() string { + return Stringify(tm) +} + +// CodeSearchResult represents the result of a code search. +type CodeSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + CodeResults []CodeResult `json:"items,omitempty"` +} + +// CodeResult represents a single search result. +type CodeResult struct { + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Repository *Repository `json:"repository,omitempty"` + TextMatches []TextMatch `json:"text_matches,omitempty"` +} + +func (c CodeResult) String() string { + return Stringify(c) +} + +// Code searches code via various criteria. +// +// GitHub API docs: https://developer.github.com/v3/search/#search-code +func (s *SearchService) Code(ctx context.Context, query string, opt *SearchOptions) (*CodeSearchResult, *Response, error) { + result := new(CodeSearchResult) + resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opt, result) + return result, resp, err +} + +// LabelsSearchResult represents the result of a code search. +type LabelsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Labels []*LabelResult `json:"items,omitempty"` +} + +// LabelResult represents a single search result. +type LabelResult struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Color *string `json:"color,omitempty"` + Default *bool `json:"default,omitempty"` + Description *string `json:"description,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +func (l LabelResult) String() string { + return Stringify(l) +} + +// Labels searches labels in the repository with ID repoID via various criteria. +// +// GitHub API docs: https://developer.github.com/v3/search/#search-labels +func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opt *SearchOptions) (*LabelsSearchResult, *Response, error) { + result := new(LabelsSearchResult) + resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opt, result) + return result, resp, err +} + +// Helper function that executes search queries against different +// GitHub search types (repositories, commits, code, issues, users, labels) +func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opt *SearchOptions, result interface{}) (*Response, error) { + params, err := qs.Values(opt) + if err != nil { + return nil, err + } + params.Set("q", parameters.Query) + if parameters.RepositoryID != nil { + params.Set("repository_id", strconv.FormatInt(*parameters.RepositoryID, 10)) + } + u := fmt.Sprintf("search/%s?%s", searchType, params.Encode()) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + + switch { + case searchType == "commits": + // Accept header for search commits preview endpoint + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCommitSearchPreview) + case searchType == "repositories": + // Accept header for search repositories based on topics preview endpoint + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + case searchType == "labels": + // Accept header for search labels based on label description preview endpoint. + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview) + case opt != nil && opt.TextMatch: + // Accept header defaults to "application/vnd.github.v3+json" + // We change it here to fetch back text-match metadata + req.Header.Set("Accept", "application/vnd.github.v3.text-match+json") + } + + return s.client.Do(ctx, req, result) +} diff --git a/vendor/github.com/google/go-github/github/strings.go b/vendor/github.com/google/go-github/github/strings.go new file mode 100644 index 00000000..431e1cc6 --- /dev/null +++ b/vendor/github.com/google/go-github/github/strings.go @@ -0,0 +1,93 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "fmt" + "io" + + "reflect" +) + +var timestampType = reflect.TypeOf(Timestamp{}) + +// Stringify attempts to create a reasonable string representation of types in +// the GitHub library. It does things like resolve pointers to their values +// and omits struct fields with nil values. +func Stringify(message interface{}) string { + var buf bytes.Buffer + v := reflect.ValueOf(message) + stringifyValue(&buf, v) + return buf.String() +} + +// stringifyValue was heavily inspired by the goprotobuf library. + +func stringifyValue(w io.Writer, val reflect.Value) { + if val.Kind() == reflect.Ptr && val.IsNil() { + w.Write([]byte("")) + return + } + + v := reflect.Indirect(val) + + switch v.Kind() { + case reflect.String: + fmt.Fprintf(w, `"%s"`, v) + case reflect.Slice: + w.Write([]byte{'['}) + for i := 0; i < v.Len(); i++ { + if i > 0 { + w.Write([]byte{' '}) + } + + stringifyValue(w, v.Index(i)) + } + + w.Write([]byte{']'}) + return + case reflect.Struct: + if v.Type().Name() != "" { + w.Write([]byte(v.Type().String())) + } + + // special handling of Timestamp values + if v.Type() == timestampType { + fmt.Fprintf(w, "{%s}", v.Interface()) + return + } + + w.Write([]byte{'{'}) + + var sep bool + for i := 0; i < v.NumField(); i++ { + fv := v.Field(i) + if fv.Kind() == reflect.Ptr && fv.IsNil() { + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + continue + } + + if sep { + w.Write([]byte(", ")) + } else { + sep = true + } + + w.Write([]byte(v.Type().Field(i).Name)) + w.Write([]byte{':'}) + stringifyValue(w, fv) + } + + w.Write([]byte{'}'}) + default: + if v.CanInterface() { + fmt.Fprint(w, v.Interface()) + } + } +} diff --git a/vendor/github.com/google/go-github/github/teams.go b/vendor/github.com/google/go-github/github/teams.go new file mode 100644 index 00000000..1021d538 --- /dev/null +++ b/vendor/github.com/google/go-github/github/teams.go @@ -0,0 +1,7 @@ +package github + +// TeamsService provides access to the team-related functions +// in the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/teams/ +type TeamsService service diff --git a/vendor/github.com/google/go-github/github/teams_discussion_comments.go b/vendor/github.com/google/go-github/github/teams_discussion_comments.go new file mode 100644 index 00000000..26d0e8c5 --- /dev/null +++ b/vendor/github.com/google/go-github/github/teams_discussion_comments.go @@ -0,0 +1,154 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DiscussionComment represents a GitHub dicussion in a team. +type DiscussionComment struct { + Author *User `json:"author,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + BodyVersion *string `json:"body_version,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` + DiscussionURL *string `json:"discussion_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int64 `json:"number,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (c DiscussionComment) String() string { + return Stringify(c) +} + +// DiscussionCommentListOptions specifies optional parameters to the +// TeamServices.ListComments method. +type DiscussionCommentListOptions struct { + // Sorts the discussion comments by the date they were created. + // Accepted values are asc and desc. Default is desc. + Direction string `url:"direction,omitempty"` +} + +// ListComments lists all comments on a team discussion. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#list-comments +func (s *TeamsService) ListComments(ctx context.Context, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discussionNumber) + u, err := addOptions(u, options) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + var comments []*DiscussionComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment gets a specific comment on a team discussion. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#get-a-single-comment +func (s *TeamsService) GetComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// CreateComment creates a new discussion post on a team discussion. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#create-a-comment +func (s *TeamsService) CreateComment(ctx context.Context, teamID int64, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments", teamID, discsusionNumber) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// EditComment edits the body text of a discussion comment. +// Authenticated user must grant write:discussion scope. +// User is allowed to edit body of a comment only. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#edit-a-comment +func (s *TeamsService) EditComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// DeleteComment deletes a comment on a team discussion. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussion_comments/#delete-a-comment +func (s *TeamsService) DeleteComment(ctx context.Context, teamID int64, discussionNumber, commentNumber int) (*Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v", teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/teams_discussions.go b/vendor/github.com/google/go-github/github/teams_discussions.go new file mode 100644 index 00000000..fc9b25a5 --- /dev/null +++ b/vendor/github.com/google/go-github/github/teams_discussions.go @@ -0,0 +1,159 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TeamDiscussion represents a GitHub dicussion in a team. +type TeamDiscussion struct { + Author *User `json:"author,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + BodyVersion *string `json:"body_version,omitempty"` + CommentsCount *int64 `json:"comments_count,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int64 `json:"number,omitempty"` + Pinned *bool `json:"pinned,omitempty"` + Private *bool `json:"private,omitempty"` + TeamURL *string `json:"team_url,omitempty"` + Title *string `json:"title,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (d TeamDiscussion) String() string { + return Stringify(d) +} + +// DiscussionListOptions specifies optional parameters to the +// TeamServices.ListDiscussions method. +type DiscussionListOptions struct { + // Sorts the discussion by the date they were created. + // Accepted values are asc and desc. Default is desc. + Direction string `url:"direction,omitempty"` +} + +// ListDiscussions lists all discussions on team's page. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussions/#list-discussions +func (s *TeamsService) ListDiscussions(ctx context.Context, teamID int64, options *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions", teamID) + u, err := addOptions(u, options) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + var teamDiscussions []*TeamDiscussion + resp, err := s.client.Do(ctx, req, &teamDiscussions) + if err != nil { + return nil, resp, err + } + + return teamDiscussions, resp, nil +} + +// GetDiscussion gets a specific discussion on a team's page. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussions/#get-a-single-discussion +func (s *TeamsService) GetDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// CreateDiscussion creates a new discussion post on a team's page. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussions/#create-a-discussion +func (s *TeamsService) CreateDiscussion(ctx context.Context, teamID int64, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions", teamID) + req, err := s.client.NewRequest("POST", u, discussion) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// EditDiscussion edits the title and body text of a discussion post. +// Authenticated user must grant write:discussion scope. +// User is allowed to change Title and Body of a discussion only. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussions/#edit-a-discussion +func (s *TeamsService) EditDiscussion(ctx context.Context, teamID int64, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) + req, err := s.client.NewRequest("PATCH", u, discussion) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// DeleteDiscussion deletes a discussion from team's page. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://developer.github.com/v3/teams/discussions/#delete-a-discussion +func (s *TeamsService) DeleteDiscussion(ctx context.Context, teamID int64, discussionNumber int) (*Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v", teamID, discussionNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTeamDiscussionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/timestamp.go b/vendor/github.com/google/go-github/github/timestamp.go new file mode 100644 index 00000000..a1c1554a --- /dev/null +++ b/vendor/github.com/google/go-github/github/timestamp.go @@ -0,0 +1,41 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "strconv" + "time" +) + +// Timestamp represents a time that can be unmarshalled from a JSON string +// formatted as either an RFC3339 or Unix timestamp. This is necessary for some +// fields since the GitHub API is inconsistent in how it represents times. All +// exported methods of time.Time can be called on Timestamp. +type Timestamp struct { + time.Time +} + +func (t Timestamp) String() string { + return t.Time.String() +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// Time is expected in RFC3339 or Unix format. +func (t *Timestamp) UnmarshalJSON(data []byte) (err error) { + str := string(data) + i, err := strconv.ParseInt(str, 10, 64) + if err == nil { + (*t).Time = time.Unix(i, 0) + } else { + (*t).Time, err = time.Parse(`"`+time.RFC3339+`"`, str) + } + return +} + +// Equal reports whether t and u are equal based on time.Equal +func (t Timestamp) Equal(u Timestamp) bool { + return t.Time.Equal(u.Time) +} diff --git a/vendor/github.com/google/go-github/github/users.go b/vendor/github.com/google/go-github/github/users.go new file mode 100644 index 00000000..8c4efe1d --- /dev/null +++ b/vendor/github.com/google/go-github/github/users.go @@ -0,0 +1,233 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// UsersService handles communication with the user related +// methods of the GitHub API. +// +// GitHub API docs: https://developer.github.com/v3/users/ +type UsersService service + +// User represents a GitHub user. +type User struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + Name *string `json:"name,omitempty"` + Company *string `json:"company,omitempty"` + Blog *string `json:"blog,omitempty"` + Location *string `json:"location,omitempty"` + Email *string `json:"email,omitempty"` + Hireable *bool `json:"hireable,omitempty"` + Bio *string `json:"bio,omitempty"` + PublicRepos *int `json:"public_repos,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` + Followers *int `json:"followers,omitempty"` + Following *int `json:"following,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + SuspendedAt *Timestamp `json:"suspended_at,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + TotalPrivateRepos *int `json:"total_private_repos,omitempty"` + OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + DiskUsage *int `json:"disk_usage,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + Plan *Plan `json:"plan,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://developer.github.com/v3/search/#text-match-metadata + TextMatches []TextMatch `json:"text_matches,omitempty"` + + // Permissions identifies the permissions that a user has on a given + // repository. This is only populated when calling Repositories.ListCollaborators. + Permissions *map[string]bool `json:"permissions,omitempty"` +} + +func (u User) String() string { + return Stringify(u) +} + +// Get fetches a user. Passing the empty string will fetch the authenticated +// user. +// +// GitHub API docs: https://developer.github.com/v3/users/#get-a-single-user +func (s *UsersService) Get(ctx context.Context, user string) (*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v", user) + } else { + u = "user" + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + uResp := new(User) + resp, err := s.client.Do(ctx, req, uResp) + if err != nil { + return nil, resp, err + } + + return uResp, resp, nil +} + +// GetByID fetches a user. +// +// Note: GetByID uses the undocumented GitHub API endpoint /user/:id. +func (s *UsersService) GetByID(ctx context.Context, id int64) (*User, *Response, error) { + u := fmt.Sprintf("user/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + user := new(User) + resp, err := s.client.Do(ctx, req, user) + if err != nil { + return nil, resp, err + } + + return user, resp, nil +} + +// Edit the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/#update-the-authenticated-user +func (s *UsersService) Edit(ctx context.Context, user *User) (*User, *Response, error) { + u := "user" + req, err := s.client.NewRequest("PATCH", u, user) + if err != nil { + return nil, nil, err + } + + uResp := new(User) + resp, err := s.client.Do(ctx, req, uResp) + if err != nil { + return nil, resp, err + } + + return uResp, resp, nil +} + +// UserListOptions specifies optional parameters to the UsersService.ListAll +// method. +type UserListOptions struct { + // ID of the last user seen + Since int64 `url:"since,omitempty"` + + // Note: Pagination is powered exclusively by the Since parameter, + // ListOptions.Page has no effect. + // ListOptions.PerPage controls an undocumented GitHub API parameter. + ListOptions +} + +// ListAll lists all GitHub users. +// +// To paginate through all users, populate 'Since' with the ID of the last user. +// +// GitHub API docs: https://developer.github.com/v3/users/#get-all-users +func (s *UsersService) ListAll(ctx context.Context, opt *UserListOptions) ([]*User, *Response, error) { + u, err := addOptions("users", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ListInvitations lists all currently-open repository invitations for the +// authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-a-users-repository-invitations +func (s *UsersService) ListInvitations(ctx context.Context, opt *ListOptions) ([]*RepositoryInvitation, *Response, error) { + u, err := addOptions("user/repository_invitations", opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) + + invites := []*RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, &invites) + if err != nil { + return nil, resp, err + } + + return invites, resp, nil +} + +// AcceptInvitation accepts the currently-open repository invitation for the +// authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/repos/invitations/#accept-a-repository-invitation +func (s *UsersService) AcceptInvitation(ctx context.Context, invitationID int64) (*Response, error) { + u := fmt.Sprintf("user/repository_invitations/%v", invitationID) + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) + + return s.client.Do(ctx, req, nil) +} + +// DeclineInvitation declines the currently-open repository invitation for the +// authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/repos/invitations/#decline-a-repository-invitation +func (s *UsersService) DeclineInvitation(ctx context.Context, invitationID int64) (*Response, error) { + u := fmt.Sprintf("user/repository_invitations/%v", invitationID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeRepositoryInvitationsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/users_administration.go b/vendor/github.com/google/go-github/github/users_administration.go new file mode 100644 index 00000000..e042398d --- /dev/null +++ b/vendor/github.com/google/go-github/github/users_administration.go @@ -0,0 +1,67 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// PromoteSiteAdmin promotes a user to a site administrator of a GitHub Enterprise instance. +// +// GitHub API docs: https://developer.github.com/v3/users/administration/#promote-an-ordinary-user-to-a-site-administrator +func (s *UsersService) PromoteSiteAdmin(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/site_admin", user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DemoteSiteAdmin demotes a user from site administrator of a GitHub Enterprise instance. +// +// GitHub API docs: https://developer.github.com/v3/users/administration/#demote-a-site-administrator-to-an-ordinary-user +func (s *UsersService) DemoteSiteAdmin(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/site_admin", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Suspend a user on a GitHub Enterprise instance. +// +// GitHub API docs: https://developer.github.com/v3/users/administration/#suspend-a-user +func (s *UsersService) Suspend(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/suspended", user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unsuspend a user on a GitHub Enterprise instance. +// +// GitHub API docs: https://developer.github.com/v3/users/administration/#unsuspend-a-user +func (s *UsersService) Unsuspend(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/suspended", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/users_blocking.go b/vendor/github.com/google/go-github/github/users_blocking.go new file mode 100644 index 00000000..39e45601 --- /dev/null +++ b/vendor/github.com/google/go-github/github/users_blocking.go @@ -0,0 +1,91 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListBlockedUsers lists all the blocked users by the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/blocking/#list-blocked-users +func (s *UsersService) ListBlockedUsers(ctx context.Context, opt *ListOptions) ([]*User, *Response, error) { + u := "user/blocks" + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + var blockedUsers []*User + resp, err := s.client.Do(ctx, req, &blockedUsers) + if err != nil { + return nil, resp, err + } + + return blockedUsers, resp, nil +} + +// IsBlocked reports whether specified user is blocked by the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/blocking/#check-whether-youve-blocked-a-user +func (s *UsersService) IsBlocked(ctx context.Context, user string) (bool, *Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + resp, err := s.client.Do(ctx, req, nil) + isBlocked, err := parseBoolResponse(err) + return isBlocked, resp, err +} + +// BlockUser blocks specified user for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/blocking/#block-a-user +func (s *UsersService) BlockUser(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnblockUser unblocks specified user for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/blocking/#unblock-a-user +func (s *UsersService) UnblockUser(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/users_emails.go b/vendor/github.com/google/go-github/github/users_emails.go new file mode 100644 index 00000000..0bbd4627 --- /dev/null +++ b/vendor/github.com/google/go-github/github/users_emails.go @@ -0,0 +1,71 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// UserEmail represents user's email address +type UserEmail struct { + Email *string `json:"email,omitempty"` + Primary *bool `json:"primary,omitempty"` + Verified *bool `json:"verified,omitempty"` +} + +// ListEmails lists all email addresses for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user +func (s *UsersService) ListEmails(ctx context.Context, opt *ListOptions) ([]*UserEmail, *Response, error) { + u := "user/emails" + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var emails []*UserEmail + resp, err := s.client.Do(ctx, req, &emails) + if err != nil { + return nil, resp, err + } + + return emails, resp, nil +} + +// AddEmails adds email addresses of the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/emails/#add-email-addresses +func (s *UsersService) AddEmails(ctx context.Context, emails []string) ([]*UserEmail, *Response, error) { + u := "user/emails" + req, err := s.client.NewRequest("POST", u, emails) + if err != nil { + return nil, nil, err + } + + var e []*UserEmail + resp, err := s.client.Do(ctx, req, &e) + if err != nil { + return nil, resp, err + } + + return e, resp, nil +} + +// DeleteEmails deletes email addresses from authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/emails/#delete-email-addresses +func (s *UsersService) DeleteEmails(ctx context.Context, emails []string) (*Response, error) { + u := "user/emails" + req, err := s.client.NewRequest("DELETE", u, emails) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/users_followers.go b/vendor/github.com/google/go-github/github/users_followers.go new file mode 100644 index 00000000..c2224096 --- /dev/null +++ b/vendor/github.com/google/go-github/github/users_followers.go @@ -0,0 +1,119 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListFollowers lists the followers for a user. Passing the empty string will +// fetch followers for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/followers/#list-followers-of-a-user +func (s *UsersService) ListFollowers(ctx context.Context, user string, opt *ListOptions) ([]*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/followers", user) + } else { + u = "user/followers" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ListFollowing lists the people that a user is following. Passing the empty +// string will list people the authenticated user is following. +// +// GitHub API docs: https://developer.github.com/v3/users/followers/#list-users-followed-by-another-user +func (s *UsersService) ListFollowing(ctx context.Context, user string, opt *ListOptions) ([]*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/following", user) + } else { + u = "user/following" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// IsFollowing checks if "user" is following "target". Passing the empty +// string for "user" will check if the authenticated user is following "target". +// +// GitHub API docs: https://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user +func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bool, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/following/%v", user, target) + } else { + u = fmt.Sprintf("user/following/%v", target) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + following, err := parseBoolResponse(err) + return following, resp, err +} + +// Follow will cause the authenticated user to follow the specified user. +// +// GitHub API docs: https://developer.github.com/v3/users/followers/#follow-a-user +func (s *UsersService) Follow(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/following/%v", user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unfollow will cause the authenticated user to unfollow the specified user. +// +// GitHub API docs: https://developer.github.com/v3/users/followers/#unfollow-a-user +func (s *UsersService) Unfollow(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/following/%v", user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/users_gpg_keys.go b/vendor/github.com/google/go-github/github/users_gpg_keys.go new file mode 100644 index 00000000..d8bbc520 --- /dev/null +++ b/vendor/github.com/google/go-github/github/users_gpg_keys.go @@ -0,0 +1,140 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// GPGKey represents a GitHub user's public GPG key used to verify GPG signed commits and tags. +// +// https://developer.github.com/changes/2016-04-04-git-signing-api-preview/ +type GPGKey struct { + ID *int64 `json:"id,omitempty"` + PrimaryKeyID *int64 `json:"primary_key_id,omitempty"` + KeyID *string `json:"key_id,omitempty"` + PublicKey *string `json:"public_key,omitempty"` + Emails []GPGEmail `json:"emails,omitempty"` + Subkeys []GPGKey `json:"subkeys,omitempty"` + CanSign *bool `json:"can_sign,omitempty"` + CanEncryptComms *bool `json:"can_encrypt_comms,omitempty"` + CanEncryptStorage *bool `json:"can_encrypt_storage,omitempty"` + CanCertify *bool `json:"can_certify,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + ExpiresAt *time.Time `json:"expires_at,omitempty"` +} + +// String stringifies a GPGKey. +func (k GPGKey) String() string { + return Stringify(k) +} + +// GPGEmail represents an email address associated to a GPG key. +type GPGEmail struct { + Email *string `json:"email,omitempty"` + Verified *bool `json:"verified,omitempty"` +} + +// ListGPGKeys lists the public GPG keys for a user. Passing the empty +// string will fetch keys for the authenticated user. It requires authentication +// via Basic Auth or via OAuth with at least read:gpg_key scope. +// +// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#list-gpg-keys-for-a-user +func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opt *ListOptions) ([]*GPGKey, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/gpg_keys", user) + } else { + u = "user/gpg_keys" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGitSigningPreview) + + var keys []*GPGKey + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetGPGKey gets extended details for a single GPG key. It requires authentication +// via Basic Auth or via OAuth with at least read:gpg_key scope. +// +// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#get-a-single-gpg-key +func (s *UsersService) GetGPGKey(ctx context.Context, id int64) (*GPGKey, *Response, error) { + u := fmt.Sprintf("user/gpg_keys/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGitSigningPreview) + + key := &GPGKey{} + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateGPGKey creates a GPG key. It requires authenticatation via Basic Auth +// or OAuth with at least write:gpg_key scope. +// +// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#create-a-gpg-key +func (s *UsersService) CreateGPGKey(ctx context.Context, armoredPublicKey string) (*GPGKey, *Response, error) { + gpgKey := &struct { + ArmoredPublicKey string `json:"armored_public_key"` + }{ArmoredPublicKey: armoredPublicKey} + req, err := s.client.NewRequest("POST", "user/gpg_keys", gpgKey) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGitSigningPreview) + + key := &GPGKey{} + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// DeleteGPGKey deletes a GPG key. It requires authentication via Basic Auth or +// via OAuth with at least admin:gpg_key scope. +// +// GitHub API docs: https://developer.github.com/v3/users/gpg_keys/#delete-a-gpg-key +func (s *UsersService) DeleteGPGKey(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("user/gpg_keys/%v", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeGitSigningPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/users_keys.go b/vendor/github.com/google/go-github/github/users_keys.go new file mode 100644 index 00000000..ddc832a1 --- /dev/null +++ b/vendor/github.com/google/go-github/github/users_keys.go @@ -0,0 +1,108 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Key represents a public SSH key used to authenticate a user or deploy script. +type Key struct { + ID *int64 `json:"id,omitempty"` + Key *string `json:"key,omitempty"` + URL *string `json:"url,omitempty"` + Title *string `json:"title,omitempty"` + ReadOnly *bool `json:"read_only,omitempty"` +} + +func (k Key) String() string { + return Stringify(k) +} + +// ListKeys lists the verified public keys for a user. Passing the empty +// string will fetch keys for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user +func (s *UsersService) ListKeys(ctx context.Context, user string, opt *ListOptions) ([]*Key, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/keys", user) + } else { + u = "user/keys" + } + u, err := addOptions(u, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*Key + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetKey fetches a single public key. +// +// GitHub API docs: https://developer.github.com/v3/users/keys/#get-a-single-public-key +func (s *UsersService) GetKey(ctx context.Context, id int64) (*Key, *Response, error) { + u := fmt.Sprintf("user/keys/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := new(Key) + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateKey adds a public key for the authenticated user. +// +// GitHub API docs: https://developer.github.com/v3/users/keys/#create-a-public-key +func (s *UsersService) CreateKey(ctx context.Context, key *Key) (*Key, *Response, error) { + u := "user/keys" + + req, err := s.client.NewRequest("POST", u, key) + if err != nil { + return nil, nil, err + } + + k := new(Key) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// DeleteKey deletes a public key. +// +// GitHub API docs: https://developer.github.com/v3/users/keys/#delete-a-public-key +func (s *UsersService) DeleteKey(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("user/keys/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/github/with_appengine.go b/vendor/github.com/google/go-github/github/with_appengine.go new file mode 100644 index 00000000..59ce26b2 --- /dev/null +++ b/vendor/github.com/google/go-github/github/with_appengine.go @@ -0,0 +1,20 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build appengine + +// This file provides glue for making github work on App Engine. + +package github + +import ( + "context" + "net/http" +) + +func withContext(ctx context.Context, req *http.Request) *http.Request { + // No-op because App Engine adds context to a request differently. + return req +} diff --git a/vendor/github.com/google/go-github/github/without_appengine.go b/vendor/github.com/google/go-github/github/without_appengine.go new file mode 100644 index 00000000..6f8fdac5 --- /dev/null +++ b/vendor/github.com/google/go-github/github/without_appengine.go @@ -0,0 +1,19 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine + +// This file provides glue for making github work without App Engine. + +package github + +import ( + "context" + "net/http" +) + +func withContext(ctx context.Context, req *http.Request) *http.Request { + return req.WithContext(ctx) +} diff --git a/vendor/github.com/google/go-querystring/LICENSE b/vendor/github.com/google/go-querystring/LICENSE new file mode 100644 index 00000000..ae121a1e --- /dev/null +++ b/vendor/github.com/google/go-querystring/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Google. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go new file mode 100644 index 00000000..37080b19 --- /dev/null +++ b/vendor/github.com/google/go-querystring/query/encode.go @@ -0,0 +1,320 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package query implements encoding of structs into URL query parameters. +// +// As a simple example: +// +// type Options struct { +// Query string `url:"q"` +// ShowAll bool `url:"all"` +// Page int `url:"page"` +// } +// +// opt := Options{ "foo", true, 2 } +// v, _ := query.Values(opt) +// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2" +// +// The exact mapping between Go values and url.Values is described in the +// documentation for the Values() function. +package query + +import ( + "bytes" + "fmt" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +var timeType = reflect.TypeOf(time.Time{}) + +var encoderType = reflect.TypeOf(new(Encoder)).Elem() + +// Encoder is an interface implemented by any type that wishes to encode +// itself into URL values in a non-standard way. +type Encoder interface { + EncodeValues(key string, v *url.Values) error +} + +// Values returns the url.Values encoding of v. +// +// Values expects to be passed a struct, and traverses it recursively using the +// following encoding rules. +// +// Each exported struct field is encoded as a URL parameter unless +// +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option +// +// The empty values are false, 0, any nil pointer or interface value, any array +// slice, map, or string of length zero, and any time.Time that returns true +// for IsZero(). +// +// The URL parameter name defaults to the struct field name but can be +// specified in the struct field's tag value. The "url" key in the struct +// field's tag value is the key name, followed by an optional comma and +// options. For example: +// +// // Field is ignored by this package. +// Field int `url:"-"` +// +// // Field appears as URL parameter "myName". +// Field int `url:"myName"` +// +// // Field appears as URL parameter "myName" and the field is omitted if +// // its value is empty +// Field int `url:"myName,omitempty"` +// +// // Field appears as URL parameter "Field" (the default), but the field +// // is skipped if empty. Note the leading comma. +// Field int `url:",omitempty"` +// +// For encoding individual field values, the following type-dependent rules +// apply: +// +// Boolean values default to encoding as the strings "true" or "false". +// Including the "int" option signals that the field should be encoded as the +// strings "1" or "0". +// +// time.Time values default to encoding as RFC3339 timestamps. Including the +// "unix" option signals that the field should be encoded as a Unix time (see +// time.Unix()) +// +// Slice and Array values default to encoding as multiple URL values of the +// same name. Including the "comma" option signals that the field should be +// encoded as a single comma-delimited value. Including the "space" option +// similarly encodes the value as a single space-delimited string. Including +// the "semicolon" option will encode the value as a semicolon-delimited string. +// Including the "brackets" option signals that the multiple URL values should +// have "[]" appended to the value name. "numbered" will append a number to +// the end of each incidence of the value name, example: +// name0=value0&name1=value1, etc. +// +// Anonymous struct fields are usually encoded as if their inner exported +// fields were fields in the outer struct, subject to the standard Go +// visibility rules. An anonymous struct field with a name given in its URL +// tag is treated as having that name, rather than being anonymous. +// +// Non-nil pointer values are encoded as the value pointed to. +// +// Nested structs are encoded including parent fields in value names for +// scoping. e.g: +// +// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO" +// +// All other values are encoded using their default string representation. +// +// Multiple fields that encode to the same URL parameter name will be included +// as multiple URL values of the same name. +func Values(v interface{}) (url.Values, error) { + values := make(url.Values) + val := reflect.ValueOf(v) + for val.Kind() == reflect.Ptr { + if val.IsNil() { + return values, nil + } + val = val.Elem() + } + + if v == nil { + return values, nil + } + + if val.Kind() != reflect.Struct { + return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind()) + } + + err := reflectValue(values, val, "") + return values, err +} + +// reflectValue populates the values parameter from the struct fields in val. +// Embedded structs are followed recursively (using the rules defined in the +// Values function documentation) breadth-first. +func reflectValue(values url.Values, val reflect.Value, scope string) error { + var embedded []reflect.Value + + typ := val.Type() + for i := 0; i < typ.NumField(); i++ { + sf := typ.Field(i) + if sf.PkgPath != "" && !sf.Anonymous { // unexported + continue + } + + sv := val.Field(i) + tag := sf.Tag.Get("url") + if tag == "-" { + continue + } + name, opts := parseTag(tag) + if name == "" { + if sf.Anonymous && sv.Kind() == reflect.Struct { + // save embedded struct for later processing + embedded = append(embedded, sv) + continue + } + + name = sf.Name + } + + if scope != "" { + name = scope + "[" + name + "]" + } + + if opts.Contains("omitempty") && isEmptyValue(sv) { + continue + } + + if sv.Type().Implements(encoderType) { + if !reflect.Indirect(sv).IsValid() { + sv = reflect.New(sv.Type().Elem()) + } + + m := sv.Interface().(Encoder) + if err := m.EncodeValues(name, &values); err != nil { + return err + } + continue + } + + if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array { + var del byte + if opts.Contains("comma") { + del = ',' + } else if opts.Contains("space") { + del = ' ' + } else if opts.Contains("semicolon") { + del = ';' + } else if opts.Contains("brackets") { + name = name + "[]" + } + + if del != 0 { + s := new(bytes.Buffer) + first := true + for i := 0; i < sv.Len(); i++ { + if first { + first = false + } else { + s.WriteByte(del) + } + s.WriteString(valueString(sv.Index(i), opts)) + } + values.Add(name, s.String()) + } else { + for i := 0; i < sv.Len(); i++ { + k := name + if opts.Contains("numbered") { + k = fmt.Sprintf("%s%d", name, i) + } + values.Add(k, valueString(sv.Index(i), opts)) + } + } + continue + } + + for sv.Kind() == reflect.Ptr { + if sv.IsNil() { + break + } + sv = sv.Elem() + } + + if sv.Type() == timeType { + values.Add(name, valueString(sv, opts)) + continue + } + + if sv.Kind() == reflect.Struct { + reflectValue(values, sv, name) + continue + } + + values.Add(name, valueString(sv, opts)) + } + + for _, f := range embedded { + if err := reflectValue(values, f, scope); err != nil { + return err + } + } + + return nil +} + +// valueString returns the string representation of a value. +func valueString(v reflect.Value, opts tagOptions) string { + for v.Kind() == reflect.Ptr { + if v.IsNil() { + return "" + } + v = v.Elem() + } + + if v.Kind() == reflect.Bool && opts.Contains("int") { + if v.Bool() { + return "1" + } + return "0" + } + + if v.Type() == timeType { + t := v.Interface().(time.Time) + if opts.Contains("unix") { + return strconv.FormatInt(t.Unix(), 10) + } + return t.Format(time.RFC3339) + } + + return fmt.Sprint(v.Interface()) +} + +// isEmptyValue checks if a value should be considered empty for the purposes +// of omitting fields with the "omitempty" option. +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + + if v.Type() == timeType { + return v.Interface().(time.Time).IsZero() + } + + return false +} + +// tagOptions is the string following a comma in a struct field's "url" tag, or +// the empty string. It does not include the leading comma. +type tagOptions []string + +// parseTag splits a struct field's url tag into its name and comma-separated +// options. +func parseTag(tag string) (string, tagOptions) { + s := strings.Split(tag, ",") + return s[0], s[1:] +} + +// Contains checks whether the tagOptions contains the specified option. +func (o tagOptions) Contains(option string) bool { + for _, s := range o { + if s == option { + return true + } + } + return false +} diff --git a/vendor/github.com/jessevdk/go-flags/.travis.yml b/vendor/github.com/jessevdk/go-flags/.travis.yml new file mode 100644 index 00000000..0f0728d2 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/.travis.yml @@ -0,0 +1,44 @@ +language: go + +os: + - linux + - osx + +go: + - 1.x + - 1.7.x + - 1.8.x + - 1.9.x + - 1.10.x + +install: + # go-flags + - go get -d -v ./... + - go build -v ./... + + # linting + - go get github.com/golang/lint/golint + + # code coverage + - go get golang.org/x/tools/cmd/cover + - go get github.com/onsi/ginkgo/ginkgo + - go get github.com/modocache/gover + - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then go get github.com/mattn/goveralls; fi + +script: + # go-flags + - $(exit $(gofmt -l . | wc -l)) + - go test -v ./... + + # linting + - go tool vet -all=true -v=true . || true + - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/golint ./... + + # code coverage + - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/ginkgo -r -cover + - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/gover + - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci -repotoken $COVERALLS_TOKEN; fi + +env: + # coveralls.io + secure: "RCYbiB4P0RjQRIoUx/vG/AjP3mmYCbzOmr86DCww1Z88yNcy3hYr3Cq8rpPtYU5v0g7wTpu4adaKIcqRE9xknYGbqj3YWZiCoBP1/n4Z+9sHW3Dsd9D/GRGeHUus0laJUGARjWoCTvoEtOgTdGQDoX7mH+pUUY0FBltNYUdOiiU=" diff --git a/vendor/github.com/jessevdk/go-flags/LICENSE b/vendor/github.com/jessevdk/go-flags/LICENSE new file mode 100644 index 00000000..bcca0d52 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2012 Jesse van den Kieboom. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/jessevdk/go-flags/README.md b/vendor/github.com/jessevdk/go-flags/README.md new file mode 100644 index 00000000..3b02394e --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/README.md @@ -0,0 +1,134 @@ +go-flags: a go library for parsing command line arguments +========================================================= + +[![GoDoc](https://godoc.org/github.com/jessevdk/go-flags?status.png)](https://godoc.org/github.com/jessevdk/go-flags) [![Build Status](https://travis-ci.org/jessevdk/go-flags.svg?branch=master)](https://travis-ci.org/jessevdk/go-flags) [![Coverage Status](https://img.shields.io/coveralls/jessevdk/go-flags.svg)](https://coveralls.io/r/jessevdk/go-flags?branch=master) + +This library provides similar functionality to the builtin flag library of +go, but provides much more functionality and nicer formatting. From the +documentation: + +Package flags provides an extensive command line option parser. +The flags package is similar in functionality to the go builtin flag package +but provides more options and uses reflection to provide a convenient and +succinct way of specifying command line options. + +Supported features: +* Options with short names (-v) +* Options with long names (--verbose) +* Options with and without arguments (bool v.s. other type) +* Options with optional arguments and default values +* Multiple option groups each containing a set of options +* Generate and print well-formatted help message +* Passing remaining command line arguments after -- (optional) +* Ignoring unknown command line options (optional) +* Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification +* Supports multiple short options -aux +* Supports all primitive go types (string, int{8..64}, uint{8..64}, float) +* Supports same option multiple times (can store in slice or last option counts) +* Supports maps +* Supports function callbacks +* Supports namespaces for (nested) option groups + +The flags package uses structs, reflection and struct field tags +to allow users to specify command line options. This results in very simple +and concise specification of your application options. For example: + +```go +type Options struct { + Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` +} +``` + +This specifies one option with a short name -v and a long name --verbose. +When either -v or --verbose is found on the command line, a 'true' value +will be appended to the Verbose field. e.g. when specifying -vvv, the +resulting value of Verbose will be {[true, true, true]}. + +Example: +-------- +```go +var opts struct { + // Slice of bool will append 'true' each time the option + // is encountered (can be set multiple times, like -vvv) + Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` + + // Example of automatic marshalling to desired type (uint) + Offset uint `long:"offset" description:"Offset"` + + // Example of a callback, called each time the option is found. + Call func(string) `short:"c" description:"Call phone number"` + + // Example of a required flag + Name string `short:"n" long:"name" description:"A name" required:"true"` + + // Example of a value name + File string `short:"f" long:"file" description:"A file" value-name:"FILE"` + + // Example of a pointer + Ptr *int `short:"p" description:"A pointer to an integer"` + + // Example of a slice of strings + StringSlice []string `short:"s" description:"A slice of strings"` + + // Example of a slice of pointers + PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` + + // Example of a map + IntMap map[string]int `long:"intmap" description:"A map from string to int"` +} + +// Callback which will invoke callto: to call a number. +// Note that this works just on OS X (and probably only with +// Skype) but it shows the idea. +opts.Call = func(num string) { + cmd := exec.Command("open", "callto:"+num) + cmd.Start() + cmd.Process.Release() +} + +// Make some fake arguments to parse. +args := []string{ + "-vv", + "--offset=5", + "-n", "Me", + "-p", "3", + "-s", "hello", + "-s", "world", + "--ptrslice", "hello", + "--ptrslice", "world", + "--intmap", "a:1", + "--intmap", "b:5", + "arg1", + "arg2", + "arg3", +} + +// Parse flags from `args'. Note that here we use flags.ParseArgs for +// the sake of making a working example. Normally, you would simply use +// flags.Parse(&opts) which uses os.Args +args, err := flags.ParseArgs(&opts, args) + +if err != nil { + panic(err) +} + +fmt.Printf("Verbosity: %v\n", opts.Verbose) +fmt.Printf("Offset: %d\n", opts.Offset) +fmt.Printf("Name: %s\n", opts.Name) +fmt.Printf("Ptr: %d\n", *opts.Ptr) +fmt.Printf("StringSlice: %v\n", opts.StringSlice) +fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1]) +fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"]) +fmt.Printf("Remaining args: %s\n", strings.Join(args, " ")) + +// Output: Verbosity: [true true] +// Offset: 5 +// Name: Me +// Ptr: 3 +// StringSlice: [hello world] +// PtrSlice: [hello world] +// IntMap: [a:1 b:5] +// Remaining args: arg1 arg2 arg3 +``` + +More information can be found in the godocs: diff --git a/vendor/github.com/jessevdk/go-flags/arg.go b/vendor/github.com/jessevdk/go-flags/arg.go new file mode 100644 index 00000000..8ec62048 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/arg.go @@ -0,0 +1,27 @@ +package flags + +import ( + "reflect" +) + +// Arg represents a positional argument on the command line. +type Arg struct { + // The name of the positional argument (used in the help) + Name string + + // A description of the positional argument (used in the help) + Description string + + // The minimal number of required positional arguments + Required int + + // The maximum number of required positional arguments + RequiredMaximum int + + value reflect.Value + tag multiTag +} + +func (a *Arg) isRemaining() bool { + return a.value.Type().Kind() == reflect.Slice +} diff --git a/vendor/github.com/jessevdk/go-flags/check_crosscompile.sh b/vendor/github.com/jessevdk/go-flags/check_crosscompile.sh new file mode 100755 index 00000000..c494f611 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/check_crosscompile.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e + +echo '# linux arm7' +GOARM=7 GOARCH=arm GOOS=linux go build +echo '# linux arm5' +GOARM=5 GOARCH=arm GOOS=linux go build +echo '# windows 386' +GOARCH=386 GOOS=windows go build +echo '# windows amd64' +GOARCH=amd64 GOOS=windows go build +echo '# darwin' +GOARCH=amd64 GOOS=darwin go build +echo '# freebsd' +GOARCH=amd64 GOOS=freebsd go build diff --git a/vendor/github.com/jessevdk/go-flags/closest.go b/vendor/github.com/jessevdk/go-flags/closest.go new file mode 100644 index 00000000..3b518757 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/closest.go @@ -0,0 +1,59 @@ +package flags + +func levenshtein(s string, t string) int { + if len(s) == 0 { + return len(t) + } + + if len(t) == 0 { + return len(s) + } + + dists := make([][]int, len(s)+1) + for i := range dists { + dists[i] = make([]int, len(t)+1) + dists[i][0] = i + } + + for j := range t { + dists[0][j] = j + } + + for i, sc := range s { + for j, tc := range t { + if sc == tc { + dists[i+1][j+1] = dists[i][j] + } else { + dists[i+1][j+1] = dists[i][j] + 1 + if dists[i+1][j] < dists[i+1][j+1] { + dists[i+1][j+1] = dists[i+1][j] + 1 + } + if dists[i][j+1] < dists[i+1][j+1] { + dists[i+1][j+1] = dists[i][j+1] + 1 + } + } + } + } + + return dists[len(s)][len(t)] +} + +func closestChoice(cmd string, choices []string) (string, int) { + if len(choices) == 0 { + return "", 0 + } + + mincmd := -1 + mindist := -1 + + for i, c := range choices { + l := levenshtein(cmd, c) + + if mincmd < 0 || l < mindist { + mindist = l + mincmd = i + } + } + + return choices[mincmd], mindist +} diff --git a/vendor/github.com/jessevdk/go-flags/command.go b/vendor/github.com/jessevdk/go-flags/command.go new file mode 100644 index 00000000..486bacba --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/command.go @@ -0,0 +1,465 @@ +package flags + +import ( + "reflect" + "sort" + "strconv" + "strings" +) + +// Command represents an application command. Commands can be added to the +// parser (which itself is a command) and are selected/executed when its name +// is specified on the command line. The Command type embeds a Group and +// therefore also carries a set of command specific options. +type Command struct { + // Embedded, see Group for more information + *Group + + // The name by which the command can be invoked + Name string + + // The active sub command (set by parsing) or nil + Active *Command + + // Whether subcommands are optional + SubcommandsOptional bool + + // Aliases for the command + Aliases []string + + // Whether positional arguments are required + ArgsRequired bool + + commands []*Command + hasBuiltinHelpGroup bool + args []*Arg +} + +// Commander is an interface which can be implemented by any command added in +// the options. When implemented, the Execute method will be called for the last +// specified (sub)command providing the remaining command line arguments. +type Commander interface { + // Execute will be called for the last active (sub)command. The + // args argument contains the remaining command line arguments. The + // error that Execute returns will be eventually passed out of the + // Parse method of the Parser. + Execute(args []string) error +} + +// Usage is an interface which can be implemented to show a custom usage string +// in the help message shown for a command. +type Usage interface { + // Usage is called for commands to allow customized printing of command + // usage in the generated help message. + Usage() string +} + +type lookup struct { + shortNames map[string]*Option + longNames map[string]*Option + + commands map[string]*Command +} + +// AddCommand adds a new command to the parser with the given name and data. The +// data needs to be a pointer to a struct from which the fields indicate which +// options are in the command. The provided data can implement the Command and +// Usage interfaces. +func (c *Command) AddCommand(command string, shortDescription string, longDescription string, data interface{}) (*Command, error) { + cmd := newCommand(command, shortDescription, longDescription, data) + + cmd.parent = c + + if err := cmd.scan(); err != nil { + return nil, err + } + + c.commands = append(c.commands, cmd) + return cmd, nil +} + +// AddGroup adds a new group to the command with the given name and data. The +// data needs to be a pointer to a struct from which the fields indicate which +// options are in the group. +func (c *Command) AddGroup(shortDescription string, longDescription string, data interface{}) (*Group, error) { + group := newGroup(shortDescription, longDescription, data) + + group.parent = c + + if err := group.scanType(c.scanSubcommandHandler(group)); err != nil { + return nil, err + } + + c.groups = append(c.groups, group) + return group, nil +} + +// Commands returns a list of subcommands of this command. +func (c *Command) Commands() []*Command { + return c.commands +} + +// Find locates the subcommand with the given name and returns it. If no such +// command can be found Find will return nil. +func (c *Command) Find(name string) *Command { + for _, cc := range c.commands { + if cc.match(name) { + return cc + } + } + + return nil +} + +// FindOptionByLongName finds an option that is part of the command, or any of +// its parent commands, by matching its long name (including the option +// namespace). +func (c *Command) FindOptionByLongName(longName string) (option *Option) { + for option == nil && c != nil { + option = c.Group.FindOptionByLongName(longName) + + c, _ = c.parent.(*Command) + } + + return option +} + +// FindOptionByShortName finds an option that is part of the command, or any of +// its parent commands, by matching its long name (including the option +// namespace). +func (c *Command) FindOptionByShortName(shortName rune) (option *Option) { + for option == nil && c != nil { + option = c.Group.FindOptionByShortName(shortName) + + c, _ = c.parent.(*Command) + } + + return option +} + +// Args returns a list of positional arguments associated with this command. +func (c *Command) Args() []*Arg { + ret := make([]*Arg, len(c.args)) + copy(ret, c.args) + + return ret +} + +func newCommand(name string, shortDescription string, longDescription string, data interface{}) *Command { + return &Command{ + Group: newGroup(shortDescription, longDescription, data), + Name: name, + } +} + +func (c *Command) scanSubcommandHandler(parentg *Group) scanHandler { + f := func(realval reflect.Value, sfield *reflect.StructField) (bool, error) { + mtag := newMultiTag(string(sfield.Tag)) + + if err := mtag.Parse(); err != nil { + return true, err + } + + positional := mtag.Get("positional-args") + + if len(positional) != 0 { + stype := realval.Type() + + for i := 0; i < stype.NumField(); i++ { + field := stype.Field(i) + + m := newMultiTag((string(field.Tag))) + + if err := m.Parse(); err != nil { + return true, err + } + + name := m.Get("positional-arg-name") + + if len(name) == 0 { + name = field.Name + } + + required := -1 + requiredMaximum := -1 + + sreq := m.Get("required") + + if sreq != "" { + required = 1 + + rng := strings.SplitN(sreq, "-", 2) + + if len(rng) > 1 { + if preq, err := strconv.ParseInt(rng[0], 10, 32); err == nil { + required = int(preq) + } + + if preq, err := strconv.ParseInt(rng[1], 10, 32); err == nil { + requiredMaximum = int(preq) + } + } else { + if preq, err := strconv.ParseInt(sreq, 10, 32); err == nil { + required = int(preq) + } + } + } + + arg := &Arg{ + Name: name, + Description: m.Get("description"), + Required: required, + RequiredMaximum: requiredMaximum, + + value: realval.Field(i), + tag: m, + } + + c.args = append(c.args, arg) + + if len(mtag.Get("required")) != 0 { + c.ArgsRequired = true + } + } + + return true, nil + } + + subcommand := mtag.Get("command") + + if len(subcommand) != 0 { + var ptrval reflect.Value + + if realval.Kind() == reflect.Ptr { + ptrval = realval + + if ptrval.IsNil() { + ptrval.Set(reflect.New(ptrval.Type().Elem())) + } + } else { + ptrval = realval.Addr() + } + + shortDescription := mtag.Get("description") + longDescription := mtag.Get("long-description") + subcommandsOptional := mtag.Get("subcommands-optional") + aliases := mtag.GetMany("alias") + + subc, err := c.AddCommand(subcommand, shortDescription, longDescription, ptrval.Interface()) + + if err != nil { + return true, err + } + + subc.Hidden = mtag.Get("hidden") != "" + + if len(subcommandsOptional) > 0 { + subc.SubcommandsOptional = true + } + + if len(aliases) > 0 { + subc.Aliases = aliases + } + + return true, nil + } + + return parentg.scanSubGroupHandler(realval, sfield) + } + + return f +} + +func (c *Command) scan() error { + return c.scanType(c.scanSubcommandHandler(c.Group)) +} + +func (c *Command) eachOption(f func(*Command, *Group, *Option)) { + c.eachCommand(func(c *Command) { + c.eachGroup(func(g *Group) { + for _, option := range g.options { + f(c, g, option) + } + }) + }, true) +} + +func (c *Command) eachCommand(f func(*Command), recurse bool) { + f(c) + + for _, cc := range c.commands { + if recurse { + cc.eachCommand(f, true) + } else { + f(cc) + } + } +} + +func (c *Command) eachActiveGroup(f func(cc *Command, g *Group)) { + c.eachGroup(func(g *Group) { + f(c, g) + }) + + if c.Active != nil { + c.Active.eachActiveGroup(f) + } +} + +func (c *Command) addHelpGroups(showHelp func() error) { + if !c.hasBuiltinHelpGroup { + c.addHelpGroup(showHelp) + c.hasBuiltinHelpGroup = true + } + + for _, cc := range c.commands { + cc.addHelpGroups(showHelp) + } +} + +func (c *Command) makeLookup() lookup { + ret := lookup{ + shortNames: make(map[string]*Option), + longNames: make(map[string]*Option), + commands: make(map[string]*Command), + } + + parent := c.parent + + var parents []*Command + + for parent != nil { + if cmd, ok := parent.(*Command); ok { + parents = append(parents, cmd) + parent = cmd.parent + } else { + parent = nil + } + } + + for i := len(parents) - 1; i >= 0; i-- { + parents[i].fillLookup(&ret, true) + } + + c.fillLookup(&ret, false) + return ret +} + +func (c *Command) fillLookup(ret *lookup, onlyOptions bool) { + c.eachGroup(func(g *Group) { + for _, option := range g.options { + if option.ShortName != 0 { + ret.shortNames[string(option.ShortName)] = option + } + + if len(option.LongName) > 0 { + ret.longNames[option.LongNameWithNamespace()] = option + } + } + }) + + if onlyOptions { + return + } + + for _, subcommand := range c.commands { + ret.commands[subcommand.Name] = subcommand + + for _, a := range subcommand.Aliases { + ret.commands[a] = subcommand + } + } +} + +func (c *Command) groupByName(name string) *Group { + if grp := c.Group.groupByName(name); grp != nil { + return grp + } + + for _, subc := range c.commands { + prefix := subc.Name + "." + + if strings.HasPrefix(name, prefix) { + if grp := subc.groupByName(name[len(prefix):]); grp != nil { + return grp + } + } else if name == subc.Name { + return subc.Group + } + } + + return nil +} + +type commandList []*Command + +func (c commandList) Less(i, j int) bool { + return c[i].Name < c[j].Name +} + +func (c commandList) Len() int { + return len(c) +} + +func (c commandList) Swap(i, j int) { + c[i], c[j] = c[j], c[i] +} + +func (c *Command) sortedVisibleCommands() []*Command { + ret := commandList(c.visibleCommands()) + sort.Sort(ret) + + return []*Command(ret) +} + +func (c *Command) visibleCommands() []*Command { + ret := make([]*Command, 0, len(c.commands)) + + for _, cmd := range c.commands { + if !cmd.Hidden { + ret = append(ret, cmd) + } + } + + return ret +} + +func (c *Command) match(name string) bool { + if c.Name == name { + return true + } + + for _, v := range c.Aliases { + if v == name { + return true + } + } + + return false +} + +func (c *Command) hasCliOptions() bool { + ret := false + + c.eachGroup(func(g *Group) { + if g.isBuiltinHelp { + return + } + + for _, opt := range g.options { + if opt.canCli() { + ret = true + } + } + }) + + return ret +} + +func (c *Command) fillParseState(s *parseState) { + s.positional = make([]*Arg, len(c.args)) + copy(s.positional, c.args) + + s.lookup = c.makeLookup() + s.command = c +} diff --git a/vendor/github.com/jessevdk/go-flags/completion.go b/vendor/github.com/jessevdk/go-flags/completion.go new file mode 100644 index 00000000..7a7a08b9 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/completion.go @@ -0,0 +1,309 @@ +package flags + +import ( + "fmt" + "path/filepath" + "reflect" + "sort" + "strings" + "unicode/utf8" +) + +// Completion is a type containing information of a completion. +type Completion struct { + // The completed item + Item string + + // A description of the completed item (optional) + Description string +} + +type completions []Completion + +func (c completions) Len() int { + return len(c) +} + +func (c completions) Less(i, j int) bool { + return c[i].Item < c[j].Item +} + +func (c completions) Swap(i, j int) { + c[i], c[j] = c[j], c[i] +} + +// Completer is an interface which can be implemented by types +// to provide custom command line argument completion. +type Completer interface { + // Complete receives a prefix representing a (partial) value + // for its type and should provide a list of possible valid + // completions. + Complete(match string) []Completion +} + +type completion struct { + parser *Parser +} + +// Filename is a string alias which provides filename completion. +type Filename string + +func completionsWithoutDescriptions(items []string) []Completion { + ret := make([]Completion, len(items)) + + for i, v := range items { + ret[i].Item = v + } + + return ret +} + +// Complete returns a list of existing files with the given +// prefix. +func (f *Filename) Complete(match string) []Completion { + ret, _ := filepath.Glob(match + "*") + return completionsWithoutDescriptions(ret) +} + +func (c *completion) skipPositional(s *parseState, n int) { + if n >= len(s.positional) { + s.positional = nil + } else { + s.positional = s.positional[n:] + } +} + +func (c *completion) completeOptionNames(s *parseState, prefix string, match string, short bool) []Completion { + if short && len(match) != 0 { + return []Completion{ + Completion{ + Item: prefix + match, + }, + } + } + + var results []Completion + repeats := map[string]bool{} + + for name, opt := range s.lookup.longNames { + if strings.HasPrefix(name, match) && !opt.Hidden { + results = append(results, Completion{ + Item: defaultLongOptDelimiter + name, + Description: opt.Description, + }) + + if short { + repeats[string(opt.ShortName)] = true + } + } + } + + if short { + for name, opt := range s.lookup.shortNames { + if _, exist := repeats[name]; !exist && strings.HasPrefix(name, match) && !opt.Hidden { + results = append(results, Completion{ + Item: string(defaultShortOptDelimiter) + name, + Description: opt.Description, + }) + } + } + } + + return results +} + +func (c *completion) completeNamesForLongPrefix(s *parseState, prefix string, match string) []Completion { + return c.completeOptionNames(s, prefix, match, false) +} + +func (c *completion) completeNamesForShortPrefix(s *parseState, prefix string, match string) []Completion { + return c.completeOptionNames(s, prefix, match, true) +} + +func (c *completion) completeCommands(s *parseState, match string) []Completion { + n := make([]Completion, 0, len(s.command.commands)) + + for _, cmd := range s.command.commands { + if cmd.data != c && strings.HasPrefix(cmd.Name, match) { + n = append(n, Completion{ + Item: cmd.Name, + Description: cmd.ShortDescription, + }) + } + } + + return n +} + +func (c *completion) completeValue(value reflect.Value, prefix string, match string) []Completion { + if value.Kind() == reflect.Slice { + value = reflect.New(value.Type().Elem()) + } + i := value.Interface() + + var ret []Completion + + if cmp, ok := i.(Completer); ok { + ret = cmp.Complete(match) + } else if value.CanAddr() { + if cmp, ok = value.Addr().Interface().(Completer); ok { + ret = cmp.Complete(match) + } + } + + for i, v := range ret { + ret[i].Item = prefix + v.Item + } + + return ret +} + +func (c *completion) complete(args []string) []Completion { + if len(args) == 0 { + args = []string{""} + } + + s := &parseState{ + args: args, + } + + c.parser.fillParseState(s) + + var opt *Option + + for len(s.args) > 1 { + arg := s.pop() + + if (c.parser.Options&PassDoubleDash) != None && arg == "--" { + opt = nil + c.skipPositional(s, len(s.args)-1) + + break + } + + if argumentIsOption(arg) { + prefix, optname, islong := stripOptionPrefix(arg) + optname, _, argument := splitOption(prefix, optname, islong) + + if argument == nil { + var o *Option + canarg := true + + if islong { + o = s.lookup.longNames[optname] + } else { + for i, r := range optname { + sname := string(r) + o = s.lookup.shortNames[sname] + + if o == nil { + break + } + + if i == 0 && o.canArgument() && len(optname) != len(sname) { + canarg = false + break + } + } + } + + if o == nil && (c.parser.Options&PassAfterNonOption) != None { + opt = nil + c.skipPositional(s, len(s.args)-1) + + break + } else if o != nil && o.canArgument() && !o.OptionalArgument && canarg { + if len(s.args) > 1 { + s.pop() + } else { + opt = o + } + } + } + } else { + if len(s.positional) > 0 { + if !s.positional[0].isRemaining() { + // Don't advance beyond a remaining positional arg (because + // it consumes all subsequent args). + s.positional = s.positional[1:] + } + } else if cmd, ok := s.lookup.commands[arg]; ok { + cmd.fillParseState(s) + } + + opt = nil + } + } + + lastarg := s.args[len(s.args)-1] + var ret []Completion + + if opt != nil { + // Completion for the argument of 'opt' + ret = c.completeValue(opt.value, "", lastarg) + } else if argumentStartsOption(lastarg) { + // Complete the option + prefix, optname, islong := stripOptionPrefix(lastarg) + optname, split, argument := splitOption(prefix, optname, islong) + + if argument == nil && !islong { + rname, n := utf8.DecodeRuneInString(optname) + sname := string(rname) + + if opt := s.lookup.shortNames[sname]; opt != nil && opt.canArgument() { + ret = c.completeValue(opt.value, prefix+sname, optname[n:]) + } else { + ret = c.completeNamesForShortPrefix(s, prefix, optname) + } + } else if argument != nil { + if islong { + opt = s.lookup.longNames[optname] + } else { + opt = s.lookup.shortNames[optname] + } + + if opt != nil { + ret = c.completeValue(opt.value, prefix+optname+split, *argument) + } + } else if islong { + ret = c.completeNamesForLongPrefix(s, prefix, optname) + } else { + ret = c.completeNamesForShortPrefix(s, prefix, optname) + } + } else if len(s.positional) > 0 { + // Complete for positional argument + ret = c.completeValue(s.positional[0].value, "", lastarg) + } else if len(s.command.commands) > 0 { + // Complete for command + ret = c.completeCommands(s, lastarg) + } + + sort.Sort(completions(ret)) + return ret +} + +func (c *completion) print(items []Completion, showDescriptions bool) { + if showDescriptions && len(items) > 1 { + maxl := 0 + + for _, v := range items { + if len(v.Item) > maxl { + maxl = len(v.Item) + } + } + + for _, v := range items { + fmt.Printf("%s", v.Item) + + if len(v.Description) > 0 { + fmt.Printf("%s # %s", strings.Repeat(" ", maxl-len(v.Item)), v.Description) + } + + fmt.Printf("\n") + } + } else { + for _, v := range items { + fmt.Println(v.Item) + } + } +} diff --git a/vendor/github.com/jessevdk/go-flags/convert.go b/vendor/github.com/jessevdk/go-flags/convert.go new file mode 100644 index 00000000..984aac89 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/convert.go @@ -0,0 +1,348 @@ +// Copyright 2012 Jesse van den Kieboom. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flags + +import ( + "fmt" + "reflect" + "strconv" + "strings" + "time" +) + +// Marshaler is the interface implemented by types that can marshal themselves +// to a string representation of the flag. +type Marshaler interface { + // MarshalFlag marshals a flag value to its string representation. + MarshalFlag() (string, error) +} + +// Unmarshaler is the interface implemented by types that can unmarshal a flag +// argument to themselves. The provided value is directly passed from the +// command line. +type Unmarshaler interface { + // UnmarshalFlag unmarshals a string value representation to the flag + // value (which therefore needs to be a pointer receiver). + UnmarshalFlag(value string) error +} + +func getBase(options multiTag, base int) (int, error) { + sbase := options.Get("base") + + var err error + var ivbase int64 + + if sbase != "" { + ivbase, err = strconv.ParseInt(sbase, 10, 32) + base = int(ivbase) + } + + return base, err +} + +func convertMarshal(val reflect.Value) (bool, string, error) { + // Check first for the Marshaler interface + if val.Type().NumMethod() > 0 && val.CanInterface() { + if marshaler, ok := val.Interface().(Marshaler); ok { + ret, err := marshaler.MarshalFlag() + return true, ret, err + } + } + + return false, "", nil +} + +func convertToString(val reflect.Value, options multiTag) (string, error) { + if ok, ret, err := convertMarshal(val); ok { + return ret, err + } + + tp := val.Type() + + // Support for time.Duration + if tp == reflect.TypeOf((*time.Duration)(nil)).Elem() { + stringer := val.Interface().(fmt.Stringer) + return stringer.String(), nil + } + + switch tp.Kind() { + case reflect.String: + return val.String(), nil + case reflect.Bool: + if val.Bool() { + return "true", nil + } + + return "false", nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + base, err := getBase(options, 10) + + if err != nil { + return "", err + } + + return strconv.FormatInt(val.Int(), base), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + base, err := getBase(options, 10) + + if err != nil { + return "", err + } + + return strconv.FormatUint(val.Uint(), base), nil + case reflect.Float32, reflect.Float64: + return strconv.FormatFloat(val.Float(), 'g', -1, tp.Bits()), nil + case reflect.Slice: + if val.Len() == 0 { + return "", nil + } + + ret := "[" + + for i := 0; i < val.Len(); i++ { + if i != 0 { + ret += ", " + } + + item, err := convertToString(val.Index(i), options) + + if err != nil { + return "", err + } + + ret += item + } + + return ret + "]", nil + case reflect.Map: + ret := "{" + + for i, key := range val.MapKeys() { + if i != 0 { + ret += ", " + } + + keyitem, err := convertToString(key, options) + + if err != nil { + return "", err + } + + item, err := convertToString(val.MapIndex(key), options) + + if err != nil { + return "", err + } + + ret += keyitem + ":" + item + } + + return ret + "}", nil + case reflect.Ptr: + return convertToString(reflect.Indirect(val), options) + case reflect.Interface: + if !val.IsNil() { + return convertToString(val.Elem(), options) + } + } + + return "", nil +} + +func convertUnmarshal(val string, retval reflect.Value) (bool, error) { + if retval.Type().NumMethod() > 0 && retval.CanInterface() { + if unmarshaler, ok := retval.Interface().(Unmarshaler); ok { + if retval.IsNil() { + retval.Set(reflect.New(retval.Type().Elem())) + + // Re-assign from the new value + unmarshaler = retval.Interface().(Unmarshaler) + } + + return true, unmarshaler.UnmarshalFlag(val) + } + } + + if retval.Type().Kind() != reflect.Ptr && retval.CanAddr() { + return convertUnmarshal(val, retval.Addr()) + } + + if retval.Type().Kind() == reflect.Interface && !retval.IsNil() { + return convertUnmarshal(val, retval.Elem()) + } + + return false, nil +} + +func convert(val string, retval reflect.Value, options multiTag) error { + if ok, err := convertUnmarshal(val, retval); ok { + return err + } + + tp := retval.Type() + + // Support for time.Duration + if tp == reflect.TypeOf((*time.Duration)(nil)).Elem() { + parsed, err := time.ParseDuration(val) + + if err != nil { + return err + } + + retval.SetInt(int64(parsed)) + return nil + } + + switch tp.Kind() { + case reflect.String: + retval.SetString(val) + case reflect.Bool: + if val == "" { + retval.SetBool(true) + } else { + b, err := strconv.ParseBool(val) + + if err != nil { + return err + } + + retval.SetBool(b) + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + base, err := getBase(options, 10) + + if err != nil { + return err + } + + parsed, err := strconv.ParseInt(val, base, tp.Bits()) + + if err != nil { + return err + } + + retval.SetInt(parsed) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + base, err := getBase(options, 10) + + if err != nil { + return err + } + + parsed, err := strconv.ParseUint(val, base, tp.Bits()) + + if err != nil { + return err + } + + retval.SetUint(parsed) + case reflect.Float32, reflect.Float64: + parsed, err := strconv.ParseFloat(val, tp.Bits()) + + if err != nil { + return err + } + + retval.SetFloat(parsed) + case reflect.Slice: + elemtp := tp.Elem() + + elemvalptr := reflect.New(elemtp) + elemval := reflect.Indirect(elemvalptr) + + if err := convert(val, elemval, options); err != nil { + return err + } + + retval.Set(reflect.Append(retval, elemval)) + case reflect.Map: + parts := strings.SplitN(val, ":", 2) + + key := parts[0] + var value string + + if len(parts) == 2 { + value = parts[1] + } + + keytp := tp.Key() + keyval := reflect.New(keytp) + + if err := convert(key, keyval, options); err != nil { + return err + } + + valuetp := tp.Elem() + valueval := reflect.New(valuetp) + + if err := convert(value, valueval, options); err != nil { + return err + } + + if retval.IsNil() { + retval.Set(reflect.MakeMap(tp)) + } + + retval.SetMapIndex(reflect.Indirect(keyval), reflect.Indirect(valueval)) + case reflect.Ptr: + if retval.IsNil() { + retval.Set(reflect.New(retval.Type().Elem())) + } + + return convert(val, reflect.Indirect(retval), options) + case reflect.Interface: + if !retval.IsNil() { + return convert(val, retval.Elem(), options) + } + } + + return nil +} + +func isPrint(s string) bool { + for _, c := range s { + if !strconv.IsPrint(c) { + return false + } + } + + return true +} + +func quoteIfNeeded(s string) string { + if !isPrint(s) { + return strconv.Quote(s) + } + + return s +} + +func quoteIfNeededV(s []string) []string { + ret := make([]string, len(s)) + + for i, v := range s { + ret[i] = quoteIfNeeded(v) + } + + return ret +} + +func quoteV(s []string) []string { + ret := make([]string, len(s)) + + for i, v := range s { + ret[i] = strconv.Quote(v) + } + + return ret +} + +func unquoteIfPossible(s string) (string, error) { + if len(s) == 0 || s[0] != '"' { + return s, nil + } + + return strconv.Unquote(s) +} diff --git a/vendor/github.com/jessevdk/go-flags/error.go b/vendor/github.com/jessevdk/go-flags/error.go new file mode 100644 index 00000000..05528d8d --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/error.go @@ -0,0 +1,134 @@ +package flags + +import ( + "fmt" +) + +// ErrorType represents the type of error. +type ErrorType uint + +const ( + // ErrUnknown indicates a generic error. + ErrUnknown ErrorType = iota + + // ErrExpectedArgument indicates that an argument was expected. + ErrExpectedArgument + + // ErrUnknownFlag indicates an unknown flag. + ErrUnknownFlag + + // ErrUnknownGroup indicates an unknown group. + ErrUnknownGroup + + // ErrMarshal indicates a marshalling error while converting values. + ErrMarshal + + // ErrHelp indicates that the built-in help was shown (the error + // contains the help message). + ErrHelp + + // ErrNoArgumentForBool indicates that an argument was given for a + // boolean flag (which don't not take any arguments). + ErrNoArgumentForBool + + // ErrRequired indicates that a required flag was not provided. + ErrRequired + + // ErrShortNameTooLong indicates that a short flag name was specified, + // longer than one character. + ErrShortNameTooLong + + // ErrDuplicatedFlag indicates that a short or long flag has been + // defined more than once + ErrDuplicatedFlag + + // ErrTag indicates an error while parsing flag tags. + ErrTag + + // ErrCommandRequired indicates that a command was required but not + // specified + ErrCommandRequired + + // ErrUnknownCommand indicates that an unknown command was specified. + ErrUnknownCommand + + // ErrInvalidChoice indicates an invalid option value which only allows + // a certain number of choices. + ErrInvalidChoice + + // ErrInvalidTag indicates an invalid tag or invalid use of an existing tag + ErrInvalidTag +) + +func (e ErrorType) String() string { + switch e { + case ErrUnknown: + return "unknown" + case ErrExpectedArgument: + return "expected argument" + case ErrUnknownFlag: + return "unknown flag" + case ErrUnknownGroup: + return "unknown group" + case ErrMarshal: + return "marshal" + case ErrHelp: + return "help" + case ErrNoArgumentForBool: + return "no argument for bool" + case ErrRequired: + return "required" + case ErrShortNameTooLong: + return "short name too long" + case ErrDuplicatedFlag: + return "duplicated flag" + case ErrTag: + return "tag" + case ErrCommandRequired: + return "command required" + case ErrUnknownCommand: + return "unknown command" + case ErrInvalidChoice: + return "invalid choice" + case ErrInvalidTag: + return "invalid tag" + } + + return "unrecognized error type" +} + +// Error represents a parser error. The error returned from Parse is of this +// type. The error contains both a Type and Message. +type Error struct { + // The type of error + Type ErrorType + + // The error message + Message string +} + +// Error returns the error's message +func (e *Error) Error() string { + return e.Message +} + +func newError(tp ErrorType, message string) *Error { + return &Error{ + Type: tp, + Message: message, + } +} + +func newErrorf(tp ErrorType, format string, args ...interface{}) *Error { + return newError(tp, fmt.Sprintf(format, args...)) +} + +func wrapError(err error) *Error { + ret, ok := err.(*Error) + + if !ok { + return newError(ErrUnknown, err.Error()) + } + + return ret +} diff --git a/vendor/github.com/jessevdk/go-flags/flags.go b/vendor/github.com/jessevdk/go-flags/flags.go new file mode 100644 index 00000000..889762d1 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/flags.go @@ -0,0 +1,258 @@ +// Copyright 2012 Jesse van den Kieboom. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package flags provides an extensive command line option parser. +The flags package is similar in functionality to the go built-in flag package +but provides more options and uses reflection to provide a convenient and +succinct way of specifying command line options. + + +Supported features + +The following features are supported in go-flags: + + Options with short names (-v) + Options with long names (--verbose) + Options with and without arguments (bool v.s. other type) + Options with optional arguments and default values + Option default values from ENVIRONMENT_VARIABLES, including slice and map values + Multiple option groups each containing a set of options + Generate and print well-formatted help message + Passing remaining command line arguments after -- (optional) + Ignoring unknown command line options (optional) + Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification + Supports multiple short options -aux + Supports all primitive go types (string, int{8..64}, uint{8..64}, float) + Supports same option multiple times (can store in slice or last option counts) + Supports maps + Supports function callbacks + Supports namespaces for (nested) option groups + +Additional features specific to Windows: + Options with short names (/v) + Options with long names (/verbose) + Windows-style options with arguments use a colon as the delimiter + Modify generated help message with Windows-style / options + Windows style options can be disabled at build time using the "forceposix" + build tag + + +Basic usage + +The flags package uses structs, reflection and struct field tags +to allow users to specify command line options. This results in very simple +and concise specification of your application options. For example: + + type Options struct { + Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` + } + +This specifies one option with a short name -v and a long name --verbose. +When either -v or --verbose is found on the command line, a 'true' value +will be appended to the Verbose field. e.g. when specifying -vvv, the +resulting value of Verbose will be {[true, true, true]}. + +Slice options work exactly the same as primitive type options, except that +whenever the option is encountered, a value is appended to the slice. + +Map options from string to primitive type are also supported. On the command +line, you specify the value for such an option as key:value. For example + + type Options struct { + AuthorInfo string[string] `short:"a"` + } + +Then, the AuthorInfo map can be filled with something like +-a name:Jesse -a "surname:van den Kieboom". + +Finally, for full control over the conversion between command line argument +values and options, user defined types can choose to implement the Marshaler +and Unmarshaler interfaces. + + +Available field tags + +The following is a list of tags for struct fields supported by go-flags: + + short: the short name of the option (single character) + long: the long name of the option + required: if non empty, makes the option required to appear on the command + line. If a required option is not present, the parser will + return ErrRequired (optional) + description: the description of the option (optional) + long-description: the long description of the option. Currently only + displayed in generated man pages (optional) + no-flag: if non-empty, this field is ignored as an option (optional) + + optional: if non-empty, makes the argument of the option optional. When an + argument is optional it can only be specified using + --option=argument (optional) + optional-value: the value of an optional option when the option occurs + without an argument. This tag can be specified multiple + times in the case of maps or slices (optional) + default: the default value of an option. This tag can be specified + multiple times in the case of slices or maps (optional) + default-mask: when specified, this value will be displayed in the help + instead of the actual default value. This is useful + mostly for hiding otherwise sensitive information from + showing up in the help. If default-mask takes the special + value "-", then no default value will be shown at all + (optional) + env: the default value of the option is overridden from the + specified environment variable, if one has been defined. + (optional) + env-delim: the 'env' default value from environment is split into + multiple values with the given delimiter string, use with + slices and maps (optional) + value-name: the name of the argument value (to be shown in the help) + (optional) + choice: limits the values for an option to a set of values. + This tag can be specified multiple times (optional) + hidden: if non-empty, the option is not visible in the help or man page. + + base: a base (radix) used to convert strings to integer values, the + default base is 10 (i.e. decimal) (optional) + + ini-name: the explicit ini option name (optional) + no-ini: if non-empty this field is ignored as an ini option + (optional) + + group: when specified on a struct field, makes the struct + field a separate group with the given name (optional) + namespace: when specified on a group struct field, the namespace + gets prepended to every option's long name and + subgroup's namespace of this group, separated by + the parser's namespace delimiter (optional) + command: when specified on a struct field, makes the struct + field a (sub)command with the given name (optional) + subcommands-optional: when specified on a command struct field, makes + any subcommands of that command optional (optional) + alias: when specified on a command struct field, adds the + specified name as an alias for the command. Can be + be specified multiple times to add more than one + alias (optional) + positional-args: when specified on a field with a struct type, + uses the fields of that struct to parse remaining + positional command line arguments into (in order + of the fields). If a field has a slice type, + then all remaining arguments will be added to it. + Positional arguments are optional by default, + unless the "required" tag is specified together + with the "positional-args" tag. The "required" tag + can also be set on the individual rest argument + fields, to require only the first N positional + arguments. If the "required" tag is set on the + rest arguments slice, then its value determines + the minimum amount of rest arguments that needs to + be provided (e.g. `required:"2"`) (optional) + positional-arg-name: used on a field in a positional argument struct; name + of the positional argument placeholder to be shown in + the help (optional) + +Either the `short:` tag or the `long:` must be specified to make the field eligible as an +option. + + +Option groups + +Option groups are a simple way to semantically separate your options. All +options in a particular group are shown together in the help under the name +of the group. Namespaces can be used to specify option long names more +precisely and emphasize the options affiliation to their group. + +There are currently three ways to specify option groups. + + 1. Use NewNamedParser specifying the various option groups. + 2. Use AddGroup to add a group to an existing parser. + 3. Add a struct field to the top-level options annotated with the + group:"group-name" tag. + + + +Commands + +The flags package also has basic support for commands. Commands are often +used in monolithic applications that support various commands or actions. +Take git for example, all of the add, commit, checkout, etc. are called +commands. Using commands you can easily separate multiple functions of your +application. + +There are currently two ways to specify a command. + + 1. Use AddCommand on an existing parser. + 2. Add a struct field to your options struct annotated with the + command:"command-name" tag. + +The most common, idiomatic way to implement commands is to define a global +parser instance and implement each command in a separate file. These +command files should define a go init function which calls AddCommand on +the global parser. + +When parsing ends and there is an active command and that command implements +the Commander interface, then its Execute method will be run with the +remaining command line arguments. + +Command structs can have options which become valid to parse after the +command has been specified on the command line, in addition to the options +of all the parent commands. I.e. considering a -v flag on the parser and an +add command, the following are equivalent: + + ./app -v add + ./app add -v + +However, if the -v flag is defined on the add command, then the first of +the two examples above would fail since the -v flag is not defined before +the add command. + + +Completion + +go-flags has builtin support to provide bash completion of flags, commands +and argument values. To use completion, the binary which uses go-flags +can be invoked in a special environment to list completion of the current +command line argument. It should be noted that this `executes` your application, +and it is up to the user to make sure there are no negative side effects (for +example from init functions). + +Setting the environment variable `GO_FLAGS_COMPLETION=1` enables completion +by replacing the argument parsing routine with the completion routine which +outputs completions for the passed arguments. The basic invocation to +complete a set of arguments is therefore: + + GO_FLAGS_COMPLETION=1 ./completion-example arg1 arg2 arg3 + +where `completion-example` is the binary, `arg1` and `arg2` are +the current arguments, and `arg3` (the last argument) is the argument +to be completed. If the GO_FLAGS_COMPLETION is set to "verbose", then +descriptions of possible completion items will also be shown, if there +are more than 1 completion items. + +To use this with bash completion, a simple file can be written which +calls the binary which supports go-flags completion: + + _completion_example() { + # All arguments except the first one + args=("${COMP_WORDS[@]:1:$COMP_CWORD}") + + # Only split on newlines + local IFS=$'\n' + + # Call completion (note that the first element of COMP_WORDS is + # the executable itself) + COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}")) + return 0 + } + + complete -F _completion_example completion-example + +Completion requires the parser option PassDoubleDash and is therefore enforced if the environment variable GO_FLAGS_COMPLETION is set. + +Customized completion for argument values is supported by implementing +the flags.Completer interface for the argument value type. An example +of a type which does so is the flags.Filename type, an alias of string +allowing simple filename completion. A slice or array argument value +whose element type implements flags.Completer will also be completed. +*/ +package flags diff --git a/vendor/github.com/jessevdk/go-flags/group.go b/vendor/github.com/jessevdk/go-flags/group.go new file mode 100644 index 00000000..9e057abd --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/group.go @@ -0,0 +1,406 @@ +// Copyright 2012 Jesse van den Kieboom. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flags + +import ( + "errors" + "reflect" + "strings" + "unicode/utf8" +) + +// ErrNotPointerToStruct indicates that a provided data container is not +// a pointer to a struct. Only pointers to structs are valid data containers +// for options. +var ErrNotPointerToStruct = errors.New("provided data is not a pointer to struct") + +// Group represents an option group. Option groups can be used to logically +// group options together under a description. Groups are only used to provide +// more structure to options both for the user (as displayed in the help message) +// and for you, since groups can be nested. +type Group struct { + // A short description of the group. The + // short description is primarily used in the built-in generated help + // message + ShortDescription string + + // A long description of the group. The long + // description is primarily used to present information on commands + // (Command embeds Group) in the built-in generated help and man pages. + LongDescription string + + // The namespace of the group + Namespace string + + // If true, the group is not displayed in the help or man page + Hidden bool + + // The parent of the group or nil if it has no parent + parent interface{} + + // All the options in the group + options []*Option + + // All the subgroups + groups []*Group + + // Whether the group represents the built-in help group + isBuiltinHelp bool + + data interface{} +} + +type scanHandler func(reflect.Value, *reflect.StructField) (bool, error) + +// AddGroup adds a new group to the command with the given name and data. The +// data needs to be a pointer to a struct from which the fields indicate which +// options are in the group. +func (g *Group) AddGroup(shortDescription string, longDescription string, data interface{}) (*Group, error) { + group := newGroup(shortDescription, longDescription, data) + + group.parent = g + + if err := group.scan(); err != nil { + return nil, err + } + + g.groups = append(g.groups, group) + return group, nil +} + +// Groups returns the list of groups embedded in this group. +func (g *Group) Groups() []*Group { + return g.groups +} + +// Options returns the list of options in this group. +func (g *Group) Options() []*Option { + return g.options +} + +// Find locates the subgroup with the given short description and returns it. +// If no such group can be found Find will return nil. Note that the description +// is matched case insensitively. +func (g *Group) Find(shortDescription string) *Group { + lshortDescription := strings.ToLower(shortDescription) + + var ret *Group + + g.eachGroup(func(gg *Group) { + if gg != g && strings.ToLower(gg.ShortDescription) == lshortDescription { + ret = gg + } + }) + + return ret +} + +func (g *Group) findOption(matcher func(*Option) bool) (option *Option) { + g.eachGroup(func(g *Group) { + for _, opt := range g.options { + if option == nil && matcher(opt) { + option = opt + } + } + }) + + return option +} + +// FindOptionByLongName finds an option that is part of the group, or any of its +// subgroups, by matching its long name (including the option namespace). +func (g *Group) FindOptionByLongName(longName string) *Option { + return g.findOption(func(option *Option) bool { + return option.LongNameWithNamespace() == longName + }) +} + +// FindOptionByShortName finds an option that is part of the group, or any of +// its subgroups, by matching its short name. +func (g *Group) FindOptionByShortName(shortName rune) *Option { + return g.findOption(func(option *Option) bool { + return option.ShortName == shortName + }) +} + +func newGroup(shortDescription string, longDescription string, data interface{}) *Group { + return &Group{ + ShortDescription: shortDescription, + LongDescription: longDescription, + + data: data, + } +} + +func (g *Group) optionByName(name string, namematch func(*Option, string) bool) *Option { + prio := 0 + var retopt *Option + + g.eachGroup(func(g *Group) { + for _, opt := range g.options { + if namematch != nil && namematch(opt, name) && prio < 4 { + retopt = opt + prio = 4 + } + + if name == opt.field.Name && prio < 3 { + retopt = opt + prio = 3 + } + + if name == opt.LongNameWithNamespace() && prio < 2 { + retopt = opt + prio = 2 + } + + if opt.ShortName != 0 && name == string(opt.ShortName) && prio < 1 { + retopt = opt + prio = 1 + } + } + }) + + return retopt +} + +func (g *Group) eachGroup(f func(*Group)) { + f(g) + + for _, gg := range g.groups { + gg.eachGroup(f) + } +} + +func isStringFalsy(s string) bool { + return s == "" || s == "false" || s == "no" || s == "0" +} + +func (g *Group) scanStruct(realval reflect.Value, sfield *reflect.StructField, handler scanHandler) error { + stype := realval.Type() + + if sfield != nil { + if ok, err := handler(realval, sfield); err != nil { + return err + } else if ok { + return nil + } + } + + for i := 0; i < stype.NumField(); i++ { + field := stype.Field(i) + + // PkgName is set only for non-exported fields, which we ignore + if field.PkgPath != "" && !field.Anonymous { + continue + } + + mtag := newMultiTag(string(field.Tag)) + + if err := mtag.Parse(); err != nil { + return err + } + + // Skip fields with the no-flag tag + if mtag.Get("no-flag") != "" { + continue + } + + // Dive deep into structs or pointers to structs + kind := field.Type.Kind() + fld := realval.Field(i) + + if kind == reflect.Struct { + if err := g.scanStruct(fld, &field, handler); err != nil { + return err + } + } else if kind == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct { + flagCountBefore := len(g.options) + len(g.groups) + + if fld.IsNil() { + fld = reflect.New(fld.Type().Elem()) + } + + if err := g.scanStruct(reflect.Indirect(fld), &field, handler); err != nil { + return err + } + + if len(g.options)+len(g.groups) != flagCountBefore { + realval.Field(i).Set(fld) + } + } + + longname := mtag.Get("long") + shortname := mtag.Get("short") + + // Need at least either a short or long name + if longname == "" && shortname == "" && mtag.Get("ini-name") == "" { + continue + } + + short := rune(0) + rc := utf8.RuneCountInString(shortname) + + if rc > 1 { + return newErrorf(ErrShortNameTooLong, + "short names can only be 1 character long, not `%s'", + shortname) + + } else if rc == 1 { + short, _ = utf8.DecodeRuneInString(shortname) + } + + description := mtag.Get("description") + def := mtag.GetMany("default") + + optionalValue := mtag.GetMany("optional-value") + valueName := mtag.Get("value-name") + defaultMask := mtag.Get("default-mask") + + optional := !isStringFalsy(mtag.Get("optional")) + required := !isStringFalsy(mtag.Get("required")) + choices := mtag.GetMany("choice") + hidden := !isStringFalsy(mtag.Get("hidden")) + + option := &Option{ + Description: description, + ShortName: short, + LongName: longname, + Default: def, + EnvDefaultKey: mtag.Get("env"), + EnvDefaultDelim: mtag.Get("env-delim"), + OptionalArgument: optional, + OptionalValue: optionalValue, + Required: required, + ValueName: valueName, + DefaultMask: defaultMask, + Choices: choices, + Hidden: hidden, + + group: g, + + field: field, + value: realval.Field(i), + tag: mtag, + } + + if option.isBool() && option.Default != nil { + return newErrorf(ErrInvalidTag, + "boolean flag `%s' may not have default values, they always default to `false' and can only be turned on", + option.shortAndLongName()) + } + + g.options = append(g.options, option) + } + + return nil +} + +func (g *Group) checkForDuplicateFlags() *Error { + shortNames := make(map[rune]*Option) + longNames := make(map[string]*Option) + + var duplicateError *Error + + g.eachGroup(func(g *Group) { + for _, option := range g.options { + if option.LongName != "" { + longName := option.LongNameWithNamespace() + + if otherOption, ok := longNames[longName]; ok { + duplicateError = newErrorf(ErrDuplicatedFlag, "option `%s' uses the same long name as option `%s'", option, otherOption) + return + } + longNames[longName] = option + } + if option.ShortName != 0 { + if otherOption, ok := shortNames[option.ShortName]; ok { + duplicateError = newErrorf(ErrDuplicatedFlag, "option `%s' uses the same short name as option `%s'", option, otherOption) + return + } + shortNames[option.ShortName] = option + } + } + }) + + return duplicateError +} + +func (g *Group) scanSubGroupHandler(realval reflect.Value, sfield *reflect.StructField) (bool, error) { + mtag := newMultiTag(string(sfield.Tag)) + + if err := mtag.Parse(); err != nil { + return true, err + } + + subgroup := mtag.Get("group") + + if len(subgroup) != 0 { + var ptrval reflect.Value + + if realval.Kind() == reflect.Ptr { + ptrval = realval + + if ptrval.IsNil() { + ptrval.Set(reflect.New(ptrval.Type())) + } + } else { + ptrval = realval.Addr() + } + + description := mtag.Get("description") + + group, err := g.AddGroup(subgroup, description, ptrval.Interface()) + + if err != nil { + return true, err + } + + group.Namespace = mtag.Get("namespace") + group.Hidden = mtag.Get("hidden") != "" + + return true, nil + } + + return false, nil +} + +func (g *Group) scanType(handler scanHandler) error { + // Get all the public fields in the data struct + ptrval := reflect.ValueOf(g.data) + + if ptrval.Type().Kind() != reflect.Ptr { + panic(ErrNotPointerToStruct) + } + + stype := ptrval.Type().Elem() + + if stype.Kind() != reflect.Struct { + panic(ErrNotPointerToStruct) + } + + realval := reflect.Indirect(ptrval) + + if err := g.scanStruct(realval, nil, handler); err != nil { + return err + } + + if err := g.checkForDuplicateFlags(); err != nil { + return err + } + + return nil +} + +func (g *Group) scan() error { + return g.scanType(g.scanSubGroupHandler) +} + +func (g *Group) groupByName(name string) *Group { + if len(name) == 0 { + return g + } + + return g.Find(name) +} diff --git a/vendor/github.com/jessevdk/go-flags/help.go b/vendor/github.com/jessevdk/go-flags/help.go new file mode 100644 index 00000000..d3803050 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/help.go @@ -0,0 +1,491 @@ +// Copyright 2012 Jesse van den Kieboom. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flags + +import ( + "bufio" + "bytes" + "fmt" + "io" + "runtime" + "strings" + "unicode/utf8" +) + +type alignmentInfo struct { + maxLongLen int + hasShort bool + hasValueName bool + terminalColumns int + indent bool +} + +const ( + paddingBeforeOption = 2 + distanceBetweenOptionAndDescription = 2 +) + +func (a *alignmentInfo) descriptionStart() int { + ret := a.maxLongLen + distanceBetweenOptionAndDescription + + if a.hasShort { + ret += 2 + } + + if a.maxLongLen > 0 { + ret += 4 + } + + if a.hasValueName { + ret += 3 + } + + return ret +} + +func (a *alignmentInfo) updateLen(name string, indent bool) { + l := utf8.RuneCountInString(name) + + if indent { + l = l + 4 + } + + if l > a.maxLongLen { + a.maxLongLen = l + } +} + +func (p *Parser) getAlignmentInfo() alignmentInfo { + ret := alignmentInfo{ + maxLongLen: 0, + hasShort: false, + hasValueName: false, + terminalColumns: getTerminalColumns(), + } + + if ret.terminalColumns <= 0 { + ret.terminalColumns = 80 + } + + var prevcmd *Command + + p.eachActiveGroup(func(c *Command, grp *Group) { + if c != prevcmd { + for _, arg := range c.args { + ret.updateLen(arg.Name, c != p.Command) + } + } + + for _, info := range grp.options { + if !info.canCli() { + continue + } + + if info.ShortName != 0 { + ret.hasShort = true + } + + if len(info.ValueName) > 0 { + ret.hasValueName = true + } + + l := info.LongNameWithNamespace() + info.ValueName + + if len(info.Choices) != 0 { + l += "[" + strings.Join(info.Choices, "|") + "]" + } + + ret.updateLen(l, c != p.Command) + } + }) + + return ret +} + +func wrapText(s string, l int, prefix string) string { + var ret string + + if l < 10 { + l = 10 + } + + // Basic text wrapping of s at spaces to fit in l + lines := strings.Split(s, "\n") + + for _, line := range lines { + var retline string + + line = strings.TrimSpace(line) + + for len(line) > l { + // Try to split on space + suffix := "" + + pos := strings.LastIndex(line[:l], " ") + + if pos < 0 { + pos = l - 1 + suffix = "-\n" + } + + if len(retline) != 0 { + retline += "\n" + prefix + } + + retline += strings.TrimSpace(line[:pos]) + suffix + line = strings.TrimSpace(line[pos:]) + } + + if len(line) > 0 { + if len(retline) != 0 { + retline += "\n" + prefix + } + + retline += line + } + + if len(ret) > 0 { + ret += "\n" + + if len(retline) > 0 { + ret += prefix + } + } + + ret += retline + } + + return ret +} + +func (p *Parser) writeHelpOption(writer *bufio.Writer, option *Option, info alignmentInfo) { + line := &bytes.Buffer{} + + prefix := paddingBeforeOption + + if info.indent { + prefix += 4 + } + + if option.Hidden { + return + } + + line.WriteString(strings.Repeat(" ", prefix)) + + if option.ShortName != 0 { + line.WriteRune(defaultShortOptDelimiter) + line.WriteRune(option.ShortName) + } else if info.hasShort { + line.WriteString(" ") + } + + descstart := info.descriptionStart() + paddingBeforeOption + + if len(option.LongName) > 0 { + if option.ShortName != 0 { + line.WriteString(", ") + } else if info.hasShort { + line.WriteString(" ") + } + + line.WriteString(defaultLongOptDelimiter) + line.WriteString(option.LongNameWithNamespace()) + } + + if option.canArgument() { + line.WriteRune(defaultNameArgDelimiter) + + if len(option.ValueName) > 0 { + line.WriteString(option.ValueName) + } + + if len(option.Choices) > 0 { + line.WriteString("[" + strings.Join(option.Choices, "|") + "]") + } + } + + written := line.Len() + line.WriteTo(writer) + + if option.Description != "" { + dw := descstart - written + writer.WriteString(strings.Repeat(" ", dw)) + + var def string + + if len(option.DefaultMask) != 0 { + if option.DefaultMask != "-" { + def = option.DefaultMask + } + } else { + def = option.defaultLiteral + } + + var envDef string + if option.EnvDefaultKey != "" { + var envPrintable string + if runtime.GOOS == "windows" { + envPrintable = "%" + option.EnvDefaultKey + "%" + } else { + envPrintable = "$" + option.EnvDefaultKey + } + envDef = fmt.Sprintf(" [%s]", envPrintable) + } + + var desc string + + if def != "" { + desc = fmt.Sprintf("%s (default: %v)%s", option.Description, def, envDef) + } else { + desc = option.Description + envDef + } + + writer.WriteString(wrapText(desc, + info.terminalColumns-descstart, + strings.Repeat(" ", descstart))) + } + + writer.WriteString("\n") +} + +func maxCommandLength(s []*Command) int { + if len(s) == 0 { + return 0 + } + + ret := len(s[0].Name) + + for _, v := range s[1:] { + l := len(v.Name) + + if l > ret { + ret = l + } + } + + return ret +} + +// WriteHelp writes a help message containing all the possible options and +// their descriptions to the provided writer. Note that the HelpFlag parser +// option provides a convenient way to add a -h/--help option group to the +// command line parser which will automatically show the help messages using +// this method. +func (p *Parser) WriteHelp(writer io.Writer) { + if writer == nil { + return + } + + wr := bufio.NewWriter(writer) + aligninfo := p.getAlignmentInfo() + + cmd := p.Command + + for cmd.Active != nil { + cmd = cmd.Active + } + + if p.Name != "" { + wr.WriteString("Usage:\n") + wr.WriteString(" ") + + allcmd := p.Command + + for allcmd != nil { + var usage string + + if allcmd == p.Command { + if len(p.Usage) != 0 { + usage = p.Usage + } else if p.Options&HelpFlag != 0 { + usage = "[OPTIONS]" + } + } else if us, ok := allcmd.data.(Usage); ok { + usage = us.Usage() + } else if allcmd.hasCliOptions() { + usage = fmt.Sprintf("[%s-OPTIONS]", allcmd.Name) + } + + if len(usage) != 0 { + fmt.Fprintf(wr, " %s %s", allcmd.Name, usage) + } else { + fmt.Fprintf(wr, " %s", allcmd.Name) + } + + if len(allcmd.args) > 0 { + fmt.Fprintf(wr, " ") + } + + for i, arg := range allcmd.args { + if i != 0 { + fmt.Fprintf(wr, " ") + } + + name := arg.Name + + if arg.isRemaining() { + name = name + "..." + } + + if !allcmd.ArgsRequired { + fmt.Fprintf(wr, "[%s]", name) + } else { + fmt.Fprintf(wr, "%s", name) + } + } + + if allcmd.Active == nil && len(allcmd.commands) > 0 { + var co, cc string + + if allcmd.SubcommandsOptional { + co, cc = "[", "]" + } else { + co, cc = "<", ">" + } + + visibleCommands := allcmd.visibleCommands() + + if len(visibleCommands) > 3 { + fmt.Fprintf(wr, " %scommand%s", co, cc) + } else { + subcommands := allcmd.sortedVisibleCommands() + names := make([]string, len(subcommands)) + + for i, subc := range subcommands { + names[i] = subc.Name + } + + fmt.Fprintf(wr, " %s%s%s", co, strings.Join(names, " | "), cc) + } + } + + allcmd = allcmd.Active + } + + fmt.Fprintln(wr) + + if len(cmd.LongDescription) != 0 { + fmt.Fprintln(wr) + + t := wrapText(cmd.LongDescription, + aligninfo.terminalColumns, + "") + + fmt.Fprintln(wr, t) + } + } + + c := p.Command + + for c != nil { + printcmd := c != p.Command + + c.eachGroup(func(grp *Group) { + first := true + + // Skip built-in help group for all commands except the top-level + // parser + if grp.Hidden || (grp.isBuiltinHelp && c != p.Command) { + return + } + + for _, info := range grp.options { + if !info.canCli() || info.Hidden { + continue + } + + if printcmd { + fmt.Fprintf(wr, "\n[%s command options]\n", c.Name) + aligninfo.indent = true + printcmd = false + } + + if first && cmd.Group != grp { + fmt.Fprintln(wr) + + if aligninfo.indent { + wr.WriteString(" ") + } + + fmt.Fprintf(wr, "%s:\n", grp.ShortDescription) + first = false + } + + p.writeHelpOption(wr, info, aligninfo) + } + }) + + var args []*Arg + for _, arg := range c.args { + if arg.Description != "" { + args = append(args, arg) + } + } + + if len(args) > 0 { + if c == p.Command { + fmt.Fprintf(wr, "\nArguments:\n") + } else { + fmt.Fprintf(wr, "\n[%s command arguments]\n", c.Name) + } + + descStart := aligninfo.descriptionStart() + paddingBeforeOption + + for _, arg := range args { + argPrefix := strings.Repeat(" ", paddingBeforeOption) + argPrefix += arg.Name + + if len(arg.Description) > 0 { + argPrefix += ":" + wr.WriteString(argPrefix) + + // Space between "arg:" and the description start + descPadding := strings.Repeat(" ", descStart-len(argPrefix)) + // How much space the description gets before wrapping + descWidth := aligninfo.terminalColumns - 1 - descStart + // Whitespace to which we can indent new description lines + descPrefix := strings.Repeat(" ", descStart) + + wr.WriteString(descPadding) + wr.WriteString(wrapText(arg.Description, descWidth, descPrefix)) + } else { + wr.WriteString(argPrefix) + } + + fmt.Fprintln(wr) + } + } + + c = c.Active + } + + scommands := cmd.sortedVisibleCommands() + + if len(scommands) > 0 { + maxnamelen := maxCommandLength(scommands) + + fmt.Fprintln(wr) + fmt.Fprintln(wr, "Available commands:") + + for _, c := range scommands { + fmt.Fprintf(wr, " %s", c.Name) + + if len(c.ShortDescription) > 0 { + pad := strings.Repeat(" ", maxnamelen-len(c.Name)) + fmt.Fprintf(wr, "%s %s", pad, c.ShortDescription) + + if len(c.Aliases) > 0 { + fmt.Fprintf(wr, " (aliases: %s)", strings.Join(c.Aliases, ", ")) + } + + } + + fmt.Fprintln(wr) + } + } + + wr.Flush() +} diff --git a/vendor/github.com/jessevdk/go-flags/ini.go b/vendor/github.com/jessevdk/go-flags/ini.go new file mode 100644 index 00000000..e714d3d3 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/ini.go @@ -0,0 +1,597 @@ +package flags + +import ( + "bufio" + "fmt" + "io" + "os" + "reflect" + "sort" + "strconv" + "strings" +) + +// IniError contains location information on where an error occurred. +type IniError struct { + // The error message. + Message string + + // The filename of the file in which the error occurred. + File string + + // The line number at which the error occurred. + LineNumber uint +} + +// Error provides a "file:line: message" formatted message of the ini error. +func (x *IniError) Error() string { + return fmt.Sprintf( + "%s:%d: %s", + x.File, + x.LineNumber, + x.Message, + ) +} + +// IniOptions for writing +type IniOptions uint + +const ( + // IniNone indicates no options. + IniNone IniOptions = 0 + + // IniIncludeDefaults indicates that default values should be written. + IniIncludeDefaults = 1 << iota + + // IniCommentDefaults indicates that if IniIncludeDefaults is used + // options with default values are written but commented out. + IniCommentDefaults + + // IniIncludeComments indicates that comments containing the description + // of an option should be written. + IniIncludeComments + + // IniDefault provides a default set of options. + IniDefault = IniIncludeComments +) + +// IniParser is a utility to read and write flags options from and to ini +// formatted strings. +type IniParser struct { + ParseAsDefaults bool // override default flags + + parser *Parser +} + +type iniValue struct { + Name string + Value string + Quoted bool + LineNumber uint +} + +type iniSection []iniValue + +type ini struct { + File string + Sections map[string]iniSection +} + +// NewIniParser creates a new ini parser for a given Parser. +func NewIniParser(p *Parser) *IniParser { + return &IniParser{ + parser: p, + } +} + +// IniParse is a convenience function to parse command line options with default +// settings from an ini formatted file. The provided data is a pointer to a struct +// representing the default option group (named "Application Options"). For +// more control, use flags.NewParser. +func IniParse(filename string, data interface{}) error { + p := NewParser(data, Default) + + return NewIniParser(p).ParseFile(filename) +} + +// ParseFile parses flags from an ini formatted file. See Parse for more +// information on the ini file format. The returned errors can be of the type +// flags.Error or flags.IniError. +func (i *IniParser) ParseFile(filename string) error { + ini, err := readIniFromFile(filename) + + if err != nil { + return err + } + + return i.parse(ini) +} + +// Parse parses flags from an ini format. You can use ParseFile as a +// convenience function to parse from a filename instead of a general +// io.Reader. +// +// The format of the ini file is as follows: +// +// [Option group name] +// option = value +// +// Each section in the ini file represents an option group or command in the +// flags parser. The default flags parser option group (i.e. when using +// flags.Parse) is named 'Application Options'. The ini option name is matched +// in the following order: +// +// 1. Compared to the ini-name tag on the option struct field (if present) +// 2. Compared to the struct field name +// 3. Compared to the option long name (if present) +// 4. Compared to the option short name (if present) +// +// Sections for nested groups and commands can be addressed using a dot `.' +// namespacing notation (i.e [subcommand.Options]). Group section names are +// matched case insensitive. +// +// The returned errors can be of the type flags.Error or flags.IniError. +func (i *IniParser) Parse(reader io.Reader) error { + ini, err := readIni(reader, "") + + if err != nil { + return err + } + + return i.parse(ini) +} + +// WriteFile writes the flags as ini format into a file. See Write +// for more information. The returned error occurs when the specified file +// could not be opened for writing. +func (i *IniParser) WriteFile(filename string, options IniOptions) error { + return writeIniToFile(i, filename, options) +} + +// Write writes the current values of all the flags to an ini format. +// See Parse for more information on the ini file format. You typically +// call this only after settings have been parsed since the default values of each +// option are stored just before parsing the flags (this is only relevant when +// IniIncludeDefaults is _not_ set in options). +func (i *IniParser) Write(writer io.Writer, options IniOptions) { + writeIni(i, writer, options) +} + +func readFullLine(reader *bufio.Reader) (string, error) { + var line []byte + + for { + l, more, err := reader.ReadLine() + + if err != nil { + return "", err + } + + if line == nil && !more { + return string(l), nil + } + + line = append(line, l...) + + if !more { + break + } + } + + return string(line), nil +} + +func optionIniName(option *Option) string { + name := option.tag.Get("_read-ini-name") + + if len(name) != 0 { + return name + } + + name = option.tag.Get("ini-name") + + if len(name) != 0 { + return name + } + + return option.field.Name +} + +func writeGroupIni(cmd *Command, group *Group, namespace string, writer io.Writer, options IniOptions) { + var sname string + + if len(namespace) != 0 { + sname = namespace + } + + if cmd.Group != group && len(group.ShortDescription) != 0 { + if len(sname) != 0 { + sname += "." + } + + sname += group.ShortDescription + } + + sectionwritten := false + comments := (options & IniIncludeComments) != IniNone + + for _, option := range group.options { + if option.isFunc() || option.Hidden { + continue + } + + if len(option.tag.Get("no-ini")) != 0 { + continue + } + + val := option.value + + if (options&IniIncludeDefaults) == IniNone && option.valueIsDefault() { + continue + } + + if !sectionwritten { + fmt.Fprintf(writer, "[%s]\n", sname) + sectionwritten = true + } + + if comments && len(option.Description) != 0 { + fmt.Fprintf(writer, "; %s\n", option.Description) + } + + oname := optionIniName(option) + + commentOption := (options&(IniIncludeDefaults|IniCommentDefaults)) == IniIncludeDefaults|IniCommentDefaults && option.valueIsDefault() + + kind := val.Type().Kind() + switch kind { + case reflect.Slice: + kind = val.Type().Elem().Kind() + + if val.Len() == 0 { + writeOption(writer, oname, kind, "", "", true, option.iniQuote) + } else { + for idx := 0; idx < val.Len(); idx++ { + v, _ := convertToString(val.Index(idx), option.tag) + + writeOption(writer, oname, kind, "", v, commentOption, option.iniQuote) + } + } + case reflect.Map: + kind = val.Type().Elem().Kind() + + if val.Len() == 0 { + writeOption(writer, oname, kind, "", "", true, option.iniQuote) + } else { + mkeys := val.MapKeys() + keys := make([]string, len(val.MapKeys())) + kkmap := make(map[string]reflect.Value) + + for i, k := range mkeys { + keys[i], _ = convertToString(k, option.tag) + kkmap[keys[i]] = k + } + + sort.Strings(keys) + + for _, k := range keys { + v, _ := convertToString(val.MapIndex(kkmap[k]), option.tag) + + writeOption(writer, oname, kind, k, v, commentOption, option.iniQuote) + } + } + default: + v, _ := convertToString(val, option.tag) + + writeOption(writer, oname, kind, "", v, commentOption, option.iniQuote) + } + + if comments { + fmt.Fprintln(writer) + } + } + + if sectionwritten && !comments { + fmt.Fprintln(writer) + } +} + +func writeOption(writer io.Writer, optionName string, optionType reflect.Kind, optionKey string, optionValue string, commentOption bool, forceQuote bool) { + if forceQuote || (optionType == reflect.String && !isPrint(optionValue)) { + optionValue = strconv.Quote(optionValue) + } + + comment := "" + if commentOption { + comment = "; " + } + + fmt.Fprintf(writer, "%s%s =", comment, optionName) + + if optionKey != "" { + fmt.Fprintf(writer, " %s:%s", optionKey, optionValue) + } else if optionValue != "" { + fmt.Fprintf(writer, " %s", optionValue) + } + + fmt.Fprintln(writer) +} + +func writeCommandIni(command *Command, namespace string, writer io.Writer, options IniOptions) { + command.eachGroup(func(group *Group) { + if !group.Hidden { + writeGroupIni(command, group, namespace, writer, options) + } + }) + + for _, c := range command.commands { + var nns string + + if c.Hidden { + continue + } + + if len(namespace) != 0 { + nns = c.Name + "." + nns + } else { + nns = c.Name + } + + writeCommandIni(c, nns, writer, options) + } +} + +func writeIni(parser *IniParser, writer io.Writer, options IniOptions) { + writeCommandIni(parser.parser.Command, "", writer, options) +} + +func writeIniToFile(parser *IniParser, filename string, options IniOptions) error { + file, err := os.Create(filename) + + if err != nil { + return err + } + + defer file.Close() + + writeIni(parser, file, options) + + return nil +} + +func readIniFromFile(filename string) (*ini, error) { + file, err := os.Open(filename) + + if err != nil { + return nil, err + } + + defer file.Close() + + return readIni(file, filename) +} + +func readIni(contents io.Reader, filename string) (*ini, error) { + ret := &ini{ + File: filename, + Sections: make(map[string]iniSection), + } + + reader := bufio.NewReader(contents) + + // Empty global section + section := make(iniSection, 0, 10) + sectionname := "" + + ret.Sections[sectionname] = section + + var lineno uint + + for { + line, err := readFullLine(reader) + + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + + lineno++ + line = strings.TrimSpace(line) + + // Skip empty lines and lines starting with ; (comments) + if len(line) == 0 || line[0] == ';' || line[0] == '#' { + continue + } + + if line[0] == '[' { + if line[0] != '[' || line[len(line)-1] != ']' { + return nil, &IniError{ + Message: "malformed section header", + File: filename, + LineNumber: lineno, + } + } + + name := strings.TrimSpace(line[1 : len(line)-1]) + + if len(name) == 0 { + return nil, &IniError{ + Message: "empty section name", + File: filename, + LineNumber: lineno, + } + } + + sectionname = name + section = ret.Sections[name] + + if section == nil { + section = make(iniSection, 0, 10) + ret.Sections[name] = section + } + + continue + } + + // Parse option here + keyval := strings.SplitN(line, "=", 2) + + if len(keyval) != 2 { + return nil, &IniError{ + Message: fmt.Sprintf("malformed key=value (%s)", line), + File: filename, + LineNumber: lineno, + } + } + + name := strings.TrimSpace(keyval[0]) + value := strings.TrimSpace(keyval[1]) + quoted := false + + if len(value) != 0 && value[0] == '"' { + if v, err := strconv.Unquote(value); err == nil { + value = v + + quoted = true + } else { + return nil, &IniError{ + Message: err.Error(), + File: filename, + LineNumber: lineno, + } + } + } + + section = append(section, iniValue{ + Name: name, + Value: value, + Quoted: quoted, + LineNumber: lineno, + }) + + ret.Sections[sectionname] = section + } + + return ret, nil +} + +func (i *IniParser) matchingGroups(name string) []*Group { + if len(name) == 0 { + var ret []*Group + + i.parser.eachGroup(func(g *Group) { + ret = append(ret, g) + }) + + return ret + } + + g := i.parser.groupByName(name) + + if g != nil { + return []*Group{g} + } + + return nil +} + +func (i *IniParser) parse(ini *ini) error { + p := i.parser + + var quotesLookup = make(map[*Option]bool) + + for name, section := range ini.Sections { + groups := i.matchingGroups(name) + + if len(groups) == 0 { + return newErrorf(ErrUnknownGroup, "could not find option group `%s'", name) + } + + for _, inival := range section { + var opt *Option + + for _, group := range groups { + opt = group.optionByName(inival.Name, func(o *Option, n string) bool { + return strings.ToLower(o.tag.Get("ini-name")) == strings.ToLower(n) + }) + + if opt != nil && len(opt.tag.Get("no-ini")) != 0 { + opt = nil + } + + if opt != nil { + break + } + } + + if opt == nil { + if (p.Options & IgnoreUnknown) == None { + return &IniError{ + Message: fmt.Sprintf("unknown option: %s", inival.Name), + File: ini.File, + LineNumber: inival.LineNumber, + } + } + + continue + } + + // ini value is ignored if override is set and + // value was previously set from non default + if i.ParseAsDefaults && !opt.isSetDefault { + continue + } + + pval := &inival.Value + + if !opt.canArgument() && len(inival.Value) == 0 { + pval = nil + } else { + if opt.value.Type().Kind() == reflect.Map { + parts := strings.SplitN(inival.Value, ":", 2) + + // only handle unquoting + if len(parts) == 2 && parts[1][0] == '"' { + if v, err := strconv.Unquote(parts[1]); err == nil { + parts[1] = v + + inival.Quoted = true + } else { + return &IniError{ + Message: err.Error(), + File: ini.File, + LineNumber: inival.LineNumber, + } + } + + s := parts[0] + ":" + parts[1] + + pval = &s + } + } + } + + if err := opt.set(pval); err != nil { + return &IniError{ + Message: err.Error(), + File: ini.File, + LineNumber: inival.LineNumber, + } + } + + // either all INI values are quoted or only values who need quoting + if _, ok := quotesLookup[opt]; !inival.Quoted || !ok { + quotesLookup[opt] = inival.Quoted + } + + opt.tag.Set("_read-ini-name", inival.Name) + } + } + + for opt, quoted := range quotesLookup { + opt.iniQuote = quoted + } + + return nil +} diff --git a/vendor/github.com/jessevdk/go-flags/man.go b/vendor/github.com/jessevdk/go-flags/man.go new file mode 100644 index 00000000..0cb114e7 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/man.go @@ -0,0 +1,205 @@ +package flags + +import ( + "fmt" + "io" + "runtime" + "strings" + "time" +) + +func manQuote(s string) string { + return strings.Replace(s, "\\", "\\\\", -1) +} + +func formatForMan(wr io.Writer, s string) { + for { + idx := strings.IndexRune(s, '`') + + if idx < 0 { + fmt.Fprintf(wr, "%s", manQuote(s)) + break + } + + fmt.Fprintf(wr, "%s", manQuote(s[:idx])) + + s = s[idx+1:] + idx = strings.IndexRune(s, '\'') + + if idx < 0 { + fmt.Fprintf(wr, "%s", manQuote(s)) + break + } + + fmt.Fprintf(wr, "\\fB%s\\fP", manQuote(s[:idx])) + s = s[idx+1:] + } +} + +func writeManPageOptions(wr io.Writer, grp *Group) { + grp.eachGroup(func(group *Group) { + if group.Hidden || len(group.options) == 0 { + return + } + + // If the parent (grp) has any subgroups, display their descriptions as + // subsection headers similar to the output of --help. + if group.ShortDescription != "" && len(grp.groups) > 0 { + fmt.Fprintf(wr, ".SS %s\n", group.ShortDescription) + + if group.LongDescription != "" { + formatForMan(wr, group.LongDescription) + fmt.Fprintln(wr, "") + } + } + + for _, opt := range group.options { + if !opt.canCli() || opt.Hidden { + continue + } + + fmt.Fprintln(wr, ".TP") + fmt.Fprintf(wr, "\\fB") + + if opt.ShortName != 0 { + fmt.Fprintf(wr, "\\fB\\-%c\\fR", opt.ShortName) + } + + if len(opt.LongName) != 0 { + if opt.ShortName != 0 { + fmt.Fprintf(wr, ", ") + } + + fmt.Fprintf(wr, "\\fB\\-\\-%s\\fR", manQuote(opt.LongNameWithNamespace())) + } + + if len(opt.ValueName) != 0 || opt.OptionalArgument { + if opt.OptionalArgument { + fmt.Fprintf(wr, " [\\fI%s=%s\\fR]", manQuote(opt.ValueName), manQuote(strings.Join(quoteV(opt.OptionalValue), ", "))) + } else { + fmt.Fprintf(wr, " \\fI%s\\fR", manQuote(opt.ValueName)) + } + } + + if len(opt.Default) != 0 { + fmt.Fprintf(wr, " ", manQuote(strings.Join(quoteV(opt.Default), ", "))) + } else if len(opt.EnvDefaultKey) != 0 { + if runtime.GOOS == "windows" { + fmt.Fprintf(wr, " ", manQuote(opt.EnvDefaultKey)) + } else { + fmt.Fprintf(wr, " ", manQuote(opt.EnvDefaultKey)) + } + } + + if opt.Required { + fmt.Fprintf(wr, " (\\fIrequired\\fR)") + } + + fmt.Fprintln(wr, "\\fP") + + if len(opt.Description) != 0 { + formatForMan(wr, opt.Description) + fmt.Fprintln(wr, "") + } + } + }) +} + +func writeManPageSubcommands(wr io.Writer, name string, root *Command) { + commands := root.sortedVisibleCommands() + + for _, c := range commands { + var nn string + + if c.Hidden { + continue + } + + if len(name) != 0 { + nn = name + " " + c.Name + } else { + nn = c.Name + } + + writeManPageCommand(wr, nn, root, c) + } +} + +func writeManPageCommand(wr io.Writer, name string, root *Command, command *Command) { + fmt.Fprintf(wr, ".SS %s\n", name) + fmt.Fprintln(wr, command.ShortDescription) + + if len(command.LongDescription) > 0 { + fmt.Fprintln(wr, "") + + cmdstart := fmt.Sprintf("The %s command", manQuote(command.Name)) + + if strings.HasPrefix(command.LongDescription, cmdstart) { + fmt.Fprintf(wr, "The \\fI%s\\fP command", manQuote(command.Name)) + + formatForMan(wr, command.LongDescription[len(cmdstart):]) + fmt.Fprintln(wr, "") + } else { + formatForMan(wr, command.LongDescription) + fmt.Fprintln(wr, "") + } + } + + var usage string + if us, ok := command.data.(Usage); ok { + usage = us.Usage() + } else if command.hasCliOptions() { + usage = fmt.Sprintf("[%s-OPTIONS]", command.Name) + } + + var pre string + if root.hasCliOptions() { + pre = fmt.Sprintf("%s [OPTIONS] %s", root.Name, command.Name) + } else { + pre = fmt.Sprintf("%s %s", root.Name, command.Name) + } + + if len(usage) > 0 { + fmt.Fprintf(wr, "\n\\fBUsage\\fP: %s %s\n.TP\n", manQuote(pre), manQuote(usage)) + } + + if len(command.Aliases) > 0 { + fmt.Fprintf(wr, "\n\\fBAliases\\fP: %s\n\n", manQuote(strings.Join(command.Aliases, ", "))) + } + + writeManPageOptions(wr, command.Group) + writeManPageSubcommands(wr, name, command) +} + +// WriteManPage writes a basic man page in groff format to the specified +// writer. +func (p *Parser) WriteManPage(wr io.Writer) { + t := time.Now() + + fmt.Fprintf(wr, ".TH %s 1 \"%s\"\n", manQuote(p.Name), t.Format("2 January 2006")) + fmt.Fprintln(wr, ".SH NAME") + fmt.Fprintf(wr, "%s \\- %s\n", manQuote(p.Name), manQuote(p.ShortDescription)) + fmt.Fprintln(wr, ".SH SYNOPSIS") + + usage := p.Usage + + if len(usage) == 0 { + usage = "[OPTIONS]" + } + + fmt.Fprintf(wr, "\\fB%s\\fP %s\n", manQuote(p.Name), manQuote(usage)) + fmt.Fprintln(wr, ".SH DESCRIPTION") + + formatForMan(wr, p.LongDescription) + fmt.Fprintln(wr, "") + + fmt.Fprintln(wr, ".SH OPTIONS") + + writeManPageOptions(wr, p.Command.Group) + + if len(p.visibleCommands()) > 0 { + fmt.Fprintln(wr, ".SH COMMANDS") + + writeManPageSubcommands(wr, "", p.Command) + } +} diff --git a/vendor/github.com/jessevdk/go-flags/multitag.go b/vendor/github.com/jessevdk/go-flags/multitag.go new file mode 100644 index 00000000..96bb1a31 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/multitag.go @@ -0,0 +1,140 @@ +package flags + +import ( + "strconv" +) + +type multiTag struct { + value string + cache map[string][]string +} + +func newMultiTag(v string) multiTag { + return multiTag{ + value: v, + } +} + +func (x *multiTag) scan() (map[string][]string, error) { + v := x.value + + ret := make(map[string][]string) + + // This is mostly copied from reflect.StructTag.Get + for v != "" { + i := 0 + + // Skip whitespace + for i < len(v) && v[i] == ' ' { + i++ + } + + v = v[i:] + + if v == "" { + break + } + + // Scan to colon to find key + i = 0 + + for i < len(v) && v[i] != ' ' && v[i] != ':' && v[i] != '"' { + i++ + } + + if i >= len(v) { + return nil, newErrorf(ErrTag, "expected `:' after key name, but got end of tag (in `%v`)", x.value) + } + + if v[i] != ':' { + return nil, newErrorf(ErrTag, "expected `:' after key name, but got `%v' (in `%v`)", v[i], x.value) + } + + if i+1 >= len(v) { + return nil, newErrorf(ErrTag, "expected `\"' to start tag value at end of tag (in `%v`)", x.value) + } + + if v[i+1] != '"' { + return nil, newErrorf(ErrTag, "expected `\"' to start tag value, but got `%v' (in `%v`)", v[i+1], x.value) + } + + name := v[:i] + v = v[i+1:] + + // Scan quoted string to find value + i = 1 + + for i < len(v) && v[i] != '"' { + if v[i] == '\n' { + return nil, newErrorf(ErrTag, "unexpected newline in tag value `%v' (in `%v`)", name, x.value) + } + + if v[i] == '\\' { + i++ + } + i++ + } + + if i >= len(v) { + return nil, newErrorf(ErrTag, "expected end of tag value `\"' at end of tag (in `%v`)", x.value) + } + + val, err := strconv.Unquote(v[:i+1]) + + if err != nil { + return nil, newErrorf(ErrTag, "Malformed value of tag `%v:%v` => %v (in `%v`)", name, v[:i+1], err, x.value) + } + + v = v[i+1:] + + ret[name] = append(ret[name], val) + } + + return ret, nil +} + +func (x *multiTag) Parse() error { + vals, err := x.scan() + x.cache = vals + + return err +} + +func (x *multiTag) cached() map[string][]string { + if x.cache == nil { + cache, _ := x.scan() + + if cache == nil { + cache = make(map[string][]string) + } + + x.cache = cache + } + + return x.cache +} + +func (x *multiTag) Get(key string) string { + c := x.cached() + + if v, ok := c[key]; ok { + return v[len(v)-1] + } + + return "" +} + +func (x *multiTag) GetMany(key string) []string { + c := x.cached() + return c[key] +} + +func (x *multiTag) Set(key string, value string) { + c := x.cached() + c[key] = []string{value} +} + +func (x *multiTag) SetMany(key string, value []string) { + c := x.cached() + c[key] = value +} diff --git a/vendor/github.com/jessevdk/go-flags/option.go b/vendor/github.com/jessevdk/go-flags/option.go new file mode 100644 index 00000000..5f852501 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/option.go @@ -0,0 +1,459 @@ +package flags + +import ( + "bytes" + "fmt" + "os" + "reflect" + "strings" + "unicode/utf8" +) + +// Option flag information. Contains a description of the option, short and +// long name as well as a default value and whether an argument for this +// flag is optional. +type Option struct { + // The description of the option flag. This description is shown + // automatically in the built-in help. + Description string + + // The short name of the option (a single character). If not 0, the + // option flag can be 'activated' using -. Either ShortName + // or LongName needs to be non-empty. + ShortName rune + + // The long name of the option. If not "", the option flag can be + // activated using --. Either ShortName or LongName needs + // to be non-empty. + LongName string + + // The default value of the option. + Default []string + + // The optional environment default value key name. + EnvDefaultKey string + + // The optional delimiter string for EnvDefaultKey values. + EnvDefaultDelim string + + // If true, specifies that the argument to an option flag is optional. + // When no argument to the flag is specified on the command line, the + // value of OptionalValue will be set in the field this option represents. + // This is only valid for non-boolean options. + OptionalArgument bool + + // The optional value of the option. The optional value is used when + // the option flag is marked as having an OptionalArgument. This means + // that when the flag is specified, but no option argument is given, + // the value of the field this option represents will be set to + // OptionalValue. This is only valid for non-boolean options. + OptionalValue []string + + // If true, the option _must_ be specified on the command line. If the + // option is not specified, the parser will generate an ErrRequired type + // error. + Required bool + + // A name for the value of an option shown in the Help as --flag [ValueName] + ValueName string + + // A mask value to show in the help instead of the default value. This + // is useful for hiding sensitive information in the help, such as + // passwords. + DefaultMask string + + // If non empty, only a certain set of values is allowed for an option. + Choices []string + + // If true, the option is not displayed in the help or man page + Hidden bool + + // The group which the option belongs to + group *Group + + // The struct field which the option represents. + field reflect.StructField + + // The struct field value which the option represents. + value reflect.Value + + // Determines if the option will be always quoted in the INI output + iniQuote bool + + tag multiTag + isSet bool + isSetDefault bool + preventDefault bool + + defaultLiteral string +} + +// LongNameWithNamespace returns the option's long name with the group namespaces +// prepended by walking up the option's group tree. Namespaces and the long name +// itself are separated by the parser's namespace delimiter. If the long name is +// empty an empty string is returned. +func (option *Option) LongNameWithNamespace() string { + if len(option.LongName) == 0 { + return "" + } + + // fetch the namespace delimiter from the parser which is always at the + // end of the group hierarchy + namespaceDelimiter := "" + g := option.group + + for { + if p, ok := g.parent.(*Parser); ok { + namespaceDelimiter = p.NamespaceDelimiter + + break + } + + switch i := g.parent.(type) { + case *Command: + g = i.Group + case *Group: + g = i + } + } + + // concatenate long name with namespace + longName := option.LongName + g = option.group + + for g != nil { + if g.Namespace != "" { + longName = g.Namespace + namespaceDelimiter + longName + } + + switch i := g.parent.(type) { + case *Command: + g = i.Group + case *Group: + g = i + case *Parser: + g = nil + } + } + + return longName +} + +// String converts an option to a human friendly readable string describing the +// option. +func (option *Option) String() string { + var s string + var short string + + if option.ShortName != 0 { + data := make([]byte, utf8.RuneLen(option.ShortName)) + utf8.EncodeRune(data, option.ShortName) + short = string(data) + + if len(option.LongName) != 0 { + s = fmt.Sprintf("%s%s, %s%s", + string(defaultShortOptDelimiter), short, + defaultLongOptDelimiter, option.LongNameWithNamespace()) + } else { + s = fmt.Sprintf("%s%s", string(defaultShortOptDelimiter), short) + } + } else if len(option.LongName) != 0 { + s = fmt.Sprintf("%s%s", defaultLongOptDelimiter, option.LongNameWithNamespace()) + } + + return s +} + +// Value returns the option value as an interface{}. +func (option *Option) Value() interface{} { + return option.value.Interface() +} + +// Field returns the reflect struct field of the option. +func (option *Option) Field() reflect.StructField { + return option.field +} + +// IsSet returns true if option has been set +func (option *Option) IsSet() bool { + return option.isSet +} + +// IsSetDefault returns true if option has been set via the default option tag +func (option *Option) IsSetDefault() bool { + return option.isSetDefault +} + +// Set the value of an option to the specified value. An error will be returned +// if the specified value could not be converted to the corresponding option +// value type. +func (option *Option) set(value *string) error { + kind := option.value.Type().Kind() + + if (kind == reflect.Map || kind == reflect.Slice) && !option.isSet { + option.empty() + } + + option.isSet = true + option.preventDefault = true + + if len(option.Choices) != 0 { + found := false + + for _, choice := range option.Choices { + if choice == *value { + found = true + break + } + } + + if !found { + allowed := strings.Join(option.Choices[0:len(option.Choices)-1], ", ") + + if len(option.Choices) > 1 { + allowed += " or " + option.Choices[len(option.Choices)-1] + } + + return newErrorf(ErrInvalidChoice, + "Invalid value `%s' for option `%s'. Allowed values are: %s", + *value, option, allowed) + } + } + + if option.isFunc() { + return option.call(value) + } else if value != nil { + return convert(*value, option.value, option.tag) + } + + return convert("", option.value, option.tag) +} + +func (option *Option) canCli() bool { + return option.ShortName != 0 || len(option.LongName) != 0 +} + +func (option *Option) canArgument() bool { + if u := option.isUnmarshaler(); u != nil { + return true + } + + return !option.isBool() +} + +func (option *Option) emptyValue() reflect.Value { + tp := option.value.Type() + + if tp.Kind() == reflect.Map { + return reflect.MakeMap(tp) + } + + return reflect.Zero(tp) +} + +func (option *Option) empty() { + if !option.isFunc() { + option.value.Set(option.emptyValue()) + } +} + +func (option *Option) clearDefault() { + usedDefault := option.Default + + if envKey := option.EnvDefaultKey; envKey != "" { + if value, ok := os.LookupEnv(envKey); ok { + if option.EnvDefaultDelim != "" { + usedDefault = strings.Split(value, + option.EnvDefaultDelim) + } else { + usedDefault = []string{value} + } + } + } + + option.isSetDefault = true + + if len(usedDefault) > 0 { + option.empty() + + for _, d := range usedDefault { + option.set(&d) + option.isSetDefault = true + } + } else { + tp := option.value.Type() + + switch tp.Kind() { + case reflect.Map: + if option.value.IsNil() { + option.empty() + } + case reflect.Slice: + if option.value.IsNil() { + option.empty() + } + } + } +} + +func (option *Option) valueIsDefault() bool { + // Check if the value of the option corresponds to its + // default value + emptyval := option.emptyValue() + + checkvalptr := reflect.New(emptyval.Type()) + checkval := reflect.Indirect(checkvalptr) + + checkval.Set(emptyval) + + if len(option.Default) != 0 { + for _, v := range option.Default { + convert(v, checkval, option.tag) + } + } + + return reflect.DeepEqual(option.value.Interface(), checkval.Interface()) +} + +func (option *Option) isUnmarshaler() Unmarshaler { + v := option.value + + for { + if !v.CanInterface() { + break + } + + i := v.Interface() + + if u, ok := i.(Unmarshaler); ok { + return u + } + + if !v.CanAddr() { + break + } + + v = v.Addr() + } + + return nil +} + +func (option *Option) isBool() bool { + tp := option.value.Type() + + for { + switch tp.Kind() { + case reflect.Slice, reflect.Ptr: + tp = tp.Elem() + case reflect.Bool: + return true + case reflect.Func: + return tp.NumIn() == 0 + default: + return false + } + } +} + +func (option *Option) isSignedNumber() bool { + tp := option.value.Type() + + for { + switch tp.Kind() { + case reflect.Slice, reflect.Ptr: + tp = tp.Elem() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64: + return true + default: + return false + } + } +} + +func (option *Option) isFunc() bool { + return option.value.Type().Kind() == reflect.Func +} + +func (option *Option) call(value *string) error { + var retval []reflect.Value + + if value == nil { + retval = option.value.Call(nil) + } else { + tp := option.value.Type().In(0) + + val := reflect.New(tp) + val = reflect.Indirect(val) + + if err := convert(*value, val, option.tag); err != nil { + return err + } + + retval = option.value.Call([]reflect.Value{val}) + } + + if len(retval) == 1 && retval[0].Type() == reflect.TypeOf((*error)(nil)).Elem() { + if retval[0].Interface() == nil { + return nil + } + + return retval[0].Interface().(error) + } + + return nil +} + +func (option *Option) updateDefaultLiteral() { + defs := option.Default + def := "" + + if len(defs) == 0 && option.canArgument() { + var showdef bool + + switch option.field.Type.Kind() { + case reflect.Func, reflect.Ptr: + showdef = !option.value.IsNil() + case reflect.Slice, reflect.String, reflect.Array: + showdef = option.value.Len() > 0 + case reflect.Map: + showdef = !option.value.IsNil() && option.value.Len() > 0 + default: + zeroval := reflect.Zero(option.field.Type) + showdef = !reflect.DeepEqual(zeroval.Interface(), option.value.Interface()) + } + + if showdef { + def, _ = convertToString(option.value, option.tag) + } + } else if len(defs) != 0 { + l := len(defs) - 1 + + for i := 0; i < l; i++ { + def += quoteIfNeeded(defs[i]) + ", " + } + + def += quoteIfNeeded(defs[l]) + } + + option.defaultLiteral = def +} + +func (option *Option) shortAndLongName() string { + ret := &bytes.Buffer{} + + if option.ShortName != 0 { + ret.WriteRune(defaultShortOptDelimiter) + ret.WriteRune(option.ShortName) + } + + if len(option.LongName) != 0 { + if option.ShortName != 0 { + ret.WriteRune('/') + } + + ret.WriteString(option.LongName) + } + + return ret.String() +} diff --git a/vendor/github.com/jessevdk/go-flags/optstyle_other.go b/vendor/github.com/jessevdk/go-flags/optstyle_other.go new file mode 100644 index 00000000..56dfdae1 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/optstyle_other.go @@ -0,0 +1,67 @@ +// +build !windows forceposix + +package flags + +import ( + "strings" +) + +const ( + defaultShortOptDelimiter = '-' + defaultLongOptDelimiter = "--" + defaultNameArgDelimiter = '=' +) + +func argumentStartsOption(arg string) bool { + return len(arg) > 0 && arg[0] == '-' +} + +func argumentIsOption(arg string) bool { + if len(arg) > 1 && arg[0] == '-' && arg[1] != '-' { + return true + } + + if len(arg) > 2 && arg[0] == '-' && arg[1] == '-' && arg[2] != '-' { + return true + } + + return false +} + +// stripOptionPrefix returns the option without the prefix and whether or +// not the option is a long option or not. +func stripOptionPrefix(optname string) (prefix string, name string, islong bool) { + if strings.HasPrefix(optname, "--") { + return "--", optname[2:], true + } else if strings.HasPrefix(optname, "-") { + return "-", optname[1:], false + } + + return "", optname, false +} + +// splitOption attempts to split the passed option into a name and an argument. +// When there is no argument specified, nil will be returned for it. +func splitOption(prefix string, option string, islong bool) (string, string, *string) { + pos := strings.Index(option, "=") + + if (islong && pos >= 0) || (!islong && pos == 1) { + rest := option[pos+1:] + return option[:pos], "=", &rest + } + + return option, "", nil +} + +// addHelpGroup adds a new group that contains default help parameters. +func (c *Command) addHelpGroup(showHelp func() error) *Group { + var help struct { + ShowHelp func() error `short:"h" long:"help" description:"Show this help message"` + } + + help.ShowHelp = showHelp + ret, _ := c.AddGroup("Help Options", "", &help) + ret.isBuiltinHelp = true + + return ret +} diff --git a/vendor/github.com/jessevdk/go-flags/optstyle_windows.go b/vendor/github.com/jessevdk/go-flags/optstyle_windows.go new file mode 100644 index 00000000..f3f28aee --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/optstyle_windows.go @@ -0,0 +1,108 @@ +// +build !forceposix + +package flags + +import ( + "strings" +) + +// Windows uses a front slash for both short and long options. Also it uses +// a colon for name/argument delimter. +const ( + defaultShortOptDelimiter = '/' + defaultLongOptDelimiter = "/" + defaultNameArgDelimiter = ':' +) + +func argumentStartsOption(arg string) bool { + return len(arg) > 0 && (arg[0] == '-' || arg[0] == '/') +} + +func argumentIsOption(arg string) bool { + // Windows-style options allow front slash for the option + // delimiter. + if len(arg) > 1 && arg[0] == '/' { + return true + } + + if len(arg) > 1 && arg[0] == '-' && arg[1] != '-' { + return true + } + + if len(arg) > 2 && arg[0] == '-' && arg[1] == '-' && arg[2] != '-' { + return true + } + + return false +} + +// stripOptionPrefix returns the option without the prefix and whether or +// not the option is a long option or not. +func stripOptionPrefix(optname string) (prefix string, name string, islong bool) { + // Determine if the argument is a long option or not. Windows + // typically supports both long and short options with a single + // front slash as the option delimiter, so handle this situation + // nicely. + possplit := 0 + + if strings.HasPrefix(optname, "--") { + possplit = 2 + islong = true + } else if strings.HasPrefix(optname, "-") { + possplit = 1 + islong = false + } else if strings.HasPrefix(optname, "/") { + possplit = 1 + islong = len(optname) > 2 + } + + return optname[:possplit], optname[possplit:], islong +} + +// splitOption attempts to split the passed option into a name and an argument. +// When there is no argument specified, nil will be returned for it. +func splitOption(prefix string, option string, islong bool) (string, string, *string) { + if len(option) == 0 { + return option, "", nil + } + + // Windows typically uses a colon for the option name and argument + // delimiter while POSIX typically uses an equals. Support both styles, + // but don't allow the two to be mixed. That is to say /foo:bar and + // --foo=bar are acceptable, but /foo=bar and --foo:bar are not. + var pos int + var sp string + + if prefix == "/" { + sp = ":" + pos = strings.Index(option, sp) + } else if len(prefix) > 0 { + sp = "=" + pos = strings.Index(option, sp) + } + + if (islong && pos >= 0) || (!islong && pos == 1) { + rest := option[pos+1:] + return option[:pos], sp, &rest + } + + return option, "", nil +} + +// addHelpGroup adds a new group that contains default help parameters. +func (c *Command) addHelpGroup(showHelp func() error) *Group { + // Windows CLI applications typically use /? for help, so make both + // that available as well as the POSIX style h and help. + var help struct { + ShowHelpWindows func() error `short:"?" description:"Show this help message"` + ShowHelpPosix func() error `short:"h" long:"help" description:"Show this help message"` + } + + help.ShowHelpWindows = showHelp + help.ShowHelpPosix = showHelp + + ret, _ := c.AddGroup("Help Options", "", &help) + ret.isBuiltinHelp = true + + return ret +} diff --git a/vendor/github.com/jessevdk/go-flags/parser.go b/vendor/github.com/jessevdk/go-flags/parser.go new file mode 100644 index 00000000..0a7922a0 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/parser.go @@ -0,0 +1,700 @@ +// Copyright 2012 Jesse van den Kieboom. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flags + +import ( + "bytes" + "fmt" + "os" + "path" + "sort" + "strings" + "unicode/utf8" +) + +// A Parser provides command line option parsing. It can contain several +// option groups each with their own set of options. +type Parser struct { + // Embedded, see Command for more information + *Command + + // A usage string to be displayed in the help message. + Usage string + + // Option flags changing the behavior of the parser. + Options Options + + // NamespaceDelimiter separates group namespaces and option long names + NamespaceDelimiter string + + // UnknownOptionsHandler is a function which gets called when the parser + // encounters an unknown option. The function receives the unknown option + // name, a SplitArgument which specifies its value if set with an argument + // separator, and the remaining command line arguments. + // It should return a new list of remaining arguments to continue parsing, + // or an error to indicate a parse failure. + UnknownOptionHandler func(option string, arg SplitArgument, args []string) ([]string, error) + + // CompletionHandler is a function gets called to handle the completion of + // items. By default, the items are printed and the application is exited. + // You can override this default behavior by specifying a custom CompletionHandler. + CompletionHandler func(items []Completion) + + // CommandHandler is a function that gets called to handle execution of a + // command. By default, the command will simply be executed. This can be + // overridden to perform certain actions (such as applying global flags) + // just before the command is executed. Note that if you override the + // handler it is your responsibility to call the command.Execute function. + // + // The command passed into CommandHandler may be nil in case there is no + // command to be executed when parsing has finished. + CommandHandler func(command Commander, args []string) error + + internalError error +} + +// SplitArgument represents the argument value of an option that was passed using +// an argument separator. +type SplitArgument interface { + // String returns the option's value as a string, and a boolean indicating + // if the option was present. + Value() (string, bool) +} + +type strArgument struct { + value *string +} + +func (s strArgument) Value() (string, bool) { + if s.value == nil { + return "", false + } + + return *s.value, true +} + +// Options provides parser options that change the behavior of the option +// parser. +type Options uint + +const ( + // None indicates no options. + None Options = 0 + + // HelpFlag adds a default Help Options group to the parser containing + // -h and --help options. When either -h or --help is specified on the + // command line, the parser will return the special error of type + // ErrHelp. When PrintErrors is also specified, then the help message + // will also be automatically printed to os.Stdout. + HelpFlag = 1 << iota + + // PassDoubleDash passes all arguments after a double dash, --, as + // remaining command line arguments (i.e. they will not be parsed for + // flags). + PassDoubleDash + + // IgnoreUnknown ignores any unknown options and passes them as + // remaining command line arguments instead of generating an error. + IgnoreUnknown + + // PrintErrors prints any errors which occurred during parsing to + // os.Stderr. In the special case of ErrHelp, the message will be printed + // to os.Stdout. + PrintErrors + + // PassAfterNonOption passes all arguments after the first non option + // as remaining command line arguments. This is equivalent to strict + // POSIX processing. + PassAfterNonOption + + // Default is a convenient default set of options which should cover + // most of the uses of the flags package. + Default = HelpFlag | PrintErrors | PassDoubleDash +) + +type parseState struct { + arg string + args []string + retargs []string + positional []*Arg + err error + + command *Command + lookup lookup +} + +// Parse is a convenience function to parse command line options with default +// settings. The provided data is a pointer to a struct representing the +// default option group (named "Application Options"). For more control, use +// flags.NewParser. +func Parse(data interface{}) ([]string, error) { + return NewParser(data, Default).Parse() +} + +// ParseArgs is a convenience function to parse command line options with default +// settings. The provided data is a pointer to a struct representing the +// default option group (named "Application Options"). The args argument is +// the list of command line arguments to parse. If you just want to parse the +// default program command line arguments (i.e. os.Args), then use flags.Parse +// instead. For more control, use flags.NewParser. +func ParseArgs(data interface{}, args []string) ([]string, error) { + return NewParser(data, Default).ParseArgs(args) +} + +// NewParser creates a new parser. It uses os.Args[0] as the application +// name and then calls Parser.NewNamedParser (see Parser.NewNamedParser for +// more details). The provided data is a pointer to a struct representing the +// default option group (named "Application Options"), or nil if the default +// group should not be added. The options parameter specifies a set of options +// for the parser. +func NewParser(data interface{}, options Options) *Parser { + p := NewNamedParser(path.Base(os.Args[0]), options) + + if data != nil { + g, err := p.AddGroup("Application Options", "", data) + + if err == nil { + g.parent = p + } + + p.internalError = err + } + + return p +} + +// NewNamedParser creates a new parser. The appname is used to display the +// executable name in the built-in help message. Option groups and commands can +// be added to this parser by using AddGroup and AddCommand. +func NewNamedParser(appname string, options Options) *Parser { + p := &Parser{ + Command: newCommand(appname, "", "", nil), + Options: options, + NamespaceDelimiter: ".", + } + + p.Command.parent = p + + return p +} + +// Parse parses the command line arguments from os.Args using Parser.ParseArgs. +// For more detailed information see ParseArgs. +func (p *Parser) Parse() ([]string, error) { + return p.ParseArgs(os.Args[1:]) +} + +// ParseArgs parses the command line arguments according to the option groups that +// were added to the parser. On successful parsing of the arguments, the +// remaining, non-option, arguments (if any) are returned. The returned error +// indicates a parsing error and can be used with PrintError to display +// contextual information on where the error occurred exactly. +// +// When the common help group has been added (AddHelp) and either -h or --help +// was specified in the command line arguments, a help message will be +// automatically printed if the PrintErrors option is enabled. +// Furthermore, the special error type ErrHelp is returned. +// It is up to the caller to exit the program if so desired. +func (p *Parser) ParseArgs(args []string) ([]string, error) { + if p.internalError != nil { + return nil, p.internalError + } + + p.eachOption(func(c *Command, g *Group, option *Option) { + option.isSet = false + option.isSetDefault = false + option.updateDefaultLiteral() + }) + + // Add built-in help group to all commands if necessary + if (p.Options & HelpFlag) != None { + p.addHelpGroups(p.showBuiltinHelp) + } + + compval := os.Getenv("GO_FLAGS_COMPLETION") + + if len(compval) != 0 { + comp := &completion{parser: p} + items := comp.complete(args) + + if p.CompletionHandler != nil { + p.CompletionHandler(items) + } else { + comp.print(items, compval == "verbose") + os.Exit(0) + } + + return nil, nil + } + + s := &parseState{ + args: args, + retargs: make([]string, 0, len(args)), + } + + p.fillParseState(s) + + for !s.eof() { + arg := s.pop() + + // When PassDoubleDash is set and we encounter a --, then + // simply append all the rest as arguments and break out + if (p.Options&PassDoubleDash) != None && arg == "--" { + s.addArgs(s.args...) + break + } + + if !argumentIsOption(arg) { + // Note: this also sets s.err, so we can just check for + // nil here and use s.err later + if p.parseNonOption(s) != nil { + break + } + + continue + } + + var err error + + prefix, optname, islong := stripOptionPrefix(arg) + optname, _, argument := splitOption(prefix, optname, islong) + + if islong { + err = p.parseLong(s, optname, argument) + } else { + err = p.parseShort(s, optname, argument) + } + + if err != nil { + ignoreUnknown := (p.Options & IgnoreUnknown) != None + parseErr := wrapError(err) + + if parseErr.Type != ErrUnknownFlag || (!ignoreUnknown && p.UnknownOptionHandler == nil) { + s.err = parseErr + break + } + + if ignoreUnknown { + s.addArgs(arg) + } else if p.UnknownOptionHandler != nil { + modifiedArgs, err := p.UnknownOptionHandler(optname, strArgument{argument}, s.args) + + if err != nil { + s.err = err + break + } + + s.args = modifiedArgs + } + } + } + + if s.err == nil { + p.eachOption(func(c *Command, g *Group, option *Option) { + if option.preventDefault { + return + } + + option.clearDefault() + }) + + s.checkRequired(p) + } + + var reterr error + + if s.err != nil { + reterr = s.err + } else if len(s.command.commands) != 0 && !s.command.SubcommandsOptional { + reterr = s.estimateCommand() + } else if cmd, ok := s.command.data.(Commander); ok { + if p.CommandHandler != nil { + reterr = p.CommandHandler(cmd, s.retargs) + } else { + reterr = cmd.Execute(s.retargs) + } + } else if p.CommandHandler != nil { + reterr = p.CommandHandler(nil, s.retargs) + } + + if reterr != nil { + var retargs []string + + if ourErr, ok := reterr.(*Error); !ok || ourErr.Type != ErrHelp { + retargs = append([]string{s.arg}, s.args...) + } else { + retargs = s.args + } + + return retargs, p.printError(reterr) + } + + return s.retargs, nil +} + +func (p *parseState) eof() bool { + return len(p.args) == 0 +} + +func (p *parseState) pop() string { + if p.eof() { + return "" + } + + p.arg = p.args[0] + p.args = p.args[1:] + + return p.arg +} + +func (p *parseState) peek() string { + if p.eof() { + return "" + } + + return p.args[0] +} + +func (p *parseState) checkRequired(parser *Parser) error { + c := parser.Command + + var required []*Option + + for c != nil { + c.eachGroup(func(g *Group) { + for _, option := range g.options { + if !option.isSet && option.Required { + required = append(required, option) + } + } + }) + + c = c.Active + } + + if len(required) == 0 { + if len(p.positional) > 0 { + var reqnames []string + + for _, arg := range p.positional { + argRequired := (!arg.isRemaining() && p.command.ArgsRequired) || arg.Required != -1 || arg.RequiredMaximum != -1 + + if !argRequired { + continue + } + + if arg.isRemaining() { + if arg.value.Len() < arg.Required { + var arguments string + + if arg.Required > 1 { + arguments = "arguments, but got only " + fmt.Sprintf("%d", arg.value.Len()) + } else { + arguments = "argument" + } + + reqnames = append(reqnames, "`"+arg.Name+" (at least "+fmt.Sprintf("%d", arg.Required)+" "+arguments+")`") + } else if arg.RequiredMaximum != -1 && arg.value.Len() > arg.RequiredMaximum { + if arg.RequiredMaximum == 0 { + reqnames = append(reqnames, "`"+arg.Name+" (zero arguments)`") + } else { + var arguments string + + if arg.RequiredMaximum > 1 { + arguments = "arguments, but got " + fmt.Sprintf("%d", arg.value.Len()) + } else { + arguments = "argument" + } + + reqnames = append(reqnames, "`"+arg.Name+" (at most "+fmt.Sprintf("%d", arg.RequiredMaximum)+" "+arguments+")`") + } + } + } else { + reqnames = append(reqnames, "`"+arg.Name+"`") + } + } + + if len(reqnames) == 0 { + return nil + } + + var msg string + + if len(reqnames) == 1 { + msg = fmt.Sprintf("the required argument %s was not provided", reqnames[0]) + } else { + msg = fmt.Sprintf("the required arguments %s and %s were not provided", + strings.Join(reqnames[:len(reqnames)-1], ", "), reqnames[len(reqnames)-1]) + } + + p.err = newError(ErrRequired, msg) + return p.err + } + + return nil + } + + names := make([]string, 0, len(required)) + + for _, k := range required { + names = append(names, "`"+k.String()+"'") + } + + sort.Strings(names) + + var msg string + + if len(names) == 1 { + msg = fmt.Sprintf("the required flag %s was not specified", names[0]) + } else { + msg = fmt.Sprintf("the required flags %s and %s were not specified", + strings.Join(names[:len(names)-1], ", "), names[len(names)-1]) + } + + p.err = newError(ErrRequired, msg) + return p.err +} + +func (p *parseState) estimateCommand() error { + commands := p.command.sortedVisibleCommands() + cmdnames := make([]string, len(commands)) + + for i, v := range commands { + cmdnames[i] = v.Name + } + + var msg string + var errtype ErrorType + + if len(p.retargs) != 0 { + c, l := closestChoice(p.retargs[0], cmdnames) + msg = fmt.Sprintf("Unknown command `%s'", p.retargs[0]) + errtype = ErrUnknownCommand + + if float32(l)/float32(len(c)) < 0.5 { + msg = fmt.Sprintf("%s, did you mean `%s'?", msg, c) + } else if len(cmdnames) == 1 { + msg = fmt.Sprintf("%s. You should use the %s command", + msg, + cmdnames[0]) + } else if len(cmdnames) > 1 { + msg = fmt.Sprintf("%s. Please specify one command of: %s or %s", + msg, + strings.Join(cmdnames[:len(cmdnames)-1], ", "), + cmdnames[len(cmdnames)-1]) + } + } else { + errtype = ErrCommandRequired + + if len(cmdnames) == 1 { + msg = fmt.Sprintf("Please specify the %s command", cmdnames[0]) + } else if len(cmdnames) > 1 { + msg = fmt.Sprintf("Please specify one command of: %s or %s", + strings.Join(cmdnames[:len(cmdnames)-1], ", "), + cmdnames[len(cmdnames)-1]) + } + } + + return newError(errtype, msg) +} + +func (p *Parser) parseOption(s *parseState, name string, option *Option, canarg bool, argument *string) (err error) { + if !option.canArgument() { + if argument != nil { + return newErrorf(ErrNoArgumentForBool, "bool flag `%s' cannot have an argument", option) + } + + err = option.set(nil) + } else if argument != nil || (canarg && !s.eof()) { + var arg string + + if argument != nil { + arg = *argument + } else { + arg = s.pop() + + if argumentIsOption(arg) && !(option.isSignedNumber() && len(arg) > 1 && arg[0] == '-' && arg[1] >= '0' && arg[1] <= '9') { + return newErrorf(ErrExpectedArgument, "expected argument for flag `%s', but got option `%s'", option, arg) + } else if p.Options&PassDoubleDash != 0 && arg == "--" { + return newErrorf(ErrExpectedArgument, "expected argument for flag `%s', but got double dash `--'", option) + } + } + + if option.tag.Get("unquote") != "false" { + arg, err = unquoteIfPossible(arg) + } + + if err == nil { + err = option.set(&arg) + } + } else if option.OptionalArgument { + option.empty() + + for _, v := range option.OptionalValue { + err = option.set(&v) + + if err != nil { + break + } + } + } else { + err = newErrorf(ErrExpectedArgument, "expected argument for flag `%s'", option) + } + + if err != nil { + if _, ok := err.(*Error); !ok { + err = newErrorf(ErrMarshal, "invalid argument for flag `%s' (expected %s): %s", + option, + option.value.Type(), + err.Error()) + } + } + + return err +} + +func (p *Parser) parseLong(s *parseState, name string, argument *string) error { + if option := s.lookup.longNames[name]; option != nil { + // Only long options that are required can consume an argument + // from the argument list + canarg := !option.OptionalArgument + + return p.parseOption(s, name, option, canarg, argument) + } + + return newErrorf(ErrUnknownFlag, "unknown flag `%s'", name) +} + +func (p *Parser) splitShortConcatArg(s *parseState, optname string) (string, *string) { + c, n := utf8.DecodeRuneInString(optname) + + if n == len(optname) { + return optname, nil + } + + first := string(c) + + if option := s.lookup.shortNames[first]; option != nil && option.canArgument() { + arg := optname[n:] + return first, &arg + } + + return optname, nil +} + +func (p *Parser) parseShort(s *parseState, optname string, argument *string) error { + if argument == nil { + optname, argument = p.splitShortConcatArg(s, optname) + } + + for i, c := range optname { + shortname := string(c) + + if option := s.lookup.shortNames[shortname]; option != nil { + // Only the last short argument can consume an argument from + // the arguments list, and only if it's non optional + canarg := (i+utf8.RuneLen(c) == len(optname)) && !option.OptionalArgument + + if err := p.parseOption(s, shortname, option, canarg, argument); err != nil { + return err + } + } else { + return newErrorf(ErrUnknownFlag, "unknown flag `%s'", shortname) + } + + // Only the first option can have a concatted argument, so just + // clear argument here + argument = nil + } + + return nil +} + +func (p *parseState) addArgs(args ...string) error { + for len(p.positional) > 0 && len(args) > 0 { + arg := p.positional[0] + + if err := convert(args[0], arg.value, arg.tag); err != nil { + p.err = err + return err + } + + if !arg.isRemaining() { + p.positional = p.positional[1:] + } + + args = args[1:] + } + + p.retargs = append(p.retargs, args...) + return nil +} + +func (p *Parser) parseNonOption(s *parseState) error { + if len(s.positional) > 0 { + return s.addArgs(s.arg) + } + + if len(s.command.commands) > 0 && len(s.retargs) == 0 { + if cmd := s.lookup.commands[s.arg]; cmd != nil { + s.command.Active = cmd + cmd.fillParseState(s) + + return nil + } else if !s.command.SubcommandsOptional { + s.addArgs(s.arg) + return newErrorf(ErrUnknownCommand, "Unknown command `%s'", s.arg) + } + } + + if (p.Options & PassAfterNonOption) != None { + // If PassAfterNonOption is set then all remaining arguments + // are considered positional + if err := s.addArgs(s.arg); err != nil { + return err + } + + if err := s.addArgs(s.args...); err != nil { + return err + } + + s.args = []string{} + } else { + return s.addArgs(s.arg) + } + + return nil +} + +func (p *Parser) showBuiltinHelp() error { + var b bytes.Buffer + + p.WriteHelp(&b) + return newError(ErrHelp, b.String()) +} + +func (p *Parser) printError(err error) error { + if err != nil && (p.Options&PrintErrors) != None { + flagsErr, ok := err.(*Error) + + if ok && flagsErr.Type == ErrHelp { + fmt.Fprintln(os.Stdout, err) + } else { + fmt.Fprintln(os.Stderr, err) + } + } + + return err +} + +func (p *Parser) clearIsSet() { + p.eachCommand(func(c *Command) { + c.eachGroup(func(g *Group) { + for _, option := range g.options { + option.isSet = false + } + }) + }, true) +} diff --git a/vendor/github.com/jessevdk/go-flags/termsize.go b/vendor/github.com/jessevdk/go-flags/termsize.go new file mode 100644 index 00000000..1ca6a850 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/termsize.go @@ -0,0 +1,28 @@ +// +build !windows,!plan9,!solaris,!appengine + +package flags + +import ( + "syscall" + "unsafe" +) + +type winsize struct { + row, col uint16 + xpixel, ypixel uint16 +} + +func getTerminalColumns() int { + ws := winsize{} + + if tIOCGWINSZ != 0 { + syscall.Syscall(syscall.SYS_IOCTL, + uintptr(0), + uintptr(tIOCGWINSZ), + uintptr(unsafe.Pointer(&ws))) + + return int(ws.col) + } + + return 80 +} diff --git a/vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go b/vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go new file mode 100644 index 00000000..3d5385b0 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go @@ -0,0 +1,7 @@ +// +build windows plan9 solaris appengine + +package flags + +func getTerminalColumns() int { + return 80 +} diff --git a/vendor/github.com/jessevdk/go-flags/tiocgwinsz_bsdish.go b/vendor/github.com/jessevdk/go-flags/tiocgwinsz_bsdish.go new file mode 100644 index 00000000..fcc11860 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/tiocgwinsz_bsdish.go @@ -0,0 +1,7 @@ +// +build darwin freebsd netbsd openbsd + +package flags + +const ( + tIOCGWINSZ = 0x40087468 +) diff --git a/vendor/github.com/jessevdk/go-flags/tiocgwinsz_linux.go b/vendor/github.com/jessevdk/go-flags/tiocgwinsz_linux.go new file mode 100644 index 00000000..e3975e28 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/tiocgwinsz_linux.go @@ -0,0 +1,7 @@ +// +build linux + +package flags + +const ( + tIOCGWINSZ = 0x5413 +) diff --git a/vendor/github.com/jessevdk/go-flags/tiocgwinsz_other.go b/vendor/github.com/jessevdk/go-flags/tiocgwinsz_other.go new file mode 100644 index 00000000..30821515 --- /dev/null +++ b/vendor/github.com/jessevdk/go-flags/tiocgwinsz_other.go @@ -0,0 +1,7 @@ +// +build !darwin,!freebsd,!netbsd,!openbsd,!linux + +package flags + +const ( + tIOCGWINSZ = 0 +) diff --git a/vendor/github.com/lucasb-eyer/go-colorful/.gitignore b/vendor/github.com/lucasb-eyer/go-colorful/.gitignore new file mode 100644 index 00000000..47fda8ee --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/.gitignore @@ -0,0 +1,28 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Vim swap files +.*.sw? + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe + +# Code coverage stuff +coverage.out diff --git a/vendor/github.com/lucasb-eyer/go-colorful/.travis.yml b/vendor/github.com/lucasb-eyer/go-colorful/.travis.yml new file mode 100644 index 00000000..ca5aed4d --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/.travis.yml @@ -0,0 +1,8 @@ +language: go +install: + - go get golang.org/x/tools/cmd/cover + - go get gopkg.in/DATA-DOG/go-sqlmock.v1 + - go get github.com/mattn/goveralls +script: + - go test -v -covermode=count -coverprofile=coverage.out + - if [[ "$TRAVIS_PULL_REQUEST" = "false" ]]; then $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN; fi diff --git a/vendor/github.com/lucasb-eyer/go-colorful/LICENSE b/vendor/github.com/lucasb-eyer/go-colorful/LICENSE new file mode 100644 index 00000000..4e402a00 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2013 Lucas Beyer + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/lucasb-eyer/go-colorful/README.md b/vendor/github.com/lucasb-eyer/go-colorful/README.md new file mode 100644 index 00000000..8c89c382 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/README.md @@ -0,0 +1,488 @@ +go-colorful +=========== +A library for playing with colors in go (golang). + +[![Build Status](https://travis-ci.org/lucasb-eyer/go-colorful.svg?branch=master)](https://travis-ci.org/lucasb-eyer/go-colorful) +[![Coverage Status](https://coveralls.io/repos/github/lucasb-eyer/go-colorful/badge.svg?branch=master)](https://coveralls.io/github/lucasb-eyer/go-colorful?branch=master) + +Why? +==== +I love games. I make games. I love detail and I get lost in detail. +One such detail popped up during the development of [Memory Which Does Not Suck](https://github.com/lucasb-eyer/mwdns/), +when we wanted the server to assign the players random colors. Sometimes +two players got very similar colors, which bugged me. The very same evening, +[I want hue](http://tools.medialab.sciences-po.fr/iwanthue/) was the top post +on HackerNews' frontpage and showed me how to Do It Right™. Last but not +least, there was no library for handling color spaces available in go. Colorful +does just that and implements Go's `color.Color` interface. + +What? +===== +Go-Colorful stores colors in RGB and provides methods from converting these to various color-spaces. Currently supported colorspaces are: + +- **RGB:** All three of Red, Green and Blue in [0..1]. +- **HSL:** Hue in [0..360], Saturation and Luminance in [0..1]. For legacy reasons; please forget that it exists. +- **HSV:** Hue in [0..360], Saturation and Value in [0..1]. You're better off using HCL, see below. +- **Hex RGB:** The "internet" color format, as in #FF00FF. +- **Linear RGB:** See [gamma correct rendering](http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/). +- **CIE-XYZ:** CIE's standard color space, almost in [0..1]. +- **CIE-xyY:** encodes chromacity in x and y and luminance in Y, all in [0..1] +- **CIE-L\*a\*b\*:** A *perceptually uniform* color space, i.e. distances are meaningful. L\* in [0..1] and a\*, b\* almost in [-1..1]. +- **CIE-L\*u\*v\*:** Very similar to CIE-L\*a\*b\*, there is [no consensus](http://en.wikipedia.org/wiki/CIELUV#Historical_background) on which one is "better". +- **CIE-L\*C\*h° (HCL):** This is generally the [most useful](http://vis4.net/blog/posts/avoid-equidistant-hsv-colors/) one; CIE-L\*a\*b\* space in polar coordinates, i.e. a *better* HSV. H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*a\*b\*. + +For the colorspaces where it makes sense (XYZ, Lab, Luv, HCl), the +[D65](http://en.wikipedia.org/wiki/Illuminant_D65) is used as reference white +by default but methods for using your own reference white are provided. + +A coordinate being *almost in* a range means that generally it is, but for very +bright colors and depending on the reference white, it might overflow this +range slightly. For example, C\* of #0000ff is 1.338. + +Unit-tests are provided. + +Nice, but what's it useful for? +------------------------------- + +- Converting color spaces. Some people like to do that. +- Blending (interpolating) between colors in a "natural" look by using the right colorspace. +- Generating random colors under some constraints (e.g. colors of the same shade, or shades of one color.) +- Generating gorgeous random palettes with distinct colors of a same temperature. + +What not (yet)? +=============== +There are a few features which are currently missing and might be useful. +I just haven't implemented them yet because I didn't have the need for it. +Pull requests welcome. + +- Sorting colors (potentially using above mentioned distances) + +So which colorspace should I use? +================================= +It depends on what you want to do. I think the folks from *I want hue* are +on-spot when they say that RGB fits to how *screens produce* color, CIE L\*a\*b\* +fits how *humans perceive* color and HCL fits how *humans think* colors. + +Whenever you'd use HSV, rather go for CIE-L\*C\*h°. for fixed lightness L\* and +chroma C\* values, the hue angle h° rotates through colors of the same +perceived brightness and intensity. + +How? +==== + +### Installing +Installing the library is as easy as + +```bash +$ go get github.com/lucasb-eyer/go-colorful +``` + +The package can then be used through an + +```go +import "github.com/lucasb-eyer/go-colorful" +``` + +### Basic usage + +Create a beautiful blue color using different source space: + +```go +// Any of the following should be the same +c := colorful.Color{0.313725, 0.478431, 0.721569} +c, err := colorful.Hex("#517AB8") +if err != nil{ + log.Fatal(err) +} +c = colorful.Hsv(216.0, 0.56, 0.722) +c = colorful.Xyz(0.189165, 0.190837, 0.480248) +c = colorful.Xyy(0.219895, 0.221839, 0.190837) +c = colorful.Lab(0.507850, 0.040585,-0.370945) +c = colorful.Luv(0.507849,-0.194172,-0.567924) +c = colorful.Hcl(276.2440, 0.373160, 0.507849) +fmt.Printf("RGB values: %v, %v, %v", c.R, c.G, c.B) +``` + +And then converting this color back into various color spaces: + +```go +hex := c.Hex() +h, s, v := c.Hsv() +x, y, z := c.Xyz() +x, y, Y := c.Xyy() +l, a, b := c.Lab() +l, u, v := c.Luv() +h, c, l := c.Hcl() +``` + +Note that, because of Go's unfortunate choice of requiring an initial uppercase, +the name of the functions relating to the xyY space are just off. If you have +any good suggestion, please open an issue. (I don't consider XyY good.) + +### The `color.Color` interface +Because a `colorful.Color` implements Go's `color.Color` interface (found in the +`image/color` package), it can be used anywhere that expects a `color.Color`. + +Furthermore, you can convert anything that implements the `color.Color` interface +into a `colorful.Color` using the `MakeColor` function: + +```go +c, ok := colorful.MakeColor(color.Gray16{12345}) +``` + +**Caveat:** Be aware that this latter conversion (using `MakeColor`) hits a +corner-case when alpha is exactly zero. Because `color.Color` uses pre-multiplied +alpha colors, this means the RGB values are lost (set to 0) and it's impossible +to recover them. In such a case `MakeColor` will return `false` as its second value. + +### Comparing colors +In the RGB color space, the Euclidian distance between colors *doesn't* correspond +to visual/perceptual distance. This means that two pairs of colors which have the +same distance in RGB space can look much further apart. This is fixed by the +CIE-L\*a\*b\*, CIE-L\*u\*v\* and CIE-L\*C\*h° color spaces. +Thus you should only compare colors in any of these space. +(Note that the distance in CIE-L\*a\*b\* and CIE-L\*C\*h° are the same, since it's the same space but in cylindrical coordinates) + +![Color distance comparison](doc/colordist/colordist.png) + +The two colors shown on the top look much more different than the two shown on +the bottom. Still, in RGB space, their distance is the same. +Here is a little example program which shows the distances between the top two +and bottom two colors in RGB, CIE-L\*a\*b\* and CIE-L\*u\*v\* space. You can find it in `doc/colordist/colordist.go`. + +```go +package main + +import "fmt" +import "github.com/lucasb-eyer/go-colorful" + +func main() { + c1a := colorful.Color{150.0/255.0, 10.0/255.0, 150.0/255.0} + c1b := colorful.Color{ 53.0/255.0, 10.0/255.0, 150.0/255.0} + c2a := colorful.Color{10.0/255.0, 150.0/255.0, 50.0/255.0} + c2b := colorful.Color{99.9/255.0, 150.0/255.0, 10.0/255.0} + + fmt.Printf("DistanceRgb: c1: %v\tand c2: %v\n", c1a.DistanceRgb(c1b), c2a.DistanceRgb(c2b)) + fmt.Printf("DistanceLab: c1: %v\tand c2: %v\n", c1a.DistanceLab(c1b), c2a.DistanceLab(c2b)) + fmt.Printf("DistanceLuv: c1: %v\tand c2: %v\n", c1a.DistanceLuv(c1b), c2a.DistanceLuv(c2b)) + fmt.Printf("DistanceCIE76: c1: %v\tand c2: %v\n", c1a.DistanceCIE76(c1b), c2a.DistanceCIE76(c2b)) + fmt.Printf("DistanceCIE94: c1: %v\tand c2: %v\n", c1a.DistanceCIE94(c1b), c2a.DistanceCIE94(c2b)) +} +``` + +Running the above program shows that you should always prefer any of the CIE distances: + +```bash +$ go run colordist.go +DistanceRgb: c1: 0.3803921568627451 and c2: 0.3858713931171159 +DistanceLab: c1: 0.3204845831279805 and c2: 0.2439715175856528 +DistanceLuv: c1: 0.5134369614199698 and c2: 0.25686928398606323 +DistanceCIE76: c1: 0.3204845831279805 and c2: 0.2439715175856528 +DistanceCIE94: c1: 0.19799168128511327 and c2: 0.12207136371167401 +``` + +It also shows that `DistanceLab` is more formally known as `DistanceCIE76` and +has been superseded by the slightly more accurate, but much more expensive +`DistanceCIE94`. + +Note that `AlmostEqualRgb` is provided mainly for (unit-)testing purposes. Use +it only if you really know what you're doing. It will eat your cat. + +### Blending colors +Blending is highly connected to distance, since it basically "walks through" the +colorspace thus, if the colorspace maps distances well, the walk is "smooth". + +Colorful comes with blending functions in RGB, HSV and any of the LAB spaces. +Of course, you'd rather want to use the blending functions of the LAB spaces since +these spaces map distances well but, just in case, here is an example showing +you how the blendings (`#fdffcc` to `#242a42`) are done in the various spaces: + +![Blending colors in different spaces.](doc/colorblend/colorblend.png) + +What you see is that HSV is really bad: it adds some green, which is not present +in the original colors at all! RGB is much better, but it stays light a little +too long. LUV and LAB both hit the right lightness but LAB has a little more +color. HCL works in the same vein as HSV (both cylindrical interpolations) but +it does it right in that there is no green appearing and the lighthness changes +in a linear manner. + +While this seems all good, you need to know one thing: When interpolating in any +of the CIE color spaces, you might get invalid RGB colors! This is important if +the starting and ending colors are user-input or random. An example of where this +happens is when blending between `#eeef61` and `#1e3140`: + +![Invalid RGB colors may crop up when blending in CIE spaces.](doc/colorblend/invalid.png) + +You can test whether a color is a valid RGB color by calling the `IsValid` method +and indeed, calling IsValid will return false for the redish colors on the bottom. +One way to "fix" this is to get a valid color close to the invalid one by calling +`Clamped`, which always returns a nearby valid color. Doing this, we get the +following result, which is satisfactory: + +![Fixing invalid RGB colors by clamping them to the valid range.](doc/colorblend/clamped.png) + +The following is the code creating the above three images; it can be found in `doc/colorblend/colorblend.go` + +```go +package main + +import "fmt" +import "github.com/lucasb-eyer/go-colorful" +import "image" +import "image/draw" +import "image/png" +import "os" + +func main() { + blocks := 10 + blockw := 40 + img := image.NewRGBA(image.Rect(0,0,blocks*blockw,200)) + + c1, _ := colorful.Hex("#fdffcc") + c2, _ := colorful.Hex("#242a42") + + // Use these colors to get invalid RGB in the gradient. + //c1, _ := colorful.Hex("#EEEF61") + //c2, _ := colorful.Hex("#1E3140") + + for i := 0 ; i < blocks ; i++ { + draw.Draw(img, image.Rect(i*blockw, 0,(i+1)*blockw, 40), &image.Uniform{c1.BlendHsv(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src) + draw.Draw(img, image.Rect(i*blockw, 40,(i+1)*blockw, 80), &image.Uniform{c1.BlendLuv(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src) + draw.Draw(img, image.Rect(i*blockw, 80,(i+1)*blockw,120), &image.Uniform{c1.BlendRgb(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src) + draw.Draw(img, image.Rect(i*blockw,120,(i+1)*blockw,160), &image.Uniform{c1.BlendLab(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src) + draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src) + + // This can be used to "fix" invalid colors in the gradient. + //draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1)).Clamped()}, image.ZP, draw.Src) + } + + toimg, err := os.Create("colorblend.png") + if err != nil { + fmt.Printf("Error: %v", err) + return + } + defer toimg.Close() + + png.Encode(toimg, img) +} +``` + +#### Generating color gradients +A very common reason to blend colors is creating gradients. There is an example +program in [doc/gradientgen.go](doc/gradientgen/gradientgen.go); it doesn't use any API +which hasn't been used in the previous example code, so I won't bother pasting +the code in here. Just look at that gorgeous gradient it generated in HCL space: + +!["Spectral" colorbrewer gradient in HCL space.](doc/gradientgen/gradientgen.png) + +### Getting random colors +It is sometimes necessary to generate random colors. You could simply do this +on your own by generating colors with random values. By restricting the random +values to a range smaller than [0..1] and using a space such as CIE-H\*C\*l° or +HSV, you can generate both random shades of a color or random colors of a +lightness: + +```go +random_blue := colorful.Hcl(180.0+rand.Float64()*50.0, 0.2+rand.Float64()*0.8, 0.3+rand.Float64()*0.7) +random_dark := colorful.Hcl(rand.Float64()*360.0, rand.Float64(), rand.Float64()*0.4) +random_light := colorful.Hcl(rand.Float64()*360.0, rand.Float64(), 0.6+rand.Float64()*0.4) +``` + +Since getting random "warm" and "happy" colors is quite a common task, there +are some helper functions: + +```go +colorful.WarmColor() +colorful.HappyColor() +colorful.FastWarmColor() +colorful.FastHappyColor() +``` + +The ones prefixed by `Fast` are faster but less coherent since they use the HSV +space as opposed to the regular ones which use CIE-L\*C\*h° space. The +following picture shows the warm colors in the top two rows and happy colors +in the bottom two rows. Within these, the first is the regular one and the +second is the fast one. + +![Warm, fast warm, happy and fast happy random colors, respectively.](doc/colorgens/colorgens.png) + +Don't forget to initialize the random seed! You can see the code used for +generating this picture in `doc/colorgens/colorgens.go`. + +### Getting random palettes +As soon as you need to generate more than one random color, you probably want +them to be distinguishible. Playing against an opponent which has almost the +same blue as I do is not fun. This is where random palettes can help. + +These palettes are generated using an algorithm which ensures that all colors +on the palette are as distinguishible as possible. Again, there is a `Fast` +method which works in HSV and is less perceptually uniform and a non-`Fast` +method which works in CIE spaces. For more theory on `SoftPalette`, check out +[I want hue](http://tools.medialab.sciences-po.fr/iwanthue/theory.php). Yet +again, there is a `Happy` and a `Warm` version, which do what you expect, but +now there is an additional `Soft` version, which is more configurable: you can +give a constraint on the color space in order to get colors within a certain *feel*. + +Let's start with the simple methods first, all they take is the amount of +colors to generate, which could, for example, be the player count. They return +an array of `colorful.Color` objects: + +```go +pal1, err1 := colorful.WarmPalette(10) +pal2 := colorful.FastWarmPalette(10) +pal3, err3 := colorful.HappyPalette(10) +pal4 := colorful.FastHappyPalette(10) +pal5, err5 := colorful.SoftPalette(10) +``` + +Note that the non-fast methods *may* fail if you ask for way too many colors. +Let's move on to the advanced one, namely `SoftPaletteEx`. Besides the color +count, this function takes a `SoftPaletteSettings` object as argument. The +interesting part here is its `CheckColor` member, which is a boolean function +taking three floating points as arguments: `l`, `a` and `b`. This function +should return `true` for colors which lie within the region you want and `false` +otherwise. The other members are `Iteration`, which should be within [5..100] +where higher means slower but more exact palette, and `ManySamples` which you +should set to `true` in case your `CheckColor` constraint rejects a large part +of the color space. + +For example, to create a palette of 10 brownish colors, you'd call it like this: + +```go +func isbrowny(l, a, b float64) bool { + h, c, L := colorful.LabToHcl(l, a, b) + return 10.0 < h && h < 50.0 && 0.1 < c && c < 0.5 && L < 0.5 +} +// Since the above function is pretty restrictive, we set ManySamples to true. +brownies := colorful.SoftPaletteEx(10, colorful.SoftPaletteSettings{isbrowny, 50, true}) +``` + +The following picture shows the palettes generated by all of these methods +(sourcecode in `doc/palettegens/palettegens.go`), in the order they were presented, i.e. +from top to bottom: `Warm`, `FastWarm`, `Happy`, `FastHappy`, `Soft`, +`SoftEx(isbrowny)`. All of them contain some randomness, so YMMV. + +![All example palettes](doc/palettegens/palettegens.png) + +### Sorting colors +TODO: Sort using dist fn. + +### Using linear RGB for computations +There are two methods for transforming RGB<->Linear RGB: a fast and almost precise one, +and a slow and precise one. + +```go +r, g, b := colorful.Hex("#FF0000").FastLinearRgb() +``` + +TODO: describe some more. + +### Want to use some other reference point? + +```go +c := colorful.LabWhiteRef(0.507850, 0.040585,-0.370945, colorful.D50) +l, a, b := c.LabWhiteRef(colorful.D50) +``` + +### Reading and writing colors from databases + +The type `HexColor` makes it easy to store colors as strings in a database. It +implements the [https://godoc.org/database/sql#Scanner](database/sql.Scanner) +and [database/sql/driver.Value](https://godoc.org/database/sql/driver.Value) +interfaces which provide automatic type conversion. + +Example: + +```go +var hc HexColor +_, err := db.QueryRow("SELECT '#ff0000';").Scan(&hc) +// hc == HexColor{R: 1, G: 0, B: 0}; err == nil +``` + +FAQ +=== + +### Q: I get all f!@#ed up values! Your library sucks! +A: You probably provided values in the wrong range. For example, RGB values are +expected to reside between 0 and 1, *not* between 0 and 255. Normalize your colors. + +### Q: Lab/Luv/HCl seem broken! Your library sucks! +They look like this: + + + +A: You're likely trying to generate and display colors that can't be represented by RGB, +and thus monitors. When you're trying to convert, say, `HCL(190.0, 1.0, 1.0).RGB255()`, +you're asking for RGB values of `(-2105.254 300.680 286.185)`, which clearly don't exist, +and the `RGB255` function just casts these numbers to `uint8`, creating wrap-around and +what looks like a completely broken gradient. What you want to do, is either use more +reasonable values of colors which actually exist in RGB, or just `Clamp()` the resulting +color to its nearest existing one, living with the consequences: +`HCL(190.0, 1.0, 1.0).Clamp().RGB255()`. It will look something like this: + + + +[Here's an issue going in-depth about this](https://github.com/lucasb-eyer/go-colorful/issues/14), +as well as [my answer](https://github.com/lucasb-eyer/go-colorful/issues/14#issuecomment-324205385), +both with code and pretty pictures. Also note that this was somewhat covered above in the +["Blending colors" section](https://github.com/lucasb-eyer/go-colorful#blending-colors). + +### Q: In a tight loop, conversion to Lab/Luv/HCl/... are slooooow! +A: Yes, they are. +This library aims for correctness, readability, and modularity; it wasn't written with speed in mind. +A large part of the slowness comes from these conversions going through `LinearRgb` which uses powers. +I implemented a fast approximation to `LinearRgb` called `FastLinearRgb` by using Taylor approximations. +The approximation is roughly 5x faster and precise up to roughly 0.5%, +the major caveat being that if the input values are outside the range 0-1, accuracy drops dramatically. +You can use these in your conversions as follows: + +```go +col := // Get your color somehow +l, a, b := XyzToLab(LinearRgbToXyz(col.LinearRgb())) +``` + +If you need faster versions of `Distance*` and `Blend*` that make use of this fast approximation, +feel free to implement them and open a pull-request, I'll happily accept. + +The derivation of these functions can be followed in [this Jupyter notebook](doc/LinearRGB Approximations.ipynb). +Here's the main figure showing the approximation quality: + +![approximation quality](doc/approx-quality.png) + +More speed could be gained by using SIMD instructions in many places. +You can also get more speed for specific conversions by approximating the full conversion function, +but that is outside the scope of this library. +Thanks to [@ZirconiumX](https://github.com/ZirconiumX) for starting this investigation, +see [issue #18](https://github.com/lucasb-eyer/go-colorful/issues/18) for details. + +### Q: Why would `MakeColor` ever fail!? +A: `MakeColor` fails when the alpha channel is zero. In that case, the +conversion is undefined. See [issue 21](https://github.com/lucasb-eyer/go-colorful/issues/21) +as well as the short caveat note in the ["The `color.Color` interface"](README.md#the-colorcolor-interface) +section above. + +Who? +==== + +This library has been developed by Lucas Beyer with contributions from +Bastien Dejean (@baskerville), Phil Kulak (@pkulak) and Christian Muehlhaeuser (@muesli). + +Release Notes +============= + +### Version 1.0 +- API Breaking change in `MakeColor`: instead of `panic`ing when alpha is zero, it now returns a secondary, boolean return value indicating success. See [the color.Color interface](https://github.com/lucasb-eyer/go-colorful#the-colorcolor-interface) section and [this FAQ entry](https://github.com/lucasb-eyer/go-colorful#q-why-would-makecolor-ever-fail) for details. + +### Version 0.9 +- Initial version number after having ignored versioning for a long time :) + +License: MIT +============ +Copyright (c) 2013 Lucas Beyer + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go b/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go new file mode 100644 index 00000000..2e2e49e1 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go @@ -0,0 +1,55 @@ +// Various ways to generate single random colors + +package colorful + +import ( + "math/rand" +) + +// Creates a random dark, "warm" color through a restricted HSV space. +func FastWarmColor() Color { + return Hsv( + rand.Float64()*360.0, + 0.5+rand.Float64()*0.3, + 0.3+rand.Float64()*0.3) +} + +// Creates a random dark, "warm" color through restricted HCL space. +// This is slower than FastWarmColor but will likely give you colors which have +// the same "warmness" if you run it many times. +func WarmColor() (c Color) { + for c = randomWarm(); !c.IsValid(); c = randomWarm() { + } + return +} + +func randomWarm() Color { + return Hcl( + rand.Float64()*360.0, + 0.1+rand.Float64()*0.3, + 0.2+rand.Float64()*0.3) +} + +// Creates a random bright, "pimpy" color through a restricted HSV space. +func FastHappyColor() Color { + return Hsv( + rand.Float64()*360.0, + 0.7+rand.Float64()*0.3, + 0.6+rand.Float64()*0.3) +} + +// Creates a random bright, "pimpy" color through restricted HCL space. +// This is slower than FastHappyColor but will likely give you colors which +// have the same "brightness" if you run it many times. +func HappyColor() (c Color) { + for c = randomPimp(); !c.IsValid(); c = randomPimp() { + } + return +} + +func randomPimp() Color { + return Hcl( + rand.Float64()*360.0, + 0.5+rand.Float64()*0.3, + 0.5+rand.Float64()*0.3) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/colors.go b/vendor/github.com/lucasb-eyer/go-colorful/colors.go new file mode 100644 index 00000000..febf94c7 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/colors.go @@ -0,0 +1,819 @@ +// The colorful package provides all kinds of functions for working with colors. +package colorful + +import ( + "fmt" + "image/color" + "math" +) + +// A color is stored internally using sRGB (standard RGB) values in the range 0-1 +type Color struct { + R, G, B float64 +} + +// Implement the Go color.Color interface. +func (col Color) RGBA() (r, g, b, a uint32) { + r = uint32(col.R*65535.0 + 0.5) + g = uint32(col.G*65535.0 + 0.5) + b = uint32(col.B*65535.0 + 0.5) + a = 0xFFFF + return +} + +// Constructs a colorful.Color from something implementing color.Color +func MakeColor(col color.Color) (Color, bool) { + r, g, b, a := col.RGBA() + if a == 0 { + return Color{0, 0, 0}, false + } + + // Since color.Color is alpha pre-multiplied, we need to divide the + // RGB values by alpha again in order to get back the original RGB. + r *= 0xffff + r /= a + g *= 0xffff + g /= a + b *= 0xffff + b /= a + + return Color{float64(r) / 65535.0, float64(g) / 65535.0, float64(b) / 65535.0}, true +} + +// Might come in handy sometimes to reduce boilerplate code. +func (col Color) RGB255() (r, g, b uint8) { + r = uint8(col.R*255.0 + 0.5) + g = uint8(col.G*255.0 + 0.5) + b = uint8(col.B*255.0 + 0.5) + return +} + +// This is the tolerance used when comparing colors using AlmostEqualRgb. +const Delta = 1.0 / 255.0 + +// This is the default reference white point. +var D65 = [3]float64{0.95047, 1.00000, 1.08883} + +// And another one. +var D50 = [3]float64{0.96422, 1.00000, 0.82521} + +// Checks whether the color exists in RGB space, i.e. all values are in [0..1] +func (c Color) IsValid() bool { + return 0.0 <= c.R && c.R <= 1.0 && + 0.0 <= c.G && c.G <= 1.0 && + 0.0 <= c.B && c.B <= 1.0 +} + +func clamp01(v float64) float64 { + return math.Max(0.0, math.Min(v, 1.0)) +} + +// Returns Clamps the color into valid range, clamping each value to [0..1] +// If the color is valid already, this is a no-op. +func (c Color) Clamped() Color { + return Color{clamp01(c.R), clamp01(c.G), clamp01(c.B)} +} + +func sq(v float64) float64 { + return v * v +} + +func cub(v float64) float64 { + return v * v * v +} + +// DistanceRgb computes the distance between two colors in RGB space. +// This is not a good measure! Rather do it in Lab space. +func (c1 Color) DistanceRgb(c2 Color) float64 { + return math.Sqrt(sq(c1.R-c2.R) + sq(c1.G-c2.G) + sq(c1.B-c2.B)) +} + +// Check for equality between colors within the tolerance Delta (1/255). +func (c1 Color) AlmostEqualRgb(c2 Color) bool { + return math.Abs(c1.R-c2.R)+ + math.Abs(c1.G-c2.G)+ + math.Abs(c1.B-c2.B) < 3.0*Delta +} + +// You don't really want to use this, do you? Go for BlendLab, BlendLuv or BlendHcl. +func (c1 Color) BlendRgb(c2 Color, t float64) Color { + return Color{c1.R + t*(c2.R-c1.R), + c1.G + t*(c2.G-c1.G), + c1.B + t*(c2.B-c1.B)} +} + +// Utility used by Hxx color-spaces for interpolating between two angles in [0,360]. +func interp_angle(a0, a1, t float64) float64 { + // Based on the answer here: http://stackoverflow.com/a/14498790/2366315 + // With potential proof that it works here: http://math.stackexchange.com/a/2144499 + delta := math.Mod(math.Mod(a1-a0, 360.0)+540, 360.0) - 180.0 + return math.Mod(a0+t*delta+360.0, 360.0) +} + +/// HSV /// +/////////// +// From http://en.wikipedia.org/wiki/HSL_and_HSV +// Note that h is in [0..360] and s,v in [0..1] + +// Hsv returns the Hue [0..360], Saturation and Value [0..1] of the color. +func (col Color) Hsv() (h, s, v float64) { + min := math.Min(math.Min(col.R, col.G), col.B) + v = math.Max(math.Max(col.R, col.G), col.B) + C := v - min + + s = 0.0 + if v != 0.0 { + s = C / v + } + + h = 0.0 // We use 0 instead of undefined as in wp. + if min != v { + if v == col.R { + h = math.Mod((col.G-col.B)/C, 6.0) + } + if v == col.G { + h = (col.B-col.R)/C + 2.0 + } + if v == col.B { + h = (col.R-col.G)/C + 4.0 + } + h *= 60.0 + if h < 0.0 { + h += 360.0 + } + } + return +} + +// Hsv creates a new Color given a Hue in [0..360], a Saturation and a Value in [0..1] +func Hsv(H, S, V float64) Color { + Hp := H / 60.0 + C := V * S + X := C * (1.0 - math.Abs(math.Mod(Hp, 2.0)-1.0)) + + m := V - C + r, g, b := 0.0, 0.0, 0.0 + + switch { + case 0.0 <= Hp && Hp < 1.0: + r = C + g = X + case 1.0 <= Hp && Hp < 2.0: + r = X + g = C + case 2.0 <= Hp && Hp < 3.0: + g = C + b = X + case 3.0 <= Hp && Hp < 4.0: + g = X + b = C + case 4.0 <= Hp && Hp < 5.0: + r = X + b = C + case 5.0 <= Hp && Hp < 6.0: + r = C + b = X + } + + return Color{m + r, m + g, m + b} +} + +// You don't really want to use this, do you? Go for BlendLab, BlendLuv or BlendHcl. +func (c1 Color) BlendHsv(c2 Color, t float64) Color { + h1, s1, v1 := c1.Hsv() + h2, s2, v2 := c2.Hsv() + + // We know that h are both in [0..360] + return Hsv(interp_angle(h1, h2, t), s1+t*(s2-s1), v1+t*(v2-v1)) +} + +/// HSL /// +/////////// + +// Hsl returns the Hue [0..360], Saturation [0..1], and Luminance (lightness) [0..1] of the color. +func (col Color) Hsl() (h, s, l float64) { + min := math.Min(math.Min(col.R, col.G), col.B) + max := math.Max(math.Max(col.R, col.G), col.B) + + l = (max + min) / 2 + + if min == max { + s = 0 + h = 0 + } else { + if l < 0.5 { + s = (max - min) / (max + min) + } else { + s = (max - min) / (2.0 - max - min) + } + + if max == col.R { + h = (col.G - col.B) / (max - min) + } else if max == col.G { + h = 2.0 + (col.B-col.R)/(max-min) + } else { + h = 4.0 + (col.R-col.G)/(max-min) + } + + h *= 60 + + if h < 0 { + h += 360 + } + } + + return +} + +// Hsl creates a new Color given a Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1] +func Hsl(h, s, l float64) Color { + if s == 0 { + return Color{l, l, l} + } + + var r, g, b float64 + var t1 float64 + var t2 float64 + var tr float64 + var tg float64 + var tb float64 + + if l < 0.5 { + t1 = l * (1.0 + s) + } else { + t1 = l + s - l*s + } + + t2 = 2*l - t1 + h = h / 360 + tr = h + 1.0/3.0 + tg = h + tb = h - 1.0/3.0 + + if tr < 0 { + tr++ + } + if tr > 1 { + tr-- + } + if tg < 0 { + tg++ + } + if tg > 1 { + tg-- + } + if tb < 0 { + tb++ + } + if tb > 1 { + tb-- + } + + // Red + if 6*tr < 1 { + r = t2 + (t1-t2)*6*tr + } else if 2*tr < 1 { + r = t1 + } else if 3*tr < 2 { + r = t2 + (t1-t2)*(2.0/3.0-tr)*6 + } else { + r = t2 + } + + // Green + if 6*tg < 1 { + g = t2 + (t1-t2)*6*tg + } else if 2*tg < 1 { + g = t1 + } else if 3*tg < 2 { + g = t2 + (t1-t2)*(2.0/3.0-tg)*6 + } else { + g = t2 + } + + // Blue + if 6*tb < 1 { + b = t2 + (t1-t2)*6*tb + } else if 2*tb < 1 { + b = t1 + } else if 3*tb < 2 { + b = t2 + (t1-t2)*(2.0/3.0-tb)*6 + } else { + b = t2 + } + + return Color{r, g, b} +} + +/// Hex /// +/////////// + +// Hex returns the hex "html" representation of the color, as in #ff0080. +func (col Color) Hex() string { + // Add 0.5 for rounding + return fmt.Sprintf("#%02x%02x%02x", uint8(col.R*255.0+0.5), uint8(col.G*255.0+0.5), uint8(col.B*255.0+0.5)) +} + +// Hex parses a "html" hex color-string, either in the 3 "#f0c" or 6 "#ff1034" digits form. +func Hex(scol string) (Color, error) { + format := "#%02x%02x%02x" + factor := 1.0 / 255.0 + if len(scol) == 4 { + format = "#%1x%1x%1x" + factor = 1.0 / 15.0 + } + + var r, g, b uint8 + n, err := fmt.Sscanf(scol, format, &r, &g, &b) + if err != nil { + return Color{}, err + } + if n != 3 { + return Color{}, fmt.Errorf("color: %v is not a hex-color", scol) + } + + return Color{float64(r) * factor, float64(g) * factor, float64(b) * factor}, nil +} + +/// Linear /// +////////////// +// http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/ +// http://www.brucelindbloom.com/Eqn_RGB_to_XYZ.html + +func linearize(v float64) float64 { + if v <= 0.04045 { + return v / 12.92 + } + return math.Pow((v+0.055)/1.055, 2.4) +} + +// LinearRgb converts the color into the linear RGB space (see http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/). +func (col Color) LinearRgb() (r, g, b float64) { + r = linearize(col.R) + g = linearize(col.G) + b = linearize(col.B) + return +} + +// A much faster and still quite precise linearization using a 6th-order Taylor approximation. +// See the accompanying Jupyter notebook for derivation of the constants. +func linearize_fast(v float64) float64 { + v1 := v - 0.5 + v2 := v1 * v1 + v3 := v2 * v1 + v4 := v2 * v2 + //v5 := v3*v2 + return -0.248750514614486 + 0.925583310193438*v + 1.16740237321695*v2 + 0.280457026598666*v3 - 0.0757991963780179*v4 //+ 0.0437040411548932*v5 +} + +// FastLinearRgb is much faster than and almost as accurate as LinearRgb. +// BUT it is important to NOTE that they only produce good results for valid colors r,g,b in [0,1]. +func (col Color) FastLinearRgb() (r, g, b float64) { + r = linearize_fast(col.R) + g = linearize_fast(col.G) + b = linearize_fast(col.B) + return +} + +func delinearize(v float64) float64 { + if v <= 0.0031308 { + return 12.92 * v + } + return 1.055*math.Pow(v, 1.0/2.4) - 0.055 +} + +// LinearRgb creates an sRGB color out of the given linear RGB color (see http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/). +func LinearRgb(r, g, b float64) Color { + return Color{delinearize(r), delinearize(g), delinearize(b)} +} + +func delinearize_fast(v float64) float64 { + // This function (fractional root) is much harder to linearize, so we need to split. + if v > 0.2 { + v1 := v - 0.6 + v2 := v1 * v1 + v3 := v2 * v1 + v4 := v2 * v2 + v5 := v3 * v2 + return 0.442430344268235 + 0.592178981271708*v - 0.287864782562636*v2 + 0.253214392068985*v3 - 0.272557158129811*v4 + 0.325554383321718*v5 + } else if v > 0.03 { + v1 := v - 0.115 + v2 := v1 * v1 + v3 := v2 * v1 + v4 := v2 * v2 + v5 := v3 * v2 + return 0.194915592891669 + 1.55227076330229*v - 3.93691860257828*v2 + 18.0679839248761*v3 - 101.468750302746*v4 + 632.341487393927*v5 + } else { + v1 := v - 0.015 + v2 := v1 * v1 + v3 := v2 * v1 + v4 := v2 * v2 + v5 := v3 * v2 + // You can clearly see from the involved constants that the low-end is highly nonlinear. + return 0.0519565234928877 + 5.09316778537561*v - 99.0338180489702*v2 + 3484.52322764895*v3 - 150028.083412663*v4 + 7168008.42971613*v5 + } +} + +// FastLinearRgb is much faster than and almost as accurate as LinearRgb. +// BUT it is important to NOTE that they only produce good results for valid inputs r,g,b in [0,1]. +func FastLinearRgb(r, g, b float64) Color { + return Color{delinearize_fast(r), delinearize_fast(g), delinearize_fast(b)} +} + +// XyzToLinearRgb converts from CIE XYZ-space to Linear RGB space. +func XyzToLinearRgb(x, y, z float64) (r, g, b float64) { + r = 3.2404542*x - 1.5371385*y - 0.4985314*z + g = -0.9692660*x + 1.8760108*y + 0.0415560*z + b = 0.0556434*x - 0.2040259*y + 1.0572252*z + return +} + +func LinearRgbToXyz(r, g, b float64) (x, y, z float64) { + x = 0.4124564*r + 0.3575761*g + 0.1804375*b + y = 0.2126729*r + 0.7151522*g + 0.0721750*b + z = 0.0193339*r + 0.1191920*g + 0.9503041*b + return +} + +/// XYZ /// +/////////// +// http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/ + +func (col Color) Xyz() (x, y, z float64) { + return LinearRgbToXyz(col.LinearRgb()) +} + +func Xyz(x, y, z float64) Color { + return LinearRgb(XyzToLinearRgb(x, y, z)) +} + +/// xyY /// +/////////// +// http://www.brucelindbloom.com/Eqn_XYZ_to_xyY.html + +// Well, the name is bad, since it's xyY but Golang needs me to start with a +// capital letter to make the method public. +func XyzToXyy(X, Y, Z float64) (x, y, Yout float64) { + return XyzToXyyWhiteRef(X, Y, Z, D65) +} + +func XyzToXyyWhiteRef(X, Y, Z float64, wref [3]float64) (x, y, Yout float64) { + Yout = Y + N := X + Y + Z + if math.Abs(N) < 1e-14 { + // When we have black, Bruce Lindbloom recommends to use + // the reference white's chromacity for x and y. + x = wref[0] / (wref[0] + wref[1] + wref[2]) + y = wref[1] / (wref[0] + wref[1] + wref[2]) + } else { + x = X / N + y = Y / N + } + return +} + +func XyyToXyz(x, y, Y float64) (X, Yout, Z float64) { + Yout = Y + + if -1e-14 < y && y < 1e-14 { + X = 0.0 + Z = 0.0 + } else { + X = Y / y * x + Z = Y / y * (1.0 - x - y) + } + + return +} + +// Converts the given color to CIE xyY space using D65 as reference white. +// (Note that the reference white is only used for black input.) +// x, y and Y are in [0..1] +func (col Color) Xyy() (x, y, Y float64) { + return XyzToXyy(col.Xyz()) +} + +// Converts the given color to CIE xyY space, taking into account +// a given reference white. (i.e. the monitor's white) +// (Note that the reference white is only used for black input.) +// x, y and Y are in [0..1] +func (col Color) XyyWhiteRef(wref [3]float64) (x, y, Y float64) { + X, Y2, Z := col.Xyz() + return XyzToXyyWhiteRef(X, Y2, Z, wref) +} + +// Generates a color by using data given in CIE xyY space. +// x, y and Y are in [0..1] +func Xyy(x, y, Y float64) Color { + return Xyz(XyyToXyz(x, y, Y)) +} + +/// L*a*b* /// +////////////// +// http://en.wikipedia.org/wiki/Lab_color_space#CIELAB-CIEXYZ_conversions +// For L*a*b*, we need to L*a*b*<->XYZ->RGB and the first one is device dependent. + +func lab_f(t float64) float64 { + if t > 6.0/29.0*6.0/29.0*6.0/29.0 { + return math.Cbrt(t) + } + return t/3.0*29.0/6.0*29.0/6.0 + 4.0/29.0 +} + +func XyzToLab(x, y, z float64) (l, a, b float64) { + // Use D65 white as reference point by default. + // http://www.fredmiranda.com/forum/topic/1035332 + // http://en.wikipedia.org/wiki/Standard_illuminant + return XyzToLabWhiteRef(x, y, z, D65) +} + +func XyzToLabWhiteRef(x, y, z float64, wref [3]float64) (l, a, b float64) { + fy := lab_f(y / wref[1]) + l = 1.16*fy - 0.16 + a = 5.0 * (lab_f(x/wref[0]) - fy) + b = 2.0 * (fy - lab_f(z/wref[2])) + return +} + +func lab_finv(t float64) float64 { + if t > 6.0/29.0 { + return t * t * t + } + return 3.0 * 6.0 / 29.0 * 6.0 / 29.0 * (t - 4.0/29.0) +} + +func LabToXyz(l, a, b float64) (x, y, z float64) { + // D65 white (see above). + return LabToXyzWhiteRef(l, a, b, D65) +} + +func LabToXyzWhiteRef(l, a, b float64, wref [3]float64) (x, y, z float64) { + l2 := (l + 0.16) / 1.16 + x = wref[0] * lab_finv(l2+a/5.0) + y = wref[1] * lab_finv(l2) + z = wref[2] * lab_finv(l2-b/2.0) + return +} + +// Converts the given color to CIE L*a*b* space using D65 as reference white. +func (col Color) Lab() (l, a, b float64) { + return XyzToLab(col.Xyz()) +} + +// Converts the given color to CIE L*a*b* space, taking into account +// a given reference white. (i.e. the monitor's white) +func (col Color) LabWhiteRef(wref [3]float64) (l, a, b float64) { + x, y, z := col.Xyz() + return XyzToLabWhiteRef(x, y, z, wref) +} + +// Generates a color by using data given in CIE L*a*b* space using D65 as reference white. +// WARNING: many combinations of `l`, `a`, and `b` values do not have corresponding +// valid RGB values, check the FAQ in the README if you're unsure. +func Lab(l, a, b float64) Color { + return Xyz(LabToXyz(l, a, b)) +} + +// Generates a color by using data given in CIE L*a*b* space, taking +// into account a given reference white. (i.e. the monitor's white) +func LabWhiteRef(l, a, b float64, wref [3]float64) Color { + return Xyz(LabToXyzWhiteRef(l, a, b, wref)) +} + +// DistanceLab is a good measure of visual similarity between two colors! +// A result of 0 would mean identical colors, while a result of 1 or higher +// means the colors differ a lot. +func (c1 Color) DistanceLab(c2 Color) float64 { + l1, a1, b1 := c1.Lab() + l2, a2, b2 := c2.Lab() + return math.Sqrt(sq(l1-l2) + sq(a1-a2) + sq(b1-b2)) +} + +// That's actually the same, but I don't want to break code. +func (c1 Color) DistanceCIE76(c2 Color) float64 { + return c1.DistanceLab(c2) +} + +// Uses the CIE94 formula to calculate color distance. More accurate than +// DistanceLab, but also more work. +func (cl Color) DistanceCIE94(cr Color) float64 { + l1, a1, b1 := cl.Lab() + l2, a2, b2 := cr.Lab() + + // NOTE: Since all those formulas expect L,a,b values 100x larger than we + // have them in this library, we either need to adjust all constants + // in the formula, or convert the ranges of L,a,b before, and then + // scale the distances down again. The latter is less error-prone. + l1, a1, b1 = l1*100.0, a1*100.0, b1*100.0 + l2, a2, b2 = l2*100.0, a2*100.0, b2*100.0 + + kl := 1.0 // 2.0 for textiles + kc := 1.0 + kh := 1.0 + k1 := 0.045 // 0.048 for textiles + k2 := 0.015 // 0.014 for textiles. + + deltaL := l1 - l2 + c1 := math.Sqrt(sq(a1) + sq(b1)) + c2 := math.Sqrt(sq(a2) + sq(b2)) + deltaCab := c1 - c2 + + // Not taking Sqrt here for stability, and it's unnecessary. + deltaHab2 := sq(a1-a2) + sq(b1-b2) - sq(deltaCab) + sl := 1.0 + sc := 1.0 + k1*c1 + sh := 1.0 + k2*c1 + + vL2 := sq(deltaL / (kl * sl)) + vC2 := sq(deltaCab / (kc * sc)) + vH2 := deltaHab2 / sq(kh*sh) + + return math.Sqrt(vL2+vC2+vH2) * 0.01 // See above. +} + +// BlendLab blends two colors in the L*a*b* color-space, which should result in a smoother blend. +// t == 0 results in c1, t == 1 results in c2 +func (c1 Color) BlendLab(c2 Color, t float64) Color { + l1, a1, b1 := c1.Lab() + l2, a2, b2 := c2.Lab() + return Lab(l1+t*(l2-l1), + a1+t*(a2-a1), + b1+t*(b2-b1)) +} + +/// L*u*v* /// +////////////// +// http://en.wikipedia.org/wiki/CIELUV#XYZ_.E2.86.92_CIELUV_and_CIELUV_.E2.86.92_XYZ_conversions +// For L*u*v*, we need to L*u*v*<->XYZ<->RGB and the first one is device dependent. + +func XyzToLuv(x, y, z float64) (l, a, b float64) { + // Use D65 white as reference point by default. + // http://www.fredmiranda.com/forum/topic/1035332 + // http://en.wikipedia.org/wiki/Standard_illuminant + return XyzToLuvWhiteRef(x, y, z, D65) +} + +func XyzToLuvWhiteRef(x, y, z float64, wref [3]float64) (l, u, v float64) { + if y/wref[1] <= 6.0/29.0*6.0/29.0*6.0/29.0 { + l = y / wref[1] * 29.0 / 3.0 * 29.0 / 3.0 * 29.0 / 3.0 + } else { + l = 1.16*math.Cbrt(y/wref[1]) - 0.16 + } + ubis, vbis := xyz_to_uv(x, y, z) + un, vn := xyz_to_uv(wref[0], wref[1], wref[2]) + u = 13.0 * l * (ubis - un) + v = 13.0 * l * (vbis - vn) + return +} + +// For this part, we do as R's graphics.hcl does, not as wikipedia does. +// Or is it the same? +func xyz_to_uv(x, y, z float64) (u, v float64) { + denom := x + 15.0*y + 3.0*z + if denom == 0.0 { + u, v = 0.0, 0.0 + } else { + u = 4.0 * x / denom + v = 9.0 * y / denom + } + return +} + +func LuvToXyz(l, u, v float64) (x, y, z float64) { + // D65 white (see above). + return LuvToXyzWhiteRef(l, u, v, D65) +} + +func LuvToXyzWhiteRef(l, u, v float64, wref [3]float64) (x, y, z float64) { + //y = wref[1] * lab_finv((l + 0.16) / 1.16) + if l <= 0.08 { + y = wref[1] * l * 100.0 * 3.0 / 29.0 * 3.0 / 29.0 * 3.0 / 29.0 + } else { + y = wref[1] * cub((l+0.16)/1.16) + } + un, vn := xyz_to_uv(wref[0], wref[1], wref[2]) + if l != 0.0 { + ubis := u/(13.0*l) + un + vbis := v/(13.0*l) + vn + x = y * 9.0 * ubis / (4.0 * vbis) + z = y * (12.0 - 3.0*ubis - 20.0*vbis) / (4.0 * vbis) + } else { + x, y = 0.0, 0.0 + } + return +} + +// Converts the given color to CIE L*u*v* space using D65 as reference white. +// L* is in [0..1] and both u* and v* are in about [-1..1] +func (col Color) Luv() (l, u, v float64) { + return XyzToLuv(col.Xyz()) +} + +// Converts the given color to CIE L*u*v* space, taking into account +// a given reference white. (i.e. the monitor's white) +// L* is in [0..1] and both u* and v* are in about [-1..1] +func (col Color) LuvWhiteRef(wref [3]float64) (l, u, v float64) { + x, y, z := col.Xyz() + return XyzToLuvWhiteRef(x, y, z, wref) +} + +// Generates a color by using data given in CIE L*u*v* space using D65 as reference white. +// L* is in [0..1] and both u* and v* are in about [-1..1] +// WARNING: many combinations of `l`, `a`, and `b` values do not have corresponding +// valid RGB values, check the FAQ in the README if you're unsure. +func Luv(l, u, v float64) Color { + return Xyz(LuvToXyz(l, u, v)) +} + +// Generates a color by using data given in CIE L*u*v* space, taking +// into account a given reference white. (i.e. the monitor's white) +// L* is in [0..1] and both u* and v* are in about [-1..1] +func LuvWhiteRef(l, u, v float64, wref [3]float64) Color { + return Xyz(LuvToXyzWhiteRef(l, u, v, wref)) +} + +// DistanceLuv is a good measure of visual similarity between two colors! +// A result of 0 would mean identical colors, while a result of 1 or higher +// means the colors differ a lot. +func (c1 Color) DistanceLuv(c2 Color) float64 { + l1, u1, v1 := c1.Luv() + l2, u2, v2 := c2.Luv() + return math.Sqrt(sq(l1-l2) + sq(u1-u2) + sq(v1-v2)) +} + +// BlendLuv blends two colors in the CIE-L*u*v* color-space, which should result in a smoother blend. +// t == 0 results in c1, t == 1 results in c2 +func (c1 Color) BlendLuv(c2 Color, t float64) Color { + l1, u1, v1 := c1.Luv() + l2, u2, v2 := c2.Luv() + return Luv(l1+t*(l2-l1), + u1+t*(u2-u1), + v1+t*(v2-v1)) +} + +/// HCL /// +/////////// +// HCL is nothing else than L*a*b* in cylindrical coordinates! +// (this was wrong on English wikipedia, I fixed it, let's hope the fix stays.) +// But it is widely popular since it is a "correct HSV" +// http://www.hunterlab.com/appnotes/an09_96a.pdf + +// Converts the given color to HCL space using D65 as reference white. +// H values are in [0..360], C and L values are in [0..1] although C can overshoot 1.0 +func (col Color) Hcl() (h, c, l float64) { + return col.HclWhiteRef(D65) +} + +func LabToHcl(L, a, b float64) (h, c, l float64) { + // Oops, floating point workaround necessary if a ~= b and both are very small (i.e. almost zero). + if math.Abs(b-a) > 1e-4 && math.Abs(a) > 1e-4 { + h = math.Mod(57.29577951308232087721*math.Atan2(b, a)+360.0, 360.0) // Rad2Deg + } else { + h = 0.0 + } + c = math.Sqrt(sq(a) + sq(b)) + l = L + return +} + +// Converts the given color to HCL space, taking into account +// a given reference white. (i.e. the monitor's white) +// H values are in [0..360], C and L values are in [0..1] +func (col Color) HclWhiteRef(wref [3]float64) (h, c, l float64) { + L, a, b := col.LabWhiteRef(wref) + return LabToHcl(L, a, b) +} + +// Generates a color by using data given in HCL space using D65 as reference white. +// H values are in [0..360], C and L values are in [0..1] +// WARNING: many combinations of `l`, `a`, and `b` values do not have corresponding +// valid RGB values, check the FAQ in the README if you're unsure. +func Hcl(h, c, l float64) Color { + return HclWhiteRef(h, c, l, D65) +} + +func HclToLab(h, c, l float64) (L, a, b float64) { + H := 0.01745329251994329576 * h // Deg2Rad + a = c * math.Cos(H) + b = c * math.Sin(H) + L = l + return +} + +// Generates a color by using data given in HCL space, taking +// into account a given reference white. (i.e. the monitor's white) +// H values are in [0..360], C and L values are in [0..1] +func HclWhiteRef(h, c, l float64, wref [3]float64) Color { + L, a, b := HclToLab(h, c, l) + return LabWhiteRef(L, a, b, wref) +} + +// BlendHcl blends two colors in the CIE-L*C*h° color-space, which should result in a smoother blend. +// t == 0 results in c1, t == 1 results in c2 +func (col1 Color) BlendHcl(col2 Color, t float64) Color { + h1, c1, l1 := col1.Hcl() + h2, c2, l2 := col2.Hcl() + + // We know that h are both in [0..360] + return Hcl(interp_angle(h1, h2, t), c1+t*(c2-c1), l1+t*(l2-l1)) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go new file mode 100644 index 00000000..bb66dfa4 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go @@ -0,0 +1,25 @@ +package colorful + +import ( + "math/rand" +) + +// Uses the HSV color space to generate colors with similar S,V but distributed +// evenly along their Hue. This is fast but not always pretty. +// If you've got time to spare, use Lab (the non-fast below). +func FastHappyPalette(colorsCount int) (colors []Color) { + colors = make([]Color, colorsCount) + + for i := 0; i < colorsCount; i++ { + colors[i] = Hsv(float64(i)*(360.0/float64(colorsCount)), 0.8+rand.Float64()*0.2, 0.65+rand.Float64()*0.2) + } + return +} + +func HappyPalette(colorsCount int) ([]Color, error) { + pimpy := func(l, a, b float64) bool { + _, c, _ := LabToHcl(l, a, b) + return 0.3 <= c && 0.4 <= l && l <= 0.8 + } + return SoftPaletteEx(colorsCount, SoftPaletteSettings{pimpy, 50, true}) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go b/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go new file mode 100644 index 00000000..86a5ed98 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go @@ -0,0 +1,37 @@ +package colorful + +import ( + "database/sql/driver" + "fmt" + "reflect" +) + +// A HexColor is a Color stored as a hex string "#rrggbb". It implements the +// database/sql.Scanner and database/sql/driver.Value interfaces. +type HexColor Color + +type errUnsupportedType struct { + got interface{} + want reflect.Type +} + +func (hc *HexColor) Scan(value interface{}) error { + s, ok := value.(string) + if !ok { + return errUnsupportedType{got: reflect.TypeOf(value), want: reflect.TypeOf("")} + } + c, err := Hex(s) + if err != nil { + return err + } + *hc = HexColor(c) + return nil +} + +func (hc *HexColor) Value() (driver.Value, error) { + return Color(*hc).Hex(), nil +} + +func (e errUnsupportedType) Error() string { + return fmt.Sprintf("unsupported type: got %v, want a %s", e.got, e.want) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go new file mode 100644 index 00000000..0154ac9b --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go @@ -0,0 +1,185 @@ +// Largely inspired by the descriptions in http://lab.medialab.sciences-po.fr/iwanthue/ +// but written from scratch. + +package colorful + +import ( + "fmt" + "math" + "math/rand" +) + +// The algorithm works in L*a*b* color space and converts to RGB in the end. +// L* in [0..1], a* and b* in [-1..1] +type lab_t struct { + L, A, B float64 +} + +type SoftPaletteSettings struct { + // A function which can be used to restrict the allowed color-space. + CheckColor func(l, a, b float64) bool + + // The higher, the better quality but the slower. Usually two figures. + Iterations int + + // Use up to 160000 or 8000 samples of the L*a*b* space (and thus calls to CheckColor). + // Set this to true only if your CheckColor shapes the Lab space weirdly. + ManySamples bool +} + +// Yeah, windows-stype Foo, FooEx, screw you golang... +// Uses K-means to cluster the color-space and return the means of the clusters +// as a new palette of distinctive colors. Falls back to K-medoid if the mean +// happens to fall outside of the color-space, which can only happen if you +// specify a CheckColor function. +func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, error) { + + // Checks whether it's a valid RGB and also fulfills the potentially provided constraint. + check := func(col lab_t) bool { + c := Lab(col.L, col.A, col.B) + return c.IsValid() && (settings.CheckColor == nil || settings.CheckColor(col.L, col.A, col.B)) + } + + // Sample the color space. These will be the points k-means is run on. + dl := 0.05 + dab := 0.1 + if settings.ManySamples { + dl = 0.01 + dab = 0.05 + } + + samples := make([]lab_t, 0, int(1.0/dl*2.0/dab*2.0/dab)) + for l := 0.0; l <= 1.0; l += dl { + for a := -1.0; a <= 1.0; a += dab { + for b := -1.0; b <= 1.0; b += dab { + if check(lab_t{l, a, b}) { + samples = append(samples, lab_t{l, a, b}) + } + } + } + } + + // That would cause some infinite loops down there... + if len(samples) < colorsCount { + return nil, fmt.Errorf("palettegen: more colors requested (%v) than samples available (%v). Your requested color count may be wrong, you might want to use many samples or your constraint function makes the valid color space too small.", colorsCount, len(samples)) + } else if len(samples) == colorsCount { + return labs2cols(samples), nil // Oops? + } + + // We take the initial means out of the samples, so they are in fact medoids. + // This helps us avoid infinite loops or arbitrary cutoffs with too restrictive constraints. + means := make([]lab_t, colorsCount) + for i := 0; i < colorsCount; i++ { + for means[i] = samples[rand.Intn(len(samples))]; in(means, i, means[i]); means[i] = samples[rand.Intn(len(samples))] { + } + } + + clusters := make([]int, len(samples)) + samples_used := make([]bool, len(samples)) + + // The actual k-means/medoid iterations + for i := 0; i < settings.Iterations; i++ { + // Reassing the samples to clusters, i.e. to their closest mean. + // By the way, also check if any sample is used as a medoid and if so, mark that. + for isample, sample := range samples { + samples_used[isample] = false + mindist := math.Inf(+1) + for imean, mean := range means { + dist := lab_dist(sample, mean) + if dist < mindist { + mindist = dist + clusters[isample] = imean + } + + // Mark samples which are used as a medoid. + if lab_eq(sample, mean) { + samples_used[isample] = true + } + } + } + + // Compute new means according to the samples. + for imean := range means { + // The new mean is the average of all samples belonging to it.. + nsamples := 0 + newmean := lab_t{0.0, 0.0, 0.0} + for isample, sample := range samples { + if clusters[isample] == imean { + nsamples++ + newmean.L += sample.L + newmean.A += sample.A + newmean.B += sample.B + } + } + if nsamples > 0 { + newmean.L /= float64(nsamples) + newmean.A /= float64(nsamples) + newmean.B /= float64(nsamples) + } else { + // That mean doesn't have any samples? Get a new mean from the sample list! + var inewmean int + for inewmean = rand.Intn(len(samples_used)); samples_used[inewmean]; inewmean = rand.Intn(len(samples_used)) { + } + newmean = samples[inewmean] + samples_used[inewmean] = true + } + + // But now we still need to check whether the new mean is an allowed color. + if nsamples > 0 && check(newmean) { + // It does, life's good (TM) + means[imean] = newmean + } else { + // New mean isn't an allowed color or doesn't have any samples! + // Switch to medoid mode and pick the closest (unused) sample. + // This should always find something thanks to len(samples) >= colorsCount + mindist := math.Inf(+1) + for isample, sample := range samples { + if !samples_used[isample] { + dist := lab_dist(sample, newmean) + if dist < mindist { + mindist = dist + newmean = sample + } + } + } + } + } + } + return labs2cols(means), nil +} + +// A wrapper which uses common parameters. +func SoftPalette(colorsCount int) ([]Color, error) { + return SoftPaletteEx(colorsCount, SoftPaletteSettings{nil, 50, false}) +} + +func in(haystack []lab_t, upto int, needle lab_t) bool { + for i := 0; i < upto && i < len(haystack); i++ { + if haystack[i] == needle { + return true + } + } + return false +} + +const LAB_DELTA = 1e-6 + +func lab_eq(lab1, lab2 lab_t) bool { + return math.Abs(lab1.L-lab2.L) < LAB_DELTA && + math.Abs(lab1.A-lab2.A) < LAB_DELTA && + math.Abs(lab1.B-lab2.B) < LAB_DELTA +} + +// That's faster than using colorful's DistanceLab since we would have to +// convert back and forth for that. Here is no conversion. +func lab_dist(lab1, lab2 lab_t) float64 { + return math.Sqrt(sq(lab1.L-lab2.L) + sq(lab1.A-lab2.A) + sq(lab1.B-lab2.B)) +} + +func labs2cols(labs []lab_t) (cols []Color) { + cols = make([]Color, len(labs)) + for k, v := range labs { + cols[k] = Lab(v.L, v.A, v.B) + } + return cols +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go new file mode 100644 index 00000000..00f42a5c --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go @@ -0,0 +1,25 @@ +package colorful + +import ( + "math/rand" +) + +// Uses the HSV color space to generate colors with similar S,V but distributed +// evenly along their Hue. This is fast but not always pretty. +// If you've got time to spare, use Lab (the non-fast below). +func FastWarmPalette(colorsCount int) (colors []Color) { + colors = make([]Color, colorsCount) + + for i := 0; i < colorsCount; i++ { + colors[i] = Hsv(float64(i)*(360.0/float64(colorsCount)), 0.55+rand.Float64()*0.2, 0.35+rand.Float64()*0.2) + } + return +} + +func WarmPalette(colorsCount int) ([]Color, error) { + warmy := func(l, a, b float64) bool { + _, c, _ := LabToHcl(l, a, b) + return 0.1 <= c && c <= 0.4 && 0.2 <= l && l <= 0.5 + } + return SoftPaletteEx(colorsCount, SoftPaletteSettings{warmy, 50, true}) +} diff --git a/vendor/github.com/mattn/go-runewidth/.travis.yml b/vendor/github.com/mattn/go-runewidth/.travis.yml new file mode 100644 index 00000000..5c9c2a30 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/.travis.yml @@ -0,0 +1,8 @@ +language: go +go: + - tip +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL diff --git a/vendor/github.com/mattn/go-runewidth/LICENSE b/vendor/github.com/mattn/go-runewidth/LICENSE new file mode 100644 index 00000000..91b5cef3 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Yasuhiro Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/mattn/go-runewidth/README.mkd b/vendor/github.com/mattn/go-runewidth/README.mkd new file mode 100644 index 00000000..66663a94 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/README.mkd @@ -0,0 +1,27 @@ +go-runewidth +============ + +[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) +[![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD) +[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) +[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth) + +Provides functions to get fixed width of the character or string. + +Usage +----- + +```go +runewidth.StringWidth("つのだ☆HIRO") == 12 +``` + + +Author +------ + +Yasuhiro Matsumoto + +License +------- + +under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go new file mode 100644 index 00000000..2164497a --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -0,0 +1,1223 @@ +package runewidth + +var ( + // EastAsianWidth will be set true if the current locale is CJK + EastAsianWidth = IsEastAsian() + + // DefaultCondition is a condition in current locale + DefaultCondition = &Condition{EastAsianWidth} +) + +type interval struct { + first rune + last rune +} + +type table []interval + +func inTables(r rune, ts ...table) bool { + for _, t := range ts { + if inTable(r, t) { + return true + } + } + return false +} + +func inTable(r rune, t table) bool { + // func (t table) IncludesRune(r rune) bool { + if r < t[0].first { + return false + } + + bot := 0 + top := len(t) - 1 + for top >= bot { + mid := (bot + top) / 2 + + switch { + case t[mid].last < r: + bot = mid + 1 + case t[mid].first > r: + top = mid - 1 + default: + return true + } + } + + return false +} + +var private = table{ + {0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD}, +} + +var nonprint = table{ + {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, + {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, + {0x202A, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, +} + +var combining = table{ + {0x0300, 0x036F}, {0x0483, 0x0489}, {0x0591, 0x05BD}, + {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5}, + {0x05C7, 0x05C7}, {0x0610, 0x061A}, {0x064B, 0x065F}, + {0x0670, 0x0670}, {0x06D6, 0x06DC}, {0x06DF, 0x06E4}, + {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x0711, 0x0711}, + {0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, + {0x0816, 0x0819}, {0x081B, 0x0823}, {0x0825, 0x0827}, + {0x0829, 0x082D}, {0x0859, 0x085B}, {0x08D4, 0x08E1}, + {0x08E3, 0x0903}, {0x093A, 0x093C}, {0x093E, 0x094F}, + {0x0951, 0x0957}, {0x0962, 0x0963}, {0x0981, 0x0983}, + {0x09BC, 0x09BC}, {0x09BE, 0x09C4}, {0x09C7, 0x09C8}, + {0x09CB, 0x09CD}, {0x09D7, 0x09D7}, {0x09E2, 0x09E3}, + {0x0A01, 0x0A03}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, + {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, + {0x0A70, 0x0A71}, {0x0A75, 0x0A75}, {0x0A81, 0x0A83}, + {0x0ABC, 0x0ABC}, {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9}, + {0x0ACB, 0x0ACD}, {0x0AE2, 0x0AE3}, {0x0B01, 0x0B03}, + {0x0B3C, 0x0B3C}, {0x0B3E, 0x0B44}, {0x0B47, 0x0B48}, + {0x0B4B, 0x0B4D}, {0x0B56, 0x0B57}, {0x0B62, 0x0B63}, + {0x0B82, 0x0B82}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, + {0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7}, {0x0C00, 0x0C03}, + {0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, + {0x0C55, 0x0C56}, {0x0C62, 0x0C63}, {0x0C81, 0x0C83}, + {0x0CBC, 0x0CBC}, {0x0CBE, 0x0CC4}, {0x0CC6, 0x0CC8}, + {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6}, {0x0CE2, 0x0CE3}, + {0x0D01, 0x0D03}, {0x0D3E, 0x0D44}, {0x0D46, 0x0D48}, + {0x0D4A, 0x0D4D}, {0x0D57, 0x0D57}, {0x0D62, 0x0D63}, + {0x0D82, 0x0D83}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, + {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, {0x0DF2, 0x0DF3}, + {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, + {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, + {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, + {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F3E, 0x0F3F}, + {0x0F71, 0x0F84}, {0x0F86, 0x0F87}, {0x0F8D, 0x0F97}, + {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102B, 0x103E}, + {0x1056, 0x1059}, {0x105E, 0x1060}, {0x1062, 0x1064}, + {0x1067, 0x106D}, {0x1071, 0x1074}, {0x1082, 0x108D}, + {0x108F, 0x108F}, {0x109A, 0x109D}, {0x135D, 0x135F}, + {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, + {0x1772, 0x1773}, {0x17B4, 0x17D3}, {0x17DD, 0x17DD}, + {0x180B, 0x180D}, {0x1885, 0x1886}, {0x18A9, 0x18A9}, + {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1A17, 0x1A1B}, + {0x1A55, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A7F}, + {0x1AB0, 0x1ABE}, {0x1B00, 0x1B04}, {0x1B34, 0x1B44}, + {0x1B6B, 0x1B73}, {0x1B80, 0x1B82}, {0x1BA1, 0x1BAD}, + {0x1BE6, 0x1BF3}, {0x1C24, 0x1C37}, {0x1CD0, 0x1CD2}, + {0x1CD4, 0x1CE8}, {0x1CED, 0x1CED}, {0x1CF2, 0x1CF4}, + {0x1CF8, 0x1CF9}, {0x1DC0, 0x1DF5}, {0x1DFB, 0x1DFF}, + {0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2D7F, 0x2D7F}, + {0x2DE0, 0x2DFF}, {0x302A, 0x302F}, {0x3099, 0x309A}, + {0xA66F, 0xA672}, {0xA674, 0xA67D}, {0xA69E, 0xA69F}, + {0xA6F0, 0xA6F1}, {0xA802, 0xA802}, {0xA806, 0xA806}, + {0xA80B, 0xA80B}, {0xA823, 0xA827}, {0xA880, 0xA881}, + {0xA8B4, 0xA8C5}, {0xA8E0, 0xA8F1}, {0xA926, 0xA92D}, + {0xA947, 0xA953}, {0xA980, 0xA983}, {0xA9B3, 0xA9C0}, + {0xA9E5, 0xA9E5}, {0xAA29, 0xAA36}, {0xAA43, 0xAA43}, + {0xAA4C, 0xAA4D}, {0xAA7B, 0xAA7D}, {0xAAB0, 0xAAB0}, + {0xAAB2, 0xAAB4}, {0xAAB7, 0xAAB8}, {0xAABE, 0xAABF}, + {0xAAC1, 0xAAC1}, {0xAAEB, 0xAAEF}, {0xAAF5, 0xAAF6}, + {0xABE3, 0xABEA}, {0xABEC, 0xABED}, {0xFB1E, 0xFB1E}, + {0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, + {0x102E0, 0x102E0}, {0x10376, 0x1037A}, {0x10A01, 0x10A03}, + {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A}, + {0x10A3F, 0x10A3F}, {0x10AE5, 0x10AE6}, {0x11000, 0x11002}, + {0x11038, 0x11046}, {0x1107F, 0x11082}, {0x110B0, 0x110BA}, + {0x11100, 0x11102}, {0x11127, 0x11134}, {0x11173, 0x11173}, + {0x11180, 0x11182}, {0x111B3, 0x111C0}, {0x111CA, 0x111CC}, + {0x1122C, 0x11237}, {0x1123E, 0x1123E}, {0x112DF, 0x112EA}, + {0x11300, 0x11303}, {0x1133C, 0x1133C}, {0x1133E, 0x11344}, + {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11357, 0x11357}, + {0x11362, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374}, + {0x11435, 0x11446}, {0x114B0, 0x114C3}, {0x115AF, 0x115B5}, + {0x115B8, 0x115C0}, {0x115DC, 0x115DD}, {0x11630, 0x11640}, + {0x116AB, 0x116B7}, {0x1171D, 0x1172B}, {0x11C2F, 0x11C36}, + {0x11C38, 0x11C3F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, + {0x16AF0, 0x16AF4}, {0x16B30, 0x16B36}, {0x16F51, 0x16F7E}, + {0x16F8F, 0x16F92}, {0x1BC9D, 0x1BC9E}, {0x1D165, 0x1D169}, + {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, + {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1DA00, 0x1DA36}, + {0x1DA3B, 0x1DA6C}, {0x1DA75, 0x1DA75}, {0x1DA84, 0x1DA84}, + {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, + {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, + {0x1E026, 0x1E02A}, {0x1E8D0, 0x1E8D6}, {0x1E944, 0x1E94A}, + {0xE0100, 0xE01EF}, +} + +var doublewidth = table{ + {0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A}, + {0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3}, + {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653}, + {0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1}, + {0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, + {0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA}, + {0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA}, + {0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B}, + {0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E}, + {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797}, + {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C}, + {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99}, + {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, + {0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF}, + {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, + {0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, + {0x3250, 0x32FE}, {0x3300, 0x4DBF}, {0x4E00, 0xA48C}, + {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, + {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, + {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, + {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE0}, {0x17000, 0x187EC}, + {0x18800, 0x18AF2}, {0x1B000, 0x1B001}, {0x1F004, 0x1F004}, + {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, + {0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, + {0x1F250, 0x1F251}, {0x1F300, 0x1F320}, {0x1F32D, 0x1F335}, + {0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA}, + {0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4}, + {0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC}, + {0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, + {0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, + {0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC}, + {0x1F6D0, 0x1F6D2}, {0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6F6}, + {0x1F910, 0x1F91E}, {0x1F920, 0x1F927}, {0x1F930, 0x1F930}, + {0x1F933, 0x1F93E}, {0x1F940, 0x1F94B}, {0x1F950, 0x1F95E}, + {0x1F980, 0x1F991}, {0x1F9C0, 0x1F9C0}, {0x20000, 0x2FFFD}, + {0x30000, 0x3FFFD}, +} + +var ambiguous = table{ + {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, + {0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4}, + {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, + {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, + {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, + {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, + {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101}, + {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, + {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, + {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, + {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, + {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE}, + {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, + {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, + {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, + {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, + {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, + {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F}, + {0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, + {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F}, + {0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016}, + {0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022}, + {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, + {0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E}, + {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, + {0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105}, + {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, + {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B}, + {0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B}, + {0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199}, + {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4}, + {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, + {0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F}, + {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A}, + {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, + {0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237}, + {0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C}, + {0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267}, + {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283}, + {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, + {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312}, + {0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573}, + {0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1}, + {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, + {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, + {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5}, + {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609}, + {0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E}, + {0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661}, + {0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D}, + {0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF}, + {0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1}, + {0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1}, + {0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC}, + {0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F}, + {0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF}, + {0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, + {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, + {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF}, + {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}, +} + +var emoji = table{ + {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F321}, {0x1F324, 0x1F32C}, + {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, {0x1F396, 0x1F397}, + {0x1F399, 0x1F39B}, {0x1F39E, 0x1F39F}, {0x1F3CB, 0x1F3CE}, + {0x1F3D4, 0x1F3DF}, {0x1F3F3, 0x1F3F5}, {0x1F3F7, 0x1F3F7}, + {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FD}, + {0x1F549, 0x1F54A}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F579}, + {0x1F587, 0x1F587}, {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590}, + {0x1F5A5, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, {0x1F5B1, 0x1F5B2}, + {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, {0x1F5D1, 0x1F5D3}, + {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, {0x1F5E3, 0x1F5E3}, + {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, {0x1F5F3, 0x1F5F3}, + {0x1F5FA, 0x1F5FA}, {0x1F6CB, 0x1F6CF}, {0x1F6E0, 0x1F6E5}, + {0x1F6E9, 0x1F6E9}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F3}, +} + +var notassigned = table{ + {0x0378, 0x0379}, {0x0380, 0x0383}, {0x038B, 0x038B}, + {0x038D, 0x038D}, {0x03A2, 0x03A2}, {0x0530, 0x0530}, + {0x0557, 0x0558}, {0x0560, 0x0560}, {0x0588, 0x0588}, + {0x058B, 0x058C}, {0x0590, 0x0590}, {0x05C8, 0x05CF}, + {0x05EB, 0x05EF}, {0x05F5, 0x05FF}, {0x061D, 0x061D}, + {0x070E, 0x070E}, {0x074B, 0x074C}, {0x07B2, 0x07BF}, + {0x07FB, 0x07FF}, {0x082E, 0x082F}, {0x083F, 0x083F}, + {0x085C, 0x085D}, {0x085F, 0x089F}, {0x08B5, 0x08B5}, + {0x08BE, 0x08D3}, {0x0984, 0x0984}, {0x098D, 0x098E}, + {0x0991, 0x0992}, {0x09A9, 0x09A9}, {0x09B1, 0x09B1}, + {0x09B3, 0x09B5}, {0x09BA, 0x09BB}, {0x09C5, 0x09C6}, + {0x09C9, 0x09CA}, {0x09CF, 0x09D6}, {0x09D8, 0x09DB}, + {0x09DE, 0x09DE}, {0x09E4, 0x09E5}, {0x09FC, 0x0A00}, + {0x0A04, 0x0A04}, {0x0A0B, 0x0A0E}, {0x0A11, 0x0A12}, + {0x0A29, 0x0A29}, {0x0A31, 0x0A31}, {0x0A34, 0x0A34}, + {0x0A37, 0x0A37}, {0x0A3A, 0x0A3B}, {0x0A3D, 0x0A3D}, + {0x0A43, 0x0A46}, {0x0A49, 0x0A4A}, {0x0A4E, 0x0A50}, + {0x0A52, 0x0A58}, {0x0A5D, 0x0A5D}, {0x0A5F, 0x0A65}, + {0x0A76, 0x0A80}, {0x0A84, 0x0A84}, {0x0A8E, 0x0A8E}, + {0x0A92, 0x0A92}, {0x0AA9, 0x0AA9}, {0x0AB1, 0x0AB1}, + {0x0AB4, 0x0AB4}, {0x0ABA, 0x0ABB}, {0x0AC6, 0x0AC6}, + {0x0ACA, 0x0ACA}, {0x0ACE, 0x0ACF}, {0x0AD1, 0x0ADF}, + {0x0AE4, 0x0AE5}, {0x0AF2, 0x0AF8}, {0x0AFA, 0x0B00}, + {0x0B04, 0x0B04}, {0x0B0D, 0x0B0E}, {0x0B11, 0x0B12}, + {0x0B29, 0x0B29}, {0x0B31, 0x0B31}, {0x0B34, 0x0B34}, + {0x0B3A, 0x0B3B}, {0x0B45, 0x0B46}, {0x0B49, 0x0B4A}, + {0x0B4E, 0x0B55}, {0x0B58, 0x0B5B}, {0x0B5E, 0x0B5E}, + {0x0B64, 0x0B65}, {0x0B78, 0x0B81}, {0x0B84, 0x0B84}, + {0x0B8B, 0x0B8D}, {0x0B91, 0x0B91}, {0x0B96, 0x0B98}, + {0x0B9B, 0x0B9B}, {0x0B9D, 0x0B9D}, {0x0BA0, 0x0BA2}, + {0x0BA5, 0x0BA7}, {0x0BAB, 0x0BAD}, {0x0BBA, 0x0BBD}, + {0x0BC3, 0x0BC5}, {0x0BC9, 0x0BC9}, {0x0BCE, 0x0BCF}, + {0x0BD1, 0x0BD6}, {0x0BD8, 0x0BE5}, {0x0BFB, 0x0BFF}, + {0x0C04, 0x0C04}, {0x0C0D, 0x0C0D}, {0x0C11, 0x0C11}, + {0x0C29, 0x0C29}, {0x0C3A, 0x0C3C}, {0x0C45, 0x0C45}, + {0x0C49, 0x0C49}, {0x0C4E, 0x0C54}, {0x0C57, 0x0C57}, + {0x0C5B, 0x0C5F}, {0x0C64, 0x0C65}, {0x0C70, 0x0C77}, + {0x0C84, 0x0C84}, {0x0C8D, 0x0C8D}, {0x0C91, 0x0C91}, + {0x0CA9, 0x0CA9}, {0x0CB4, 0x0CB4}, {0x0CBA, 0x0CBB}, + {0x0CC5, 0x0CC5}, {0x0CC9, 0x0CC9}, {0x0CCE, 0x0CD4}, + {0x0CD7, 0x0CDD}, {0x0CDF, 0x0CDF}, {0x0CE4, 0x0CE5}, + {0x0CF0, 0x0CF0}, {0x0CF3, 0x0D00}, {0x0D04, 0x0D04}, + {0x0D0D, 0x0D0D}, {0x0D11, 0x0D11}, {0x0D3B, 0x0D3C}, + {0x0D45, 0x0D45}, {0x0D49, 0x0D49}, {0x0D50, 0x0D53}, + {0x0D64, 0x0D65}, {0x0D80, 0x0D81}, {0x0D84, 0x0D84}, + {0x0D97, 0x0D99}, {0x0DB2, 0x0DB2}, {0x0DBC, 0x0DBC}, + {0x0DBE, 0x0DBF}, {0x0DC7, 0x0DC9}, {0x0DCB, 0x0DCE}, + {0x0DD5, 0x0DD5}, {0x0DD7, 0x0DD7}, {0x0DE0, 0x0DE5}, + {0x0DF0, 0x0DF1}, {0x0DF5, 0x0E00}, {0x0E3B, 0x0E3E}, + {0x0E5C, 0x0E80}, {0x0E83, 0x0E83}, {0x0E85, 0x0E86}, + {0x0E89, 0x0E89}, {0x0E8B, 0x0E8C}, {0x0E8E, 0x0E93}, + {0x0E98, 0x0E98}, {0x0EA0, 0x0EA0}, {0x0EA4, 0x0EA4}, + {0x0EA6, 0x0EA6}, {0x0EA8, 0x0EA9}, {0x0EAC, 0x0EAC}, + {0x0EBA, 0x0EBA}, {0x0EBE, 0x0EBF}, {0x0EC5, 0x0EC5}, + {0x0EC7, 0x0EC7}, {0x0ECE, 0x0ECF}, {0x0EDA, 0x0EDB}, + {0x0EE0, 0x0EFF}, {0x0F48, 0x0F48}, {0x0F6D, 0x0F70}, + {0x0F98, 0x0F98}, {0x0FBD, 0x0FBD}, {0x0FCD, 0x0FCD}, + {0x0FDB, 0x0FFF}, {0x10C6, 0x10C6}, {0x10C8, 0x10CC}, + {0x10CE, 0x10CF}, {0x1249, 0x1249}, {0x124E, 0x124F}, + {0x1257, 0x1257}, {0x1259, 0x1259}, {0x125E, 0x125F}, + {0x1289, 0x1289}, {0x128E, 0x128F}, {0x12B1, 0x12B1}, + {0x12B6, 0x12B7}, {0x12BF, 0x12BF}, {0x12C1, 0x12C1}, + {0x12C6, 0x12C7}, {0x12D7, 0x12D7}, {0x1311, 0x1311}, + {0x1316, 0x1317}, {0x135B, 0x135C}, {0x137D, 0x137F}, + {0x139A, 0x139F}, {0x13F6, 0x13F7}, {0x13FE, 0x13FF}, + {0x169D, 0x169F}, {0x16F9, 0x16FF}, {0x170D, 0x170D}, + {0x1715, 0x171F}, {0x1737, 0x173F}, {0x1754, 0x175F}, + {0x176D, 0x176D}, {0x1771, 0x1771}, {0x1774, 0x177F}, + {0x17DE, 0x17DF}, {0x17EA, 0x17EF}, {0x17FA, 0x17FF}, + {0x180F, 0x180F}, {0x181A, 0x181F}, {0x1878, 0x187F}, + {0x18AB, 0x18AF}, {0x18F6, 0x18FF}, {0x191F, 0x191F}, + {0x192C, 0x192F}, {0x193C, 0x193F}, {0x1941, 0x1943}, + {0x196E, 0x196F}, {0x1975, 0x197F}, {0x19AC, 0x19AF}, + {0x19CA, 0x19CF}, {0x19DB, 0x19DD}, {0x1A1C, 0x1A1D}, + {0x1A5F, 0x1A5F}, {0x1A7D, 0x1A7E}, {0x1A8A, 0x1A8F}, + {0x1A9A, 0x1A9F}, {0x1AAE, 0x1AAF}, {0x1ABF, 0x1AFF}, + {0x1B4C, 0x1B4F}, {0x1B7D, 0x1B7F}, {0x1BF4, 0x1BFB}, + {0x1C38, 0x1C3A}, {0x1C4A, 0x1C4C}, {0x1C89, 0x1CBF}, + {0x1CC8, 0x1CCF}, {0x1CF7, 0x1CF7}, {0x1CFA, 0x1CFF}, + {0x1DF6, 0x1DFA}, {0x1F16, 0x1F17}, {0x1F1E, 0x1F1F}, + {0x1F46, 0x1F47}, {0x1F4E, 0x1F4F}, {0x1F58, 0x1F58}, + {0x1F5A, 0x1F5A}, {0x1F5C, 0x1F5C}, {0x1F5E, 0x1F5E}, + {0x1F7E, 0x1F7F}, {0x1FB5, 0x1FB5}, {0x1FC5, 0x1FC5}, + {0x1FD4, 0x1FD5}, {0x1FDC, 0x1FDC}, {0x1FF0, 0x1FF1}, + {0x1FF5, 0x1FF5}, {0x1FFF, 0x1FFF}, {0x2065, 0x2065}, + {0x2072, 0x2073}, {0x208F, 0x208F}, {0x209D, 0x209F}, + {0x20BF, 0x20CF}, {0x20F1, 0x20FF}, {0x218C, 0x218F}, + {0x23FF, 0x23FF}, {0x2427, 0x243F}, {0x244B, 0x245F}, + {0x2B74, 0x2B75}, {0x2B96, 0x2B97}, {0x2BBA, 0x2BBC}, + {0x2BC9, 0x2BC9}, {0x2BD2, 0x2BEB}, {0x2BF0, 0x2BFF}, + {0x2C2F, 0x2C2F}, {0x2C5F, 0x2C5F}, {0x2CF4, 0x2CF8}, + {0x2D26, 0x2D26}, {0x2D28, 0x2D2C}, {0x2D2E, 0x2D2F}, + {0x2D68, 0x2D6E}, {0x2D71, 0x2D7E}, {0x2D97, 0x2D9F}, + {0x2DA7, 0x2DA7}, {0x2DAF, 0x2DAF}, {0x2DB7, 0x2DB7}, + {0x2DBF, 0x2DBF}, {0x2DC7, 0x2DC7}, {0x2DCF, 0x2DCF}, + {0x2DD7, 0x2DD7}, {0x2DDF, 0x2DDF}, {0x2E45, 0x2E7F}, + {0x2E9A, 0x2E9A}, {0x2EF4, 0x2EFF}, {0x2FD6, 0x2FEF}, + {0x2FFC, 0x2FFF}, {0x3040, 0x3040}, {0x3097, 0x3098}, + {0x3100, 0x3104}, {0x312E, 0x3130}, {0x318F, 0x318F}, + {0x31BB, 0x31BF}, {0x31E4, 0x31EF}, {0x321F, 0x321F}, + {0x32FF, 0x32FF}, {0x4DB6, 0x4DBF}, {0x9FD6, 0x9FFF}, + {0xA48D, 0xA48F}, {0xA4C7, 0xA4CF}, {0xA62C, 0xA63F}, + {0xA6F8, 0xA6FF}, {0xA7AF, 0xA7AF}, {0xA7B8, 0xA7F6}, + {0xA82C, 0xA82F}, {0xA83A, 0xA83F}, {0xA878, 0xA87F}, + {0xA8C6, 0xA8CD}, {0xA8DA, 0xA8DF}, {0xA8FE, 0xA8FF}, + {0xA954, 0xA95E}, {0xA97D, 0xA97F}, {0xA9CE, 0xA9CE}, + {0xA9DA, 0xA9DD}, {0xA9FF, 0xA9FF}, {0xAA37, 0xAA3F}, + {0xAA4E, 0xAA4F}, {0xAA5A, 0xAA5B}, {0xAAC3, 0xAADA}, + {0xAAF7, 0xAB00}, {0xAB07, 0xAB08}, {0xAB0F, 0xAB10}, + {0xAB17, 0xAB1F}, {0xAB27, 0xAB27}, {0xAB2F, 0xAB2F}, + {0xAB66, 0xAB6F}, {0xABEE, 0xABEF}, {0xABFA, 0xABFF}, + {0xD7A4, 0xD7AF}, {0xD7C7, 0xD7CA}, {0xD7FC, 0xD7FF}, + {0xFA6E, 0xFA6F}, {0xFADA, 0xFAFF}, {0xFB07, 0xFB12}, + {0xFB18, 0xFB1C}, {0xFB37, 0xFB37}, {0xFB3D, 0xFB3D}, + {0xFB3F, 0xFB3F}, {0xFB42, 0xFB42}, {0xFB45, 0xFB45}, + {0xFBC2, 0xFBD2}, {0xFD40, 0xFD4F}, {0xFD90, 0xFD91}, + {0xFDC8, 0xFDEF}, {0xFDFE, 0xFDFF}, {0xFE1A, 0xFE1F}, + {0xFE53, 0xFE53}, {0xFE67, 0xFE67}, {0xFE6C, 0xFE6F}, + {0xFE75, 0xFE75}, {0xFEFD, 0xFEFE}, {0xFF00, 0xFF00}, + {0xFFBF, 0xFFC1}, {0xFFC8, 0xFFC9}, {0xFFD0, 0xFFD1}, + {0xFFD8, 0xFFD9}, {0xFFDD, 0xFFDF}, {0xFFE7, 0xFFE7}, + {0xFFEF, 0xFFF8}, {0xFFFE, 0xFFFF}, {0x1000C, 0x1000C}, + {0x10027, 0x10027}, {0x1003B, 0x1003B}, {0x1003E, 0x1003E}, + {0x1004E, 0x1004F}, {0x1005E, 0x1007F}, {0x100FB, 0x100FF}, + {0x10103, 0x10106}, {0x10134, 0x10136}, {0x1018F, 0x1018F}, + {0x1019C, 0x1019F}, {0x101A1, 0x101CF}, {0x101FE, 0x1027F}, + {0x1029D, 0x1029F}, {0x102D1, 0x102DF}, {0x102FC, 0x102FF}, + {0x10324, 0x1032F}, {0x1034B, 0x1034F}, {0x1037B, 0x1037F}, + {0x1039E, 0x1039E}, {0x103C4, 0x103C7}, {0x103D6, 0x103FF}, + {0x1049E, 0x1049F}, {0x104AA, 0x104AF}, {0x104D4, 0x104D7}, + {0x104FC, 0x104FF}, {0x10528, 0x1052F}, {0x10564, 0x1056E}, + {0x10570, 0x105FF}, {0x10737, 0x1073F}, {0x10756, 0x1075F}, + {0x10768, 0x107FF}, {0x10806, 0x10807}, {0x10809, 0x10809}, + {0x10836, 0x10836}, {0x10839, 0x1083B}, {0x1083D, 0x1083E}, + {0x10856, 0x10856}, {0x1089F, 0x108A6}, {0x108B0, 0x108DF}, + {0x108F3, 0x108F3}, {0x108F6, 0x108FA}, {0x1091C, 0x1091E}, + {0x1093A, 0x1093E}, {0x10940, 0x1097F}, {0x109B8, 0x109BB}, + {0x109D0, 0x109D1}, {0x10A04, 0x10A04}, {0x10A07, 0x10A0B}, + {0x10A14, 0x10A14}, {0x10A18, 0x10A18}, {0x10A34, 0x10A37}, + {0x10A3B, 0x10A3E}, {0x10A48, 0x10A4F}, {0x10A59, 0x10A5F}, + {0x10AA0, 0x10ABF}, {0x10AE7, 0x10AEA}, {0x10AF7, 0x10AFF}, + {0x10B36, 0x10B38}, {0x10B56, 0x10B57}, {0x10B73, 0x10B77}, + {0x10B92, 0x10B98}, {0x10B9D, 0x10BA8}, {0x10BB0, 0x10BFF}, + {0x10C49, 0x10C7F}, {0x10CB3, 0x10CBF}, {0x10CF3, 0x10CF9}, + {0x10D00, 0x10E5F}, {0x10E7F, 0x10FFF}, {0x1104E, 0x11051}, + {0x11070, 0x1107E}, {0x110C2, 0x110CF}, {0x110E9, 0x110EF}, + {0x110FA, 0x110FF}, {0x11135, 0x11135}, {0x11144, 0x1114F}, + {0x11177, 0x1117F}, {0x111CE, 0x111CF}, {0x111E0, 0x111E0}, + {0x111F5, 0x111FF}, {0x11212, 0x11212}, {0x1123F, 0x1127F}, + {0x11287, 0x11287}, {0x11289, 0x11289}, {0x1128E, 0x1128E}, + {0x1129E, 0x1129E}, {0x112AA, 0x112AF}, {0x112EB, 0x112EF}, + {0x112FA, 0x112FF}, {0x11304, 0x11304}, {0x1130D, 0x1130E}, + {0x11311, 0x11312}, {0x11329, 0x11329}, {0x11331, 0x11331}, + {0x11334, 0x11334}, {0x1133A, 0x1133B}, {0x11345, 0x11346}, + {0x11349, 0x1134A}, {0x1134E, 0x1134F}, {0x11351, 0x11356}, + {0x11358, 0x1135C}, {0x11364, 0x11365}, {0x1136D, 0x1136F}, + {0x11375, 0x113FF}, {0x1145A, 0x1145A}, {0x1145C, 0x1145C}, + {0x1145E, 0x1147F}, {0x114C8, 0x114CF}, {0x114DA, 0x1157F}, + {0x115B6, 0x115B7}, {0x115DE, 0x115FF}, {0x11645, 0x1164F}, + {0x1165A, 0x1165F}, {0x1166D, 0x1167F}, {0x116B8, 0x116BF}, + {0x116CA, 0x116FF}, {0x1171A, 0x1171C}, {0x1172C, 0x1172F}, + {0x11740, 0x1189F}, {0x118F3, 0x118FE}, {0x11900, 0x11ABF}, + {0x11AF9, 0x11BFF}, {0x11C09, 0x11C09}, {0x11C37, 0x11C37}, + {0x11C46, 0x11C4F}, {0x11C6D, 0x11C6F}, {0x11C90, 0x11C91}, + {0x11CA8, 0x11CA8}, {0x11CB7, 0x11FFF}, {0x1239A, 0x123FF}, + {0x1246F, 0x1246F}, {0x12475, 0x1247F}, {0x12544, 0x12FFF}, + {0x1342F, 0x143FF}, {0x14647, 0x167FF}, {0x16A39, 0x16A3F}, + {0x16A5F, 0x16A5F}, {0x16A6A, 0x16A6D}, {0x16A70, 0x16ACF}, + {0x16AEE, 0x16AEF}, {0x16AF6, 0x16AFF}, {0x16B46, 0x16B4F}, + {0x16B5A, 0x16B5A}, {0x16B62, 0x16B62}, {0x16B78, 0x16B7C}, + {0x16B90, 0x16EFF}, {0x16F45, 0x16F4F}, {0x16F7F, 0x16F8E}, + {0x16FA0, 0x16FDF}, {0x16FE1, 0x16FFF}, {0x187ED, 0x187FF}, + {0x18AF3, 0x1AFFF}, {0x1B002, 0x1BBFF}, {0x1BC6B, 0x1BC6F}, + {0x1BC7D, 0x1BC7F}, {0x1BC89, 0x1BC8F}, {0x1BC9A, 0x1BC9B}, + {0x1BCA4, 0x1CFFF}, {0x1D0F6, 0x1D0FF}, {0x1D127, 0x1D128}, + {0x1D1E9, 0x1D1FF}, {0x1D246, 0x1D2FF}, {0x1D357, 0x1D35F}, + {0x1D372, 0x1D3FF}, {0x1D455, 0x1D455}, {0x1D49D, 0x1D49D}, + {0x1D4A0, 0x1D4A1}, {0x1D4A3, 0x1D4A4}, {0x1D4A7, 0x1D4A8}, + {0x1D4AD, 0x1D4AD}, {0x1D4BA, 0x1D4BA}, {0x1D4BC, 0x1D4BC}, + {0x1D4C4, 0x1D4C4}, {0x1D506, 0x1D506}, {0x1D50B, 0x1D50C}, + {0x1D515, 0x1D515}, {0x1D51D, 0x1D51D}, {0x1D53A, 0x1D53A}, + {0x1D53F, 0x1D53F}, {0x1D545, 0x1D545}, {0x1D547, 0x1D549}, + {0x1D551, 0x1D551}, {0x1D6A6, 0x1D6A7}, {0x1D7CC, 0x1D7CD}, + {0x1DA8C, 0x1DA9A}, {0x1DAA0, 0x1DAA0}, {0x1DAB0, 0x1DFFF}, + {0x1E007, 0x1E007}, {0x1E019, 0x1E01A}, {0x1E022, 0x1E022}, + {0x1E025, 0x1E025}, {0x1E02B, 0x1E7FF}, {0x1E8C5, 0x1E8C6}, + {0x1E8D7, 0x1E8FF}, {0x1E94B, 0x1E94F}, {0x1E95A, 0x1E95D}, + {0x1E960, 0x1EDFF}, {0x1EE04, 0x1EE04}, {0x1EE20, 0x1EE20}, + {0x1EE23, 0x1EE23}, {0x1EE25, 0x1EE26}, {0x1EE28, 0x1EE28}, + {0x1EE33, 0x1EE33}, {0x1EE38, 0x1EE38}, {0x1EE3A, 0x1EE3A}, + {0x1EE3C, 0x1EE41}, {0x1EE43, 0x1EE46}, {0x1EE48, 0x1EE48}, + {0x1EE4A, 0x1EE4A}, {0x1EE4C, 0x1EE4C}, {0x1EE50, 0x1EE50}, + {0x1EE53, 0x1EE53}, {0x1EE55, 0x1EE56}, {0x1EE58, 0x1EE58}, + {0x1EE5A, 0x1EE5A}, {0x1EE5C, 0x1EE5C}, {0x1EE5E, 0x1EE5E}, + {0x1EE60, 0x1EE60}, {0x1EE63, 0x1EE63}, {0x1EE65, 0x1EE66}, + {0x1EE6B, 0x1EE6B}, {0x1EE73, 0x1EE73}, {0x1EE78, 0x1EE78}, + {0x1EE7D, 0x1EE7D}, {0x1EE7F, 0x1EE7F}, {0x1EE8A, 0x1EE8A}, + {0x1EE9C, 0x1EEA0}, {0x1EEA4, 0x1EEA4}, {0x1EEAA, 0x1EEAA}, + {0x1EEBC, 0x1EEEF}, {0x1EEF2, 0x1EFFF}, {0x1F02C, 0x1F02F}, + {0x1F094, 0x1F09F}, {0x1F0AF, 0x1F0B0}, {0x1F0C0, 0x1F0C0}, + {0x1F0D0, 0x1F0D0}, {0x1F0F6, 0x1F0FF}, {0x1F10D, 0x1F10F}, + {0x1F12F, 0x1F12F}, {0x1F16C, 0x1F16F}, {0x1F1AD, 0x1F1E5}, + {0x1F203, 0x1F20F}, {0x1F23C, 0x1F23F}, {0x1F249, 0x1F24F}, + {0x1F252, 0x1F2FF}, {0x1F6D3, 0x1F6DF}, {0x1F6ED, 0x1F6EF}, + {0x1F6F7, 0x1F6FF}, {0x1F774, 0x1F77F}, {0x1F7D5, 0x1F7FF}, + {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F}, {0x1F85A, 0x1F85F}, + {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F90F}, {0x1F91F, 0x1F91F}, + {0x1F928, 0x1F92F}, {0x1F931, 0x1F932}, {0x1F93F, 0x1F93F}, + {0x1F94C, 0x1F94F}, {0x1F95F, 0x1F97F}, {0x1F992, 0x1F9BF}, + {0x1F9C1, 0x1FFFF}, {0x2A6D7, 0x2A6FF}, {0x2B735, 0x2B73F}, + {0x2B81E, 0x2B81F}, {0x2CEA2, 0x2F7FF}, {0x2FA1E, 0xE0000}, + {0xE0002, 0xE001F}, {0xE0080, 0xE00FF}, {0xE01F0, 0xEFFFF}, + {0xFFFFE, 0xFFFFF}, +} + +var neutral = table{ + {0x0000, 0x001F}, {0x007F, 0x007F}, {0x0080, 0x009F}, + {0x00A0, 0x00A0}, {0x00A9, 0x00A9}, {0x00AB, 0x00AB}, + {0x00B5, 0x00B5}, {0x00BB, 0x00BB}, {0x00C0, 0x00C5}, + {0x00C7, 0x00CF}, {0x00D1, 0x00D6}, {0x00D9, 0x00DD}, + {0x00E2, 0x00E5}, {0x00E7, 0x00E7}, {0x00EB, 0x00EB}, + {0x00EE, 0x00EF}, {0x00F1, 0x00F1}, {0x00F4, 0x00F6}, + {0x00FB, 0x00FB}, {0x00FD, 0x00FD}, {0x00FF, 0x00FF}, + {0x0100, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112}, + {0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A}, + {0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E}, + {0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C}, + {0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A}, + {0x016C, 0x017F}, {0x0180, 0x01BA}, {0x01BB, 0x01BB}, + {0x01BC, 0x01BF}, {0x01C0, 0x01C3}, {0x01C4, 0x01CD}, + {0x01CF, 0x01CF}, {0x01D1, 0x01D1}, {0x01D3, 0x01D3}, + {0x01D5, 0x01D5}, {0x01D7, 0x01D7}, {0x01D9, 0x01D9}, + {0x01DB, 0x01DB}, {0x01DD, 0x024F}, {0x0250, 0x0250}, + {0x0252, 0x0260}, {0x0262, 0x0293}, {0x0294, 0x0294}, + {0x0295, 0x02AF}, {0x02B0, 0x02C1}, {0x02C2, 0x02C3}, + {0x02C5, 0x02C5}, {0x02C6, 0x02C6}, {0x02C8, 0x02C8}, + {0x02CC, 0x02CC}, {0x02CE, 0x02CF}, {0x02D1, 0x02D1}, + {0x02D2, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE}, + {0x02E0, 0x02E4}, {0x02E5, 0x02EB}, {0x02EC, 0x02EC}, + {0x02ED, 0x02ED}, {0x02EE, 0x02EE}, {0x02EF, 0x02FF}, + {0x0370, 0x0373}, {0x0374, 0x0374}, {0x0375, 0x0375}, + {0x0376, 0x0377}, {0x037A, 0x037A}, {0x037B, 0x037D}, + {0x037E, 0x037E}, {0x037F, 0x037F}, {0x0384, 0x0385}, + {0x0386, 0x0386}, {0x0387, 0x0387}, {0x0388, 0x038A}, + {0x038C, 0x038C}, {0x038E, 0x0390}, {0x03AA, 0x03B0}, + {0x03C2, 0x03C2}, {0x03CA, 0x03F5}, {0x03F6, 0x03F6}, + {0x03F7, 0x03FF}, {0x0400, 0x0400}, {0x0402, 0x040F}, + {0x0450, 0x0450}, {0x0452, 0x0481}, {0x0482, 0x0482}, + {0x0483, 0x0487}, {0x0488, 0x0489}, {0x048A, 0x04FF}, + {0x0500, 0x052F}, {0x0531, 0x0556}, {0x0559, 0x0559}, + {0x055A, 0x055F}, {0x0561, 0x0587}, {0x0589, 0x0589}, + {0x058A, 0x058A}, {0x058D, 0x058E}, {0x058F, 0x058F}, + {0x0591, 0x05BD}, {0x05BE, 0x05BE}, {0x05BF, 0x05BF}, + {0x05C0, 0x05C0}, {0x05C1, 0x05C2}, {0x05C3, 0x05C3}, + {0x05C4, 0x05C5}, {0x05C6, 0x05C6}, {0x05C7, 0x05C7}, + {0x05D0, 0x05EA}, {0x05F0, 0x05F2}, {0x05F3, 0x05F4}, + {0x0600, 0x0605}, {0x0606, 0x0608}, {0x0609, 0x060A}, + {0x060B, 0x060B}, {0x060C, 0x060D}, {0x060E, 0x060F}, + {0x0610, 0x061A}, {0x061B, 0x061B}, {0x061C, 0x061C}, + {0x061E, 0x061F}, {0x0620, 0x063F}, {0x0640, 0x0640}, + {0x0641, 0x064A}, {0x064B, 0x065F}, {0x0660, 0x0669}, + {0x066A, 0x066D}, {0x066E, 0x066F}, {0x0670, 0x0670}, + {0x0671, 0x06D3}, {0x06D4, 0x06D4}, {0x06D5, 0x06D5}, + {0x06D6, 0x06DC}, {0x06DD, 0x06DD}, {0x06DE, 0x06DE}, + {0x06DF, 0x06E4}, {0x06E5, 0x06E6}, {0x06E7, 0x06E8}, + {0x06E9, 0x06E9}, {0x06EA, 0x06ED}, {0x06EE, 0x06EF}, + {0x06F0, 0x06F9}, {0x06FA, 0x06FC}, {0x06FD, 0x06FE}, + {0x06FF, 0x06FF}, {0x0700, 0x070D}, {0x070F, 0x070F}, + {0x0710, 0x0710}, {0x0711, 0x0711}, {0x0712, 0x072F}, + {0x0730, 0x074A}, {0x074D, 0x074F}, {0x0750, 0x077F}, + {0x0780, 0x07A5}, {0x07A6, 0x07B0}, {0x07B1, 0x07B1}, + {0x07C0, 0x07C9}, {0x07CA, 0x07EA}, {0x07EB, 0x07F3}, + {0x07F4, 0x07F5}, {0x07F6, 0x07F6}, {0x07F7, 0x07F9}, + {0x07FA, 0x07FA}, {0x0800, 0x0815}, {0x0816, 0x0819}, + {0x081A, 0x081A}, {0x081B, 0x0823}, {0x0824, 0x0824}, + {0x0825, 0x0827}, {0x0828, 0x0828}, {0x0829, 0x082D}, + {0x0830, 0x083E}, {0x0840, 0x0858}, {0x0859, 0x085B}, + {0x085E, 0x085E}, {0x08A0, 0x08B4}, {0x08B6, 0x08BD}, + {0x08D4, 0x08E1}, {0x08E2, 0x08E2}, {0x08E3, 0x08FF}, + {0x0900, 0x0902}, {0x0903, 0x0903}, {0x0904, 0x0939}, + {0x093A, 0x093A}, {0x093B, 0x093B}, {0x093C, 0x093C}, + {0x093D, 0x093D}, {0x093E, 0x0940}, {0x0941, 0x0948}, + {0x0949, 0x094C}, {0x094D, 0x094D}, {0x094E, 0x094F}, + {0x0950, 0x0950}, {0x0951, 0x0957}, {0x0958, 0x0961}, + {0x0962, 0x0963}, {0x0964, 0x0965}, {0x0966, 0x096F}, + {0x0970, 0x0970}, {0x0971, 0x0971}, {0x0972, 0x097F}, + {0x0980, 0x0980}, {0x0981, 0x0981}, {0x0982, 0x0983}, + {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8}, + {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, + {0x09BC, 0x09BC}, {0x09BD, 0x09BD}, {0x09BE, 0x09C0}, + {0x09C1, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CC}, + {0x09CD, 0x09CD}, {0x09CE, 0x09CE}, {0x09D7, 0x09D7}, + {0x09DC, 0x09DD}, {0x09DF, 0x09E1}, {0x09E2, 0x09E3}, + {0x09E6, 0x09EF}, {0x09F0, 0x09F1}, {0x09F2, 0x09F3}, + {0x09F4, 0x09F9}, {0x09FA, 0x09FA}, {0x09FB, 0x09FB}, + {0x0A01, 0x0A02}, {0x0A03, 0x0A03}, {0x0A05, 0x0A0A}, + {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, + {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, + {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A40}, {0x0A41, 0x0A42}, + {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, + {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, {0x0A66, 0x0A6F}, + {0x0A70, 0x0A71}, {0x0A72, 0x0A74}, {0x0A75, 0x0A75}, + {0x0A81, 0x0A82}, {0x0A83, 0x0A83}, {0x0A85, 0x0A8D}, + {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, + {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0ABC}, + {0x0ABD, 0x0ABD}, {0x0ABE, 0x0AC0}, {0x0AC1, 0x0AC5}, + {0x0AC7, 0x0AC8}, {0x0AC9, 0x0AC9}, {0x0ACB, 0x0ACC}, + {0x0ACD, 0x0ACD}, {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE1}, + {0x0AE2, 0x0AE3}, {0x0AE6, 0x0AEF}, {0x0AF0, 0x0AF0}, + {0x0AF1, 0x0AF1}, {0x0AF9, 0x0AF9}, {0x0B01, 0x0B01}, + {0x0B02, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, + {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, + {0x0B35, 0x0B39}, {0x0B3C, 0x0B3C}, {0x0B3D, 0x0B3D}, + {0x0B3E, 0x0B3E}, {0x0B3F, 0x0B3F}, {0x0B40, 0x0B40}, + {0x0B41, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4C}, + {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B57, 0x0B57}, + {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B61}, {0x0B62, 0x0B63}, + {0x0B66, 0x0B6F}, {0x0B70, 0x0B70}, {0x0B71, 0x0B71}, + {0x0B72, 0x0B77}, {0x0B82, 0x0B82}, {0x0B83, 0x0B83}, + {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, + {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, + {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9}, + {0x0BBE, 0x0BBF}, {0x0BC0, 0x0BC0}, {0x0BC1, 0x0BC2}, + {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCC}, {0x0BCD, 0x0BCD}, + {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BEF}, + {0x0BF0, 0x0BF2}, {0x0BF3, 0x0BF8}, {0x0BF9, 0x0BF9}, + {0x0BFA, 0x0BFA}, {0x0C00, 0x0C00}, {0x0C01, 0x0C03}, + {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, + {0x0C2A, 0x0C39}, {0x0C3D, 0x0C3D}, {0x0C3E, 0x0C40}, + {0x0C41, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, + {0x0C55, 0x0C56}, {0x0C58, 0x0C5A}, {0x0C60, 0x0C61}, + {0x0C62, 0x0C63}, {0x0C66, 0x0C6F}, {0x0C78, 0x0C7E}, + {0x0C7F, 0x0C7F}, {0x0C80, 0x0C80}, {0x0C81, 0x0C81}, + {0x0C82, 0x0C83}, {0x0C85, 0x0C8C}, {0x0C8E, 0x0C90}, + {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, + {0x0CBC, 0x0CBC}, {0x0CBD, 0x0CBD}, {0x0CBE, 0x0CBE}, + {0x0CBF, 0x0CBF}, {0x0CC0, 0x0CC4}, {0x0CC6, 0x0CC6}, + {0x0CC7, 0x0CC8}, {0x0CCA, 0x0CCB}, {0x0CCC, 0x0CCD}, + {0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE1}, + {0x0CE2, 0x0CE3}, {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, + {0x0D01, 0x0D01}, {0x0D02, 0x0D03}, {0x0D05, 0x0D0C}, + {0x0D0E, 0x0D10}, {0x0D12, 0x0D3A}, {0x0D3D, 0x0D3D}, + {0x0D3E, 0x0D40}, {0x0D41, 0x0D44}, {0x0D46, 0x0D48}, + {0x0D4A, 0x0D4C}, {0x0D4D, 0x0D4D}, {0x0D4E, 0x0D4E}, + {0x0D4F, 0x0D4F}, {0x0D54, 0x0D56}, {0x0D57, 0x0D57}, + {0x0D58, 0x0D5E}, {0x0D5F, 0x0D61}, {0x0D62, 0x0D63}, + {0x0D66, 0x0D6F}, {0x0D70, 0x0D78}, {0x0D79, 0x0D79}, + {0x0D7A, 0x0D7F}, {0x0D82, 0x0D83}, {0x0D85, 0x0D96}, + {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, + {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD1}, + {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, + {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF3}, {0x0DF4, 0x0DF4}, + {0x0E01, 0x0E30}, {0x0E31, 0x0E31}, {0x0E32, 0x0E33}, + {0x0E34, 0x0E3A}, {0x0E3F, 0x0E3F}, {0x0E40, 0x0E45}, + {0x0E46, 0x0E46}, {0x0E47, 0x0E4E}, {0x0E4F, 0x0E4F}, + {0x0E50, 0x0E59}, {0x0E5A, 0x0E5B}, {0x0E81, 0x0E82}, + {0x0E84, 0x0E84}, {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, + {0x0E8D, 0x0E8D}, {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, + {0x0EA1, 0x0EA3}, {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EA7}, + {0x0EAA, 0x0EAB}, {0x0EAD, 0x0EB0}, {0x0EB1, 0x0EB1}, + {0x0EB2, 0x0EB3}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, + {0x0EBD, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6}, + {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF}, + {0x0F00, 0x0F00}, {0x0F01, 0x0F03}, {0x0F04, 0x0F12}, + {0x0F13, 0x0F13}, {0x0F14, 0x0F14}, {0x0F15, 0x0F17}, + {0x0F18, 0x0F19}, {0x0F1A, 0x0F1F}, {0x0F20, 0x0F29}, + {0x0F2A, 0x0F33}, {0x0F34, 0x0F34}, {0x0F35, 0x0F35}, + {0x0F36, 0x0F36}, {0x0F37, 0x0F37}, {0x0F38, 0x0F38}, + {0x0F39, 0x0F39}, {0x0F3A, 0x0F3A}, {0x0F3B, 0x0F3B}, + {0x0F3C, 0x0F3C}, {0x0F3D, 0x0F3D}, {0x0F3E, 0x0F3F}, + {0x0F40, 0x0F47}, {0x0F49, 0x0F6C}, {0x0F71, 0x0F7E}, + {0x0F7F, 0x0F7F}, {0x0F80, 0x0F84}, {0x0F85, 0x0F85}, + {0x0F86, 0x0F87}, {0x0F88, 0x0F8C}, {0x0F8D, 0x0F97}, + {0x0F99, 0x0FBC}, {0x0FBE, 0x0FC5}, {0x0FC6, 0x0FC6}, + {0x0FC7, 0x0FCC}, {0x0FCE, 0x0FCF}, {0x0FD0, 0x0FD4}, + {0x0FD5, 0x0FD8}, {0x0FD9, 0x0FDA}, {0x1000, 0x102A}, + {0x102B, 0x102C}, {0x102D, 0x1030}, {0x1031, 0x1031}, + {0x1032, 0x1037}, {0x1038, 0x1038}, {0x1039, 0x103A}, + {0x103B, 0x103C}, {0x103D, 0x103E}, {0x103F, 0x103F}, + {0x1040, 0x1049}, {0x104A, 0x104F}, {0x1050, 0x1055}, + {0x1056, 0x1057}, {0x1058, 0x1059}, {0x105A, 0x105D}, + {0x105E, 0x1060}, {0x1061, 0x1061}, {0x1062, 0x1064}, + {0x1065, 0x1066}, {0x1067, 0x106D}, {0x106E, 0x1070}, + {0x1071, 0x1074}, {0x1075, 0x1081}, {0x1082, 0x1082}, + {0x1083, 0x1084}, {0x1085, 0x1086}, {0x1087, 0x108C}, + {0x108D, 0x108D}, {0x108E, 0x108E}, {0x108F, 0x108F}, + {0x1090, 0x1099}, {0x109A, 0x109C}, {0x109D, 0x109D}, + {0x109E, 0x109F}, {0x10A0, 0x10C5}, {0x10C7, 0x10C7}, + {0x10CD, 0x10CD}, {0x10D0, 0x10FA}, {0x10FB, 0x10FB}, + {0x10FC, 0x10FC}, {0x10FD, 0x10FF}, {0x1160, 0x11FF}, + {0x1200, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256}, + {0x1258, 0x1258}, {0x125A, 0x125D}, {0x1260, 0x1288}, + {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, + {0x12B8, 0x12BE}, {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, + {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, + {0x1318, 0x135A}, {0x135D, 0x135F}, {0x1360, 0x1368}, + {0x1369, 0x137C}, {0x1380, 0x138F}, {0x1390, 0x1399}, + {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1400, 0x1400}, + {0x1401, 0x166C}, {0x166D, 0x166E}, {0x166F, 0x167F}, + {0x1680, 0x1680}, {0x1681, 0x169A}, {0x169B, 0x169B}, + {0x169C, 0x169C}, {0x16A0, 0x16EA}, {0x16EB, 0x16ED}, + {0x16EE, 0x16F0}, {0x16F1, 0x16F8}, {0x1700, 0x170C}, + {0x170E, 0x1711}, {0x1712, 0x1714}, {0x1720, 0x1731}, + {0x1732, 0x1734}, {0x1735, 0x1736}, {0x1740, 0x1751}, + {0x1752, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770}, + {0x1772, 0x1773}, {0x1780, 0x17B3}, {0x17B4, 0x17B5}, + {0x17B6, 0x17B6}, {0x17B7, 0x17BD}, {0x17BE, 0x17C5}, + {0x17C6, 0x17C6}, {0x17C7, 0x17C8}, {0x17C9, 0x17D3}, + {0x17D4, 0x17D6}, {0x17D7, 0x17D7}, {0x17D8, 0x17DA}, + {0x17DB, 0x17DB}, {0x17DC, 0x17DC}, {0x17DD, 0x17DD}, + {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x1805}, + {0x1806, 0x1806}, {0x1807, 0x180A}, {0x180B, 0x180D}, + {0x180E, 0x180E}, {0x1810, 0x1819}, {0x1820, 0x1842}, + {0x1843, 0x1843}, {0x1844, 0x1877}, {0x1880, 0x1884}, + {0x1885, 0x1886}, {0x1887, 0x18A8}, {0x18A9, 0x18A9}, + {0x18AA, 0x18AA}, {0x18B0, 0x18F5}, {0x1900, 0x191E}, + {0x1920, 0x1922}, {0x1923, 0x1926}, {0x1927, 0x1928}, + {0x1929, 0x192B}, {0x1930, 0x1931}, {0x1932, 0x1932}, + {0x1933, 0x1938}, {0x1939, 0x193B}, {0x1940, 0x1940}, + {0x1944, 0x1945}, {0x1946, 0x194F}, {0x1950, 0x196D}, + {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, + {0x19D0, 0x19D9}, {0x19DA, 0x19DA}, {0x19DE, 0x19DF}, + {0x19E0, 0x19FF}, {0x1A00, 0x1A16}, {0x1A17, 0x1A18}, + {0x1A19, 0x1A1A}, {0x1A1B, 0x1A1B}, {0x1A1E, 0x1A1F}, + {0x1A20, 0x1A54}, {0x1A55, 0x1A55}, {0x1A56, 0x1A56}, + {0x1A57, 0x1A57}, {0x1A58, 0x1A5E}, {0x1A60, 0x1A60}, + {0x1A61, 0x1A61}, {0x1A62, 0x1A62}, {0x1A63, 0x1A64}, + {0x1A65, 0x1A6C}, {0x1A6D, 0x1A72}, {0x1A73, 0x1A7C}, + {0x1A7F, 0x1A7F}, {0x1A80, 0x1A89}, {0x1A90, 0x1A99}, + {0x1AA0, 0x1AA6}, {0x1AA7, 0x1AA7}, {0x1AA8, 0x1AAD}, + {0x1AB0, 0x1ABD}, {0x1ABE, 0x1ABE}, {0x1B00, 0x1B03}, + {0x1B04, 0x1B04}, {0x1B05, 0x1B33}, {0x1B34, 0x1B34}, + {0x1B35, 0x1B35}, {0x1B36, 0x1B3A}, {0x1B3B, 0x1B3B}, + {0x1B3C, 0x1B3C}, {0x1B3D, 0x1B41}, {0x1B42, 0x1B42}, + {0x1B43, 0x1B44}, {0x1B45, 0x1B4B}, {0x1B50, 0x1B59}, + {0x1B5A, 0x1B60}, {0x1B61, 0x1B6A}, {0x1B6B, 0x1B73}, + {0x1B74, 0x1B7C}, {0x1B80, 0x1B81}, {0x1B82, 0x1B82}, + {0x1B83, 0x1BA0}, {0x1BA1, 0x1BA1}, {0x1BA2, 0x1BA5}, + {0x1BA6, 0x1BA7}, {0x1BA8, 0x1BA9}, {0x1BAA, 0x1BAA}, + {0x1BAB, 0x1BAD}, {0x1BAE, 0x1BAF}, {0x1BB0, 0x1BB9}, + {0x1BBA, 0x1BBF}, {0x1BC0, 0x1BE5}, {0x1BE6, 0x1BE6}, + {0x1BE7, 0x1BE7}, {0x1BE8, 0x1BE9}, {0x1BEA, 0x1BEC}, + {0x1BED, 0x1BED}, {0x1BEE, 0x1BEE}, {0x1BEF, 0x1BF1}, + {0x1BF2, 0x1BF3}, {0x1BFC, 0x1BFF}, {0x1C00, 0x1C23}, + {0x1C24, 0x1C2B}, {0x1C2C, 0x1C33}, {0x1C34, 0x1C35}, + {0x1C36, 0x1C37}, {0x1C3B, 0x1C3F}, {0x1C40, 0x1C49}, + {0x1C4D, 0x1C4F}, {0x1C50, 0x1C59}, {0x1C5A, 0x1C77}, + {0x1C78, 0x1C7D}, {0x1C7E, 0x1C7F}, {0x1C80, 0x1C88}, + {0x1CC0, 0x1CC7}, {0x1CD0, 0x1CD2}, {0x1CD3, 0x1CD3}, + {0x1CD4, 0x1CE0}, {0x1CE1, 0x1CE1}, {0x1CE2, 0x1CE8}, + {0x1CE9, 0x1CEC}, {0x1CED, 0x1CED}, {0x1CEE, 0x1CF1}, + {0x1CF2, 0x1CF3}, {0x1CF4, 0x1CF4}, {0x1CF5, 0x1CF6}, + {0x1CF8, 0x1CF9}, {0x1D00, 0x1D2B}, {0x1D2C, 0x1D6A}, + {0x1D6B, 0x1D77}, {0x1D78, 0x1D78}, {0x1D79, 0x1D7F}, + {0x1D80, 0x1D9A}, {0x1D9B, 0x1DBF}, {0x1DC0, 0x1DF5}, + {0x1DFB, 0x1DFF}, {0x1E00, 0x1EFF}, {0x1F00, 0x1F15}, + {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, + {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, + {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, + {0x1FB6, 0x1FBC}, {0x1FBD, 0x1FBD}, {0x1FBE, 0x1FBE}, + {0x1FBF, 0x1FC1}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, + {0x1FCD, 0x1FCF}, {0x1FD0, 0x1FD3}, {0x1FD6, 0x1FDB}, + {0x1FDD, 0x1FDF}, {0x1FE0, 0x1FEC}, {0x1FED, 0x1FEF}, + {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x1FFD, 0x1FFE}, + {0x2000, 0x200A}, {0x200B, 0x200F}, {0x2011, 0x2012}, + {0x2017, 0x2017}, {0x201A, 0x201A}, {0x201B, 0x201B}, + {0x201E, 0x201E}, {0x201F, 0x201F}, {0x2023, 0x2023}, + {0x2028, 0x2028}, {0x2029, 0x2029}, {0x202A, 0x202E}, + {0x202F, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034}, + {0x2036, 0x2038}, {0x2039, 0x2039}, {0x203A, 0x203A}, + {0x203C, 0x203D}, {0x203F, 0x2040}, {0x2041, 0x2043}, + {0x2044, 0x2044}, {0x2045, 0x2045}, {0x2046, 0x2046}, + {0x2047, 0x2051}, {0x2052, 0x2052}, {0x2053, 0x2053}, + {0x2054, 0x2054}, {0x2055, 0x205E}, {0x205F, 0x205F}, + {0x2060, 0x2064}, {0x2066, 0x206F}, {0x2070, 0x2070}, + {0x2071, 0x2071}, {0x2075, 0x2079}, {0x207A, 0x207C}, + {0x207D, 0x207D}, {0x207E, 0x207E}, {0x2080, 0x2080}, + {0x2085, 0x2089}, {0x208A, 0x208C}, {0x208D, 0x208D}, + {0x208E, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8}, + {0x20AA, 0x20AB}, {0x20AD, 0x20BE}, {0x20D0, 0x20DC}, + {0x20DD, 0x20E0}, {0x20E1, 0x20E1}, {0x20E2, 0x20E4}, + {0x20E5, 0x20F0}, {0x2100, 0x2101}, {0x2102, 0x2102}, + {0x2104, 0x2104}, {0x2106, 0x2106}, {0x2107, 0x2107}, + {0x2108, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2114}, + {0x2115, 0x2115}, {0x2117, 0x2117}, {0x2118, 0x2118}, + {0x2119, 0x211D}, {0x211E, 0x2120}, {0x2123, 0x2123}, + {0x2124, 0x2124}, {0x2125, 0x2125}, {0x2127, 0x2127}, + {0x2128, 0x2128}, {0x2129, 0x2129}, {0x212A, 0x212A}, + {0x212C, 0x212D}, {0x212E, 0x212E}, {0x212F, 0x2134}, + {0x2135, 0x2138}, {0x2139, 0x2139}, {0x213A, 0x213B}, + {0x213C, 0x213F}, {0x2140, 0x2144}, {0x2145, 0x2149}, + {0x214A, 0x214A}, {0x214B, 0x214B}, {0x214C, 0x214D}, + {0x214E, 0x214E}, {0x214F, 0x214F}, {0x2150, 0x2152}, + {0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F}, + {0x217A, 0x2182}, {0x2183, 0x2184}, {0x2185, 0x2188}, + {0x218A, 0x218B}, {0x219A, 0x219B}, {0x219C, 0x219F}, + {0x21A0, 0x21A0}, {0x21A1, 0x21A2}, {0x21A3, 0x21A3}, + {0x21A4, 0x21A5}, {0x21A6, 0x21A6}, {0x21A7, 0x21AD}, + {0x21AE, 0x21AE}, {0x21AF, 0x21B7}, {0x21BA, 0x21CD}, + {0x21CE, 0x21CF}, {0x21D0, 0x21D1}, {0x21D3, 0x21D3}, + {0x21D5, 0x21E6}, {0x21E8, 0x21F3}, {0x21F4, 0x21FF}, + {0x2201, 0x2201}, {0x2204, 0x2206}, {0x2209, 0x220A}, + {0x220C, 0x220E}, {0x2210, 0x2210}, {0x2212, 0x2214}, + {0x2216, 0x2219}, {0x221B, 0x221C}, {0x2221, 0x2222}, + {0x2224, 0x2224}, {0x2226, 0x2226}, {0x222D, 0x222D}, + {0x222F, 0x2233}, {0x2238, 0x223B}, {0x223E, 0x2247}, + {0x2249, 0x224B}, {0x224D, 0x2251}, {0x2253, 0x225F}, + {0x2262, 0x2263}, {0x2268, 0x2269}, {0x226C, 0x226D}, + {0x2270, 0x2281}, {0x2284, 0x2285}, {0x2288, 0x2294}, + {0x2296, 0x2298}, {0x229A, 0x22A4}, {0x22A6, 0x22BE}, + {0x22C0, 0x22FF}, {0x2300, 0x2307}, {0x2308, 0x2308}, + {0x2309, 0x2309}, {0x230A, 0x230A}, {0x230B, 0x230B}, + {0x230C, 0x2311}, {0x2313, 0x2319}, {0x231C, 0x231F}, + {0x2320, 0x2321}, {0x2322, 0x2328}, {0x232B, 0x237B}, + {0x237C, 0x237C}, {0x237D, 0x239A}, {0x239B, 0x23B3}, + {0x23B4, 0x23DB}, {0x23DC, 0x23E1}, {0x23E2, 0x23E8}, + {0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x23FE}, + {0x2400, 0x2426}, {0x2440, 0x244A}, {0x24EA, 0x24EA}, + {0x254C, 0x254F}, {0x2574, 0x257F}, {0x2590, 0x2591}, + {0x2596, 0x259F}, {0x25A2, 0x25A2}, {0x25AA, 0x25B1}, + {0x25B4, 0x25B5}, {0x25B8, 0x25BB}, {0x25BE, 0x25BF}, + {0x25C2, 0x25C5}, {0x25C9, 0x25CA}, {0x25CC, 0x25CD}, + {0x25D2, 0x25E1}, {0x25E6, 0x25EE}, {0x25F0, 0x25F7}, + {0x25F8, 0x25FC}, {0x25FF, 0x25FF}, {0x2600, 0x2604}, + {0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613}, + {0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x263F}, + {0x2641, 0x2641}, {0x2643, 0x2647}, {0x2654, 0x265F}, + {0x2662, 0x2662}, {0x2666, 0x2666}, {0x266B, 0x266B}, + {0x266E, 0x266E}, {0x2670, 0x267E}, {0x2680, 0x2692}, + {0x2694, 0x269D}, {0x26A0, 0x26A0}, {0x26A2, 0x26A9}, + {0x26AC, 0x26BC}, {0x26C0, 0x26C3}, {0x26E2, 0x26E2}, + {0x26E4, 0x26E7}, {0x2700, 0x2704}, {0x2706, 0x2709}, + {0x270C, 0x2727}, {0x2729, 0x273C}, {0x273E, 0x274B}, + {0x274D, 0x274D}, {0x274F, 0x2752}, {0x2756, 0x2756}, + {0x2758, 0x2767}, {0x2768, 0x2768}, {0x2769, 0x2769}, + {0x276A, 0x276A}, {0x276B, 0x276B}, {0x276C, 0x276C}, + {0x276D, 0x276D}, {0x276E, 0x276E}, {0x276F, 0x276F}, + {0x2770, 0x2770}, {0x2771, 0x2771}, {0x2772, 0x2772}, + {0x2773, 0x2773}, {0x2774, 0x2774}, {0x2775, 0x2775}, + {0x2780, 0x2793}, {0x2794, 0x2794}, {0x2798, 0x27AF}, + {0x27B1, 0x27BE}, {0x27C0, 0x27C4}, {0x27C5, 0x27C5}, + {0x27C6, 0x27C6}, {0x27C7, 0x27E5}, {0x27EE, 0x27EE}, + {0x27EF, 0x27EF}, {0x27F0, 0x27FF}, {0x2800, 0x28FF}, + {0x2900, 0x297F}, {0x2980, 0x2982}, {0x2983, 0x2983}, + {0x2984, 0x2984}, {0x2987, 0x2987}, {0x2988, 0x2988}, + {0x2989, 0x2989}, {0x298A, 0x298A}, {0x298B, 0x298B}, + {0x298C, 0x298C}, {0x298D, 0x298D}, {0x298E, 0x298E}, + {0x298F, 0x298F}, {0x2990, 0x2990}, {0x2991, 0x2991}, + {0x2992, 0x2992}, {0x2993, 0x2993}, {0x2994, 0x2994}, + {0x2995, 0x2995}, {0x2996, 0x2996}, {0x2997, 0x2997}, + {0x2998, 0x2998}, {0x2999, 0x29D7}, {0x29D8, 0x29D8}, + {0x29D9, 0x29D9}, {0x29DA, 0x29DA}, {0x29DB, 0x29DB}, + {0x29DC, 0x29FB}, {0x29FC, 0x29FC}, {0x29FD, 0x29FD}, + {0x29FE, 0x29FF}, {0x2A00, 0x2AFF}, {0x2B00, 0x2B1A}, + {0x2B1D, 0x2B2F}, {0x2B30, 0x2B44}, {0x2B45, 0x2B46}, + {0x2B47, 0x2B4C}, {0x2B4D, 0x2B4F}, {0x2B51, 0x2B54}, + {0x2B5A, 0x2B73}, {0x2B76, 0x2B95}, {0x2B98, 0x2BB9}, + {0x2BBD, 0x2BC8}, {0x2BCA, 0x2BD1}, {0x2BEC, 0x2BEF}, + {0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2C7B}, + {0x2C7C, 0x2C7D}, {0x2C7E, 0x2C7F}, {0x2C80, 0x2CE4}, + {0x2CE5, 0x2CEA}, {0x2CEB, 0x2CEE}, {0x2CEF, 0x2CF1}, + {0x2CF2, 0x2CF3}, {0x2CF9, 0x2CFC}, {0x2CFD, 0x2CFD}, + {0x2CFE, 0x2CFF}, {0x2D00, 0x2D25}, {0x2D27, 0x2D27}, + {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D6F}, + {0x2D70, 0x2D70}, {0x2D7F, 0x2D7F}, {0x2D80, 0x2D96}, + {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, + {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, + {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x2DE0, 0x2DFF}, + {0x2E00, 0x2E01}, {0x2E02, 0x2E02}, {0x2E03, 0x2E03}, + {0x2E04, 0x2E04}, {0x2E05, 0x2E05}, {0x2E06, 0x2E08}, + {0x2E09, 0x2E09}, {0x2E0A, 0x2E0A}, {0x2E0B, 0x2E0B}, + {0x2E0C, 0x2E0C}, {0x2E0D, 0x2E0D}, {0x2E0E, 0x2E16}, + {0x2E17, 0x2E17}, {0x2E18, 0x2E19}, {0x2E1A, 0x2E1A}, + {0x2E1B, 0x2E1B}, {0x2E1C, 0x2E1C}, {0x2E1D, 0x2E1D}, + {0x2E1E, 0x2E1F}, {0x2E20, 0x2E20}, {0x2E21, 0x2E21}, + {0x2E22, 0x2E22}, {0x2E23, 0x2E23}, {0x2E24, 0x2E24}, + {0x2E25, 0x2E25}, {0x2E26, 0x2E26}, {0x2E27, 0x2E27}, + {0x2E28, 0x2E28}, {0x2E29, 0x2E29}, {0x2E2A, 0x2E2E}, + {0x2E2F, 0x2E2F}, {0x2E30, 0x2E39}, {0x2E3A, 0x2E3B}, + {0x2E3C, 0x2E3F}, {0x2E40, 0x2E40}, {0x2E41, 0x2E41}, + {0x2E42, 0x2E42}, {0x2E43, 0x2E44}, {0x303F, 0x303F}, + {0x4DC0, 0x4DFF}, {0xA4D0, 0xA4F7}, {0xA4F8, 0xA4FD}, + {0xA4FE, 0xA4FF}, {0xA500, 0xA60B}, {0xA60C, 0xA60C}, + {0xA60D, 0xA60F}, {0xA610, 0xA61F}, {0xA620, 0xA629}, + {0xA62A, 0xA62B}, {0xA640, 0xA66D}, {0xA66E, 0xA66E}, + {0xA66F, 0xA66F}, {0xA670, 0xA672}, {0xA673, 0xA673}, + {0xA674, 0xA67D}, {0xA67E, 0xA67E}, {0xA67F, 0xA67F}, + {0xA680, 0xA69B}, {0xA69C, 0xA69D}, {0xA69E, 0xA69F}, + {0xA6A0, 0xA6E5}, {0xA6E6, 0xA6EF}, {0xA6F0, 0xA6F1}, + {0xA6F2, 0xA6F7}, {0xA700, 0xA716}, {0xA717, 0xA71F}, + {0xA720, 0xA721}, {0xA722, 0xA76F}, {0xA770, 0xA770}, + {0xA771, 0xA787}, {0xA788, 0xA788}, {0xA789, 0xA78A}, + {0xA78B, 0xA78E}, {0xA78F, 0xA78F}, {0xA790, 0xA7AE}, + {0xA7B0, 0xA7B7}, {0xA7F7, 0xA7F7}, {0xA7F8, 0xA7F9}, + {0xA7FA, 0xA7FA}, {0xA7FB, 0xA7FF}, {0xA800, 0xA801}, + {0xA802, 0xA802}, {0xA803, 0xA805}, {0xA806, 0xA806}, + {0xA807, 0xA80A}, {0xA80B, 0xA80B}, {0xA80C, 0xA822}, + {0xA823, 0xA824}, {0xA825, 0xA826}, {0xA827, 0xA827}, + {0xA828, 0xA82B}, {0xA830, 0xA835}, {0xA836, 0xA837}, + {0xA838, 0xA838}, {0xA839, 0xA839}, {0xA840, 0xA873}, + {0xA874, 0xA877}, {0xA880, 0xA881}, {0xA882, 0xA8B3}, + {0xA8B4, 0xA8C3}, {0xA8C4, 0xA8C5}, {0xA8CE, 0xA8CF}, + {0xA8D0, 0xA8D9}, {0xA8E0, 0xA8F1}, {0xA8F2, 0xA8F7}, + {0xA8F8, 0xA8FA}, {0xA8FB, 0xA8FB}, {0xA8FC, 0xA8FC}, + {0xA8FD, 0xA8FD}, {0xA900, 0xA909}, {0xA90A, 0xA925}, + {0xA926, 0xA92D}, {0xA92E, 0xA92F}, {0xA930, 0xA946}, + {0xA947, 0xA951}, {0xA952, 0xA953}, {0xA95F, 0xA95F}, + {0xA980, 0xA982}, {0xA983, 0xA983}, {0xA984, 0xA9B2}, + {0xA9B3, 0xA9B3}, {0xA9B4, 0xA9B5}, {0xA9B6, 0xA9B9}, + {0xA9BA, 0xA9BB}, {0xA9BC, 0xA9BC}, {0xA9BD, 0xA9C0}, + {0xA9C1, 0xA9CD}, {0xA9CF, 0xA9CF}, {0xA9D0, 0xA9D9}, + {0xA9DE, 0xA9DF}, {0xA9E0, 0xA9E4}, {0xA9E5, 0xA9E5}, + {0xA9E6, 0xA9E6}, {0xA9E7, 0xA9EF}, {0xA9F0, 0xA9F9}, + {0xA9FA, 0xA9FE}, {0xAA00, 0xAA28}, {0xAA29, 0xAA2E}, + {0xAA2F, 0xAA30}, {0xAA31, 0xAA32}, {0xAA33, 0xAA34}, + {0xAA35, 0xAA36}, {0xAA40, 0xAA42}, {0xAA43, 0xAA43}, + {0xAA44, 0xAA4B}, {0xAA4C, 0xAA4C}, {0xAA4D, 0xAA4D}, + {0xAA50, 0xAA59}, {0xAA5C, 0xAA5F}, {0xAA60, 0xAA6F}, + {0xAA70, 0xAA70}, {0xAA71, 0xAA76}, {0xAA77, 0xAA79}, + {0xAA7A, 0xAA7A}, {0xAA7B, 0xAA7B}, {0xAA7C, 0xAA7C}, + {0xAA7D, 0xAA7D}, {0xAA7E, 0xAA7F}, {0xAA80, 0xAAAF}, + {0xAAB0, 0xAAB0}, {0xAAB1, 0xAAB1}, {0xAAB2, 0xAAB4}, + {0xAAB5, 0xAAB6}, {0xAAB7, 0xAAB8}, {0xAAB9, 0xAABD}, + {0xAABE, 0xAABF}, {0xAAC0, 0xAAC0}, {0xAAC1, 0xAAC1}, + {0xAAC2, 0xAAC2}, {0xAADB, 0xAADC}, {0xAADD, 0xAADD}, + {0xAADE, 0xAADF}, {0xAAE0, 0xAAEA}, {0xAAEB, 0xAAEB}, + {0xAAEC, 0xAAED}, {0xAAEE, 0xAAEF}, {0xAAF0, 0xAAF1}, + {0xAAF2, 0xAAF2}, {0xAAF3, 0xAAF4}, {0xAAF5, 0xAAF5}, + {0xAAF6, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, + {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, + {0xAB30, 0xAB5A}, {0xAB5B, 0xAB5B}, {0xAB5C, 0xAB5F}, + {0xAB60, 0xAB65}, {0xAB70, 0xABBF}, {0xABC0, 0xABE2}, + {0xABE3, 0xABE4}, {0xABE5, 0xABE5}, {0xABE6, 0xABE7}, + {0xABE8, 0xABE8}, {0xABE9, 0xABEA}, {0xABEB, 0xABEB}, + {0xABEC, 0xABEC}, {0xABED, 0xABED}, {0xABF0, 0xABF9}, + {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDB7F}, + {0xDB80, 0xDBFF}, {0xDC00, 0xDFFF}, {0xFB00, 0xFB06}, + {0xFB13, 0xFB17}, {0xFB1D, 0xFB1D}, {0xFB1E, 0xFB1E}, + {0xFB1F, 0xFB28}, {0xFB29, 0xFB29}, {0xFB2A, 0xFB36}, + {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41}, + {0xFB43, 0xFB44}, {0xFB46, 0xFB4F}, {0xFB50, 0xFBB1}, + {0xFBB2, 0xFBC1}, {0xFBD3, 0xFD3D}, {0xFD3E, 0xFD3E}, + {0xFD3F, 0xFD3F}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, + {0xFDF0, 0xFDFB}, {0xFDFC, 0xFDFC}, {0xFDFD, 0xFDFD}, + {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFC, 0xFFFC}, + {0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, + {0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D}, + {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133}, + {0x10137, 0x1013F}, {0x10140, 0x10174}, {0x10175, 0x10178}, + {0x10179, 0x10189}, {0x1018A, 0x1018B}, {0x1018C, 0x1018E}, + {0x10190, 0x1019B}, {0x101A0, 0x101A0}, {0x101D0, 0x101FC}, + {0x101FD, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0}, + {0x102E0, 0x102E0}, {0x102E1, 0x102FB}, {0x10300, 0x1031F}, + {0x10320, 0x10323}, {0x10330, 0x10340}, {0x10341, 0x10341}, + {0x10342, 0x10349}, {0x1034A, 0x1034A}, {0x10350, 0x10375}, + {0x10376, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x1039F}, + {0x103A0, 0x103C3}, {0x103C8, 0x103CF}, {0x103D0, 0x103D0}, + {0x103D1, 0x103D5}, {0x10400, 0x1044F}, {0x10450, 0x1047F}, + {0x10480, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, + {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563}, + {0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755}, + {0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808}, + {0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C}, + {0x1083F, 0x1083F}, {0x10840, 0x10855}, {0x10857, 0x10857}, + {0x10858, 0x1085F}, {0x10860, 0x10876}, {0x10877, 0x10878}, + {0x10879, 0x1087F}, {0x10880, 0x1089E}, {0x108A7, 0x108AF}, + {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x108FF}, + {0x10900, 0x10915}, {0x10916, 0x1091B}, {0x1091F, 0x1091F}, + {0x10920, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x1099F}, + {0x109A0, 0x109B7}, {0x109BC, 0x109BD}, {0x109BE, 0x109BF}, + {0x109C0, 0x109CF}, {0x109D2, 0x109FF}, {0x10A00, 0x10A00}, + {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, + {0x10A10, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A33}, + {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x10A40, 0x10A47}, + {0x10A50, 0x10A58}, {0x10A60, 0x10A7C}, {0x10A7D, 0x10A7E}, + {0x10A7F, 0x10A7F}, {0x10A80, 0x10A9C}, {0x10A9D, 0x10A9F}, + {0x10AC0, 0x10AC7}, {0x10AC8, 0x10AC8}, {0x10AC9, 0x10AE4}, + {0x10AE5, 0x10AE6}, {0x10AEB, 0x10AEF}, {0x10AF0, 0x10AF6}, + {0x10B00, 0x10B35}, {0x10B39, 0x10B3F}, {0x10B40, 0x10B55}, + {0x10B58, 0x10B5F}, {0x10B60, 0x10B72}, {0x10B78, 0x10B7F}, + {0x10B80, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF}, + {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, + {0x10CFA, 0x10CFF}, {0x10E60, 0x10E7E}, {0x11000, 0x11000}, + {0x11001, 0x11001}, {0x11002, 0x11002}, {0x11003, 0x11037}, + {0x11038, 0x11046}, {0x11047, 0x1104D}, {0x11052, 0x11065}, + {0x11066, 0x1106F}, {0x1107F, 0x1107F}, {0x11080, 0x11081}, + {0x11082, 0x11082}, {0x11083, 0x110AF}, {0x110B0, 0x110B2}, + {0x110B3, 0x110B6}, {0x110B7, 0x110B8}, {0x110B9, 0x110BA}, + {0x110BB, 0x110BC}, {0x110BD, 0x110BD}, {0x110BE, 0x110C1}, + {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, {0x11100, 0x11102}, + {0x11103, 0x11126}, {0x11127, 0x1112B}, {0x1112C, 0x1112C}, + {0x1112D, 0x11134}, {0x11136, 0x1113F}, {0x11140, 0x11143}, + {0x11150, 0x11172}, {0x11173, 0x11173}, {0x11174, 0x11175}, + {0x11176, 0x11176}, {0x11180, 0x11181}, {0x11182, 0x11182}, + {0x11183, 0x111B2}, {0x111B3, 0x111B5}, {0x111B6, 0x111BE}, + {0x111BF, 0x111C0}, {0x111C1, 0x111C4}, {0x111C5, 0x111C9}, + {0x111CA, 0x111CC}, {0x111CD, 0x111CD}, {0x111D0, 0x111D9}, + {0x111DA, 0x111DA}, {0x111DB, 0x111DB}, {0x111DC, 0x111DC}, + {0x111DD, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211}, + {0x11213, 0x1122B}, {0x1122C, 0x1122E}, {0x1122F, 0x11231}, + {0x11232, 0x11233}, {0x11234, 0x11234}, {0x11235, 0x11235}, + {0x11236, 0x11237}, {0x11238, 0x1123D}, {0x1123E, 0x1123E}, + {0x11280, 0x11286}, {0x11288, 0x11288}, {0x1128A, 0x1128D}, + {0x1128F, 0x1129D}, {0x1129F, 0x112A8}, {0x112A9, 0x112A9}, + {0x112B0, 0x112DE}, {0x112DF, 0x112DF}, {0x112E0, 0x112E2}, + {0x112E3, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11301}, + {0x11302, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310}, + {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333}, + {0x11335, 0x11339}, {0x1133C, 0x1133C}, {0x1133D, 0x1133D}, + {0x1133E, 0x1133F}, {0x11340, 0x11340}, {0x11341, 0x11344}, + {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11350, 0x11350}, + {0x11357, 0x11357}, {0x1135D, 0x11361}, {0x11362, 0x11363}, + {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x11434}, + {0x11435, 0x11437}, {0x11438, 0x1143F}, {0x11440, 0x11441}, + {0x11442, 0x11444}, {0x11445, 0x11445}, {0x11446, 0x11446}, + {0x11447, 0x1144A}, {0x1144B, 0x1144F}, {0x11450, 0x11459}, + {0x1145B, 0x1145B}, {0x1145D, 0x1145D}, {0x11480, 0x114AF}, + {0x114B0, 0x114B2}, {0x114B3, 0x114B8}, {0x114B9, 0x114B9}, + {0x114BA, 0x114BA}, {0x114BB, 0x114BE}, {0x114BF, 0x114C0}, + {0x114C1, 0x114C1}, {0x114C2, 0x114C3}, {0x114C4, 0x114C5}, + {0x114C6, 0x114C6}, {0x114C7, 0x114C7}, {0x114D0, 0x114D9}, + {0x11580, 0x115AE}, {0x115AF, 0x115B1}, {0x115B2, 0x115B5}, + {0x115B8, 0x115BB}, {0x115BC, 0x115BD}, {0x115BE, 0x115BE}, + {0x115BF, 0x115C0}, {0x115C1, 0x115D7}, {0x115D8, 0x115DB}, + {0x115DC, 0x115DD}, {0x11600, 0x1162F}, {0x11630, 0x11632}, + {0x11633, 0x1163A}, {0x1163B, 0x1163C}, {0x1163D, 0x1163D}, + {0x1163E, 0x1163E}, {0x1163F, 0x11640}, {0x11641, 0x11643}, + {0x11644, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C}, + {0x11680, 0x116AA}, {0x116AB, 0x116AB}, {0x116AC, 0x116AC}, + {0x116AD, 0x116AD}, {0x116AE, 0x116AF}, {0x116B0, 0x116B5}, + {0x116B6, 0x116B6}, {0x116B7, 0x116B7}, {0x116C0, 0x116C9}, + {0x11700, 0x11719}, {0x1171D, 0x1171F}, {0x11720, 0x11721}, + {0x11722, 0x11725}, {0x11726, 0x11726}, {0x11727, 0x1172B}, + {0x11730, 0x11739}, {0x1173A, 0x1173B}, {0x1173C, 0x1173E}, + {0x1173F, 0x1173F}, {0x118A0, 0x118DF}, {0x118E0, 0x118E9}, + {0x118EA, 0x118F2}, {0x118FF, 0x118FF}, {0x11AC0, 0x11AF8}, + {0x11C00, 0x11C08}, {0x11C0A, 0x11C2E}, {0x11C2F, 0x11C2F}, + {0x11C30, 0x11C36}, {0x11C38, 0x11C3D}, {0x11C3E, 0x11C3E}, + {0x11C3F, 0x11C3F}, {0x11C40, 0x11C40}, {0x11C41, 0x11C45}, + {0x11C50, 0x11C59}, {0x11C5A, 0x11C6C}, {0x11C70, 0x11C71}, + {0x11C72, 0x11C8F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CA9}, + {0x11CAA, 0x11CB0}, {0x11CB1, 0x11CB1}, {0x11CB2, 0x11CB3}, + {0x11CB4, 0x11CB4}, {0x11CB5, 0x11CB6}, {0x12000, 0x12399}, + {0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543}, + {0x13000, 0x1342E}, {0x14400, 0x14646}, {0x16800, 0x16A38}, + {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16A6F}, + {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF4}, {0x16AF5, 0x16AF5}, + {0x16B00, 0x16B2F}, {0x16B30, 0x16B36}, {0x16B37, 0x16B3B}, + {0x16B3C, 0x16B3F}, {0x16B40, 0x16B43}, {0x16B44, 0x16B44}, + {0x16B45, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, + {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16F00, 0x16F44}, + {0x16F50, 0x16F50}, {0x16F51, 0x16F7E}, {0x16F8F, 0x16F92}, + {0x16F93, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, + {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BC9C}, + {0x1BC9D, 0x1BC9E}, {0x1BC9F, 0x1BC9F}, {0x1BCA0, 0x1BCA3}, + {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D164}, + {0x1D165, 0x1D166}, {0x1D167, 0x1D169}, {0x1D16A, 0x1D16C}, + {0x1D16D, 0x1D172}, {0x1D173, 0x1D17A}, {0x1D17B, 0x1D182}, + {0x1D183, 0x1D184}, {0x1D185, 0x1D18B}, {0x1D18C, 0x1D1A9}, + {0x1D1AA, 0x1D1AD}, {0x1D1AE, 0x1D1E8}, {0x1D200, 0x1D241}, + {0x1D242, 0x1D244}, {0x1D245, 0x1D245}, {0x1D300, 0x1D356}, + {0x1D360, 0x1D371}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, + {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, + {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, + {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, + {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, + {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D546, 0x1D546}, + {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D6C0}, + {0x1D6C1, 0x1D6C1}, {0x1D6C2, 0x1D6DA}, {0x1D6DB, 0x1D6DB}, + {0x1D6DC, 0x1D6FA}, {0x1D6FB, 0x1D6FB}, {0x1D6FC, 0x1D714}, + {0x1D715, 0x1D715}, {0x1D716, 0x1D734}, {0x1D735, 0x1D735}, + {0x1D736, 0x1D74E}, {0x1D74F, 0x1D74F}, {0x1D750, 0x1D76E}, + {0x1D76F, 0x1D76F}, {0x1D770, 0x1D788}, {0x1D789, 0x1D789}, + {0x1D78A, 0x1D7A8}, {0x1D7A9, 0x1D7A9}, {0x1D7AA, 0x1D7C2}, + {0x1D7C3, 0x1D7C3}, {0x1D7C4, 0x1D7CB}, {0x1D7CE, 0x1D7FF}, + {0x1D800, 0x1D9FF}, {0x1DA00, 0x1DA36}, {0x1DA37, 0x1DA3A}, + {0x1DA3B, 0x1DA6C}, {0x1DA6D, 0x1DA74}, {0x1DA75, 0x1DA75}, + {0x1DA76, 0x1DA83}, {0x1DA84, 0x1DA84}, {0x1DA85, 0x1DA86}, + {0x1DA87, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, + {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, + {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E800, 0x1E8C4}, + {0x1E8C7, 0x1E8CF}, {0x1E8D0, 0x1E8D6}, {0x1E900, 0x1E943}, + {0x1E944, 0x1E94A}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F}, + {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, + {0x1EE24, 0x1EE24}, {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, + {0x1EE34, 0x1EE37}, {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, + {0x1EE42, 0x1EE42}, {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, + {0x1EE4B, 0x1EE4B}, {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, + {0x1EE54, 0x1EE54}, {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, + {0x1EE5B, 0x1EE5B}, {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, + {0x1EE61, 0x1EE62}, {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, + {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, + {0x1EE7E, 0x1EE7E}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, + {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, + {0x1EEF0, 0x1EEF1}, {0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, + {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, + {0x1F0C1, 0x1F0CE}, {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10C}, + {0x1F12E, 0x1F12E}, {0x1F16A, 0x1F16B}, {0x1F1E6, 0x1F1FF}, + {0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, + {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF}, + {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F}, + {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A}, + {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594}, + {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F}, + {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6E0, 0x1F6EA}, + {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D4}, + {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859}, + {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0xE0001, 0xE0001}, + {0xE0020, 0xE007F}, +} + +// Condition have flag EastAsianWidth whether the current locale is CJK or not. +type Condition struct { + EastAsianWidth bool +} + +// NewCondition return new instance of Condition which is current locale. +func NewCondition() *Condition { + return &Condition{EastAsianWidth} +} + +// RuneWidth returns the number of cells in r. +// See http://www.unicode.org/reports/tr11/ +func (c *Condition) RuneWidth(r rune) int { + switch { + case r < 0 || r > 0x10FFFF || + inTables(r, nonprint, combining, notassigned): + return 0 + case (c.EastAsianWidth && IsAmbiguousWidth(r)) || + inTables(r, doublewidth, emoji): + return 2 + default: + return 1 + } +} + +// StringWidth return width as you can see +func (c *Condition) StringWidth(s string) (width int) { + for _, r := range []rune(s) { + width += c.RuneWidth(r) + } + return width +} + +// Truncate return string truncated with w cells +func (c *Condition) Truncate(s string, w int, tail string) string { + if c.StringWidth(s) <= w { + return s + } + r := []rune(s) + tw := c.StringWidth(tail) + w -= tw + width := 0 + i := 0 + for ; i < len(r); i++ { + cw := c.RuneWidth(r[i]) + if width+cw > w { + break + } + width += cw + } + return string(r[0:i]) + tail +} + +// Wrap return string wrapped with w cells +func (c *Condition) Wrap(s string, w int) string { + width := 0 + out := "" + for _, r := range []rune(s) { + cw := RuneWidth(r) + if r == '\n' { + out += string(r) + width = 0 + continue + } else if width+cw > w { + out += "\n" + width = 0 + out += string(r) + width += cw + continue + } + out += string(r) + width += cw + } + return out +} + +// FillLeft return string filled in left by spaces in w cells +func (c *Condition) FillLeft(s string, w int) string { + width := c.StringWidth(s) + count := w - width + if count > 0 { + b := make([]byte, count) + for i := range b { + b[i] = ' ' + } + return string(b) + s + } + return s +} + +// FillRight return string filled in left by spaces in w cells +func (c *Condition) FillRight(s string, w int) string { + width := c.StringWidth(s) + count := w - width + if count > 0 { + b := make([]byte, count) + for i := range b { + b[i] = ' ' + } + return s + string(b) + } + return s +} + +// RuneWidth returns the number of cells in r. +// See http://www.unicode.org/reports/tr11/ +func RuneWidth(r rune) int { + return DefaultCondition.RuneWidth(r) +} + +// IsAmbiguousWidth returns whether is ambiguous width or not. +func IsAmbiguousWidth(r rune) bool { + return inTables(r, private, ambiguous) +} + +// IsNeutralWidth returns whether is neutral width or not. +func IsNeutralWidth(r rune) bool { + return inTable(r, neutral) +} + +// StringWidth return width as you can see +func StringWidth(s string) (width int) { + return DefaultCondition.StringWidth(s) +} + +// Truncate return string truncated with w cells +func Truncate(s string, w int, tail string) string { + return DefaultCondition.Truncate(s, w, tail) +} + +// Wrap return string wrapped with w cells +func Wrap(s string, w int) string { + return DefaultCondition.Wrap(s, w) +} + +// FillLeft return string filled in left by spaces in w cells +func FillLeft(s string, w int) string { + return DefaultCondition.FillLeft(s, w) +} + +// FillRight return string filled in left by spaces in w cells +func FillRight(s string, w int) string { + return DefaultCondition.FillRight(s, w) +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_js.go b/vendor/github.com/mattn/go-runewidth/runewidth_js.go new file mode 100644 index 00000000..0ce32c5e --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_js.go @@ -0,0 +1,8 @@ +// +build js + +package runewidth + +func IsEastAsian() bool { + // TODO: Implement this for the web. Detect east asian in a compatible way, and return true. + return false +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go new file mode 100644 index 00000000..c579e9a3 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go @@ -0,0 +1,77 @@ +// +build !windows,!js + +package runewidth + +import ( + "os" + "regexp" + "strings" +) + +var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) + +var mblenTable = map[string]int{ + "utf-8": 6, + "utf8": 6, + "jis": 8, + "eucjp": 3, + "euckr": 2, + "euccn": 2, + "sjis": 2, + "cp932": 2, + "cp51932": 2, + "cp936": 2, + "cp949": 2, + "cp950": 2, + "big5": 2, + "gbk": 2, + "gb2312": 2, +} + +func isEastAsian(locale string) bool { + charset := strings.ToLower(locale) + r := reLoc.FindStringSubmatch(locale) + if len(r) == 2 { + charset = strings.ToLower(r[1]) + } + + if strings.HasSuffix(charset, "@cjk_narrow") { + return false + } + + for pos, b := range []byte(charset) { + if b == '@' { + charset = charset[:pos] + break + } + } + max := 1 + if m, ok := mblenTable[charset]; ok { + max = m + } + if max > 1 && (charset[0] != 'u' || + strings.HasPrefix(locale, "ja") || + strings.HasPrefix(locale, "ko") || + strings.HasPrefix(locale, "zh")) { + return true + } + return false +} + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + locale := os.Getenv("LC_CTYPE") + if locale == "" { + locale = os.Getenv("LANG") + } + + // ignore C locale + if locale == "POSIX" || locale == "C" { + return false + } + if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { + return false + } + + return isEastAsian(locale) +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go new file mode 100644 index 00000000..0258876b --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go @@ -0,0 +1,25 @@ +package runewidth + +import ( + "syscall" +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32") + procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") +) + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + r1, _, _ := procGetConsoleOutputCP.Call() + if r1 == 0 { + return false + } + + switch int(r1) { + case 932, 51932, 936, 949, 950: + return true + } + + return false +} diff --git a/vendor/github.com/olebedev/config/.gitignore b/vendor/github.com/olebedev/config/.gitignore new file mode 100644 index 00000000..00268614 --- /dev/null +++ b/vendor/github.com/olebedev/config/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/olebedev/config/LICENSE b/vendor/github.com/olebedev/config/LICENSE new file mode 100644 index 00000000..c09d13e5 --- /dev/null +++ b/vendor/github.com/olebedev/config/LICENSE @@ -0,0 +1,20 @@ +JSON or YAML configuration wrapper with convenient access methods +Copyright (C) 2014 Oleg Lebedev + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/olebedev/config/README.md b/vendor/github.com/olebedev/config/README.md new file mode 100644 index 00000000..7f554252 --- /dev/null +++ b/vendor/github.com/olebedev/config/README.md @@ -0,0 +1,19 @@ +# Config [![wercker status](https://app.wercker.com/status/b4e8561d9a711afcb016bf0018e83897/s/ "wercker status")](https://app.wercker.com/project/bykey/b4e8561d9a711afcb016bf0018e83897) [![GoDoc](https://godoc.org/github.com/olebedev/config?status.png)](https://godoc.org/github.com/olebedev/config) + +Package config provides convenient access methods to configuration +stored as JSON or YAML. + +This is a fork of the [original version](https://github.com/moraes/config). +This version extends the functionality of the original without losing compatibility. +Major features added: + +- [`Set(path string, value interface{}) error`](http://godoc.org/github.com/olebedev/config#Config.Set) method +- [`Env() *config.Config`](http://godoc.org/github.com/olebedev/config#Config.Env) method, for OS environment variables parsing +- [`Flag() *config.Config`](http://godoc.org/github.com/olebedev/config#Config.Flag) method, for command line arguments parsing usign pkg/flag singleton +- [`Args(args ...string) *config.Config`](http://godoc.org/github.com/olebedev/config#Config.Args) method, for command line arguments parsing +- [`U*`](https://godoc.org/github.com/olebedev/config#Config.UBool) methods +- [`Copy(...path) (*config.config, error)`](https://godoc.org/github.com/olebedev/config#Config.Copy) method +- [`Extend(*config.Config) (*config.Config, error)`](https://godoc.org/github.com/olebedev/config#Config.Extend) method +- [`Error() error`](https://godoc.org/github.com/olebedev/config#Config.Error) method to show last parsing error, works only with `.Args()` method + +Example and more information you can find [here](http://godoc.org/github.com/olebedev/config). diff --git a/vendor/github.com/olebedev/config/config.go b/vendor/github.com/olebedev/config/config.go new file mode 100644 index 00000000..b007f9db --- /dev/null +++ b/vendor/github.com/olebedev/config/config.go @@ -0,0 +1,642 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package config + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "strconv" + "strings" + "syscall" + + yaml "gopkg.in/yaml.v2" +) + +// Config --------------------------------------------------------------------- + +// Config represents a configuration with convenient access methods. +type Config struct { + Root interface{} + lastErr error +} + +// Error return last error +func (c *Config) Error() error { + return c.lastErr +} + +// Get returns a nested config according to a dotted path. +func (cfg *Config) Get(path string) (*Config, error) { + n, err := Get(cfg.Root, path) + if err != nil { + return nil, err + } + return &Config{Root: n}, nil +} + +// Set a nested config according to a dotted path. +func (cfg *Config) Set(path string, val interface{}) error { + return Set(cfg.Root, path, val) +} + +// Fetch data from system env, based on existing config keys. +func (cfg *Config) Env() *Config { + return cfg.EnvPrefix("") +} + +// Fetch data from system env using prefix, based on existing config keys. +func (cfg *Config) EnvPrefix(prefix string) *Config { + if prefix != "" { + prefix = strings.ToUpper(prefix) + "_" + } + + keys := getKeys(cfg.Root) + for _, key := range keys { + k := strings.ToUpper(strings.Join(key, "_")) + if val, exist := syscall.Getenv(prefix + k); exist { + cfg.Set(strings.Join(key, "."), val) + } + } + return cfg +} + +// Parse command line arguments, based on existing config keys. +func (cfg *Config) Flag() *Config { + keys := getKeys(cfg.Root) + hash := map[string]*string{} + for _, key := range keys { + k := strings.Join(key, "-") + hash[k] = new(string) + val, _ := cfg.String(k) + flag.StringVar(hash[k], k, val, "") + } + + flag.Parse() + + flag.Visit(func(f *flag.Flag) { + name := strings.Replace(f.Name, "-", ".", -1) + cfg.Set(name, f.Value.String()) + }) + + return cfg +} + +// Args command line arguments, based on existing config keys. +func (cfg *Config) Args(args ...string) *Config { + if len(args) <= 1 { + return cfg + } + + keys := getKeys(cfg.Root) + hash := map[string]*string{} + _flag := flag.NewFlagSet(args[0], flag.ContinueOnError) + var _err bytes.Buffer + _flag.SetOutput(&_err) + for _, key := range keys { + k := strings.Join(key, "-") + hash[k] = new(string) + val, _ := cfg.String(k) + _flag.StringVar(hash[k], k, val, "") + } + + cfg.lastErr = _flag.Parse(args[1:]) + + _flag.Visit(func(f *flag.Flag) { + name := strings.Replace(f.Name, "-", ".", -1) + cfg.Set(name, f.Value.String()) + }) + + return cfg +} + +// Get all keys for given interface +func getKeys(source interface{}, base ...string) [][]string { + acc := [][]string{} + + // Copy "base" so that underlying slice array is not + // modified in recursive calls + nextBase := make([]string, len(base)) + copy(nextBase, base) + + switch c := source.(type) { + case map[string]interface{}: + for k, v := range c { + keys := getKeys(v, append(nextBase, k)...) + acc = append(acc, keys...) + } + case []interface{}: + for i, v := range c { + k := strconv.Itoa(i) + keys := getKeys(v, append(nextBase, k)...) + acc = append(acc, keys...) + } + default: + acc = append(acc, nextBase) + return acc + } + return acc +} + +// Bool returns a bool according to a dotted path. +func (cfg *Config) Bool(path string) (bool, error) { + n, err := Get(cfg.Root, path) + if err != nil { + return false, err + } + switch n := n.(type) { + case bool: + return n, nil + case string: + return strconv.ParseBool(n) + } + return false, typeMismatch("bool or string", n) +} + +// UBool returns a bool according to a dotted path or default value or false. +func (c *Config) UBool(path string, defaults ...bool) bool { + value, err := c.Bool(path) + + if err == nil { + return value + } + + for _, def := range defaults { + return def + } + return false +} + +// Float64 returns a float64 according to a dotted path. +func (cfg *Config) Float64(path string) (float64, error) { + n, err := Get(cfg.Root, path) + if err != nil { + return 0, err + } + switch n := n.(type) { + case float64: + return n, nil + case int: + return float64(n), nil + case string: + return strconv.ParseFloat(n, 64) + } + return 0, typeMismatch("float64, int or string", n) +} + +// UFloat64 returns a float64 according to a dotted path or default value or 0. +func (c *Config) UFloat64(path string, defaults ...float64) float64 { + value, err := c.Float64(path) + + if err == nil { + return value + } + + for _, def := range defaults { + return def + } + return float64(0) +} + +// Int returns an int according to a dotted path. +func (cfg *Config) Int(path string) (int, error) { + n, err := Get(cfg.Root, path) + if err != nil { + return 0, err + } + switch n := n.(type) { + case float64: + // encoding/json unmarshals numbers into floats, so we compare + // the string representation to see if we can return an int. + if i := int(n); fmt.Sprint(i) == fmt.Sprint(n) { + return i, nil + } else { + return 0, fmt.Errorf("Value can't be converted to int: %v", n) + } + case int: + return n, nil + case string: + if v, err := strconv.ParseInt(n, 10, 0); err == nil { + return int(v), nil + } else { + return 0, err + } + } + return 0, typeMismatch("float64, int or string", n) +} + +// UInt returns an int according to a dotted path or default value or 0. +func (c *Config) UInt(path string, defaults ...int) int { + value, err := c.Int(path) + + if err == nil { + return value + } + + for _, def := range defaults { + return def + } + return 0 +} + +// List returns a []interface{} according to a dotted path. +func (cfg *Config) List(path string) ([]interface{}, error) { + n, err := Get(cfg.Root, path) + if err != nil { + return nil, err + } + if value, ok := n.([]interface{}); ok { + return value, nil + } + return nil, typeMismatch("[]interface{}", n) +} + +// UList returns a []interface{} according to a dotted path or defaults or []interface{}. +func (c *Config) UList(path string, defaults ...[]interface{}) []interface{} { + value, err := c.List(path) + + if err == nil { + return value + } + + for _, def := range defaults { + return def + } + return make([]interface{}, 0) +} + +// Map returns a map[string]interface{} according to a dotted path. +func (cfg *Config) Map(path string) (map[string]interface{}, error) { + n, err := Get(cfg.Root, path) + if err != nil { + return nil, err + } + if value, ok := n.(map[string]interface{}); ok { + return value, nil + } + return nil, typeMismatch("map[string]interface{}", n) +} + +// UMap returns a map[string]interface{} according to a dotted path or default or map[string]interface{}. +func (c *Config) UMap(path string, defaults ...map[string]interface{}) map[string]interface{} { + value, err := c.Map(path) + + if err == nil { + return value + } + + for _, def := range defaults { + return def + } + return map[string]interface{}{} +} + +// String returns a string according to a dotted path. +func (cfg *Config) String(path string) (string, error) { + n, err := Get(cfg.Root, path) + if err != nil { + return "", err + } + switch n := n.(type) { + case bool, float64, int: + return fmt.Sprint(n), nil + case string: + return n, nil + } + return "", typeMismatch("bool, float64, int or string", n) +} + +// UString returns a string according to a dotted path or default or "". +func (c *Config) UString(path string, defaults ...string) string { + value, err := c.String(path) + + if err == nil { + return value + } + + for _, def := range defaults { + return def + } + return "" +} + +// Copy returns a deep copy with given path or without. +func (c *Config) Copy(dottedPath ...string) (*Config, error) { + toJoin := []string{} + for _, part := range dottedPath { + if len(part) != 0 { + toJoin = append(toJoin, part) + } + } + + var err error + var path = strings.Join(toJoin, ".") + var cfg = c + var root = "" + + if len(path) > 0 { + if cfg, err = c.Get(path); err != nil { + return nil, err + } + } + + if root, err = RenderYaml(cfg.Root); err != nil { + return nil, err + } + return ParseYaml(root) +} + +// Extend returns extended copy of current config with applied +// values from the given config instance. Note that if you extend +// with different structure you will get an error. See: `.Set()` method +// for details. +func (c *Config) Extend(cfg *Config) (*Config, error) { + n, err := c.Copy() + if err != nil { + return nil, err + } + + keys := getKeys(cfg.Root) + for _, key := range keys { + k := strings.Join(key, ".") + i, err := Get(cfg.Root, k) + if err != nil { + return nil, err + } + if err := n.Set(k, i); err != nil { + return nil, err + } + } + return n, nil +} + +// typeMismatch returns an error for an expected type. +func typeMismatch(expected string, got interface{}) error { + return fmt.Errorf("Type mismatch: expected %s; got %T", expected, got) +} + +// Fetching ------------------------------------------------------------------- + +// Get returns a child of the given value according to a dotted path. +func Get(cfg interface{}, path string) (interface{}, error) { + parts := strings.Split(path, ".") + // Normalize path. + for k, v := range parts { + if v == "" { + if k == 0 { + parts = parts[1:] + } else { + return nil, fmt.Errorf("Invalid path %q", path) + } + } + } + // Get the value. + for pos, part := range parts { + switch c := cfg.(type) { + case []interface{}: + if i, error := strconv.ParseInt(part, 10, 0); error == nil { + if int(i) < len(c) { + cfg = c[i] + } else { + return nil, fmt.Errorf( + "Index out of range at %q: list has only %v items", + strings.Join(parts[:pos+1], "."), len(c)) + } + } else { + return nil, fmt.Errorf("Invalid list index at %q", + strings.Join(parts[:pos+1], ".")) + } + case map[string]interface{}: + if value, ok := c[part]; ok { + cfg = value + } else { + return nil, fmt.Errorf("Nonexistent map key at %q", + strings.Join(parts[:pos+1], ".")) + } + default: + return nil, fmt.Errorf( + "Invalid type at %q: expected []interface{} or map[string]interface{}; got %T", + strings.Join(parts[:pos+1], "."), cfg) + } + } + + return cfg, nil +} + +// Set returns an error, in case when it is not possible to +// establish the value obtained in accordance with given dotted path. +func Set(cfg interface{}, path string, value interface{}) error { + parts := strings.Split(path, ".") + // Normalize path. + for k, v := range parts { + if v == "" { + if k == 0 { + parts = parts[1:] + } else { + return fmt.Errorf("Invalid path %q", path) + } + } + } + + point := &cfg + for pos, part := range parts { + switch c := (*point).(type) { + case []interface{}: + if i, error := strconv.ParseInt(part, 10, 0); error == nil { + // 1. normalize slice capacity + if int(i) >= cap(c) { + c = append(c, make([]interface{}, int(i)-cap(c)+1, int(i)-cap(c)+1)...) + } + + // 2. set value or go further + if pos+1 == len(parts) { + c[i] = value + } else { + + // if exists just pick the pointer + if va := c[i]; va != nil { + point = &va + } else { + // is next part slice or map? + if i, err := strconv.ParseInt(parts[pos+1], 10, 0); err == nil { + va = make([]interface{}, int(i)+1, int(i)+1) + } else { + va = make(map[string]interface{}) + } + c[i] = va + point = &va + } + + } + + } else { + return fmt.Errorf("Invalid list index at %q", + strings.Join(parts[:pos+1], ".")) + } + case map[string]interface{}: + if pos+1 == len(parts) { + c[part] = value + } else { + // if exists just pick the pointer + if va, ok := c[part]; ok { + point = &va + } else { + // is next part slice or map? + if i, err := strconv.ParseInt(parts[pos+1], 10, 0); err == nil { + va = make([]interface{}, int(i)+1, int(i)+1) + } else { + va = make(map[string]interface{}) + } + c[part] = va + point = &va + } + } + default: + return fmt.Errorf( + "Invalid type at %q: expected []interface{} or map[string]interface{}; got %T", + strings.Join(parts[:pos+1], "."), cfg) + } + } + + return nil +} + +// Parsing -------------------------------------------------------------------- + +// Must is a wrapper for parsing functions to be used during initialization. +// It panics on failure. +func Must(cfg *Config, err error) *Config { + if err != nil { + panic(err) + } + return cfg +} + +// normalizeValue normalizes a unmarshalled value. This is needed because +// encoding/json doesn't support marshalling map[interface{}]interface{}. +func normalizeValue(value interface{}) (interface{}, error) { + switch value := value.(type) { + case map[interface{}]interface{}: + node := make(map[string]interface{}, len(value)) + for k, v := range value { + key, ok := k.(string) + if !ok { + return nil, fmt.Errorf("Unsupported map key: %#v", k) + } + item, err := normalizeValue(v) + if err != nil { + return nil, fmt.Errorf("Unsupported map value: %#v", v) + } + node[key] = item + } + return node, nil + case map[string]interface{}: + node := make(map[string]interface{}, len(value)) + for key, v := range value { + item, err := normalizeValue(v) + if err != nil { + return nil, fmt.Errorf("Unsupported map value: %#v", v) + } + node[key] = item + } + return node, nil + case []interface{}: + node := make([]interface{}, len(value)) + for key, v := range value { + item, err := normalizeValue(v) + if err != nil { + return nil, fmt.Errorf("Unsupported list item: %#v", v) + } + node[key] = item + } + return node, nil + case bool, float64, int, string, nil: + return value, nil + } + return nil, fmt.Errorf("Unsupported type: %T", value) +} + +// JSON ----------------------------------------------------------------------- + +// ParseJson reads a JSON configuration from the given string. +func ParseJson(cfg string) (*Config, error) { + return parseJson([]byte(cfg)) +} + +// ParseJsonFile reads a JSON configuration from the given filename. +func ParseJsonFile(filename string) (*Config, error) { + cfg, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + return parseJson(cfg) +} + +// parseJson performs the real JSON parsing. +func parseJson(cfg []byte) (*Config, error) { + var out interface{} + var err error + if err = json.Unmarshal(cfg, &out); err != nil { + return nil, err + } + if out, err = normalizeValue(out); err != nil { + return nil, err + } + return &Config{Root: out}, nil +} + +// RenderJson renders a JSON configuration. +func RenderJson(cfg interface{}) (string, error) { + b, err := json.Marshal(cfg) + if err != nil { + return "", err + } + return string(b), nil +} + +// YAML ----------------------------------------------------------------------- + +// ParseYamlBytes reads a YAML configuration from the given []byte. +func ParseYamlBytes(cfg []byte) (*Config, error) { + return parseYaml(cfg) +} + +// ParseYaml reads a YAML configuration from the given string. +func ParseYaml(cfg string) (*Config, error) { + return parseYaml([]byte(cfg)) +} + +// ParseYamlFile reads a YAML configuration from the given filename. +func ParseYamlFile(filename string) (*Config, error) { + cfg, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + return parseYaml(cfg) +} + +// parseYaml performs the real YAML parsing. +func parseYaml(cfg []byte) (*Config, error) { + var out interface{} + var err error + if err = yaml.Unmarshal(cfg, &out); err != nil { + return nil, err + } + if out, err = normalizeValue(out); err != nil { + return nil, err + } + return &Config{Root: out}, nil +} + +// RenderYaml renders a YAML configuration. +func RenderYaml(cfg interface{}) (string, error) { + b, err := yaml.Marshal(cfg) + if err != nil { + return "", err + } + return string(b), nil +} diff --git a/vendor/github.com/olebedev/config/doc.go b/vendor/github.com/olebedev/config/doc.go new file mode 100644 index 00000000..a71e76c8 --- /dev/null +++ b/vendor/github.com/olebedev/config/doc.go @@ -0,0 +1,141 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package config provides convenient access methods to configuration stored as +JSON or YAML. + +Let's start with a simple YAML example: + + development: + database: + host: localhost + users: + - name: calvin + password: yukon + - name: hobbes + password: tuna + production: + database: + host: 192.168.1.1 + +We can parse it using ParseYaml(), which will return a *Config instance on +success: + + cfg, err := config.ParseYaml(yamlString) + +An equivalent JSON configuration could be built using ParseJson(): + + cfg, err := config.ParseJson(jsonString) + +From now, we can retrieve configuration values using a path in dotted notation: + + // "localhost" + host, err := cfg.String("development.database.host") + + // or... + + // "192.168.1.1" + host, err := cfg.String("production.database.host") + +Besides String(), other types can be fetched directly: Bool(), Float64(), +Int(), Map() and List(). All these methods will return an error if the path +doesn't exist, or the value doesn't match or can't be converted to the +requested type. + +A nested configuration can be fetched using Get(). Here we get a new *Config +instance with a subset of the configuration: + + cfg, err := cfg.Get("development") + +Then the inner values are fetched relatively to the subset: + + // "localhost" + host, err := cfg.String("database.host") + +For lists, the dotted path must use an index to refer to a specific value. +To retrieve the information from a user stored in the configuration above: + + // map[string]interface{}{ ... } + user1, err := cfg.Map("development.users.0") + // map[string]interface{}{ ... } + user2, err := cfg.Map("development.users.1") + + // or... + + // "calvin" + name1, err := cfg.String("development.users.0.name") + // "hobbes" + name2, err := cfg.String("development.users.1.name") + +JSON or YAML strings can be created calling the appropriate Render*() +functions. Here's how we render a configuration like the one used in these +examples: + + cfg := map[string]interface{}{ + "development": map[string]interface{}{ + "database": map[string]interface{}{ + "host": "localhost", + }, + "users": []interface{}{ + map[string]interface{}{ + "name": "calvin", + "password": "yukon", + }, + map[string]interface{}{ + "name": "hobbes", + "password": "tuna", + }, + }, + }, + "production": map[string]interface{}{ + "database": map[string]interface{}{ + "host": "192.168.1.1", + }, + }, + } + + json, err := config.RenderJson(cfg) + + // or... + + yaml, err := config.RenderYaml(cfg) + +This results in a configuration string to be stored in a file or database. + +For more more convenience it can parse OS environment variables and command line arguments. + + cfg, err := config.ParseYaml(yamlString) + cfg.Env() + + // or + + cfg.Flag() + +We can also specify the order of parsing: + + cfg.Env().Flag() + + // or + + cfg.Flag().Env() + +In case of OS environment all existing at the moment of parsing keys will be scanned in OS environment, +but in uppercase and the separator will be `_` instead of a `.`. If EnvPrefix() is used the given prefix +will be used to lookup the environment variable, e.g PREFIX_FOO_BAR will set foo.bar. +In case of flags separator will be `-`. +In case of command line arguments possible to use regular dot notation syntax for all keys. +For see existing keys we can run application with `-h`. + +We can use unsafe method to get value: + + // "" + cfg.UString("undefined.key") + + // or with default value + unsafeValue := cfg.UString("undefined.key", "default value") + +There is unsafe methods, like regular, but wuth prefix `U`. +*/ +package config diff --git a/vendor/github.com/olebedev/config/wercker.yml b/vendor/github.com/olebedev/config/wercker.yml new file mode 100644 index 00000000..4a47bb17 --- /dev/null +++ b/vendor/github.com/olebedev/config/wercker.yml @@ -0,0 +1 @@ +box: wercker/golang@1.1.1 diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/vendor/github.com/pkg/errors/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml new file mode 100644 index 00000000..588ceca1 --- /dev/null +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -0,0 +1,11 @@ +language: go +go_import_path: github.com/pkg/errors +go: + - 1.4.3 + - 1.5.4 + - 1.6.2 + - 1.7.1 + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE new file mode 100644 index 00000000..835ba3e7 --- /dev/null +++ b/vendor/github.com/pkg/errors/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md new file mode 100644 index 00000000..273db3c9 --- /dev/null +++ b/vendor/github.com/pkg/errors/README.md @@ -0,0 +1,52 @@ +# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) + +Package errors provides simple error handling primitives. + +`go get github.com/pkg/errors` + +The traditional error handling idiom in Go is roughly akin to +```go +if err != nil { + return err +} +``` +which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. + +## Adding context to an error + +The errors.Wrap function returns a new error that adds context to the original error. For example +```go +_, err := ioutil.ReadAll(r) +if err != nil { + return errors.Wrap(err, "read failed") +} +``` +## Retrieving the cause of an error + +Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. +```go +type causer interface { + Cause() error +} +``` +`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: +```go +switch err := errors.Cause(err).(type) { +case *MyError: + // handle specifically +default: + // unknown error +} +``` + +[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). + +## Contributing + +We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. + +Before proposing a change, please discuss your change by raising an issue. + +## Licence + +BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml new file mode 100644 index 00000000..a932eade --- /dev/null +++ b/vendor/github.com/pkg/errors/appveyor.yml @@ -0,0 +1,32 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\pkg\errors +shallow_clone: true # for startup speed + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +# http://www.appveyor.com/docs/installed-software +install: + # some helpful output for debugging builds + - go version + - go env + # pre-installed MinGW at C:\MinGW is 32bit only + # but MSYS2 at C:\msys64 has mingw64 + - set PATH=C:\msys64\mingw64\bin;%PATH% + - gcc --version + - g++ --version + +build_script: + - go install -v ./... + +test_script: + - set PATH=C:\gopath\bin;%PATH% + - go test -v ./... + +#artifacts: +# - path: '%GOPATH%\bin\*.exe' +deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go new file mode 100644 index 00000000..842ee804 --- /dev/null +++ b/vendor/github.com/pkg/errors/errors.go @@ -0,0 +1,269 @@ +// Package errors provides simple error handling primitives. +// +// The traditional error handling idiom in Go is roughly akin to +// +// if err != nil { +// return err +// } +// +// which applied recursively up the call stack results in error reports +// without context or debugging information. The errors package allows +// programmers to add context to the failure path in their code in a way +// that does not destroy the original value of the error. +// +// Adding context to an error +// +// The errors.Wrap function returns a new error that adds context to the +// original error by recording a stack trace at the point Wrap is called, +// and the supplied message. For example +// +// _, err := ioutil.ReadAll(r) +// if err != nil { +// return errors.Wrap(err, "read failed") +// } +// +// If additional control is required the errors.WithStack and errors.WithMessage +// functions destructure errors.Wrap into its component operations of annotating +// an error with a stack trace and an a message, respectively. +// +// Retrieving the cause of an error +// +// Using errors.Wrap constructs a stack of errors, adding context to the +// preceding error. Depending on the nature of the error it may be necessary +// to reverse the operation of errors.Wrap to retrieve the original error +// for inspection. Any error value which implements this interface +// +// type causer interface { +// Cause() error +// } +// +// can be inspected by errors.Cause. errors.Cause will recursively retrieve +// the topmost error which does not implement causer, which is assumed to be +// the original cause. For example: +// +// switch err := errors.Cause(err).(type) { +// case *MyError: +// // handle specifically +// default: +// // unknown error +// } +// +// causer interface is not exported by this package, but is considered a part +// of stable public API. +// +// Formatted printing of errors +// +// All error values returned from this package implement fmt.Formatter and can +// be formatted by the fmt package. The following verbs are supported +// +// %s print the error. If the error has a Cause it will be +// printed recursively +// %v see %s +// %+v extended format. Each Frame of the error's StackTrace will +// be printed in detail. +// +// Retrieving the stack trace of an error or wrapper +// +// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are +// invoked. This information can be retrieved with the following interface. +// +// type stackTracer interface { +// StackTrace() errors.StackTrace +// } +// +// Where errors.StackTrace is defined as +// +// type StackTrace []Frame +// +// The Frame type represents a call site in the stack trace. Frame supports +// the fmt.Formatter interface that can be used for printing information about +// the stack trace of this error. For example: +// +// if err, ok := err.(stackTracer); ok { +// for _, f := range err.StackTrace() { +// fmt.Printf("%+s:%d", f) +// } +// } +// +// stackTracer interface is not exported by this package, but is considered a part +// of stable public API. +// +// See the documentation for Frame.Format for more details. +package errors + +import ( + "fmt" + "io" +) + +// New returns an error with the supplied message. +// New also records the stack trace at the point it was called. +func New(message string) error { + return &fundamental{ + msg: message, + stack: callers(), + } +} + +// Errorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// Errorf also records the stack trace at the point it was called. +func Errorf(format string, args ...interface{}) error { + return &fundamental{ + msg: fmt.Sprintf(format, args...), + stack: callers(), + } +} + +// fundamental is an error that has a message and a stack, but no caller. +type fundamental struct { + msg string + *stack +} + +func (f *fundamental) Error() string { return f.msg } + +func (f *fundamental) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + io.WriteString(s, f.msg) + f.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, f.msg) + case 'q': + fmt.Fprintf(s, "%q", f.msg) + } +} + +// WithStack annotates err with a stack trace at the point WithStack was called. +// If err is nil, WithStack returns nil. +func WithStack(err error) error { + if err == nil { + return nil + } + return &withStack{ + err, + callers(), + } +} + +type withStack struct { + error + *stack +} + +func (w *withStack) Cause() error { return w.error } + +func (w *withStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +// Wrap returns an error annotating err with a stack trace +// at the point Wrap is called, and the supplied message. +// If err is nil, Wrap returns nil. +func Wrap(err error, message string) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: message, + } + return &withStack{ + err, + callers(), + } +} + +// Wrapf returns an error annotating err with a stack trace +// at the point Wrapf is call, and the format specifier. +// If err is nil, Wrapf returns nil. +func Wrapf(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } + return &withStack{ + err, + callers(), + } +} + +// WithMessage annotates err with a new message. +// If err is nil, WithMessage returns nil. +func WithMessage(err error, message string) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: message, + } +} + +type withMessage struct { + cause error + msg string +} + +func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } +func (w *withMessage) Cause() error { return w.cause } + +func (w *withMessage) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v\n", w.Cause()) + io.WriteString(s, w.msg) + return + } + fallthrough + case 's', 'q': + io.WriteString(s, w.Error()) + } +} + +// Cause returns the underlying cause of the error, if possible. +// An error value has a cause if it implements the following +// interface: +// +// type causer interface { +// Cause() error +// } +// +// If the error does not implement Cause, the original error will +// be returned. If the error is nil, nil will be returned without further +// investigation. +func Cause(err error) error { + type causer interface { + Cause() error + } + + for err != nil { + cause, ok := err.(causer) + if !ok { + break + } + err = cause.Cause() + } + return err +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go new file mode 100644 index 00000000..6b1f2891 --- /dev/null +++ b/vendor/github.com/pkg/errors/stack.go @@ -0,0 +1,178 @@ +package errors + +import ( + "fmt" + "io" + "path" + "runtime" + "strings" +) + +// Frame represents a program counter inside a stack frame. +type Frame uintptr + +// pc returns the program counter for this frame; +// multiple frames may have the same PC value. +func (f Frame) pc() uintptr { return uintptr(f) - 1 } + +// file returns the full path to the file that contains the +// function for this Frame's pc. +func (f Frame) file() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + file, _ := fn.FileLine(f.pc()) + return file +} + +// line returns the line number of source code of the +// function for this Frame's pc. +func (f Frame) line() int { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return 0 + } + _, line := fn.FileLine(f.pc()) + return line +} + +// Format formats the frame according to the fmt.Formatter interface. +// +// %s source file +// %d source line +// %n function name +// %v equivalent to %s:%d +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+s path of source file relative to the compile time GOPATH +// %+v equivalent to %+s:%d +func (f Frame) Format(s fmt.State, verb rune) { + switch verb { + case 's': + switch { + case s.Flag('+'): + pc := f.pc() + fn := runtime.FuncForPC(pc) + if fn == nil { + io.WriteString(s, "unknown") + } else { + file, _ := fn.FileLine(pc) + fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) + } + default: + io.WriteString(s, path.Base(f.file())) + } + case 'd': + fmt.Fprintf(s, "%d", f.line()) + case 'n': + name := runtime.FuncForPC(f.pc()).Name() + io.WriteString(s, funcname(name)) + case 'v': + f.Format(s, 's') + io.WriteString(s, ":") + f.Format(s, 'd') + } +} + +// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). +type StackTrace []Frame + +func (st StackTrace) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case s.Flag('+'): + for _, f := range st { + fmt.Fprintf(s, "\n%+v", f) + } + case s.Flag('#'): + fmt.Fprintf(s, "%#v", []Frame(st)) + default: + fmt.Fprintf(s, "%v", []Frame(st)) + } + case 's': + fmt.Fprintf(s, "%s", []Frame(st)) + } +} + +// stack represents a stack of program counters. +type stack []uintptr + +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + for _, pc := range *s { + f := Frame(pc) + fmt.Fprintf(st, "\n%+v", f) + } + } + } +} + +func (s *stack) StackTrace() StackTrace { + f := make([]Frame, len(*s)) + for i := 0; i < len(f); i++ { + f[i] = Frame((*s)[i]) + } + return f +} + +func callers() *stack { + const depth = 32 + var pcs [depth]uintptr + n := runtime.Callers(3, pcs[:]) + var st stack = pcs[0:n] + return &st +} + +// funcname removes the path prefix component of a function's name reported by func.Name(). +func funcname(name string) string { + i := strings.LastIndex(name, "/") + name = name[i+1:] + i = strings.Index(name, ".") + return name[i+1:] +} + +func trimGOPATH(name, file string) string { + // Here we want to get the source file path relative to the compile time + // GOPATH. As of Go 1.6.x there is no direct way to know the compiled + // GOPATH at runtime, but we can infer the number of path segments in the + // GOPATH. We note that fn.Name() returns the function name qualified by + // the import path, which does not include the GOPATH. Thus we can trim + // segments from the beginning of the file path until the number of path + // separators remaining is one more than the number of path separators in + // the function name. For example, given: + // + // GOPATH /home/user + // file /home/user/src/pkg/sub/file.go + // fn.Name() pkg/sub.Type.Method + // + // We want to produce: + // + // pkg/sub/file.go + // + // From this we can easily see that fn.Name() has one less path separator + // than our desired output. We count separators from the end of the file + // path until it finds two more than in the function name and then move + // one character forward to preserve the initial path segment without a + // leading separator. + const sep = "/" + goal := strings.Count(name, sep) + 2 + i := len(file) + for n := 0; n < goal; n++ { + i = strings.LastIndex(file[:i], sep) + if i == -1 { + // not enough separators found, set i so that the slice expression + // below leaves file unmodified + i = -len(sep) + break + } + } + // get back to 0 or trim the leading separator + file = file[i+len(sep):] + return file +} diff --git a/vendor/github.com/radovskyb/watcher/.travis.yml b/vendor/github.com/radovskyb/watcher/.travis.yml new file mode 100644 index 00000000..3f478f10 --- /dev/null +++ b/vendor/github.com/radovskyb/watcher/.travis.yml @@ -0,0 +1,4 @@ +language: go +go: + - 1.7 + - tip \ No newline at end of file diff --git a/vendor/github.com/radovskyb/watcher/LICENSE b/vendor/github.com/radovskyb/watcher/LICENSE new file mode 100644 index 00000000..92ef0e91 --- /dev/null +++ b/vendor/github.com/radovskyb/watcher/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2016, Benjamin Radovsky. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of watcher nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/radovskyb/watcher/README.md b/vendor/github.com/radovskyb/watcher/README.md new file mode 100644 index 00000000..c0ef08bc --- /dev/null +++ b/vendor/github.com/radovskyb/watcher/README.md @@ -0,0 +1,172 @@ +# watcher + +[![Build Status](https://travis-ci.org/radovskyb/watcher.svg?branch=master)](https://travis-ci.org/radovskyb/watcher) + +`watcher` is a Go package for watching for files or directory changes (recursively or non recursively) without using filesystem events, which allows it to work cross platform consistently. + +`watcher` watches for changes and notifies over channels either anytime an event or an error has occurred. + +Events contain the `os.FileInfo` of the file or directory that the event is based on and the type of event and file or directory path. + +[Installation](#installation) +[Features](#features) +[Example](#example) +[Contributing](#contributing) +[Watcher Command](#command) + +# Update +Event.Path for Rename and Move events is now returned in the format of `fromPath -> toPath` + +#### Chmod event is not supported under windows. + +# Installation + +```shell +go get -u github.com/radovskyb/watcher/... +``` + +# Features + +- Customizable polling interval. +- Filter Events. +- Watch folders recursively or non-recursively. +- Choose to ignore hidden files. +- Choose to ignore specified files and folders. +- Notifies the `os.FileInfo` of the file that the event is based on. e.g `Name`, `ModTime`, `IsDir`, etc. +- Notifies the full path of the file that the event is based on or the old and new paths if the event was a `Rename` or `Move` event. +- Limit amount of events that can be received per watching cycle. +- List the files being watched. +- Trigger custom events. + +# Todo + +- Write more tests. +- Write benchmarks. + +# Example + +```go +package main + +import ( + "fmt" + "log" + "time" + + "github.com/radovskyb/watcher" +) + +func main() { + w := watcher.New() + + // SetMaxEvents to 1 to allow at most 1 event's to be received + // on the Event channel per watching cycle. + // + // If SetMaxEvents is not set, the default is to send all events. + w.SetMaxEvents(1) + + // Only notify rename and move events. + w.FilterOps(watcher.Rename, watcher.Move) + + go func() { + for { + select { + case event := <-w.Event: + fmt.Println(event) // Print the event's info. + case err := <-w.Error: + log.Fatalln(err) + case <-w.Closed: + return + } + } + }() + + // Watch this folder for changes. + if err := w.Add("."); err != nil { + log.Fatalln(err) + } + + // Watch test_folder recursively for changes. + if err := w.AddRecursive("../test_folder"); err != nil { + log.Fatalln(err) + } + + // Print a list of all of the files and folders currently + // being watched and their paths. + for path, f := range w.WatchedFiles() { + fmt.Printf("%s: %s\n", path, f.Name()) + } + + fmt.Println() + + // Trigger 2 events after watcher started. + go func() { + w.Wait() + w.TriggerEvent(watcher.Create, nil) + w.TriggerEvent(watcher.Remove, nil) + }() + + // Start the watching process - it'll check for changes every 100ms. + if err := w.Start(time.Millisecond * 100); err != nil { + log.Fatalln(err) + } +} +``` + +# Contributing +If you would ike to contribute, simply submit a pull request. + +# Command + +`watcher` comes with a simple command which is installed when using the `go get` command from above. + +# Usage + +``` +Usage of watcher: + -cmd string + command to run when an event occurs + -dotfiles + watch dot files (default true) + -interval string + watcher poll interval (default "100ms") + -keepalive + keep alive when a cmd returns code != 0 + -list + list watched files on start + -pipe + pipe event's info to command's stdin + -recursive + watch folders recursively (default true) + -startcmd + run the command when watcher starts +``` + +All of the flags are optional and watcher can also be called by itself: +```shell +watcher +``` +(watches the current directory recursively for changes and notifies any events that occur.) + +A more elaborate example using the `watcher` command: +```shell +watcher -dotfiles=false -recursive=false -cmd="./myscript" main.go ../ +``` +In this example, `watcher` will ignore dot files and folders and won't watch any of the specified folders recursively. It will also run the script `./myscript` anytime an event occurs while watching `main.go` or any files or folders in the previous directory (`../`). + +Using the `pipe` and `cmd` flags together will send the event's info to the command's stdin when changes are detected. + +First create a file called `script.py` with the following contents: +```python +import sys + +for line in sys.stdin: + print (line + " - python") +``` + +Next, start watcher with the `pipe` and `cmd` flags enabled: +```shell +watcher -cmd="python script.py" -pipe=true +``` + +Now when changes are detected, the event's info will be output from the running python script. diff --git a/vendor/github.com/radovskyb/watcher/samefile.go b/vendor/github.com/radovskyb/watcher/samefile.go new file mode 100644 index 00000000..8c9cb325 --- /dev/null +++ b/vendor/github.com/radovskyb/watcher/samefile.go @@ -0,0 +1,9 @@ +// +build !windows + +package watcher + +import "os" + +func SameFile(fi1, fi2 os.FileInfo) bool { + return os.SameFile(fi1, fi2) +} diff --git a/vendor/github.com/radovskyb/watcher/samefile_windows.go b/vendor/github.com/radovskyb/watcher/samefile_windows.go new file mode 100644 index 00000000..1ea95120 --- /dev/null +++ b/vendor/github.com/radovskyb/watcher/samefile_windows.go @@ -0,0 +1,12 @@ +// +build windows + +package watcher + +import "os" + +func SameFile(fi1, fi2 os.FileInfo) bool { + return fi1.ModTime() == fi2.ModTime() && + fi1.Size() == fi2.Size() && + fi1.Mode() == fi2.Mode() && + fi1.IsDir() == fi2.IsDir() +} diff --git a/vendor/github.com/radovskyb/watcher/watcher.go b/vendor/github.com/radovskyb/watcher/watcher.go new file mode 100644 index 00000000..e486ea0a --- /dev/null +++ b/vendor/github.com/radovskyb/watcher/watcher.go @@ -0,0 +1,621 @@ +package watcher + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "sync" + "time" +) + +var ( + // ErrDurationTooShort occurs when calling the watcher's Start + // method with a duration that's less than 1 nanosecond. + ErrDurationTooShort = errors.New("error: duration is less than 1ns") + + // ErrWatcherRunning occurs when trying to call the watcher's + // Start method and the polling cycle is still already running + // from previously calling Start and not yet calling Close. + ErrWatcherRunning = errors.New("error: watcher is already running") + + // ErrWatchedFileDeleted is an error that occurs when a file or folder that was + // being watched has been deleted. + ErrWatchedFileDeleted = errors.New("error: watched file or folder deleted") +) + +// An Op is a type that is used to describe what type +// of event has occurred during the watching process. +type Op uint32 + +// Ops +const ( + Create Op = iota + Write + Remove + Rename + Chmod + Move +) + +var ops = map[Op]string{ + Create: "CREATE", + Write: "WRITE", + Remove: "REMOVE", + Rename: "RENAME", + Chmod: "CHMOD", + Move: "MOVE", +} + +// String prints the string version of the Op consts +func (e Op) String() string { + if op, found := ops[e]; found { + return op + } + return "???" +} + +// An Event describes an event that is received when files or directory +// changes occur. It includes the os.FileInfo of the changed file or +// directory and the type of event that's occurred and the full path of the file. +type Event struct { + Op + Path string + os.FileInfo +} + +// String returns a string depending on what type of event occurred and the +// file name associated with the event. +func (e Event) String() string { + if e.FileInfo != nil { + pathType := "FILE" + if e.IsDir() { + pathType = "DIRECTORY" + } + return fmt.Sprintf("%s %q %s [%s]", pathType, e.Name(), e.Op, e.Path) + } + return "???" +} + +type Watcher struct { + Event chan Event + Error chan error + Closed chan struct{} + close chan struct{} + wg *sync.WaitGroup + + // mu protects the following. + mu *sync.Mutex + running bool + names map[string]bool // bool for recursive or not. + files map[string]os.FileInfo // map of files. + ignored map[string]struct{} // ignored files or directories. + ops map[Op]struct{} // Op filtering. + ignoreHidden bool // ignore hidden files or not. + maxEvents int // max sent events per cycle +} + +// New creates a new Watcher. +func New() *Watcher { + // Set up the WaitGroup for w.Wait(). + var wg sync.WaitGroup + wg.Add(1) + + return &Watcher{ + Event: make(chan Event), + Error: make(chan error), + Closed: make(chan struct{}), + close: make(chan struct{}), + mu: new(sync.Mutex), + wg: &wg, + files: make(map[string]os.FileInfo), + ignored: make(map[string]struct{}), + names: make(map[string]bool), + } +} + +// SetMaxEvents controls the maximum amount of events that are sent on +// the Event channel per watching cycle. If max events is less than 1, there is +// no limit, which is the default. +func (w *Watcher) SetMaxEvents(delta int) { + w.mu.Lock() + w.maxEvents = delta + w.mu.Unlock() +} + +// IgnoreHiddenFiles sets the watcher to ignore any file or directory +// that starts with a dot. +func (w *Watcher) IgnoreHiddenFiles(ignore bool) { + w.mu.Lock() + w.ignoreHidden = ignore + w.mu.Unlock() +} + +// FilterOps filters which event op types should be returned +// when an event occurs. +func (w *Watcher) FilterOps(ops ...Op) { + w.mu.Lock() + w.ops = make(map[Op]struct{}) + for _, op := range ops { + w.ops[op] = struct{}{} + } + w.mu.Unlock() +} + +// Add adds either a single file or directory to the file list. +func (w *Watcher) Add(name string) (err error) { + w.mu.Lock() + defer w.mu.Unlock() + + name, err = filepath.Abs(name) + if err != nil { + return err + } + + // If name is on the ignored list or if hidden files are + // ignored and name is a hidden file or directory, simply return. + _, ignored := w.ignored[name] + if ignored || (w.ignoreHidden && strings.HasPrefix(name, ".")) { + return nil + } + + // Add the directory's contents to the files list. + fileList, err := w.list(name) + if err != nil { + return err + } + for k, v := range fileList { + w.files[k] = v + } + + // Add the name to the names list. + w.names[name] = false + + return nil +} + +func (w *Watcher) list(name string) (map[string]os.FileInfo, error) { + fileList := make(map[string]os.FileInfo) + + // Make sure name exists. + stat, err := os.Stat(name) + if err != nil { + return nil, err + } + + fileList[name] = stat + + // If it's not a directory, just return. + if !stat.IsDir() { + return fileList, nil + } + + // It's a directory. + fInfoList, err := ioutil.ReadDir(name) + if err != nil { + return nil, err + } + // Add all of the files in the directory to the file list as long + // as they aren't on the ignored list or are hidden files if ignoreHidden + // is set to true. + for _, fInfo := range fInfoList { + path := filepath.Join(name, fInfo.Name()) + _, ignored := w.ignored[path] + if ignored || (w.ignoreHidden && strings.HasPrefix(fInfo.Name(), ".")) { + continue + } + fileList[path] = fInfo + } + return fileList, nil +} + +// Add adds either a single file or directory recursively to the file list. +func (w *Watcher) AddRecursive(name string) (err error) { + w.mu.Lock() + defer w.mu.Unlock() + + name, err = filepath.Abs(name) + if err != nil { + return err + } + + fileList, err := w.listRecursive(name) + if err != nil { + return err + } + for k, v := range fileList { + w.files[k] = v + } + + // Add the name to the names list. + w.names[name] = true + + return nil +} + +func (w *Watcher) listRecursive(name string) (map[string]os.FileInfo, error) { + fileList := make(map[string]os.FileInfo) + + return fileList, filepath.Walk(name, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + // If path is ignored and it's a directory, skip the directory. If it's + // ignored and it's a single file, skip the file. + _, ignored := w.ignored[path] + if ignored || (w.ignoreHidden && strings.HasPrefix(info.Name(), ".")) { + if info.IsDir() { + return filepath.SkipDir + } + return nil + } + // Add the path and it's info to the file list. + fileList[path] = info + return nil + }) +} + +// Remove removes either a single file or directory from the file's list. +func (w *Watcher) Remove(name string) (err error) { + w.mu.Lock() + defer w.mu.Unlock() + + name, err = filepath.Abs(name) + if err != nil { + return err + } + + // Remove the name from w's names list. + delete(w.names, name) + + // If name is a single file, remove it and return. + info, found := w.files[name] + if !found { + return nil // Doesn't exist, just return. + } + if !info.IsDir() { + delete(w.files, name) + return nil + } + + // Delete the actual directory from w.files + delete(w.files, name) + + // If it's a directory, delete all of it's contents from w.files. + for path := range w.files { + if filepath.Dir(path) == name { + delete(w.files, path) + } + } + return nil +} + +// Remove removes either a single file or a directory recursively from +// the file's list. +func (w *Watcher) RemoveRecursive(name string) (err error) { + w.mu.Lock() + defer w.mu.Unlock() + + name, err = filepath.Abs(name) + if err != nil { + return err + } + + // Remove the name from w's names list. + delete(w.names, name) + + // If name is a single file, remove it and return. + info, found := w.files[name] + if !found { + return nil // Doesn't exist, just return. + } + if !info.IsDir() { + delete(w.files, name) + return nil + } + + // If it's a directory, delete all of it's contents recursively + // from w.files. + for path := range w.files { + if strings.HasPrefix(path, name) { + delete(w.files, path) + } + } + return nil +} + +// Ignore adds paths that should be ignored. +// +// For files that are already added, Ignore removes them. +func (w *Watcher) Ignore(paths ...string) (err error) { + for _, path := range paths { + path, err = filepath.Abs(path) + if err != nil { + return err + } + // Remove any of the paths that were already added. + if err := w.RemoveRecursive(path); err != nil { + return err + } + w.mu.Lock() + w.ignored[path] = struct{}{} + w.mu.Unlock() + } + return nil +} + +func (w *Watcher) WatchedFiles() map[string]os.FileInfo { + w.mu.Lock() + defer w.mu.Unlock() + + return w.files +} + +// fileInfo is an implementation of os.FileInfo that can be used +// as a mocked os.FileInfo when triggering an event when the specified +// os.FileInfo is nil. +type fileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time + sys interface{} + dir bool +} + +func (fs *fileInfo) IsDir() bool { + return fs.dir +} +func (fs *fileInfo) ModTime() time.Time { + return fs.modTime +} +func (fs *fileInfo) Mode() os.FileMode { + return fs.mode +} +func (fs *fileInfo) Name() string { + return fs.name +} +func (fs *fileInfo) Size() int64 { + return fs.size +} +func (fs *fileInfo) Sys() interface{} { + return fs.sys +} + +// TriggerEvent is a method that can be used to trigger an event, separate to +// the file watching process. +func (w *Watcher) TriggerEvent(eventType Op, file os.FileInfo) { + w.Wait() + if file == nil { + file = &fileInfo{name: "triggered event", modTime: time.Now()} + } + w.Event <- Event{Op: eventType, Path: "-", FileInfo: file} +} + +func (w *Watcher) retrieveFileList() map[string]os.FileInfo { + w.mu.Lock() + defer w.mu.Unlock() + + fileList := make(map[string]os.FileInfo) + + var list map[string]os.FileInfo + var err error + + for name, recursive := range w.names { + if recursive { + list, err = w.listRecursive(name) + if err != nil { + if os.IsNotExist(err) { + w.Error <- ErrWatchedFileDeleted + w.mu.Unlock() + w.RemoveRecursive(name) + w.mu.Lock() + } else { + w.Error <- err + } + } + } else { + list, err = w.list(name) + if err != nil { + if os.IsNotExist(err) { + w.Error <- ErrWatchedFileDeleted + w.mu.Unlock() + w.Remove(name) + w.mu.Lock() + } else { + w.Error <- err + } + } + } + // Add the file's to the file list. + for k, v := range list { + fileList[k] = v + } + } + + return fileList +} + +// Start begins the polling cycle which repeats every specified +// duration until Close is called. +func (w *Watcher) Start(d time.Duration) error { + // Return an error if d is less than 1 nanosecond. + if d < time.Nanosecond { + return ErrDurationTooShort + } + + // Make sure the Watcher is not already running. + w.mu.Lock() + if w.running { + w.mu.Unlock() + return ErrWatcherRunning + } + w.running = true + w.mu.Unlock() + + // Unblock w.Wait(). + w.wg.Done() + + for { + // done lets the inner polling cycle loop know when the + // current cycle's method has finished executing. + done := make(chan struct{}) + + // Any events that are found are first piped to evt before + // being sent to the main Event channel. + evt := make(chan Event) + + // Retrieve the file list for all watched file's and dirs. + fileList := w.retrieveFileList() + + // cancel can be used to cancel the current event polling function. + cancel := make(chan struct{}) + + // Look for events. + go func() { + w.pollEvents(fileList, evt, cancel) + done <- struct{}{} + }() + + // numEvents holds the number of events for the current cycle. + numEvents := 0 + + inner: + for { + select { + case <-w.close: + close(cancel) + close(w.Closed) + return nil + case event := <-evt: + if len(w.ops) > 0 { // Filter Ops. + _, found := w.ops[event.Op] + if !found { + continue + } + } + numEvents++ + if w.maxEvents > 0 && numEvents > w.maxEvents { + close(cancel) + break inner + } + w.Event <- event + case <-done: // Current cycle is finished. + break inner + } + } + + // Update the file's list. + w.mu.Lock() + w.files = fileList + w.mu.Unlock() + + // Sleep and then continue to the next loop iteration. + time.Sleep(d) + } +} + +func (w *Watcher) pollEvents(files map[string]os.FileInfo, evt chan Event, + cancel chan struct{}) { + w.mu.Lock() + defer w.mu.Unlock() + + // Store create and remove events for use to check for rename events. + creates := make(map[string]os.FileInfo) + removes := make(map[string]os.FileInfo) + + // Check for removed files. + for path, info := range w.files { + if _, found := files[path]; !found { + removes[path] = info + } + } + + // Check for created files, writes and chmods. + for path, info := range files { + oldInfo, found := w.files[path] + if !found { + // A file was created. + creates[path] = info + continue + } + if oldInfo.ModTime() != info.ModTime() { + select { + case <-cancel: + return + case evt <- Event{Write, path, info}: + } + } + if oldInfo.Mode() != info.Mode() { + select { + case <-cancel: + return + case evt <- Event{Chmod, path, info}: + } + } + } + + // Check for renames and moves. + for path1, info1 := range removes { + for path2, info2 := range creates { + if SameFile(info1, info2) { + e := Event{ + Op: Move, + Path: fmt.Sprintf("%s -> %s", path1, path2), + FileInfo: info1, + } + // If they are from the same directory, it's a rename + // instead of a move event. + if filepath.Dir(path1) == filepath.Dir(path2) { + e.Op = Rename + } + + delete(removes, path1) + delete(creates, path2) + + select { + case <-cancel: + return + case evt <- e: + } + } + } + } + + // Send all the remaining create and remove events. + for path, info := range creates { + select { + case <-cancel: + return + case evt <- Event{Create, path, info}: + } + } + for path, info := range removes { + select { + case <-cancel: + return + case evt <- Event{Remove, path, info}: + } + } +} + +// Wait blocks until the watcher is started. +func (w *Watcher) Wait() { + w.wg.Wait() +} + +func (w *Watcher) Close() { + w.mu.Lock() + if !w.running { + w.mu.Unlock() + return + } + w.running = false + w.files = make(map[string]os.FileInfo) + w.names = make(map[string]bool) + w.mu.Unlock() + // Send a close signal to the Start method. + w.close <- struct{}{} +} diff --git a/vendor/github.com/rivo/tview/CODE_OF_CONDUCT.md b/vendor/github.com/rivo/tview/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..601e63b8 --- /dev/null +++ b/vendor/github.com/rivo/tview/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at https://rentafounder.com/page/about-me/. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/vendor/github.com/rivo/tview/CONTRIBUTING.md b/vendor/github.com/rivo/tview/CONTRIBUTING.md new file mode 100644 index 00000000..0d962926 --- /dev/null +++ b/vendor/github.com/rivo/tview/CONTRIBUTING.md @@ -0,0 +1,31 @@ +# Contributing to tview + +First of all, thank you for taking the time to contribute. + +The following provides you with some guidance on how to contribute to this project. Mainly, it is meant to save us all some time so please read it, it's not long. + +Please note that this document is work in progress so I might add to it in the future. + +## Issues + +- Please include enough information so everybody understands your request. +- Screenshots or code that illustrates your point always helps. +- It's fine to ask for help. But you should have checked out the [documentation](https://godoc.org/github.com/rivo/tview) first in any case. +- If you request a new feature, state your motivation and share a use case that you faced where you needed that new feature. It should be something that others will also need. + +## Pull Requests + +If you have a feature request, open an issue first before sending me a pull request. It may save you from writing code that will get rejected. If your case is strong, there is a good chance that I will add the feature for you. + +I'm very picky about the code that goes into this repo. So if you violate any of the following guidelines, there is a good chance I won't merge your pull request. + +- There must be a strong case for your additions/changes, such as: + - Bug fixes + - Features that are needed (see "Issues" above; state your motivation) + - Improvements in stability or performance (if readability does not suffer) +- Your code must follow the structure of the existing code. Don't just patch something on. Try to understand how `tview` is currently designed and follow that design. Your code needs to be consistent with existing code. +- If you're adding code that increases the work required to maintain the project, you must be willing to take responsibility for that extra work. I will ask you to maintain your part of the code in the long run. +- Function/type/variable/constant names must be as descriptive as they are right now. Follow the conventions of the package. +- All functions/types/variables/constants, even private ones, must have comments in good English. These comments must be elaborate enough so that new users of the package understand them and can follow them. Provide examples if you have to. +- Your changes must not decrease the project's [Go Report](https://goreportcard.com/report/github.com/rivo/tview) rating. +- No breaking changes unless there is absolutely no other way. diff --git a/vendor/github.com/rivo/tview/LICENSE.txt b/vendor/github.com/rivo/tview/LICENSE.txt new file mode 100644 index 00000000..8aa26455 --- /dev/null +++ b/vendor/github.com/rivo/tview/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/rivo/tview/README.md b/vendor/github.com/rivo/tview/README.md new file mode 100644 index 00000000..1ebfc01b --- /dev/null +++ b/vendor/github.com/rivo/tview/README.md @@ -0,0 +1,101 @@ +# Rich Interactive Widgets for Terminal UIs + +[![Godoc Reference](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/rivo/tview) +[![Go Report](https://img.shields.io/badge/go%20report-A%2B-brightgreen.svg)](https://goreportcard.com/report/github.com/rivo/tview) + +This Go package provides commonly needed components for terminal based user interfaces. + +![Screenshot](tview.gif) + +Among these components are: + +- __Input forms__ (include __input/password fields__, __drop-down selections__, __checkboxes__, and __buttons__) +- Navigable multi-color __text views__ +- Sophisticated navigable __table views__ +- Selectable __lists__ +- __Grid__, __Flexbox__ and __page layouts__ +- Modal __message windows__ +- An __application__ wrapper + +They come with lots of customization options and can be easily extended to fit your needs. + +## Installation + +```bash +go get github.com/rivo/tview +``` + +## Hello World + +This basic example creates a box titled "Hello, World!" and displays it in your terminal: + +```go +package main + +import ( + "github.com/rivo/tview" +) + +func main() { + box := tview.NewBox().SetBorder(true).SetTitle("Hello, world!") + if err := tview.NewApplication().SetRoot(box, true).Run(); err != nil { + panic(err) + } +} +``` + +Check out the [GitHub Wiki](https://github.com/rivo/tview/wiki) for more examples along with screenshots. Or try the examples in the "demos" subdirectory. + +For a presentation highlighting this package, compile and run the program found in the "demos/presentation" subdirectory. + +## Documentation + +Refer to https://godoc.org/github.com/rivo/tview for the package's documentation. + +## Dependencies + +This package is based on [github.com/gdamore/tcell](https://github.com/gdamore/tcell) (and its dependencies). + +## Your Feedback + +Add your issue here on GitHub. Feel free to get in touch if you have any questions. + +## Version History + +(There are no corresponding tags in the project. I only keep such a history in this README.) + +- v0.15 (2018-05-02) + - `Flex` and `Grid` don't clear their background per default, thus allowing for custom modals. See the [Wiki](https://github.com/rivo/tview/wiki/Modal) for an example. +- v0.14 (2018-04-13) + - Added an `Escape()` function which keep strings like color or region tags from being recognized as such. + - Added `ANSIIWriter()` and `TranslateANSII()` which convert ANSII escape sequences to `tview` color tags. +- v0.13 (2018-04-01) + - Added background colors and text attributes to color tags. +- v0.12 (2018-03-13) + - Added "suspended mode" to `Application`. +- v0.11 (2018-03-02) + - Added a `RemoveItem()` function to `Grid` and `Flex`. +- v0.10 (2018-02-22) + - Direct access to the `screen` object through callback in `Box` (i.e. for all primitives). +- v0.9 (2018-02-20) + - Introduced `Grid` layout. + - Direct access to the `screen` object through callbacks in `Application`. +- v0.8 (2018-01-17) + - Color tags can now be used almost everywhere. +- v0.7 (2018-01-16) + - Forms can now also have a horizontal layout. +- v0.6 (2018-01-14) + - All primitives can now intercept all key events when they have focus. + - Key events can also be intercepted globally (changed to a more general, consistent handling) +- v0.5 (2018-01-13) + - `TextView` now has word wrapping and text alignment +- v0.4 (2018-01-12) + - `TextView` now accepts color tags with any W3C color (including RGB hex values). + - Support for wide unicode characters. +- v0.3 (2018-01-11) + - Added masking to `InputField` and password entry to `Form`. +- v0.2 (2018-01-10) + - Added `Styles` variable with default colors for primitives. + - Completed some missing InputField functions. +- v0.1 (2018-01-06) + - First Release. diff --git a/vendor/github.com/rivo/tview/ansii.go b/vendor/github.com/rivo/tview/ansii.go new file mode 100644 index 00000000..0ce3d4a7 --- /dev/null +++ b/vendor/github.com/rivo/tview/ansii.go @@ -0,0 +1,237 @@ +package tview + +import ( + "bytes" + "fmt" + "io" + "strconv" + "strings" +) + +// The states of the ANSII escape code parser. +const ( + ansiiText = iota + ansiiEscape + ansiiSubstring + ansiiControlSequence +) + +// ansii is a io.Writer which translates ANSII escape codes into tview color +// tags. +type ansii struct { + io.Writer + + // Reusable buffers. + buffer *bytes.Buffer // The entire output text of one Write(). + csiParameter, csiIntermediate *bytes.Buffer // Partial CSI strings. + + // The current state of the parser. One of the ansii constants. + state int +} + +// ANSIIWriter returns an io.Writer which translates any ANSII escape codes +// written to it into tview color tags. Other escape codes don't have an effect +// and are simply removed. The translated text is written to the provided +// writer. +func ANSIIWriter(writer io.Writer) io.Writer { + return &ansii{ + Writer: writer, + buffer: new(bytes.Buffer), + csiParameter: new(bytes.Buffer), + csiIntermediate: new(bytes.Buffer), + state: ansiiText, + } +} + +// Write parses the given text as a string of runes, translates ANSII escape +// codes to color tags and writes them to the output writer. +func (a *ansii) Write(text []byte) (int, error) { + defer func() { + a.buffer.Reset() + }() + + for _, r := range string(text) { + switch a.state { + + // We just entered an escape sequence. + case ansiiEscape: + switch r { + case '[': // Control Sequence Introducer. + a.csiParameter.Reset() + a.csiIntermediate.Reset() + a.state = ansiiControlSequence + case 'c': // Reset. + fmt.Fprint(a.buffer, "[-:-:-]") + a.state = ansiiText + case 'P', ']', 'X', '^', '_': // Substrings and commands. + a.state = ansiiSubstring + default: // Ignore. + a.state = ansiiText + } + + // CSI Sequences. + case ansiiControlSequence: + switch { + case r >= 0x30 && r <= 0x3f: // Parameter bytes. + if _, err := a.csiParameter.WriteRune(r); err != nil { + return 0, err + } + case r >= 0x20 && r <= 0x2f: // Intermediate bytes. + if _, err := a.csiIntermediate.WriteRune(r); err != nil { + return 0, err + } + case r >= 0x40 && r <= 0x7e: // Final byte. + switch r { + case 'E': // Next line. + count, _ := strconv.Atoi(a.csiParameter.String()) + if count == 0 { + count = 1 + } + fmt.Fprint(a.buffer, strings.Repeat("\n", count)) + case 'm': // Select Graphic Rendition. + var ( + background, foreground, attributes string + clearAttributes bool + ) + fields := strings.Split(a.csiParameter.String(), ";") + if len(fields) == 0 || len(fields) == 1 && fields[0] == "0" { + // Reset. + if _, err := a.buffer.WriteString("[-:-:-]"); err != nil { + return 0, err + } + break + } + lookupColor := func(colorNumber int, bright bool) string { + if colorNumber < 0 || colorNumber > 7 { + return "black" + } + if bright { + colorNumber += 8 + } + return [...]string{ + "black", + "red", + "green", + "yellow", + "blue", + "darkmagenta", + "darkcyan", + "white", + "#7f7f7f", + "#ff0000", + "#00ff00", + "#ffff00", + "#5c5cff", + "#ff00ff", + "#00ffff", + "#ffffff", + }[colorNumber] + } + for index, field := range fields { + switch field { + case "1", "01": + attributes += "b" + case "2", "02": + attributes += "d" + case "4", "04": + attributes += "u" + case "5", "05": + attributes += "l" + case "7", "07": + attributes += "7" + case "22", "24", "25", "27": + clearAttributes = true + case "30", "31", "32", "33", "34", "35", "36", "37": + colorNumber, _ := strconv.Atoi(field) + foreground = lookupColor(colorNumber-30, false) + case "40", "41", "42", "43", "44", "45", "46", "47": + colorNumber, _ := strconv.Atoi(field) + background = lookupColor(colorNumber-40, false) + case "90", "91", "92", "93", "94", "95", "96", "97": + colorNumber, _ := strconv.Atoi(field) + foreground = lookupColor(colorNumber-90, true) + case "100", "101", "102", "103", "104", "105", "106", "107": + colorNumber, _ := strconv.Atoi(field) + background = lookupColor(colorNumber-100, true) + case "38", "48": + var color string + if len(fields) > index+1 { + if fields[index+1] == "5" && len(fields) > index+2 { // 8-bit colors. + colorNumber, _ := strconv.Atoi(fields[index+2]) + if colorNumber <= 7 { + color = lookupColor(colorNumber, false) + } else if colorNumber <= 15 { + color = lookupColor(colorNumber, true) + } else if colorNumber <= 231 { + red := (colorNumber - 16) / 36 + green := ((colorNumber - 16) / 6) % 6 + blue := (colorNumber - 16) % 6 + color = fmt.Sprintf("%02x%02x%02x", 255*red/5, 255*green/5, 255*blue/5) + } else if colorNumber <= 255 { + grey := 255 * (colorNumber - 232) / 23 + color = fmt.Sprintf("%02x%02x%02x", grey, grey, grey) + } + } else if fields[index+1] == "2" && len(fields) > index+4 { // 24-bit colors. + red, _ := strconv.Atoi(fields[index+2]) + green, _ := strconv.Atoi(fields[index+3]) + blue, _ := strconv.Atoi(fields[index+4]) + color = fmt.Sprintf("%02x%02x%02x", red, green, blue) + } + } + if len(color) > 0 { + if field == "38" { + foreground = color + } else { + background = color + } + } + } + } + if len(attributes) > 0 || clearAttributes { + attributes = ":" + attributes + } + if len(foreground) > 0 || len(background) > 0 || len(attributes) > 0 { + fmt.Fprintf(a.buffer, "[%s:%s%s]", foreground, background, attributes) + } + } + a.state = ansiiText + default: // Undefined byte. + a.state = ansiiText // Abort CSI. + } + + // We just entered a substring/command sequence. + case ansiiSubstring: + if r == 27 { // Most likely the end of the substring. + a.state = ansiiEscape + } // Ignore all other characters. + + // "ansiiText" and all others. + default: + if r == 27 { + // This is the start of an escape sequence. + a.state = ansiiEscape + } else { + // Just a regular rune. Send to buffer. + if _, err := a.buffer.WriteRune(r); err != nil { + return 0, err + } + } + } + } + + // Write buffer to target writer. + n, err := a.buffer.WriteTo(a.Writer) + if err != nil { + return int(n), err + } + return len(text), nil +} + +// TranslateANSII replaces ANSII escape sequences found in the provided string +// with tview's color tags and returns the resulting string. +func TranslateANSII(text string) string { + var buffer bytes.Buffer + writer := ANSIIWriter(&buffer) + writer.Write([]byte(text)) + return buffer.String() +} diff --git a/vendor/github.com/rivo/tview/application.go b/vendor/github.com/rivo/tview/application.go new file mode 100644 index 00000000..31821d9d --- /dev/null +++ b/vendor/github.com/rivo/tview/application.go @@ -0,0 +1,375 @@ +package tview + +import ( + "fmt" + "os" + "sync" + + "github.com/gdamore/tcell" +) + +// Application represents the top node of an application. +// +// It is not strictly required to use this class as none of the other classes +// depend on it. However, it provides useful tools to set up an application and +// plays nicely with all widgets. +type Application struct { + sync.RWMutex + + // The application's screen. + screen tcell.Screen + + // The primitive which currently has the keyboard focus. + focus Primitive + + // The root primitive to be seen on the screen. + root Primitive + + // Whether or not the application resizes the root primitive. + rootFullscreen bool + + // An optional capture function which receives a key event and returns the + // event to be forwarded to the default input handler (nil if nothing should + // be forwarded). + inputCapture func(event *tcell.EventKey) *tcell.EventKey + + // An optional callback function which is invoked just before the root + // primitive is drawn. + beforeDraw func(screen tcell.Screen) bool + + // An optional callback function which is invoked after the root primitive + // was drawn. + afterDraw func(screen tcell.Screen) + + // If this value is true, the application has entered suspended mode. + suspended bool +} + +// NewApplication creates and returns a new application. +func NewApplication() *Application { + return &Application{} +} + +// SetInputCapture sets a function which captures all key events before they are +// forwarded to the key event handler of the primitive which currently has +// focus. This function can then choose to forward that key event (or a +// different one) by returning it or stop the key event processing by returning +// nil. +// +// Note that this also affects the default event handling of the application +// itself: Such a handler can intercept the Ctrl-C event which closes the +// applicatoon. +func (a *Application) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Application { + a.inputCapture = capture + return a +} + +// GetInputCapture returns the function installed with SetInputCapture() or nil +// if no such function has been installed. +func (a *Application) GetInputCapture() func(event *tcell.EventKey) *tcell.EventKey { + return a.inputCapture +} + +// Run starts the application and thus the event loop. This function returns +// when Stop() was called. +func (a *Application) Run() error { + var err error + a.Lock() + + // Make a screen. + a.screen, err = tcell.NewScreen() + if err != nil { + a.Unlock() + return err + } + if err = a.screen.Init(); err != nil { + a.Unlock() + return err + } + + // We catch panics to clean up because they mess up the terminal. + defer func() { + if p := recover(); p != nil { + if a.screen != nil { + a.screen.Fini() + } + panic(p) + } + }() + + // Draw the screen for the first time. + a.Unlock() + a.Draw() + + // Start event loop. + for { + a.Lock() + screen := a.screen + if a.suspended { + a.suspended = false // Clear previous suspended flag. + } + a.Unlock() + if screen == nil { + break + } + + // Wait for next event. + event := a.screen.PollEvent() + if event == nil { + a.Lock() + if a.suspended { + // This screen was renewed due to suspended mode. + a.suspended = false + a.Unlock() + continue // Resume. + } + a.Unlock() + + // The screen was finalized. Exit the loop. + break + } + + switch event := event.(type) { + case *tcell.EventKey: + a.RLock() + p := a.focus + a.RUnlock() + + // Intercept keys. + if a.inputCapture != nil { + event = a.inputCapture(event) + if event == nil { + break // Don't forward event. + } + } + + // Ctrl-C closes the application. + if event.Key() == tcell.KeyCtrlC { + a.Stop() + } + + // Pass other key events to the currently focused primitive. + if p != nil { + if handler := p.InputHandler(); handler != nil { + handler(event, func(p Primitive) { + a.SetFocus(p) + }) + a.Draw() + } + } + case *tcell.EventResize: + a.Lock() + screen := a.screen + a.Unlock() + screen.Clear() + a.Draw() + } + } + + return nil +} + +// Stop stops the application, causing Run() to return. +func (a *Application) Stop() { + a.RLock() + defer a.RUnlock() + if a.screen == nil { + return + } + a.screen.Fini() + a.screen = nil +} + +// Suspend temporarily suspends the application by exiting terminal UI mode and +// invoking the provided function "f". When "f" returns, terminal UI mode is +// entered again and the application resumes. +// +// A return value of true indicates that the application was suspended and "f" +// was called. If false is returned, the application was already suspended, +// terminal UI mode was not exited, and "f" was not called. +func (a *Application) Suspend(f func()) bool { + a.Lock() + + if a.suspended || a.screen == nil { + // Application is already suspended. + a.Unlock() + return false + } + + // Enter suspended mode. + a.suspended = true + a.Unlock() + a.Stop() + + // Deal with panics during suspended mode. Exit the program. + defer func() { + if p := recover(); p != nil { + fmt.Println(p) + os.Exit(1) + } + }() + + // Wait for "f" to return. + f() + + // Make a new screen and redraw. + a.Lock() + var err error + a.screen, err = tcell.NewScreen() + if err != nil { + a.Unlock() + panic(err) + } + if err = a.screen.Init(); err != nil { + a.Unlock() + panic(err) + } + a.Unlock() + a.Draw() + + // Continue application loop. + return true +} + +// Draw refreshes the screen. It calls the Draw() function of the application's +// root primitive and then syncs the screen buffer. +func (a *Application) Draw() *Application { + a.RLock() + screen := a.screen + root := a.root + fullscreen := a.rootFullscreen + before := a.beforeDraw + after := a.afterDraw + a.RUnlock() + + // Maybe we're not ready yet or not anymore. + if screen == nil || root == nil { + return a + } + + // Resize if requested. + if fullscreen && root != nil { + width, height := screen.Size() + root.SetRect(0, 0, width, height) + } + + // Call before handler if there is one. + if before != nil { + if before(screen) { + screen.Show() + return a + } + } + + // Draw all primitives. + root.Draw(screen) + + // Call after handler if there is one. + if after != nil { + after(screen) + } + + // Sync screen. + screen.Show() + + return a +} + +// SetBeforeDrawFunc installs a callback function which is invoked just before +// the root primitive is drawn during screen updates. If the function returns +// true, drawing will not continue, i.e. the root primitive will not be drawn +// (and an after-draw-handler will not be called). +// +// Note that the screen is not cleared by the application. To clear the screen, +// you may call screen.Clear(). +// +// Provide nil to uninstall the callback function. +func (a *Application) SetBeforeDrawFunc(handler func(screen tcell.Screen) bool) *Application { + a.beforeDraw = handler + return a +} + +// GetBeforeDrawFunc returns the callback function installed with +// SetBeforeDrawFunc() or nil if none has been installed. +func (a *Application) GetBeforeDrawFunc() func(screen tcell.Screen) bool { + return a.beforeDraw +} + +// SetAfterDrawFunc installs a callback function which is invoked after the root +// primitive was drawn during screen updates. +// +// Provide nil to uninstall the callback function. +func (a *Application) SetAfterDrawFunc(handler func(screen tcell.Screen)) *Application { + a.afterDraw = handler + return a +} + +// GetAfterDrawFunc returns the callback function installed with +// SetAfterDrawFunc() or nil if none has been installed. +func (a *Application) GetAfterDrawFunc() func(screen tcell.Screen) { + return a.afterDraw +} + +// SetRoot sets the root primitive for this application. If "fullscreen" is set +// to true, the root primitive's position will be changed to fill the screen. +// +// This function must be called at least once or nothing will be displayed when +// the application starts. +// +// It also calls SetFocus() on the primitive. +func (a *Application) SetRoot(root Primitive, fullscreen bool) *Application { + a.Lock() + a.root = root + a.rootFullscreen = fullscreen + if a.screen != nil { + a.screen.Clear() + } + a.Unlock() + + a.SetFocus(root) + + return a +} + +// ResizeToFullScreen resizes the given primitive such that it fills the entire +// screen. +func (a *Application) ResizeToFullScreen(p Primitive) *Application { + a.RLock() + width, height := a.screen.Size() + a.RUnlock() + p.SetRect(0, 0, width, height) + return a +} + +// SetFocus sets the focus on a new primitive. All key events will be redirected +// to that primitive. Callers must ensure that the primitive will handle key +// events. +// +// Blur() will be called on the previously focused primitive. Focus() will be +// called on the new primitive. +func (a *Application) SetFocus(p Primitive) *Application { + a.Lock() + if a.focus != nil { + a.focus.Blur() + } + a.focus = p + if a.screen != nil { + a.screen.HideCursor() + } + a.Unlock() + if p != nil { + p.Focus(func(p Primitive) { + a.SetFocus(p) + }) + } + + return a +} + +// GetFocus returns the primitive which has the current focus. If none has it, +// nil is returned. +func (a *Application) GetFocus() Primitive { + a.RLock() + defer a.RUnlock() + return a.focus +} diff --git a/vendor/github.com/rivo/tview/borders.go b/vendor/github.com/rivo/tview/borders.go new file mode 100644 index 00000000..946c8783 --- /dev/null +++ b/vendor/github.com/rivo/tview/borders.go @@ -0,0 +1,45 @@ +package tview + +// Borders defines various borders used when primitives are drawn. +// These may be changed to accommodate a different look and feel. +var Borders = struct { + Horizontal rune + Vertical rune + TopLeft rune + TopRight rune + BottomLeft rune + BottomRight rune + + LeftT rune + RightT rune + TopT rune + BottomT rune + Cross rune + + HorizontalFocus rune + VerticalFocus rune + TopLeftFocus rune + TopRightFocus rune + BottomLeftFocus rune + BottomRightFocus rune +}{ + Horizontal: BoxDrawingsLightHorizontal, + Vertical: BoxDrawingsLightVertical, + TopLeft: BoxDrawingsLightDownAndRight, + TopRight: BoxDrawingsLightDownAndLeft, + BottomLeft: BoxDrawingsLightUpAndRight, + BottomRight: BoxDrawingsLightUpAndLeft, + + LeftT: BoxDrawingsLightVerticalAndRight, + RightT: BoxDrawingsLightVerticalAndLeft, + TopT: BoxDrawingsLightDownAndHorizontal, + BottomT: BoxDrawingsLightUpAndHorizontal, + Cross: BoxDrawingsLightVerticalAndHorizontal, + + HorizontalFocus: BoxDrawingsDoubleHorizontal, + VerticalFocus: BoxDrawingsDoubleVertical, + TopLeftFocus: BoxDrawingsDoubleDownAndRight, + TopRightFocus: BoxDrawingsDoubleDownAndLeft, + BottomLeftFocus: BoxDrawingsDoubleUpAndRight, + BottomRightFocus: BoxDrawingsDoubleUpAndLeft, +} diff --git a/vendor/github.com/rivo/tview/box.go b/vendor/github.com/rivo/tview/box.go new file mode 100644 index 00000000..654d907c --- /dev/null +++ b/vendor/github.com/rivo/tview/box.go @@ -0,0 +1,324 @@ +package tview + +import ( + "github.com/gdamore/tcell" +) + +// Box implements Primitive with a background and optional elements such as a +// border and a title. Most subclasses keep their content contained in the box +// but don't necessarily have to. +// +// Note that all classes which subclass from Box will also have access to its +// functions. +// +// See https://github.com/rivo/tview/wiki/Box for an example. +type Box struct { + // The position of the rect. + x, y, width, height int + + // The inner rect reserved for the box's content. + innerX, innerY, innerWidth, innerHeight int + + // Border padding. + paddingTop, paddingBottom, paddingLeft, paddingRight int + + // The box's background color. + backgroundColor tcell.Color + + // Whether or not a border is drawn, reducing the box's space for content by + // two in width and height. + border bool + + // The color of the border. + borderColor tcell.Color + + // The title. Only visible if there is a border, too. + title string + + // The color of the title. + titleColor tcell.Color + + // The alignment of the title. + titleAlign int + + // Provides a way to find out if this box has focus. We always go through + // this interface because it may be overridden by implementing classes. + focus Focusable + + // Whether or not this box has focus. + hasFocus bool + + // If set to true, the inner rect of this box will be within the screen at the + // last time the box was drawn. + clampToScreen bool + + // An optional capture function which receives a key event and returns the + // event to be forwarded to the primitive's default input handler (nil if + // nothing should be forwarded). + inputCapture func(event *tcell.EventKey) *tcell.EventKey + + // An optional function which is called before the box is drawn. + draw func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) +} + +// NewBox returns a Box without a border. +func NewBox() *Box { + b := &Box{ + width: 15, + height: 10, + innerX: -1, // Mark as uninitialized. + backgroundColor: Styles.PrimitiveBackgroundColor, + borderColor: Styles.BorderColor, + titleColor: Styles.TitleColor, + titleAlign: AlignCenter, + clampToScreen: true, + } + b.focus = b + return b +} + +// SetBorderPadding sets the size of the borders around the box content. +func (b *Box) SetBorderPadding(top, bottom, left, right int) *Box { + b.paddingTop, b.paddingBottom, b.paddingLeft, b.paddingRight = top, bottom, left, right + return b +} + +// GetRect returns the current position of the rectangle, x, y, width, and +// height. +func (b *Box) GetRect() (int, int, int, int) { + return b.x, b.y, b.width, b.height +} + +// GetInnerRect returns the position of the inner rectangle (x, y, width, +// height), without the border and without any padding. +func (b *Box) GetInnerRect() (int, int, int, int) { + if b.innerX >= 0 { + return b.innerX, b.innerY, b.innerWidth, b.innerHeight + } + x, y, width, height := b.GetRect() + if b.border { + x++ + y++ + width -= 2 + height -= 2 + } + return x + b.paddingLeft, + y + b.paddingTop, + width - b.paddingLeft - b.paddingRight, + height - b.paddingTop - b.paddingBottom +} + +// SetRect sets a new position of the primitive. +func (b *Box) SetRect(x, y, width, height int) { + b.x = x + b.y = y + b.width = width + b.height = height +} + +// SetDrawFunc sets a callback function which is invoked after the box primitive +// has been drawn. This allows you to add a more individual style to the box +// (and all primitives which extend it). +// +// The function is provided with the box's dimensions (set via SetRect()). It +// must return the box's inner dimensions (x, y, width, height) which will be +// returned by GetInnerRect(), used by descendent primitives to draw their own +// content. +func (b *Box) SetDrawFunc(handler func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)) *Box { + b.draw = handler + return b +} + +// GetDrawFunc returns the callback function which was installed with +// SetDrawFunc() or nil if no such function has been installed. +func (b *Box) GetDrawFunc() func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) { + return b.draw +} + +// WrapInputHandler wraps an input handler (see InputHandler()) with the +// functionality to capture input (see SetInputCapture()) before passing it +// on to the provided (default) input handler. +// +// This is only meant to be used by subclassing primitives. +func (b *Box) WrapInputHandler(inputHandler func(*tcell.EventKey, func(p Primitive))) func(*tcell.EventKey, func(p Primitive)) { + return func(event *tcell.EventKey, setFocus func(p Primitive)) { + if b.inputCapture != nil { + event = b.inputCapture(event) + } + if event != nil && inputHandler != nil { + inputHandler(event, setFocus) + } + } +} + +// InputHandler returns nil. +func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return b.WrapInputHandler(nil) +} + +// SetInputCapture installs a function which captures key events before they are +// forwarded to the primitive's default key event handler. This function can +// then choose to forward that key event (or a different one) to the default +// handler by returning it. If nil is returned, the default handler will not +// be called. +// +// Providing a nil handler will remove a previously existing handler. +func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Box { + b.inputCapture = capture + return b +} + +// GetInputCapture returns the function installed with SetInputCapture() or nil +// if no such function has been installed. +func (b *Box) GetInputCapture() func(event *tcell.EventKey) *tcell.EventKey { + return b.inputCapture +} + +// SetBackgroundColor sets the box's background color. +func (b *Box) SetBackgroundColor(color tcell.Color) *Box { + b.backgroundColor = color + return b +} + +// SetBorder sets the flag indicating whether or not the box should have a +// border. +func (b *Box) SetBorder(show bool) *Box { + b.border = show + return b +} + +// SetBorderColor sets the box's border color. +func (b *Box) SetBorderColor(color tcell.Color) *Box { + b.borderColor = color + return b +} + +// SetTitle sets the box's title. +func (b *Box) SetTitle(title string) *Box { + b.title = title + return b +} + +// SetTitleColor sets the box's title color. +func (b *Box) SetTitleColor(color tcell.Color) *Box { + b.titleColor = color + return b +} + +// SetTitleAlign sets the alignment of the title, one of AlignLeft, AlignCenter, +// or AlignRight. +func (b *Box) SetTitleAlign(align int) *Box { + b.titleAlign = align + return b +} + +// Draw draws this primitive onto the screen. +func (b *Box) Draw(screen tcell.Screen) { + // Don't draw anything if there is no space. + if b.width <= 0 || b.height <= 0 { + return + } + + def := tcell.StyleDefault + + // Fill background. + background := def.Background(b.backgroundColor) + if b.backgroundColor != tcell.ColorDefault { + for y := b.y; y < b.y+b.height; y++ { + for x := b.x; x < b.x+b.width; x++ { + screen.SetContent(x, y, ' ', nil, background) + } + } + } + + // Draw border. + if b.border && b.width >= 2 && b.height >= 2 { + border := background.Foreground(b.borderColor) + var vertical, horizontal, topLeft, topRight, bottomLeft, bottomRight rune + if b.focus.HasFocus() { + horizontal = Borders.HorizontalFocus + vertical = Borders.VerticalFocus + topLeft = Borders.TopLeftFocus + topRight = Borders.TopRightFocus + bottomLeft = Borders.BottomLeftFocus + bottomRight = Borders.BottomRightFocus + } else { + horizontal = Borders.Horizontal + vertical = Borders.Vertical + topLeft = Borders.TopLeft + topRight = Borders.TopRight + bottomLeft = Borders.BottomLeft + bottomRight = Borders.BottomRight + } + for x := b.x + 1; x < b.x+b.width-1; x++ { + screen.SetContent(x, b.y, horizontal, nil, border) + screen.SetContent(x, b.y+b.height-1, horizontal, nil, border) + } + for y := b.y + 1; y < b.y+b.height-1; y++ { + screen.SetContent(b.x, y, vertical, nil, border) + screen.SetContent(b.x+b.width-1, y, vertical, nil, border) + } + screen.SetContent(b.x, b.y, topLeft, nil, border) + screen.SetContent(b.x+b.width-1, b.y, topRight, nil, border) + screen.SetContent(b.x, b.y+b.height-1, bottomLeft, nil, border) + screen.SetContent(b.x+b.width-1, b.y+b.height-1, bottomRight, nil, border) + + // Draw title. + if b.title != "" && b.width >= 4 { + _, printed := Print(screen, b.title, b.x+1, b.y, b.width-2, b.titleAlign, b.titleColor) + if StringWidth(b.title)-printed > 0 && printed > 0 { + _, _, style, _ := screen.GetContent(b.x+b.width-2, b.y) + fg, _, _ := style.Decompose() + Print(screen, string(SemigraphicsHorizontalEllipsis), b.x+b.width-2, b.y, 1, AlignLeft, fg) + } + } + } + + // Call custom draw function. + if b.draw != nil { + b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.draw(screen, b.x, b.y, b.width, b.height) + } else { + // Remember the inner rect. + b.innerX = -1 + b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.GetInnerRect() + } + + // Clamp inner rect to screen. + if b.clampToScreen { + width, height := screen.Size() + if b.innerX < 0 { + b.innerWidth += b.innerX + b.innerX = 0 + } + if b.innerX+b.innerWidth >= width { + b.innerWidth = width - b.innerX + } + if b.innerY+b.innerHeight >= height { + b.innerHeight = height - b.innerY + } + if b.innerY < 0 { + b.innerHeight += b.innerY + b.innerY = 0 + } + } +} + +// Focus is called when this primitive receives focus. +func (b *Box) Focus(delegate func(p Primitive)) { + b.hasFocus = true +} + +// Blur is called when this primitive loses focus. +func (b *Box) Blur() { + b.hasFocus = false +} + +// HasFocus returns whether or not this primitive has focus. +func (b *Box) HasFocus() bool { + return b.hasFocus +} + +// GetFocusable returns the item's Focusable. +func (b *Box) GetFocusable() Focusable { + return b.focus +} diff --git a/vendor/github.com/rivo/tview/button.go b/vendor/github.com/rivo/tview/button.go new file mode 100644 index 00000000..5efc31ae --- /dev/null +++ b/vendor/github.com/rivo/tview/button.go @@ -0,0 +1,137 @@ +package tview + +import ( + "github.com/gdamore/tcell" +) + +// Button is labeled box that triggers an action when selected. +// +// See https://github.com/rivo/tview/wiki/Button for an example. +type Button struct { + *Box + + // The text to be displayed before the input area. + label string + + // The label color. + labelColor tcell.Color + + // The label color when the button is in focus. + labelColorActivated tcell.Color + + // The background color when the button is in focus. + backgroundColorActivated tcell.Color + + // An optional function which is called when the button was selected. + selected func() + + // An optional function which is called when the user leaves the button. A + // key is provided indicating which key was pressed to leave (tab or backtab). + blur func(tcell.Key) +} + +// NewButton returns a new input field. +func NewButton(label string) *Button { + box := NewBox().SetBackgroundColor(Styles.ContrastBackgroundColor) + box.SetRect(0, 0, StringWidth(label)+4, 1) + return &Button{ + Box: box, + label: label, + labelColor: Styles.PrimaryTextColor, + labelColorActivated: Styles.InverseTextColor, + backgroundColorActivated: Styles.PrimaryTextColor, + } +} + +// SetLabel sets the button text. +func (b *Button) SetLabel(label string) *Button { + b.label = label + return b +} + +// GetLabel returns the button text. +func (b *Button) GetLabel() string { + return b.label +} + +// SetLabelColor sets the color of the button text. +func (b *Button) SetLabelColor(color tcell.Color) *Button { + b.labelColor = color + return b +} + +// SetLabelColorActivated sets the color of the button text when the button is +// in focus. +func (b *Button) SetLabelColorActivated(color tcell.Color) *Button { + b.labelColorActivated = color + return b +} + +// SetBackgroundColorActivated sets the background color of the button text when +// the button is in focus. +func (b *Button) SetBackgroundColorActivated(color tcell.Color) *Button { + b.backgroundColorActivated = color + return b +} + +// SetSelectedFunc sets a handler which is called when the button was selected. +func (b *Button) SetSelectedFunc(handler func()) *Button { + b.selected = handler + return b +} + +// SetBlurFunc sets a handler which is called when the user leaves the button. +// The callback function is provided with the key that was pressed, which is one +// of the following: +// +// - KeyEscape: Leaving the button with no specific direction. +// - KeyTab: Move to the next field. +// - KeyBacktab: Move to the previous field. +func (b *Button) SetBlurFunc(handler func(key tcell.Key)) *Button { + b.blur = handler + return b +} + +// Draw draws this primitive onto the screen. +func (b *Button) Draw(screen tcell.Screen) { + // Draw the box. + borderColor := b.borderColor + backgroundColor := b.backgroundColor + if b.focus.HasFocus() { + b.backgroundColor = b.backgroundColorActivated + b.borderColor = b.labelColorActivated + defer func() { + b.borderColor = borderColor + }() + } + b.Box.Draw(screen) + b.backgroundColor = backgroundColor + + // Draw label. + x, y, width, height := b.GetInnerRect() + if width > 0 && height > 0 { + y = y + height/2 + labelColor := b.labelColor + if b.focus.HasFocus() { + labelColor = b.labelColorActivated + } + Print(screen, b.label, x, y, width, AlignCenter, labelColor) + } +} + +// InputHandler returns the handler for this primitive. +func (b *Button) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return b.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { + // Process key event. + switch key := event.Key(); key { + case tcell.KeyEnter: // Selected. + if b.selected != nil { + b.selected() + } + case tcell.KeyBacktab, tcell.KeyTab, tcell.KeyEscape: // Leave. No action. + if b.blur != nil { + b.blur(key) + } + } + }) +} diff --git a/vendor/github.com/rivo/tview/checkbox.go b/vendor/github.com/rivo/tview/checkbox.go new file mode 100644 index 00000000..768c112e --- /dev/null +++ b/vendor/github.com/rivo/tview/checkbox.go @@ -0,0 +1,203 @@ +package tview + +import ( + "github.com/gdamore/tcell" +) + +// Checkbox implements a simple box for boolean values which can be checked and +// unchecked. +// +// See https://github.com/rivo/tview/wiki/Checkbox for an example. +type Checkbox struct { + *Box + + // Whether or not this box is checked. + checked bool + + // The text to be displayed before the input area. + label string + + // The screen width of the label area. A value of 0 means use the width of + // the label text. + labelWidth int + + // The label color. + labelColor tcell.Color + + // The background color of the input area. + fieldBackgroundColor tcell.Color + + // The text color of the input area. + fieldTextColor tcell.Color + + // An optional function which is called when the user changes the checked + // state of this checkbox. + changed func(checked bool) + + // An optional function which is called when the user indicated that they + // are done entering text. The key which was pressed is provided (tab, + // shift-tab, or escape). + done func(tcell.Key) + + // A callback function set by the Form class and called when the user leaves + // this form item. + finished func(tcell.Key) +} + +// NewCheckbox returns a new input field. +func NewCheckbox() *Checkbox { + return &Checkbox{ + Box: NewBox(), + labelColor: Styles.SecondaryTextColor, + fieldBackgroundColor: Styles.ContrastBackgroundColor, + fieldTextColor: Styles.PrimaryTextColor, + } +} + +// SetChecked sets the state of the checkbox. +func (c *Checkbox) SetChecked(checked bool) *Checkbox { + c.checked = checked + return c +} + +// IsChecked returns whether or not the box is checked. +func (c *Checkbox) IsChecked() bool { + return c.checked +} + +// SetLabel sets the text to be displayed before the input area. +func (c *Checkbox) SetLabel(label string) *Checkbox { + c.label = label + return c +} + +// GetLabel returns the text to be displayed before the input area. +func (c *Checkbox) GetLabel() string { + return c.label +} + +// SetLabelWidth sets the screen width of the label. A value of 0 will cause the +// primitive to use the width of the label string. +func (c *Checkbox) SetLabelWidth(width int) *Checkbox { + c.labelWidth = width + return c +} + +// SetLabelColor sets the color of the label. +func (c *Checkbox) SetLabelColor(color tcell.Color) *Checkbox { + c.labelColor = color + return c +} + +// SetFieldBackgroundColor sets the background color of the input area. +func (c *Checkbox) SetFieldBackgroundColor(color tcell.Color) *Checkbox { + c.fieldBackgroundColor = color + return c +} + +// SetFieldTextColor sets the text color of the input area. +func (c *Checkbox) SetFieldTextColor(color tcell.Color) *Checkbox { + c.fieldTextColor = color + return c +} + +// SetFormAttributes sets attributes shared by all form items. +func (c *Checkbox) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem { + c.labelWidth = labelWidth + c.labelColor = labelColor + c.backgroundColor = bgColor + c.fieldTextColor = fieldTextColor + c.fieldBackgroundColor = fieldBgColor + return c +} + +// GetFieldWidth returns this primitive's field width. +func (c *Checkbox) GetFieldWidth() int { + return 1 +} + +// SetChangedFunc sets a handler which is called when the checked state of this +// checkbox was changed by the user. The handler function receives the new +// state. +func (c *Checkbox) SetChangedFunc(handler func(checked bool)) *Checkbox { + c.changed = handler + return c +} + +// SetDoneFunc sets a handler which is called when the user is done entering +// text. The callback function is provided with the key that was pressed, which +// is one of the following: +// +// - KeyEscape: Abort text input. +// - KeyTab: Move to the next field. +// - KeyBacktab: Move to the previous field. +func (c *Checkbox) SetDoneFunc(handler func(key tcell.Key)) *Checkbox { + c.done = handler + return c +} + +// SetFinishedFunc sets a callback invoked when the user leaves this form item. +func (c *Checkbox) SetFinishedFunc(handler func(key tcell.Key)) FormItem { + c.finished = handler + return c +} + +// Draw draws this primitive onto the screen. +func (c *Checkbox) Draw(screen tcell.Screen) { + c.Box.Draw(screen) + + // Prepare + x, y, width, height := c.GetInnerRect() + rightLimit := x + width + if height < 1 || rightLimit <= x { + return + } + + // Draw label. + if c.labelWidth > 0 { + labelWidth := c.labelWidth + if labelWidth > rightLimit-x { + labelWidth = rightLimit - x + } + Print(screen, c.label, x, y, labelWidth, AlignLeft, c.labelColor) + x += labelWidth + } else { + _, drawnWidth := Print(screen, c.label, x, y, rightLimit-x, AlignLeft, c.labelColor) + x += drawnWidth + } + + // Draw checkbox. + fieldStyle := tcell.StyleDefault.Background(c.fieldBackgroundColor).Foreground(c.fieldTextColor) + if c.focus.HasFocus() { + fieldStyle = fieldStyle.Background(c.fieldTextColor).Foreground(c.fieldBackgroundColor) + } + checkedRune := 'X' + if !c.checked { + checkedRune = ' ' + } + screen.SetContent(x, y, checkedRune, nil, fieldStyle) +} + +// InputHandler returns the handler for this primitive. +func (c *Checkbox) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return c.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { + // Process key event. + switch key := event.Key(); key { + case tcell.KeyRune, tcell.KeyEnter: // Check. + if key == tcell.KeyRune && event.Rune() != ' ' { + break + } + c.checked = !c.checked + if c.changed != nil { + c.changed(c.checked) + } + case tcell.KeyTab, tcell.KeyBacktab, tcell.KeyEscape: // We're done. + if c.done != nil { + c.done(key) + } + if c.finished != nil { + c.finished(key) + } + } + }) +} diff --git a/vendor/github.com/rivo/tview/doc.go b/vendor/github.com/rivo/tview/doc.go new file mode 100644 index 00000000..211185f3 --- /dev/null +++ b/vendor/github.com/rivo/tview/doc.go @@ -0,0 +1,151 @@ +/* +Package tview implements rich widgets for terminal based user interfaces. The +widgets provided with this package are useful for data exploration and data +entry. + +Widgets + +The package implements the following widgets: + + - TextView: Scrollable windows that display multi-colored text. Text may also + be highlighted. + - Table: Scrollable display of tabular data. Table cells, rows, or columns may + also be highlighted. + - List: A navigable text list with optional keyboard shortcuts. + - InputField: One-line input fields to enter text. + - DropDown: Drop-down selection fields. + - Checkbox: Selectable checkbox for boolean values. + - Button: Buttons which get activated when the user selects them. + - Form: Forms composed of input fields, drop down selections, checkboxes, and + buttons. + - Modal: A centered window with a text message and one or more buttons. + - Flex: A Flexbox based layout manager. + - Pages: A page based layout manager. + +The package also provides Application which is used to poll the event queue and +draw widgets on screen. + +Hello World + +The following is a very basic example showing a box with the title "Hello, +world!": + + package main + + import ( + "github.com/rivo/tview" + ) + + func main() { + box := tview.NewBox().SetBorder(true).SetTitle("Hello, world!") + if err := tview.NewApplication().SetRoot(box, true).Run(); err != nil { + panic(err) + } + } + +First, we create a box primitive with a border and a title. Then we create an +application, set the box as its root primitive, and run the event loop. The +application exits when the application's Stop() function is called or when +Ctrl-C is pressed. + +If we have a primitive which consumes key presses, we call the application's +SetFocus() function to redirect all key presses to that primitive. Most +primitives then offer ways to install handlers that allow you to react to any +actions performed on them. + +More Demos + +You will find more demos in the "demos" subdirectory. It also contains a +presentation (written using tview) which gives an overview of the different +widgets and how they can be used. + +Colors + +Throughout this package, colors are specified using the tcell.Color type. +Functions such as tcell.GetColor(), tcell.NewHexColor(), and tcell.NewRGBColor() +can be used to create colors from W3C color names or RGB values. + +Almost all strings which are displayed can contain color tags. Color tags are +W3C color names or six hexadecimal digits following a hash tag, wrapped in +square brackets. Examples: + + This is a [red]warning[white]! + The sky is [#8080ff]blue[#ffffff]. + +A color tag changes the color of the characters following that color tag. This +applies to almost everything from box titles, list text, form item labels, to +table cells. In a TextView, this functionality has to be switched on explicitly. +See the TextView documentation for more information. + +Color tags may contain not just the foreground (text) color but also the +background color and additional flags. In fact, the full definition of a color +tag is as follows: + + [::] + +Each of the three fields can be left blank and trailing fields can be ommitted. +(Empty square brackets "[]", however, are not considered color tags.) Colors +that are not specified will be left unchanged. A field with just a dash ("-") +means "reset to default". + +You can specify the following flags (some flags may not be supported by your +terminal): + + l: blink + b: bold + d: dim + r: reverse (switch foreground and background color) + u: underline + +Examples: + + [yellow]Yellow text + [yellow:red]Yellow text on red background + [:red]Red background, text color unchanged + [yellow::u]Yellow text underlined + [::bl]Bold, blinking text + [::-]Colors unchanged, flags reset + [-]Reset foreground color + [-:-:-]Reset everything + [:]No effect + []Not a valid color tag, will print square brackets as they are + +In the rare event that you want to display a string such as "[red]" or +"[#00ff1a]" without applying its effect, you need to put an opening square +bracket before the closing square bracket. Note that the text inside the +brackets will be matched less strictly than region or colors tags. I.e. any +character that may be used in color or region tags will be recognized. Examples: + + [red[] will be output as [red] + ["123"[] will be output as ["123"] + [#6aff00[[] will be output as [#6aff00[] + [a#"[[[] will be output as [a#"[[] + [] will be output as [] (see color tags above) + [[] will be output as [[] (not an escaped tag) + +You can use the Escape() function to insert brackets automatically where needed. + +Styles + +When primitives are instantiated, they are initialized with colors taken from +the global Styles variable. You may change this variable to adapt the look and +feel of the primitives to your preferred style. + +Unicode Support + +This package supports unicode characters including wide characters. + +Type Hierarchy + +All widgets listed above contain the Box type. All of Box's functions are +therefore available for all widgets, too. + +All widgets also implement the Primitive interface. There is also the Focusable +interface which is used to override functions in subclassing types. + +The tview package is based on https://github.com/gdamore/tcell. It uses types +and constants from that package (e.g. colors and keyboard values). + +This package does not process mouse input (yet). +*/ +package tview diff --git a/vendor/github.com/rivo/tview/dropdown.go b/vendor/github.com/rivo/tview/dropdown.go new file mode 100644 index 00000000..14307487 --- /dev/null +++ b/vendor/github.com/rivo/tview/dropdown.go @@ -0,0 +1,408 @@ +package tview + +import ( + "strings" + + "github.com/gdamore/tcell" + runewidth "github.com/mattn/go-runewidth" +) + +// dropDownOption is one option that can be selected in a drop-down primitive. +type dropDownOption struct { + Text string // The text to be displayed in the drop-down. + Selected func() // The (optional) callback for when this option was selected. +} + +// DropDown implements a selection widget whose options become visible in a +// drop-down list when activated. +// +// See https://github.com/rivo/tview/wiki/DropDown for an example. +type DropDown struct { + *Box + + // The options from which the user can choose. + options []*dropDownOption + + // The index of the currently selected option. Negative if no option is + // currently selected. + currentOption int + + // Set to true if the options are visible and selectable. + open bool + + // The runes typed so far to directly access one of the list items. + prefix string + + // The list element for the options. + list *List + + // The text to be displayed before the input area. + label string + + // The label color. + labelColor tcell.Color + + // The background color of the input area. + fieldBackgroundColor tcell.Color + + // The text color of the input area. + fieldTextColor tcell.Color + + // The color for prefixes. + prefixTextColor tcell.Color + + // The screen width of the label area. A value of 0 means use the width of + // the label text. + labelWidth int + + // The screen width of the input area. A value of 0 means extend as much as + // possible. + fieldWidth int + + // An optional function which is called when the user indicated that they + // are done selecting options. The key which was pressed is provided (tab, + // shift-tab, or escape). + done func(tcell.Key) + + // A callback function set by the Form class and called when the user leaves + // this form item. + finished func(tcell.Key) +} + +// NewDropDown returns a new drop-down. +func NewDropDown() *DropDown { + list := NewList().ShowSecondaryText(false) + list.SetMainTextColor(Styles.PrimitiveBackgroundColor). + SetSelectedTextColor(Styles.PrimitiveBackgroundColor). + SetSelectedBackgroundColor(Styles.PrimaryTextColor). + SetBackgroundColor(Styles.MoreContrastBackgroundColor) + + d := &DropDown{ + Box: NewBox(), + currentOption: -1, + list: list, + labelColor: Styles.SecondaryTextColor, + fieldBackgroundColor: Styles.ContrastBackgroundColor, + fieldTextColor: Styles.PrimaryTextColor, + prefixTextColor: Styles.ContrastSecondaryTextColor, + } + + d.focus = d + + return d +} + +// SetCurrentOption sets the index of the currently selected option. This may +// be a negative value to indicate that no option is currently selected. +func (d *DropDown) SetCurrentOption(index int) *DropDown { + d.currentOption = index + d.list.SetCurrentItem(index) + return d +} + +// GetCurrentOption returns the index of the currently selected option as well +// as its text. If no option was selected, -1 and an empty string is returned. +func (d *DropDown) GetCurrentOption() (int, string) { + var text string + if d.currentOption >= 0 && d.currentOption < len(d.options) { + text = d.options[d.currentOption].Text + } + return d.currentOption, text +} + +// SetLabel sets the text to be displayed before the input area. +func (d *DropDown) SetLabel(label string) *DropDown { + d.label = label + return d +} + +// GetLabel returns the text to be displayed before the input area. +func (d *DropDown) GetLabel() string { + return d.label +} + +// SetLabelWidth sets the screen width of the label. A value of 0 will cause the +// primitive to use the width of the label string. +func (d *DropDown) SetLabelWidth(width int) *DropDown { + d.labelWidth = width + return d +} + +// SetLabelColor sets the color of the label. +func (d *DropDown) SetLabelColor(color tcell.Color) *DropDown { + d.labelColor = color + return d +} + +// SetFieldBackgroundColor sets the background color of the options area. +func (d *DropDown) SetFieldBackgroundColor(color tcell.Color) *DropDown { + d.fieldBackgroundColor = color + return d +} + +// SetFieldTextColor sets the text color of the options area. +func (d *DropDown) SetFieldTextColor(color tcell.Color) *DropDown { + d.fieldTextColor = color + return d +} + +// SetPrefixTextColor sets the color of the prefix string. The prefix string is +// shown when the user starts typing text, which directly selects the first +// option that starts with the typed string. +func (d *DropDown) SetPrefixTextColor(color tcell.Color) *DropDown { + d.prefixTextColor = color + return d +} + +// SetFormAttributes sets attributes shared by all form items. +func (d *DropDown) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem { + d.labelWidth = labelWidth + d.labelColor = labelColor + d.backgroundColor = bgColor + d.fieldTextColor = fieldTextColor + d.fieldBackgroundColor = fieldBgColor + return d +} + +// SetFieldWidth sets the screen width of the options area. A value of 0 means +// extend to as long as the longest option text. +func (d *DropDown) SetFieldWidth(width int) *DropDown { + d.fieldWidth = width + return d +} + +// GetFieldWidth returns this primitive's field screen width. +func (d *DropDown) GetFieldWidth() int { + if d.fieldWidth > 0 { + return d.fieldWidth + } + fieldWidth := 0 + for _, option := range d.options { + width := StringWidth(option.Text) + if width > fieldWidth { + fieldWidth = width + } + } + return fieldWidth +} + +// AddOption adds a new selectable option to this drop-down. The "selected" +// callback is called when this option was selected. It may be nil. +func (d *DropDown) AddOption(text string, selected func()) *DropDown { + d.options = append(d.options, &dropDownOption{Text: text, Selected: selected}) + d.list.AddItem(text, "", 0, nil) + return d +} + +// SetOptions replaces all current options with the ones provided and installs +// one callback function which is called when one of the options is selected. +// It will be called with the option's text and its index into the options +// slice. The "selected" parameter may be nil. +func (d *DropDown) SetOptions(texts []string, selected func(text string, index int)) *DropDown { + d.list.Clear() + d.options = nil + for index, text := range texts { + func(t string, i int) { + d.AddOption(text, func() { + if selected != nil { + selected(t, i) + } + }) + }(text, index) + } + return d +} + +// SetDoneFunc sets a handler which is called when the user is done selecting +// options. The callback function is provided with the key that was pressed, +// which is one of the following: +// +// - KeyEscape: Abort selection. +// - KeyTab: Move to the next field. +// - KeyBacktab: Move to the previous field. +func (d *DropDown) SetDoneFunc(handler func(key tcell.Key)) *DropDown { + d.done = handler + return d +} + +// SetFinishedFunc sets a callback invoked when the user leaves this form item. +func (d *DropDown) SetFinishedFunc(handler func(key tcell.Key)) FormItem { + d.finished = handler + return d +} + +// Draw draws this primitive onto the screen. +func (d *DropDown) Draw(screen tcell.Screen) { + d.Box.Draw(screen) + + // Prepare. + x, y, width, height := d.GetInnerRect() + rightLimit := x + width + if height < 1 || rightLimit <= x { + return + } + + // Draw label. + if d.labelWidth > 0 { + labelWidth := d.labelWidth + if labelWidth > rightLimit-x { + labelWidth = rightLimit - x + } + Print(screen, d.label, x, y, labelWidth, AlignLeft, d.labelColor) + x += labelWidth + } else { + _, drawnWidth := Print(screen, d.label, x, y, rightLimit-x, AlignLeft, d.labelColor) + x += drawnWidth + } + + // What's the longest option text? + maxWidth := 0 + for _, option := range d.options { + strWidth := StringWidth(option.Text) + if strWidth > maxWidth { + maxWidth = strWidth + } + } + + // Draw selection area. + fieldWidth := d.fieldWidth + if fieldWidth == 0 { + fieldWidth = maxWidth + } + if rightLimit-x < fieldWidth { + fieldWidth = rightLimit - x + } + fieldStyle := tcell.StyleDefault.Background(d.fieldBackgroundColor) + if d.GetFocusable().HasFocus() && !d.open { + fieldStyle = fieldStyle.Background(d.fieldTextColor) + } + for index := 0; index < fieldWidth; index++ { + screen.SetContent(x+index, y, ' ', nil, fieldStyle) + } + + // Draw selected text. + if d.open && len(d.prefix) > 0 { + // Show the prefix. + Print(screen, d.prefix, x, y, fieldWidth, AlignLeft, d.prefixTextColor) + prefixWidth := runewidth.StringWidth(d.prefix) + listItemText := d.options[d.list.GetCurrentItem()].Text + if prefixWidth < fieldWidth && len(d.prefix) < len(listItemText) { + Print(screen, listItemText[len(d.prefix):], x+prefixWidth, y, fieldWidth-prefixWidth, AlignLeft, d.fieldTextColor) + } + } else { + if d.currentOption >= 0 && d.currentOption < len(d.options) { + color := d.fieldTextColor + // Just show the current selection. + if d.GetFocusable().HasFocus() && !d.open { + color = d.fieldBackgroundColor + } + Print(screen, d.options[d.currentOption].Text, x, y, fieldWidth, AlignLeft, color) + } + } + + // Draw options list. + if d.HasFocus() && d.open { + // We prefer to drop down but if there is no space, maybe drop up? + lx := x + ly := y + 1 + lwidth := maxWidth + lheight := len(d.options) + _, sheight := screen.Size() + if ly+lheight >= sheight && ly-2 > lheight-ly { + ly = y - lheight + if ly < 0 { + ly = 0 + } + } + if ly+lheight >= sheight { + lheight = sheight - ly + } + d.list.SetRect(lx, ly, lwidth, lheight) + d.list.Draw(screen) + } +} + +// InputHandler returns the handler for this primitive. +func (d *DropDown) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { + // A helper function which selects an item in the drop-down list based on + // the current prefix. + evalPrefix := func() { + if len(d.prefix) > 0 { + for index, option := range d.options { + if strings.HasPrefix(strings.ToLower(option.Text), d.prefix) { + d.list.SetCurrentItem(index) + return + } + } + // Prefix does not match any item. Remove last rune. + r := []rune(d.prefix) + d.prefix = string(r[:len(r)-1]) + } + } + + // Process key event. + switch key := event.Key(); key { + case tcell.KeyEnter, tcell.KeyRune, tcell.KeyDown: + d.prefix = "" + + // If the first key was a letter already, it becomes part of the prefix. + if r := event.Rune(); key == tcell.KeyRune && r != ' ' { + d.prefix += string(r) + evalPrefix() + } + + // Hand control over to the list. + d.open = true + d.list.SetSelectedFunc(func(index int, mainText, secondaryText string, shortcut rune) { + // An option was selected. Close the list again. + d.open = false + setFocus(d) + d.currentOption = index + + // Trigger "selected" event. + if d.options[d.currentOption].Selected != nil { + d.options[d.currentOption].Selected() + } + }).SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + if event.Key() == tcell.KeyRune { + d.prefix += string(event.Rune()) + evalPrefix() + } else if event.Key() == tcell.KeyBackspace || event.Key() == tcell.KeyBackspace2 { + if len(d.prefix) > 0 { + r := []rune(d.prefix) + d.prefix = string(r[:len(r)-1]) + } + evalPrefix() + } else { + d.prefix = "" + } + return event + }) + setFocus(d.list) + case tcell.KeyEscape, tcell.KeyTab, tcell.KeyBacktab: + if d.done != nil { + d.done(key) + } + if d.finished != nil { + d.finished(key) + } + } + }) +} + +// Focus is called by the application when the primitive receives focus. +func (d *DropDown) Focus(delegate func(p Primitive)) { + d.Box.Focus(delegate) + if d.open { + delegate(d.list) + } +} + +// HasFocus returns whether or not this primitive has focus. +func (d *DropDown) HasFocus() bool { + if d.open { + return d.list.HasFocus() + } + return d.hasFocus +} diff --git a/vendor/github.com/rivo/tview/flex.go b/vendor/github.com/rivo/tview/flex.go new file mode 100644 index 00000000..7235614f --- /dev/null +++ b/vendor/github.com/rivo/tview/flex.go @@ -0,0 +1,193 @@ +package tview + +import ( + "github.com/gdamore/tcell" +) + +// Configuration values. +const ( + FlexRow = iota + FlexColumn +) + +// flexItem holds layout options for one item. +type flexItem struct { + Item Primitive // The item to be positioned. May be nil for an empty item. + FixedSize int // The item's fixed size which may not be changed, 0 if it has no fixed size. + Proportion int // The item's proportion. + Focus bool // Whether or not this item attracts the layout's focus. +} + +// Flex is a basic implementation of the Flexbox layout. The contained +// primitives are arranged horizontally or vertically. The way they are +// distributed along that dimension depends on their layout settings, which is +// either a fixed length or a proportional length. See AddItem() for details. +// +// See https://github.com/rivo/tview/wiki/Flex for an example. +type Flex struct { + *Box + + // The items to be positioned. + items []*flexItem + + // FlexRow or FlexColumn. + direction int + + // If set to true, Flex will use the entire screen as its available space + // instead its box dimensions. + fullScreen bool +} + +// NewFlex returns a new flexbox layout container with no primitives and its +// direction set to FlexColumn. To add primitives to this layout, see AddItem(). +// To change the direction, see SetDirection(). +// +// Note that Box, the superclass of Flex, will have its background color set to +// transparent so that any nil flex items will leave their background unchanged. +// To clear a Flex's background before any items are drawn, set it to the +// desired color: +// +// flex.SetBackgroundColor(tview.Styles.PrimitiveBackgroundColor) +func NewFlex() *Flex { + f := &Flex{ + Box: NewBox().SetBackgroundColor(tcell.ColorDefault), + direction: FlexColumn, + } + f.focus = f + return f +} + +// SetDirection sets the direction in which the contained primitives are +// distributed. This can be either FlexColumn (default) or FlexRow. +func (f *Flex) SetDirection(direction int) *Flex { + f.direction = direction + return f +} + +// SetFullScreen sets the flag which, when true, causes the flex layout to use +// the entire screen space instead of whatever size it is currently assigned to. +func (f *Flex) SetFullScreen(fullScreen bool) *Flex { + f.fullScreen = fullScreen + return f +} + +// AddItem adds a new item to the container. The "fixedSize" argument is a width +// or height that may not be changed by the layout algorithm. A value of 0 means +// that its size is flexible and may be changed. The "proportion" argument +// defines the relative size of the item compared to other flexible-size items. +// For example, items with a proportion of 2 will be twice as large as items +// with a proportion of 1. The proportion must be at least 1 if fixedSize == 0 +// (ignored otherwise). +// +// If "focus" is set to true, the item will receive focus when the Flex +// primitive receives focus. If multiple items have the "focus" flag set to +// true, the first one will receive focus. +// +// You can provide a nil value for the primitive. This will still consume screen +// space but nothing will be drawn. +func (f *Flex) AddItem(item Primitive, fixedSize, proportion int, focus bool) *Flex { + f.items = append(f.items, &flexItem{Item: item, FixedSize: fixedSize, Proportion: proportion, Focus: focus}) + return f +} + +// RemoveItem removes all items for the given primitive from the container, +// keeping the order of the remaining items intact. +func (f *Flex) RemoveItem(p Primitive) *Flex { + for index := len(f.items) - 1; index >= 0; index-- { + if f.items[index].Item == p { + f.items = append(f.items[:index], f.items[index+1:]...) + } + } + return f +} + +// ResizeItem sets a new size for the item(s) with the given primitive. If there +// are multiple Flex items with the same primitive, they will all receive the +// same size. For details regarding the size parameters, see AddItem(). +func (f *Flex) ResizeItem(p Primitive, fixedSize, proportion int) *Flex { + for _, item := range f.items { + if item.Item == p { + item.FixedSize = fixedSize + item.Proportion = proportion + } + } + return f +} + +// Draw draws this primitive onto the screen. +func (f *Flex) Draw(screen tcell.Screen) { + f.Box.Draw(screen) + + // Calculate size and position of the items. + + // Do we use the entire screen? + if f.fullScreen { + width, height := screen.Size() + f.SetRect(0, 0, width, height) + } + + // How much space can we distribute? + x, y, width, height := f.GetInnerRect() + var proportionSum int + distSize := width + if f.direction == FlexRow { + distSize = height + } + for _, item := range f.items { + if item.FixedSize > 0 { + distSize -= item.FixedSize + } else { + proportionSum += item.Proportion + } + } + + // Calculate positions and draw items. + pos := x + if f.direction == FlexRow { + pos = y + } + for _, item := range f.items { + size := item.FixedSize + if size <= 0 { + size = distSize * item.Proportion / proportionSum + distSize -= size + proportionSum -= item.Proportion + } + if item.Item != nil { + if f.direction == FlexColumn { + item.Item.SetRect(pos, y, size, height) + } else { + item.Item.SetRect(x, pos, width, size) + } + } + pos += size + + if item.Item != nil { + if item.Item.GetFocusable().HasFocus() { + defer item.Item.Draw(screen) + } else { + item.Item.Draw(screen) + } + } + } +} + +// Focus is called when this primitive receives focus. +func (f *Flex) Focus(delegate func(p Primitive)) { + for _, item := range f.items { + if item.Item != nil && item.Focus { + delegate(item.Item) + return + } + } +} + +// HasFocus returns whether or not this primitive has focus. +func (f *Flex) HasFocus() bool { + for _, item := range f.items { + if item.Item != nil && item.Item.GetFocusable().HasFocus() { + return true + } + } + return false +} diff --git a/vendor/github.com/rivo/tview/focusable.go b/vendor/github.com/rivo/tview/focusable.go new file mode 100644 index 00000000..99fdaaf4 --- /dev/null +++ b/vendor/github.com/rivo/tview/focusable.go @@ -0,0 +1,8 @@ +package tview + +// Focusable provides a method which determines if a primitive has focus. +// Composed primitives may be focused based on the focused state of their +// contained primitives. +type Focusable interface { + HasFocus() bool +} diff --git a/vendor/github.com/rivo/tview/form.go b/vendor/github.com/rivo/tview/form.go new file mode 100644 index 00000000..d778a6a0 --- /dev/null +++ b/vendor/github.com/rivo/tview/form.go @@ -0,0 +1,513 @@ +package tview + +import ( + "github.com/gdamore/tcell" +) + +// DefaultFormFieldWidth is the default field screen width of form elements +// whose field width is flexible (0). This is used in the Form class for +// horizontal layouts. +var DefaultFormFieldWidth = 10 + +// FormItem is the interface all form items must implement to be able to be +// included in a form. +type FormItem interface { + Primitive + + // GetLabel returns the item's label text. + GetLabel() string + + // SetFormAttributes sets a number of item attributes at once. + SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem + + // GetFieldWidth returns the width of the form item's field (the area which + // is manipulated by the user) in number of screen cells. A value of 0 + // indicates the the field width is flexible and may use as much space as + // required. + GetFieldWidth() int + + // SetEnteredFunc sets the handler function for when the user finished + // entering data into the item. The handler may receive events for the + // Enter key (we're done), the Escape key (cancel input), the Tab key (move to + // next field), and the Backtab key (move to previous field). + SetFinishedFunc(handler func(key tcell.Key)) FormItem +} + +// Form allows you to combine multiple one-line form elements into a vertical +// or horizontal layout. Form elements include types such as InputField or +// Checkbox. These elements can be optionally followed by one or more buttons +// for which you can define form-wide actions (e.g. Save, Clear, Cancel). +// +// See https://github.com/rivo/tview/wiki/Form for an example. +type Form struct { + *Box + + // The items of the form (one row per item). + items []FormItem + + // The buttons of the form. + buttons []*Button + + // If set to true, instead of position items and buttons from top to bottom, + // they are positioned from left to right. + horizontal bool + + // The alignment of the buttons. + buttonsAlign int + + // The number of empty rows between items. + itemPadding int + + // The index of the item or button which has focus. (Items are counted first, + // buttons are counted last.) + focusedElement int + + // The label color. + labelColor tcell.Color + + // The background color of the input area. + fieldBackgroundColor tcell.Color + + // The text color of the input area. + fieldTextColor tcell.Color + + // The background color of the buttons. + buttonBackgroundColor tcell.Color + + // The color of the button text. + buttonTextColor tcell.Color + + // An optional function which is called when the user hits Escape. + cancel func() +} + +// NewForm returns a new form. +func NewForm() *Form { + box := NewBox().SetBorderPadding(1, 1, 1, 1) + + f := &Form{ + Box: box, + itemPadding: 1, + labelColor: Styles.SecondaryTextColor, + fieldBackgroundColor: Styles.ContrastBackgroundColor, + fieldTextColor: Styles.PrimaryTextColor, + buttonBackgroundColor: Styles.ContrastBackgroundColor, + buttonTextColor: Styles.PrimaryTextColor, + } + + f.focus = f + + return f +} + +// SetItemPadding sets the number of empty rows between form items for vertical +// layouts and the number of empty cells between form items for horizontal +// layouts. +func (f *Form) SetItemPadding(padding int) *Form { + f.itemPadding = padding + return f +} + +// SetHorizontal sets the direction the form elements are laid out. If set to +// true, instead of positioning them from top to bottom (the default), they are +// positioned from left to right, moving into the next row if there is not +// enough space. +func (f *Form) SetHorizontal(horizontal bool) *Form { + f.horizontal = horizontal + return f +} + +// SetLabelColor sets the color of the labels. +func (f *Form) SetLabelColor(color tcell.Color) *Form { + f.labelColor = color + return f +} + +// SetFieldBackgroundColor sets the background color of the input areas. +func (f *Form) SetFieldBackgroundColor(color tcell.Color) *Form { + f.fieldBackgroundColor = color + return f +} + +// SetFieldTextColor sets the text color of the input areas. +func (f *Form) SetFieldTextColor(color tcell.Color) *Form { + f.fieldTextColor = color + return f +} + +// SetButtonsAlign sets how the buttons align horizontally, one of AlignLeft +// (the default), AlignCenter, and AlignRight. This is only +func (f *Form) SetButtonsAlign(align int) *Form { + f.buttonsAlign = align + return f +} + +// SetButtonBackgroundColor sets the background color of the buttons. +func (f *Form) SetButtonBackgroundColor(color tcell.Color) *Form { + f.buttonBackgroundColor = color + return f +} + +// SetButtonTextColor sets the color of the button texts. +func (f *Form) SetButtonTextColor(color tcell.Color) *Form { + f.buttonTextColor = color + return f +} + +// AddInputField adds an input field to the form. It has a label, an optional +// initial value, a field width (a value of 0 extends it as far as possible), +// an optional accept function to validate the item's value (set to nil to +// accept any text), and an (optional) callback function which is invoked when +// the input field's text has changed. +func (f *Form) AddInputField(label, value string, fieldWidth int, accept func(textToCheck string, lastChar rune) bool, changed func(text string)) *Form { + f.items = append(f.items, NewInputField(). + SetLabel(label). + SetText(value). + SetFieldWidth(fieldWidth). + SetAcceptanceFunc(accept). + SetChangedFunc(changed)) + return f +} + +// AddPasswordField adds a password field to the form. This is similar to an +// input field except that the user's input not shown. Instead, a "mask" +// character is displayed. The password field has a label, an optional initial +// value, a field width (a value of 0 extends it as far as possible), and an +// (optional) callback function which is invoked when the input field's text has +// changed. +func (f *Form) AddPasswordField(label, value string, fieldWidth int, mask rune, changed func(text string)) *Form { + if mask == 0 { + mask = '*' + } + f.items = append(f.items, NewInputField(). + SetLabel(label). + SetText(value). + SetFieldWidth(fieldWidth). + SetMaskCharacter(mask). + SetChangedFunc(changed)) + return f +} + +// AddDropDown adds a drop-down element to the form. It has a label, options, +// and an (optional) callback function which is invoked when an option was +// selected. The initial option may be a negative value to indicate that no +// option is currently selected. +func (f *Form) AddDropDown(label string, options []string, initialOption int, selected func(option string, optionIndex int)) *Form { + f.items = append(f.items, NewDropDown(). + SetLabel(label). + SetCurrentOption(initialOption). + SetOptions(options, selected)) + return f +} + +// AddCheckbox adds a checkbox to the form. It has a label, an initial state, +// and an (optional) callback function which is invoked when the state of the +// checkbox was changed by the user. +func (f *Form) AddCheckbox(label string, checked bool, changed func(checked bool)) *Form { + f.items = append(f.items, NewCheckbox(). + SetLabel(label). + SetChecked(checked). + SetChangedFunc(changed)) + return f +} + +// AddButton adds a new button to the form. The "selected" function is called +// when the user selects this button. It may be nil. +func (f *Form) AddButton(label string, selected func()) *Form { + f.buttons = append(f.buttons, NewButton(label).SetSelectedFunc(selected)) + return f +} + +// Clear removes all input elements from the form, including the buttons if +// specified. +func (f *Form) Clear(includeButtons bool) *Form { + f.items = nil + if includeButtons { + f.buttons = nil + } + f.focusedElement = 0 + return f +} + +// AddFormItem adds a new item to the form. This can be used to add your own +// objects to the form. Note, however, that the Form class will override some +// of its attributes to make it work in the form context. Specifically, these +// are: +// +// - The label width +// - The label color +// - The background color +// - The field text color +// - The field background color +func (f *Form) AddFormItem(item FormItem) *Form { + f.items = append(f.items, item) + return f +} + +// GetFormItem returns the form element at the given position, starting with +// index 0. Elements are referenced in the order they were added. Buttons are +// not included. +func (f *Form) GetFormItem(index int) FormItem { + return f.items[index] +} + +// GetFormItemByLabel returns the first form element with the given label. If +// no such element is found, nil is returned. Buttons are not searched and will +// therefore not be returned. +func (f *Form) GetFormItemByLabel(label string) FormItem { + for _, item := range f.items { + if item.GetLabel() == label { + return item + } + } + return nil +} + +// SetCancelFunc sets a handler which is called when the user hits the Escape +// key. +func (f *Form) SetCancelFunc(callback func()) *Form { + f.cancel = callback + return f +} + +// Draw draws this primitive onto the screen. +func (f *Form) Draw(screen tcell.Screen) { + f.Box.Draw(screen) + + // Determine the dimensions. + x, y, width, height := f.GetInnerRect() + topLimit := y + bottomLimit := y + height + rightLimit := x + width + startX := x + + // Find the longest label. + var maxLabelWidth int + for _, item := range f.items { + labelWidth := StringWidth(item.GetLabel()) + if labelWidth > maxLabelWidth { + maxLabelWidth = labelWidth + } + } + maxLabelWidth++ // Add one space. + + // Calculate positions of form items. + positions := make([]struct{ x, y, width, height int }, len(f.items)+len(f.buttons)) + var focusedPosition struct{ x, y, width, height int } + for index, item := range f.items { + // Calculate the space needed. + labelWidth := StringWidth(item.GetLabel()) + var itemWidth int + if f.horizontal { + fieldWidth := item.GetFieldWidth() + if fieldWidth == 0 { + fieldWidth = DefaultFormFieldWidth + } + labelWidth++ + itemWidth = labelWidth + fieldWidth + } else { + // We want all fields to align vertically. + labelWidth = maxLabelWidth + itemWidth = width + } + + // Advance to next line if there is no space. + if f.horizontal && x+labelWidth+1 >= rightLimit { + x = startX + y += 2 + } + + // Adjust the item's attributes. + if x+itemWidth >= rightLimit { + itemWidth = rightLimit - x + } + item.SetFormAttributes( + labelWidth, + f.labelColor, + f.backgroundColor, + f.fieldTextColor, + f.fieldBackgroundColor, + ) + + // Save position. + positions[index].x = x + positions[index].y = y + positions[index].width = itemWidth + positions[index].height = 1 + if item.GetFocusable().HasFocus() { + focusedPosition = positions[index] + } + + // Advance to next item. + if f.horizontal { + x += itemWidth + f.itemPadding + } else { + y += 1 + f.itemPadding + } + } + + // How wide are the buttons? + buttonWidths := make([]int, len(f.buttons)) + buttonsWidth := 0 + for index, button := range f.buttons { + w := StringWidth(button.GetLabel()) + 4 + buttonWidths[index] = w + buttonsWidth += w + 1 + } + buttonsWidth-- + + // Where do we place them? + if !f.horizontal && x+buttonsWidth < rightLimit { + if f.buttonsAlign == AlignRight { + x = rightLimit - buttonsWidth + } else if f.buttonsAlign == AlignCenter { + x = (x + rightLimit - buttonsWidth) / 2 + } + + // In vertical layouts, buttons always appear after an empty line. + if f.itemPadding == 0 { + y++ + } + } + + // Calculate positions of buttons. + for index, button := range f.buttons { + space := rightLimit - x + buttonWidth := buttonWidths[index] + if f.horizontal { + if space < buttonWidth-4 { + x = startX + y += 2 + space = width + } + } else { + if space < 1 { + break // No space for this button anymore. + } + } + if buttonWidth > space { + buttonWidth = space + } + button.SetLabelColor(f.buttonTextColor). + SetLabelColorActivated(f.buttonBackgroundColor). + SetBackgroundColorActivated(f.buttonTextColor). + SetBackgroundColor(f.buttonBackgroundColor) + + buttonIndex := index + len(f.items) + positions[buttonIndex].x = x + positions[buttonIndex].y = y + positions[buttonIndex].width = buttonWidth + positions[buttonIndex].height = 1 + + if button.HasFocus() { + focusedPosition = positions[buttonIndex] + } + + x += buttonWidth + 1 + } + + // Determine vertical offset based on the position of the focused item. + var offset int + if focusedPosition.y+focusedPosition.height > bottomLimit { + offset = focusedPosition.y + focusedPosition.height - bottomLimit + if focusedPosition.y-offset < topLimit { + offset = focusedPosition.y - topLimit + } + } + + // Draw items. + for index, item := range f.items { + // Set position. + y := positions[index].y - offset + height := positions[index].height + item.SetRect(positions[index].x, y, positions[index].width, height) + + // Is this item visible? + if y+height <= topLimit || y >= bottomLimit { + continue + } + + // Draw items with focus last (in case of overlaps). + if item.GetFocusable().HasFocus() { + defer item.Draw(screen) + } else { + item.Draw(screen) + } + } + + // Draw buttons. + for index, button := range f.buttons { + // Set position. + buttonIndex := index + len(f.items) + y := positions[buttonIndex].y - offset + height := positions[buttonIndex].height + button.SetRect(positions[buttonIndex].x, y, positions[buttonIndex].width, height) + + // Is this button visible? + if y+height <= topLimit || y >= bottomLimit { + continue + } + + // Draw button. + button.Draw(screen) + } +} + +// Focus is called by the application when the primitive receives focus. +func (f *Form) Focus(delegate func(p Primitive)) { + if len(f.items)+len(f.buttons) == 0 { + return + } + + // Hand on the focus to one of our child elements. + if f.focusedElement < 0 || f.focusedElement >= len(f.items)+len(f.buttons) { + f.focusedElement = 0 + } + handler := func(key tcell.Key) { + switch key { + case tcell.KeyTab, tcell.KeyEnter: + f.focusedElement++ + f.Focus(delegate) + case tcell.KeyBacktab: + f.focusedElement-- + if f.focusedElement < 0 { + f.focusedElement = len(f.items) + len(f.buttons) - 1 + } + f.Focus(delegate) + case tcell.KeyEscape: + if f.cancel != nil { + f.cancel() + } else { + f.focusedElement = 0 + f.Focus(delegate) + } + } + } + + if f.focusedElement < len(f.items) { + // We're selecting an item. + item := f.items[f.focusedElement] + item.SetFinishedFunc(handler) + delegate(item) + } else { + // We're selecting a button. + button := f.buttons[f.focusedElement-len(f.items)] + button.SetBlurFunc(handler) + delegate(button) + } +} + +// HasFocus returns whether or not this primitive has focus. +func (f *Form) HasFocus() bool { + for _, item := range f.items { + if item.GetFocusable().HasFocus() { + return true + } + } + for _, button := range f.buttons { + if button.focus.HasFocus() { + return true + } + } + return false +} diff --git a/vendor/github.com/rivo/tview/frame.go b/vendor/github.com/rivo/tview/frame.go new file mode 100644 index 00000000..77c5316e --- /dev/null +++ b/vendor/github.com/rivo/tview/frame.go @@ -0,0 +1,157 @@ +package tview + +import ( + "github.com/gdamore/tcell" +) + +// frameText holds information about a line of text shown in the frame. +type frameText struct { + Text string // The text to be displayed. + Header bool // true = place in header, false = place in footer. + Align int // One of the Align constants. + Color tcell.Color // The text color. +} + +// Frame is a wrapper which adds a border around another primitive. The top area +// (header) and the bottom area (footer) may also contain text. +// +// See https://github.com/rivo/tview/wiki/Frame for an example. +type Frame struct { + *Box + + // The contained primitive. + primitive Primitive + + // The lines of text to be displayed. + text []*frameText + + // Border spacing. + top, bottom, header, footer, left, right int +} + +// NewFrame returns a new frame around the given primitive. The primitive's +// size will be changed to fit within this frame. +func NewFrame(primitive Primitive) *Frame { + box := NewBox() + + f := &Frame{ + Box: box, + primitive: primitive, + top: 1, + bottom: 1, + header: 1, + footer: 1, + left: 1, + right: 1, + } + + f.focus = f + + return f +} + +// AddText adds text to the frame. Set "header" to true if the text is to appear +// in the header, above the contained primitive. Set it to false for it to +// appear in the footer, below the contained primitive. "align" must be one of +// the Align constants. Rows in the header are printed top to bottom, rows in +// the footer are printed bottom to top. Note that long text can overlap as +// different alignments will be placed on the same row. +func (f *Frame) AddText(text string, header bool, align int, color tcell.Color) *Frame { + f.text = append(f.text, &frameText{ + Text: text, + Header: header, + Align: align, + Color: color, + }) + return f +} + +// Clear removes all text from the frame. +func (f *Frame) Clear() *Frame { + f.text = nil + return f +} + +// SetBorders sets the width of the frame borders as well as "header" and +// "footer", the vertical space between the header and footer text and the +// contained primitive (does not apply if there is no text). +func (f *Frame) SetBorders(top, bottom, header, footer, left, right int) *Frame { + f.top, f.bottom, f.header, f.footer, f.left, f.right = top, bottom, header, footer, left, right + return f +} + +// Draw draws this primitive onto the screen. +func (f *Frame) Draw(screen tcell.Screen) { + f.Box.Draw(screen) + + // Calculate start positions. + x, top, width, height := f.GetInnerRect() + bottom := top + height - 1 + x += f.left + top += f.top + bottom -= f.bottom + width -= f.left + f.right + if width <= 0 || top >= bottom { + return // No space left. + } + + // Draw text. + var rows [6]int // top-left, top-center, top-right, bottom-left, bottom-center, bottom-right. + topMax := top + bottomMin := bottom + for _, text := range f.text { + // Where do we place this text? + var y int + if text.Header { + y = top + rows[text.Align] + rows[text.Align]++ + if y >= bottomMin { + continue + } + if y+1 > topMax { + topMax = y + 1 + } + } else { + y = bottom - rows[3+text.Align] + rows[3+text.Align]++ + if y <= topMax { + continue + } + if y-1 < bottomMin { + bottomMin = y - 1 + } + } + + // Draw text. + Print(screen, text.Text, x, y, width, text.Align, text.Color) + } + + // Set the size of the contained primitive. + if topMax > top { + top = topMax + f.header + } + if bottomMin < bottom { + bottom = bottomMin - f.footer + } + if top > bottom { + return // No space for the primitive. + } + f.primitive.SetRect(x, top, width, bottom+1-top) + + // Finally, draw the contained primitive. + f.primitive.Draw(screen) +} + +// Focus is called when this primitive receives focus. +func (f *Frame) Focus(delegate func(p Primitive)) { + delegate(f.primitive) +} + +// HasFocus returns whether or not this primitive has focus. +func (f *Frame) HasFocus() bool { + focusable, ok := f.primitive.(Focusable) + if ok { + return focusable.HasFocus() + } + return false +} diff --git a/vendor/github.com/rivo/tview/grid.go b/vendor/github.com/rivo/tview/grid.go new file mode 100644 index 00000000..9c3fb793 --- /dev/null +++ b/vendor/github.com/rivo/tview/grid.go @@ -0,0 +1,631 @@ +package tview + +import ( + "math" + + "github.com/gdamore/tcell" +) + +// gridItem represents one primitive and its possible position on a grid. +type gridItem struct { + Item Primitive // The item to be positioned. May be nil for an empty item. + Row, Column int // The top-left grid cell where the item is placed. + Width, Height int // The number of rows and columns the item occupies. + MinGridWidth, MinGridHeight int // The minimum grid width/height for which this item is visible. + Focus bool // Whether or not this item attracts the layout's focus. + + visible bool // Whether or not this item was visible the last time the grid was drawn. + x, y, w, h int // The last position of the item relative to the top-left corner of the grid. Undefined if visible is false. +} + +// Grid is an implementation of a grid-based layout. It works by defining the +// size of the rows and columns, then placing primitives into the grid. +// +// Some settings can lead to the grid exceeding its available space. SetOffset() +// can then be used to scroll in steps of rows and columns. These offset values +// can also be controlled with the arrow keys (or the "g","G", "j", "k", "h", +// and "l" keys) while the grid has focus and none of its contained primitives +// do. +// +// See https://github.com/rivo/tview/wiki/Grid for an example. +type Grid struct { + *Box + + // The items to be positioned. + items []*gridItem + + // The definition of the rows and columns of the grid. See + // SetRows()/SetColumns() for details. + rows, columns []int + + // The minimum sizes for rows and columns. + minWidth, minHeight int + + // The size of the gaps between neighboring primitives. This is automatically + // set to 1 if borders is true. + gapRows, gapColumns int + + // The number of rows and columns skipped before drawing the top-left corner + // of the grid. + rowOffset, columnOffset int + + // Whether or not borders are drawn around grid items. If this is set to true, + // a gap size of 1 is automatically assumed (which is filled with the border + // graphics). + borders bool + + // The color of the borders around grid items. + bordersColor tcell.Color +} + +// NewGrid returns a new grid-based layout container with no initial primitives. +// +// Note that Box, the superclass of Grid, will have its background color set to +// transparent so that any grid areas not covered by any primitives will leave +// their background unchanged. To clear a Grid's background before any items are +// drawn, set it to the desired color: +// +// grid.SetBackgroundColor(tview.Styles.PrimitiveBackgroundColor) +func NewGrid() *Grid { + g := &Grid{ + Box: NewBox().SetBackgroundColor(tcell.ColorDefault), + bordersColor: Styles.GraphicsColor, + } + g.focus = g + return g +} + +// SetRows defines how the rows of the grid are distributed. Each value defines +// the size of one row, starting with the leftmost row. Values greater 0 +// represent absolute row widths (gaps not included). Values less or equal 0 +// represent proportional row widths or fractions of the remaining free space, +// where 0 is treated the same as -1. That is, a row with a value of -3 will +// have three times the width of a row with a value of -1 (or 0). The minimum +// width set with SetMinSize() is always observed. +// +// Primitives may extend beyond the rows defined explicitly with this function. +// A value of 0 is assumed for any undefined row. In fact, if you never call +// this function, all rows occupied by primitives will have the same width. +// On the other hand, unoccupied rows defined with this function will always +// take their place. +// +// Assuming a total width of the grid of 100 cells and a minimum width of 0, the +// following call will result in rows with widths of 30, 10, 15, 15, and 30 +// cells: +// +// grid.SetRows(30, 10, -1, -1, -2) +// +// If a primitive were then placed in the 6th and 7th row, the resulting widths +// would be: 30, 10, 10, 10, 20, 10, and 10 cells. +// +// If you then called SetMinSize() as follows: +// +// grid.SetMinSize(15, 20) +// +// The resulting widths would be: 30, 15, 15, 15, 20, 15, and 15 cells, a total +// of 125 cells, 25 cells wider than the available grid width. +func (g *Grid) SetRows(rows ...int) *Grid { + g.rows = rows + return g +} + +// SetColumns defines how the columns of the grid are distributed. These values +// behave the same as the row values provided with SetRows(), see there for +// a definition and examples. +// +// The provided values correspond to column heights, the first value defining +// the height of the topmost column. +func (g *Grid) SetColumns(columns ...int) *Grid { + g.columns = columns + return g +} + +// SetSize is a shortcut for SetRows() and SetColumns() where all row and column +// values are set to the given size values. See SetRows() for details on sizes. +func (g *Grid) SetSize(numRows, numColumns, rowSize, columnSize int) *Grid { + g.rows = make([]int, numRows) + for index := range g.rows { + g.rows[index] = rowSize + } + g.columns = make([]int, numColumns) + for index := range g.columns { + g.columns[index] = columnSize + } + return g +} + +// SetMinSize sets an absolute minimum width for rows and an absolute minimum +// height for columns. Panics if negative values are provided. +func (g *Grid) SetMinSize(row, column int) *Grid { + if row < 0 || column < 0 { + panic("Invalid minimum row/column size") + } + g.minHeight, g.minWidth = row, column + return g +} + +// SetGap sets the size of the gaps between neighboring primitives on the grid. +// If borders are drawn (see SetBorders()), these values are ignored and a gap +// of 1 is assumed. Panics if negative values are provided. +func (g *Grid) SetGap(row, column int) *Grid { + if row < 0 || column < 0 { + panic("Invalid gap size") + } + g.gapRows, g.gapColumns = row, column + return g +} + +// SetBorders sets whether or not borders are drawn around grid items. Setting +// this value to true will cause the gap values (see SetGap()) to be ignored and +// automatically assumed to be 1 where the border graphics are drawn. +func (g *Grid) SetBorders(borders bool) *Grid { + g.borders = borders + return g +} + +// SetBordersColor sets the color of the item borders. +func (g *Grid) SetBordersColor(color tcell.Color) *Grid { + g.bordersColor = color + return g +} + +// AddItem adds a primitive and its position to the grid. The top-left corner +// of the primitive will be located in the top-left corner of the grid cell at +// the given row and column and will span "width" rows and "height" columns. For +// example, for a primitive to occupy rows 2, 3, and 4 and columns 5 and 6: +// +// grid.AddItem(p, 2, 4, 3, 2, true) +// +// If width or height is 0, the primitive will not be drawn. +// +// You can add the same primitive multiple times with different grid positions. +// The minGridWidth and minGridHeight values will then determine which of those +// positions will be used. This is similar to CSS media queries. These minimum +// values refer to the overall size of the grid. If multiple items for the same +// primitive apply, the one that has at least one highest minimum value will be +// used, or the primitive added last if those values are the same. Example: +// +// grid.AddItem(p, 0, 0, 0, 0, 0, 0, true). // Hide in small grids. +// AddItem(p, 0, 0, 1, 2, 100, 0, true). // One-column layout for medium grids. +// AddItem(p, 1, 1, 3, 2, 300, 0, true) // Multi-column layout for large grids. +// +// To use the same grid layout for all sizes, simply set minGridWidth and +// minGridHeight to 0. +// +// If the item's focus is set to true, it will receive focus when the grid +// receives focus. If there are multiple items with a true focus flag, the last +// visible one that was added will receive focus. +func (g *Grid) AddItem(p Primitive, row, column, height, width, minGridHeight, minGridWidth int, focus bool) *Grid { + g.items = append(g.items, &gridItem{ + Item: p, + Row: row, + Column: column, + Height: height, + Width: width, + MinGridHeight: minGridHeight, + MinGridWidth: minGridWidth, + Focus: focus, + }) + return g +} + +// RemoveItem removes all items for the given primitive from the grid, keeping +// the order of the remaining items intact. +func (g *Grid) RemoveItem(p Primitive) *Grid { + for index := len(g.items) - 1; index >= 0; index-- { + if g.items[index].Item == p { + g.items = append(g.items[:index], g.items[index+1:]...) + } + } + return g +} + +// Clear removes all items from the grid. +func (g *Grid) Clear() *Grid { + g.items = nil + return g +} + +// SetOffset sets the number of rows and columns which are skipped before +// drawing the first grid cell in the top-left corner. As the grid will never +// completely move off the screen, these values may be adjusted the next time +// the grid is drawn. The actual position of the grid may also be adjusted such +// that contained primitives that have focus are visible. +func (g *Grid) SetOffset(rows, columns int) *Grid { + g.rowOffset, g.columnOffset = rows, columns + return g +} + +// GetOffset returns the current row and column offset (see SetOffset() for +// details). +func (g *Grid) GetOffset() (rows, columns int) { + return g.rowOffset, g.columnOffset +} + +// Focus is called when this primitive receives focus. +func (g *Grid) Focus(delegate func(p Primitive)) { + for _, item := range g.items { + if item.Focus { + delegate(item.Item) + return + } + } + g.hasFocus = true +} + +// Blur is called when this primitive loses focus. +func (g *Grid) Blur() { + g.hasFocus = false +} + +// HasFocus returns whether or not this primitive has focus. +func (g *Grid) HasFocus() bool { + for _, item := range g.items { + if item.visible && item.Item.GetFocusable().HasFocus() { + return true + } + } + return g.hasFocus +} + +// InputHandler returns the handler for this primitive. +func (g *Grid) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return g.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { + switch event.Key() { + case tcell.KeyRune: + switch event.Rune() { + case 'g': + g.rowOffset, g.columnOffset = 0, 0 + case 'G': + g.rowOffset = math.MaxInt32 + case 'j': + g.rowOffset++ + case 'k': + g.rowOffset-- + case 'h': + g.columnOffset-- + case 'l': + g.columnOffset++ + } + case tcell.KeyHome: + g.rowOffset, g.columnOffset = 0, 0 + case tcell.KeyEnd: + g.rowOffset = math.MaxInt32 + case tcell.KeyUp: + g.rowOffset-- + case tcell.KeyDown: + g.rowOffset++ + case tcell.KeyLeft: + g.columnOffset-- + case tcell.KeyRight: + g.columnOffset++ + } + }) +} + +// Draw draws this primitive onto the screen. +func (g *Grid) Draw(screen tcell.Screen) { + g.Box.Draw(screen) + x, y, width, height := g.GetInnerRect() + + // Make a list of items which apply. + items := make(map[Primitive]*gridItem) + for _, item := range g.items { + item.visible = false + if item.Width <= 0 || item.Height <= 0 || width < item.MinGridWidth || height < item.MinGridHeight { + continue + } + previousItem, ok := items[item.Item] + if ok && item.Width < previousItem.Width && item.Height < previousItem.Height { + continue + } + items[item.Item] = item + } + + // How many rows and columns do we have? + rows := len(g.rows) + columns := len(g.columns) + for _, item := range items { + rowEnd := item.Row + item.Height + if rowEnd > rows { + rows = rowEnd + } + columnEnd := item.Column + item.Width + if columnEnd > columns { + columns = columnEnd + } + } + if rows == 0 || columns == 0 { + return // No content. + } + + // Where are they located? + rowPos := make([]int, rows) + rowHeight := make([]int, rows) + columnPos := make([]int, columns) + columnWidth := make([]int, columns) + + // How much space do we distribute? + remainingWidth := width + remainingHeight := height + proportionalWidth := 0 + proportionalHeight := 0 + for index, row := range g.rows { + if row > 0 { + if row < g.minHeight { + row = g.minHeight + } + remainingHeight -= row + rowHeight[index] = row + } else if row == 0 { + proportionalHeight++ + } else { + proportionalHeight += -row + } + } + for index, column := range g.columns { + if column > 0 { + if column < g.minWidth { + column = g.minWidth + } + remainingWidth -= column + columnWidth[index] = column + } else if column == 0 { + proportionalWidth++ + } else { + proportionalWidth += -column + } + } + if g.borders { + remainingHeight -= rows + 1 + remainingWidth -= columns + 1 + } else { + remainingHeight -= (rows - 1) * g.gapRows + remainingWidth -= (columns - 1) * g.gapColumns + } + if rows > len(g.rows) { + proportionalHeight += rows - len(g.rows) + } + if columns > len(g.columns) { + proportionalWidth += columns - len(g.columns) + } + + // Distribute proportional rows/columns. + gridWidth := 0 + gridHeight := 0 + for index := 0; index < rows; index++ { + row := 0 + if index < len(g.rows) { + row = g.rows[index] + } + if row > 0 { + if row < g.minHeight { + row = g.minHeight + } + gridHeight += row + continue // Not proportional. We already know the width. + } else if row == 0 { + row = 1 + } else { + row = -row + } + rowAbs := row * remainingHeight / proportionalHeight + remainingHeight -= rowAbs + proportionalHeight -= row + if rowAbs < g.minHeight { + rowAbs = g.minHeight + } + rowHeight[index] = rowAbs + gridHeight += rowAbs + } + for index := 0; index < columns; index++ { + column := 0 + if index < len(g.columns) { + column = g.columns[index] + } + if column > 0 { + if column < g.minWidth { + column = g.minWidth + } + gridWidth += column + continue // Not proportional. We already know the height. + } else if column == 0 { + column = 1 + } else { + column = -column + } + columnAbs := column * remainingWidth / proportionalWidth + remainingWidth -= columnAbs + proportionalWidth -= column + if columnAbs < g.minWidth { + columnAbs = g.minWidth + } + columnWidth[index] = columnAbs + gridWidth += columnAbs + } + if g.borders { + gridHeight += rows + 1 + gridWidth += columns + 1 + } else { + gridHeight += (rows - 1) * g.gapRows + gridWidth += (columns - 1) * g.gapColumns + } + + // Calculate row/column positions. + columnX, rowY := x, y + if g.borders { + columnX++ + rowY++ + } + for index, row := range rowHeight { + rowPos[index] = rowY + gap := g.gapRows + if g.borders { + gap = 1 + } + rowY += row + gap + } + for index, column := range columnWidth { + columnPos[index] = columnX + gap := g.gapColumns + if g.borders { + gap = 1 + } + columnX += column + gap + } + + // Calculate primitive positions. + var focus *gridItem // The item which has focus. + for primitive, item := range items { + px := columnPos[item.Column] + py := rowPos[item.Row] + var pw, ph int + for index := 0; index < item.Height; index++ { + ph += rowHeight[item.Row+index] + } + for index := 0; index < item.Width; index++ { + pw += columnWidth[item.Column+index] + } + if g.borders { + pw += item.Width - 1 + ph += item.Height - 1 + } else { + pw += (item.Width - 1) * g.gapColumns + ph += (item.Height - 1) * g.gapRows + } + item.x, item.y, item.w, item.h = px, py, pw, ph + item.visible = true + if primitive.GetFocusable().HasFocus() { + focus = item + } + } + + // Calculate screen offsets. + var offsetX, offsetY, add int + if g.rowOffset < 0 { + g.rowOffset = 0 + } + if g.columnOffset < 0 { + g.columnOffset = 0 + } + if g.borders { + add = 1 + } + for row := 0; row < rows-1; row++ { + remainingHeight := gridHeight - offsetY + if focus != nil && focus.y-add <= offsetY || // Don't let the focused item move out of screen. + row >= g.rowOffset && (focus == nil || focus != nil && focus.y-offsetY < height) || // We've reached the requested offset. + remainingHeight <= height { // We have enough space to show the rest. + if row > 0 { + if focus != nil && focus.y+focus.h+add-offsetY > height { + offsetY += focus.y + focus.h + add - offsetY - height + } + if remainingHeight < height { + offsetY = gridHeight - height + } + } + g.rowOffset = row + break + } + offsetY = rowPos[row+1] - add + } + for column := 0; column < columns-1; column++ { + remainingWidth := gridWidth - offsetX + if focus != nil && focus.x-add <= offsetX || // Don't let the focused item move out of screen. + column >= g.columnOffset && (focus == nil || focus != nil && focus.x-offsetX < width) || // We've reached the requested offset. + remainingWidth <= width { // We have enough space to show the rest. + if column > 0 { + if focus != nil && focus.x+focus.w+add-offsetX > width { + offsetX += focus.x + focus.w + add - offsetX - width + } else if remainingWidth < width { + offsetX = gridWidth - width + } + } + g.columnOffset = column + break + } + offsetX = columnPos[column+1] - add + } + + // Draw primitives and borders. + for primitive, item := range items { + // Final primitive position. + if !item.visible { + continue + } + item.x -= offsetX + item.y -= offsetY + if item.x+item.w > width { + item.w = width - item.x + } + if item.y+item.h > height { + item.h = height - item.y + } + if item.x < 0 { + item.w += item.x + item.x = 0 + } + if item.y < 0 { + item.h += item.y + item.y = 0 + } + if item.w <= 0 || item.h <= 0 { + item.visible = false + continue + } + primitive.SetRect(x+item.x, y+item.y, item.w, item.h) + + // Draw primitive. + if item == focus { + defer primitive.Draw(screen) + } else { + primitive.Draw(screen) + } + + // Draw border around primitive. + if g.borders { + for bx := item.x; bx < item.x+item.w; bx++ { // Top/bottom lines. + if bx < 0 || bx >= width { + continue + } + by := item.y - 1 + if by >= 0 && by < height { + PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Horizontal, g.bordersColor) + } + by = item.y + item.h + if by >= 0 && by < height { + PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Horizontal, g.bordersColor) + } + } + for by := item.y; by < item.y+item.h; by++ { // Left/right lines. + if by < 0 || by >= height { + continue + } + bx := item.x - 1 + if bx >= 0 && bx < width { + PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Vertical, g.bordersColor) + } + bx = item.x + item.w + if bx >= 0 && bx < width { + PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.Vertical, g.bordersColor) + } + } + bx, by := item.x-1, item.y-1 // Top-left corner. + if bx >= 0 && bx < width && by >= 0 && by < height { + PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.TopLeft, g.bordersColor) + } + bx, by = item.x+item.w, item.y-1 // Top-right corner. + if bx >= 0 && bx < width && by >= 0 && by < height { + PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.TopRight, g.bordersColor) + } + bx, by = item.x-1, item.y+item.h // Bottom-left corner. + if bx >= 0 && bx < width && by >= 0 && by < height { + PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.BottomLeft, g.bordersColor) + } + bx, by = item.x+item.w, item.y+item.h // Bottom-right corner. + if bx >= 0 && bx < width && by >= 0 && by < height { + PrintJoinedSemigraphics(screen, x+bx, y+by, Borders.BottomRight, g.bordersColor) + } + } + } +} diff --git a/vendor/github.com/rivo/tview/inputfield.go b/vendor/github.com/rivo/tview/inputfield.go new file mode 100644 index 00000000..f738859c --- /dev/null +++ b/vendor/github.com/rivo/tview/inputfield.go @@ -0,0 +1,338 @@ +package tview + +import ( + "math" + "regexp" + "strings" + "unicode/utf8" + + "github.com/gdamore/tcell" + runewidth "github.com/mattn/go-runewidth" +) + +// InputField is a one-line box (three lines if there is a title) where the +// user can enter text. +// +// Use SetMaskCharacter() to hide input from onlookers (e.g. for password +// input). +// +// See https://github.com/rivo/tview/wiki/InputField for an example. +type InputField struct { + *Box + + // The text that was entered. + text string + + // The text to be displayed before the input area. + label string + + // The text to be displayed in the input area when "text" is empty. + placeholder string + + // The label color. + labelColor tcell.Color + + // The background color of the input area. + fieldBackgroundColor tcell.Color + + // The text color of the input area. + fieldTextColor tcell.Color + + // The text color of the placeholder. + placeholderTextColor tcell.Color + + // The screen width of the label area. A value of 0 means use the width of + // the label text. + labelWidth int + + // The screen width of the input area. A value of 0 means extend as much as + // possible. + fieldWidth int + + // A character to mask entered text (useful for password fields). A value of 0 + // disables masking. + maskCharacter rune + + // An optional function which may reject the last character that was entered. + accept func(text string, ch rune) bool + + // An optional function which is called when the input has changed. + changed func(text string) + + // An optional function which is called when the user indicated that they + // are done entering text. The key which was pressed is provided (tab, + // shift-tab, enter, or escape). + done func(tcell.Key) + + // A callback function set by the Form class and called when the user leaves + // this form item. + finished func(tcell.Key) +} + +// NewInputField returns a new input field. +func NewInputField() *InputField { + return &InputField{ + Box: NewBox(), + labelColor: Styles.SecondaryTextColor, + fieldBackgroundColor: Styles.ContrastBackgroundColor, + fieldTextColor: Styles.PrimaryTextColor, + placeholderTextColor: Styles.ContrastSecondaryTextColor, + } +} + +// SetText sets the current text of the input field. +func (i *InputField) SetText(text string) *InputField { + i.text = text + if i.changed != nil { + i.changed(text) + } + return i +} + +// GetText returns the current text of the input field. +func (i *InputField) GetText() string { + return i.text +} + +// SetLabel sets the text to be displayed before the input area. +func (i *InputField) SetLabel(label string) *InputField { + i.label = label + return i +} + +// GetLabel returns the text to be displayed before the input area. +func (i *InputField) GetLabel() string { + return i.label +} + +// SetLabelWidth sets the screen width of the label. A value of 0 will cause the +// primitive to use the width of the label string. +func (i *InputField) SetLabelWidth(width int) *InputField { + i.labelWidth = width + return i +} + +// SetPlaceholder sets the text to be displayed when the input text is empty. +func (i *InputField) SetPlaceholder(text string) *InputField { + i.placeholder = text + return i +} + +// SetLabelColor sets the color of the label. +func (i *InputField) SetLabelColor(color tcell.Color) *InputField { + i.labelColor = color + return i +} + +// SetFieldBackgroundColor sets the background color of the input area. +func (i *InputField) SetFieldBackgroundColor(color tcell.Color) *InputField { + i.fieldBackgroundColor = color + return i +} + +// SetFieldTextColor sets the text color of the input area. +func (i *InputField) SetFieldTextColor(color tcell.Color) *InputField { + i.fieldTextColor = color + return i +} + +// SetPlaceholderTextColor sets the text color of placeholder text. +func (i *InputField) SetPlaceholderTextColor(color tcell.Color) *InputField { + i.placeholderTextColor = color + return i +} + +// SetFormAttributes sets attributes shared by all form items. +func (i *InputField) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem { + i.labelWidth = labelWidth + i.labelColor = labelColor + i.backgroundColor = bgColor + i.fieldTextColor = fieldTextColor + i.fieldBackgroundColor = fieldBgColor + return i +} + +// SetFieldWidth sets the screen width of the input area. A value of 0 means +// extend as much as possible. +func (i *InputField) SetFieldWidth(width int) *InputField { + i.fieldWidth = width + return i +} + +// GetFieldWidth returns this primitive's field width. +func (i *InputField) GetFieldWidth() int { + return i.fieldWidth +} + +// SetMaskCharacter sets a character that masks user input on a screen. A value +// of 0 disables masking. +func (i *InputField) SetMaskCharacter(mask rune) *InputField { + i.maskCharacter = mask + return i +} + +// SetAcceptanceFunc sets a handler which may reject the last character that was +// entered (by returning false). +// +// This package defines a number of variables Prefixed with InputField which may +// be used for common input (e.g. numbers, maximum text length). +func (i *InputField) SetAcceptanceFunc(handler func(textToCheck string, lastChar rune) bool) *InputField { + i.accept = handler + return i +} + +// SetChangedFunc sets a handler which is called whenever the text of the input +// field has changed. It receives the current text (after the change). +func (i *InputField) SetChangedFunc(handler func(text string)) *InputField { + i.changed = handler + return i +} + +// SetDoneFunc sets a handler which is called when the user is done entering +// text. The callback function is provided with the key that was pressed, which +// is one of the following: +// +// - KeyEnter: Done entering text. +// - KeyEscape: Abort text input. +// - KeyTab: Move to the next field. +// - KeyBacktab: Move to the previous field. +func (i *InputField) SetDoneFunc(handler func(key tcell.Key)) *InputField { + i.done = handler + return i +} + +// SetFinishedFunc sets a callback invoked when the user leaves this form item. +func (i *InputField) SetFinishedFunc(handler func(key tcell.Key)) FormItem { + i.finished = handler + return i +} + +// Draw draws this primitive onto the screen. +func (i *InputField) Draw(screen tcell.Screen) { + i.Box.Draw(screen) + + // Prepare + x, y, width, height := i.GetInnerRect() + rightLimit := x + width + if height < 1 || rightLimit <= x { + return + } + + // Draw label. + if i.labelWidth > 0 { + labelWidth := i.labelWidth + if labelWidth > rightLimit-x { + labelWidth = rightLimit - x + } + Print(screen, i.label, x, y, labelWidth, AlignLeft, i.labelColor) + x += labelWidth + } else { + _, drawnWidth := Print(screen, i.label, x, y, rightLimit-x, AlignLeft, i.labelColor) + x += drawnWidth + } + + // Draw input area. + fieldWidth := i.fieldWidth + if fieldWidth == 0 { + fieldWidth = math.MaxInt32 + } + if rightLimit-x < fieldWidth { + fieldWidth = rightLimit - x + } + fieldStyle := tcell.StyleDefault.Background(i.fieldBackgroundColor) + for index := 0; index < fieldWidth; index++ { + screen.SetContent(x+index, y, ' ', nil, fieldStyle) + } + + // Draw placeholder text. + text := i.text + if text == "" && i.placeholder != "" { + Print(screen, i.placeholder, x, y, fieldWidth, AlignLeft, i.placeholderTextColor) + } else { + // Draw entered text. + if i.maskCharacter > 0 { + text = strings.Repeat(string(i.maskCharacter), utf8.RuneCountInString(i.text)) + } else { + text = Escape(text) + } + fieldWidth-- // We need one cell for the cursor. + if fieldWidth < runewidth.StringWidth(text) { + Print(screen, text, x, y, fieldWidth, AlignRight, i.fieldTextColor) + } else { + Print(screen, text, x, y, fieldWidth, AlignLeft, i.fieldTextColor) + } + } + + // Set cursor. + if i.focus.HasFocus() { + i.setCursor(screen) + } +} + +// setCursor sets the cursor position. +func (i *InputField) setCursor(screen tcell.Screen) { + x := i.x + y := i.y + rightLimit := x + i.width + if i.border { + x++ + y++ + rightLimit -= 2 + } + fieldWidth := runewidth.StringWidth(i.text) + if i.fieldWidth > 0 && fieldWidth > i.fieldWidth-1 { + fieldWidth = i.fieldWidth - 1 + } + if i.labelWidth > 0 { + x += i.labelWidth + fieldWidth + } else { + x += StringWidth(i.label) + fieldWidth + } + if x >= rightLimit { + x = rightLimit - 1 + } + screen.ShowCursor(x, y) +} + +// InputHandler returns the handler for this primitive. +func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return i.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { + // Trigger changed events. + currentText := i.text + defer func() { + if i.text != currentText && i.changed != nil { + i.changed(i.text) + } + }() + + // Process key event. + switch key := event.Key(); key { + case tcell.KeyRune: // Regular character. + newText := i.text + string(event.Rune()) + if i.accept != nil { + if !i.accept(newText, event.Rune()) { + break + } + } + i.text = newText + case tcell.KeyCtrlU: // Delete all. + i.text = "" + case tcell.KeyCtrlW: // Delete last word. + lastWord := regexp.MustCompile(`\s*\S+\s*$`) + i.text = lastWord.ReplaceAllString(i.text, "") + case tcell.KeyBackspace, tcell.KeyBackspace2: // Delete last character. + if len(i.text) == 0 { + break + } + runes := []rune(i.text) + i.text = string(runes[:len(runes)-1]) + case tcell.KeyEnter, tcell.KeyTab, tcell.KeyBacktab, tcell.KeyEscape: // We're done. + if i.done != nil { + i.done(key) + } + if i.finished != nil { + i.finished(key) + } + } + }) +} diff --git a/vendor/github.com/rivo/tview/list.go b/vendor/github.com/rivo/tview/list.go new file mode 100644 index 00000000..296141a8 --- /dev/null +++ b/vendor/github.com/rivo/tview/list.go @@ -0,0 +1,349 @@ +package tview + +import ( + "fmt" + + "github.com/gdamore/tcell" +) + +// listItem represents one item in a List. +type listItem struct { + MainText string // The main text of the list item. + SecondaryText string // A secondary text to be shown underneath the main text. + Shortcut rune // The key to select the list item directly, 0 if there is no shortcut. + Selected func() // The optional function which is called when the item is selected. +} + +// List displays rows of items, each of which can be selected. +// +// See https://github.com/rivo/tview/wiki/List for an example. +type List struct { + *Box + + // The items of the list. + items []*listItem + + // The index of the currently selected item. + currentItem int + + // Whether or not to show the secondary item texts. + showSecondaryText bool + + // The item main text color. + mainTextColor tcell.Color + + // The item secondary text color. + secondaryTextColor tcell.Color + + // The item shortcut text color. + shortcutColor tcell.Color + + // The text color for selected items. + selectedTextColor tcell.Color + + // The background color for selected items. + selectedBackgroundColor tcell.Color + + // An optional function which is called when the user has navigated to a list + // item. + changed func(index int, mainText, secondaryText string, shortcut rune) + + // An optional function which is called when a list item was selected. This + // function will be called even if the list item defines its own callback. + selected func(index int, mainText, secondaryText string, shortcut rune) + + // An optional function which is called when the user presses the Escape key. + done func() +} + +// NewList returns a new form. +func NewList() *List { + return &List{ + Box: NewBox(), + showSecondaryText: true, + mainTextColor: Styles.PrimaryTextColor, + secondaryTextColor: Styles.TertiaryTextColor, + shortcutColor: Styles.SecondaryTextColor, + selectedTextColor: Styles.PrimitiveBackgroundColor, + selectedBackgroundColor: Styles.PrimaryTextColor, + } +} + +// SetCurrentItem sets the currently selected item by its index. This triggers +// a "changed" event. +func (l *List) SetCurrentItem(index int) *List { + l.currentItem = index + if l.currentItem < len(l.items) && l.changed != nil { + item := l.items[l.currentItem] + l.changed(l.currentItem, item.MainText, item.SecondaryText, item.Shortcut) + } + return l +} + +// GetCurrentItem returns the index of the currently selected list item. +func (l *List) GetCurrentItem() int { + return l.currentItem +} + +// SetMainTextColor sets the color of the items' main text. +func (l *List) SetMainTextColor(color tcell.Color) *List { + l.mainTextColor = color + return l +} + +// SetSecondaryTextColor sets the color of the items' secondary text. +func (l *List) SetSecondaryTextColor(color tcell.Color) *List { + l.secondaryTextColor = color + return l +} + +// SetShortcutColor sets the color of the items' shortcut. +func (l *List) SetShortcutColor(color tcell.Color) *List { + l.shortcutColor = color + return l +} + +// SetSelectedTextColor sets the text color of selected items. +func (l *List) SetSelectedTextColor(color tcell.Color) *List { + l.selectedTextColor = color + return l +} + +// SetSelectedBackgroundColor sets the background color of selected items. +func (l *List) SetSelectedBackgroundColor(color tcell.Color) *List { + l.selectedBackgroundColor = color + return l +} + +// ShowSecondaryText determines whether or not to show secondary item texts. +func (l *List) ShowSecondaryText(show bool) *List { + l.showSecondaryText = show + return l +} + +// SetChangedFunc sets the function which is called when the user navigates to +// a list item. The function receives the item's index in the list of items +// (starting with 0), its main text, secondary text, and its shortcut rune. +// +// This function is also called when the first item is added or when +// SetCurrentItem() is called. +func (l *List) SetChangedFunc(handler func(int, string, string, rune)) *List { + l.changed = handler + return l +} + +// SetSelectedFunc sets the function which is called when the user selects a +// list item by pressing Enter on the current selection. The function receives +// the item's index in the list of items (starting with 0), its main text, +// secondary text, and its shortcut rune. +func (l *List) SetSelectedFunc(handler func(int, string, string, rune)) *List { + l.selected = handler + return l +} + +// SetDoneFunc sets a function which is called when the user presses the Escape +// key. +func (l *List) SetDoneFunc(handler func()) *List { + l.done = handler + return l +} + +// AddItem adds a new item to the list. An item has a main text which will be +// highlighted when selected. It also has a secondary text which is shown +// underneath the main text (if it is set to visible) but which may remain +// empty. +// +// The shortcut is a key binding. If the specified rune is entered, the item +// is selected immediately. Set to 0 for no binding. +// +// The "selected" callback will be invoked when the user selects the item. You +// may provide nil if no such item is needed or if all events are handled +// through the selected callback set with SetSelectedFunc(). +func (l *List) AddItem(mainText, secondaryText string, shortcut rune, selected func()) *List { + l.items = append(l.items, &listItem{ + MainText: mainText, + SecondaryText: secondaryText, + Shortcut: shortcut, + Selected: selected, + }) + if len(l.items) == 1 && l.changed != nil { + item := l.items[0] + l.changed(0, item.MainText, item.SecondaryText, item.Shortcut) + } + return l +} + +// GetItemCount returns the number of items in the list. +func (l *List) GetItemCount() int { + return len(l.items) +} + +// GetItemText returns an item's texts (main and secondary). Panics if the index +// is out of range. +func (l *List) GetItemText(index int) (main, secondary string) { + return l.items[index].MainText, l.items[index].SecondaryText +} + +// SetItemText sets an item's main and secondary text. Panics if the index is +// out of range. +func (l *List) SetItemText(index int, main, secondary string) *List { + item := l.items[index] + item.MainText = main + item.SecondaryText = secondary + return l +} + +// Clear removes all items from the list. +func (l *List) Clear() *List { + l.items = nil + l.currentItem = 0 + return l +} + +// Draw draws this primitive onto the screen. +func (l *List) Draw(screen tcell.Screen) { + l.Box.Draw(screen) + + // Determine the dimensions. + x, y, width, height := l.GetInnerRect() + bottomLimit := y + height + + // Do we show any shortcuts? + var showShortcuts bool + for _, item := range l.items { + if item.Shortcut != 0 { + showShortcuts = true + x += 4 + width -= 4 + break + } + } + + // We want to keep the current selection in view. What is our offset? + var offset int + if l.showSecondaryText { + if 2*l.currentItem >= height { + offset = (2*l.currentItem + 2 - height) / 2 + } + } else { + if l.currentItem >= height { + offset = l.currentItem + 1 - height + } + } + + // Draw the list items. + for index, item := range l.items { + if index < offset { + continue + } + + if y >= bottomLimit { + break + } + + // Shortcuts. + if showShortcuts && item.Shortcut != 0 { + Print(screen, fmt.Sprintf("(%s)", string(item.Shortcut)), x-5, y, 4, AlignRight, l.shortcutColor) + } + + // Main text. + Print(screen, item.MainText, x, y, width, AlignLeft, l.mainTextColor) + + // Background color of selected text. + if index == l.currentItem { + textWidth := StringWidth(item.MainText) + for bx := 0; bx < textWidth && bx < width; bx++ { + m, c, style, _ := screen.GetContent(x+bx, y) + fg, _, _ := style.Decompose() + if fg == l.mainTextColor { + fg = l.selectedTextColor + } + style = style.Background(l.selectedBackgroundColor).Foreground(fg) + screen.SetContent(x+bx, y, m, c, style) + } + } + + y++ + + if y >= bottomLimit { + break + } + + // Secondary text. + if l.showSecondaryText { + Print(screen, item.SecondaryText, x, y, width, AlignLeft, l.secondaryTextColor) + y++ + } + } +} + +// InputHandler returns the handler for this primitive. +func (l *List) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return l.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { + previousItem := l.currentItem + + switch key := event.Key(); key { + case tcell.KeyTab, tcell.KeyDown, tcell.KeyRight: + l.currentItem++ + case tcell.KeyBacktab, tcell.KeyUp, tcell.KeyLeft: + l.currentItem-- + case tcell.KeyHome: + l.currentItem = 0 + case tcell.KeyEnd: + l.currentItem = len(l.items) - 1 + case tcell.KeyPgDn: + l.currentItem += 5 + case tcell.KeyPgUp: + l.currentItem -= 5 + case tcell.KeyEnter: + if l.currentItem >= 0 && l.currentItem < len(l.items) { + item := l.items[l.currentItem] + if item.Selected != nil { + item.Selected() + } + if l.selected != nil { + l.selected(l.currentItem, item.MainText, item.SecondaryText, item.Shortcut) + } + } + case tcell.KeyEscape: + if l.done != nil { + l.done() + } + case tcell.KeyRune: + ch := event.Rune() + if ch != ' ' { + // It's not a space bar. Is it a shortcut? + var found bool + for index, item := range l.items { + if item.Shortcut == ch { + // We have a shortcut. + found = true + l.currentItem = index + break + } + } + if !found { + break + } + } + item := l.items[l.currentItem] + if item.Selected != nil { + item.Selected() + } + if l.selected != nil { + l.selected(l.currentItem, item.MainText, item.SecondaryText, item.Shortcut) + } + } + + if l.currentItem < 0 { + l.currentItem = len(l.items) - 1 + } else if l.currentItem >= len(l.items) { + l.currentItem = 0 + } + + if l.currentItem != previousItem && l.currentItem < len(l.items) && l.changed != nil { + item := l.items[l.currentItem] + l.changed(l.currentItem, item.MainText, item.SecondaryText, item.Shortcut) + } + }) +} diff --git a/vendor/github.com/rivo/tview/modal.go b/vendor/github.com/rivo/tview/modal.go new file mode 100644 index 00000000..8ed535e7 --- /dev/null +++ b/vendor/github.com/rivo/tview/modal.go @@ -0,0 +1,131 @@ +package tview + +import ( + "github.com/gdamore/tcell" +) + +// Modal is a centered message window used to inform the user or prompt them +// for an immediate decision. It needs to have at least one button (added via +// AddButtons()) or it will never disappear. +// +// See https://github.com/rivo/tview/wiki/Modal for an example. +type Modal struct { + *Box + + // The framed embedded in the modal. + frame *Frame + + // The form embedded in the modal's frame. + form *Form + + // The message text (original, not word-wrapped). + text string + + // The text color. + textColor tcell.Color + + // The optional callback for when the user clicked one of the buttons. It + // receives the index of the clicked button and the button's label. + done func(buttonIndex int, buttonLabel string) +} + +// NewModal returns a new modal message window. +func NewModal() *Modal { + m := &Modal{ + Box: NewBox(), + textColor: Styles.PrimaryTextColor, + } + m.form = NewForm(). + SetButtonsAlign(AlignCenter). + SetButtonBackgroundColor(Styles.PrimitiveBackgroundColor). + SetButtonTextColor(Styles.PrimaryTextColor) + m.form.SetBackgroundColor(Styles.ContrastBackgroundColor).SetBorderPadding(0, 0, 0, 0) + m.frame = NewFrame(m.form).SetBorders(0, 0, 1, 0, 0, 0) + m.frame.SetBorder(true). + SetBackgroundColor(Styles.ContrastBackgroundColor). + SetBorderPadding(1, 1, 1, 1) + m.focus = m + return m +} + +// SetTextColor sets the color of the message text. +func (m *Modal) SetTextColor(color tcell.Color) *Modal { + m.textColor = color + return m +} + +// SetDoneFunc sets a handler which is called when one of the buttons was +// pressed. It receives the index of the button as well as its label text. The +// handler is also called when the user presses the Escape key. The index will +// then be negative and the label text an emptry string. +func (m *Modal) SetDoneFunc(handler func(buttonIndex int, buttonLabel string)) *Modal { + m.done = handler + return m +} + +// SetText sets the message text of the window. The text may contain line +// breaks. Note that words are wrapped, too, based on the final size of the +// window. +func (m *Modal) SetText(text string) *Modal { + m.text = text + return m +} + +// AddButtons adds buttons to the window. There must be at least one button and +// a "done" handler so the window can be closed again. +func (m *Modal) AddButtons(labels []string) *Modal { + for index, label := range labels { + func(i int, l string) { + m.form.AddButton(label, func() { + if m.done != nil { + m.done(i, l) + } + }) + }(index, label) + } + return m +} + +// Focus is called when this primitive receives focus. +func (m *Modal) Focus(delegate func(p Primitive)) { + delegate(m.form) +} + +// HasFocus returns whether or not this primitive has focus. +func (m *Modal) HasFocus() bool { + return m.form.HasFocus() +} + +// Draw draws this primitive onto the screen. +func (m *Modal) Draw(screen tcell.Screen) { + // Calculate the width of this modal. + buttonsWidth := 0 + for _, button := range m.form.buttons { + buttonsWidth += StringWidth(button.label) + 4 + 2 + } + buttonsWidth -= 2 + screenWidth, screenHeight := screen.Size() + width := screenWidth / 3 + if width < buttonsWidth { + width = buttonsWidth + } + // width is now without the box border. + + // Reset the text and find out how wide it is. + m.frame.Clear() + lines := WordWrap(m.text, width) + for _, line := range lines { + m.frame.AddText(line, true, AlignCenter, m.textColor) + } + + // Set the modal's position and size. + height := len(lines) + 6 + width += 4 + x := (screenWidth - width) / 2 + y := (screenHeight - height) / 2 + m.SetRect(x, y, width, height) + + // Draw the frame. + m.frame.SetRect(x, y, width, height) + m.frame.Draw(screen) +} diff --git a/vendor/github.com/rivo/tview/pages.go b/vendor/github.com/rivo/tview/pages.go new file mode 100644 index 00000000..9af7fe97 --- /dev/null +++ b/vendor/github.com/rivo/tview/pages.go @@ -0,0 +1,248 @@ +package tview + +import ( + "github.com/gdamore/tcell" +) + +// page represents one page of a Pages object. +type page struct { + Name string // The page's name. + Item Primitive // The page's primitive. + Resize bool // Whether or not to resize the page when it is drawn. + Visible bool // Whether or not this page is visible. +} + +// Pages is a container for other primitives often used as the application's +// root primitive. It allows to easily switch the visibility of the contained +// primitives. +// +// See https://github.com/rivo/tview/wiki/Pages for an example. +type Pages struct { + *Box + + // The contained pages. + pages []*page + + // We keep a reference to the function which allows us to set the focus to + // a newly visible page. + setFocus func(p Primitive) + + // An optional handler which is called whenever the visibility or the order of + // pages changes. + changed func() +} + +// NewPages returns a new Pages object. +func NewPages() *Pages { + p := &Pages{ + Box: NewBox(), + } + p.focus = p + return p +} + +// SetChangedFunc sets a handler which is called whenever the visibility or the +// order of any visible pages changes. This can be used to redraw the pages. +func (p *Pages) SetChangedFunc(handler func()) *Pages { + p.changed = handler + return p +} + +// AddPage adds a new page with the given name and primitive. If there was +// previously a page with the same name, it is overwritten. Leaving the name +// empty may cause conflicts in other functions. +// +// Visible pages will be drawn in the order they were added (unless that order +// was changed in one of the other functions). If "resize" is set to true, the +// primitive will be set to the size available to the Pages primitive whenever +// the pages are drawn. +func (p *Pages) AddPage(name string, item Primitive, resize, visible bool) *Pages { + for index, pg := range p.pages { + if pg.Name == name { + p.pages = append(p.pages[:index], p.pages[index+1:]...) + break + } + } + p.pages = append(p.pages, &page{Item: item, Name: name, Resize: resize, Visible: visible}) + if p.changed != nil { + p.changed() + } + if p.HasFocus() { + p.Focus(p.setFocus) + } + return p +} + +// AddAndSwitchToPage calls AddPage(), then SwitchToPage() on that newly added +// page. +func (p *Pages) AddAndSwitchToPage(name string, item Primitive, resize bool) *Pages { + p.AddPage(name, item, resize, true) + p.SwitchToPage(name) + return p +} + +// RemovePage removes the page with the given name. +func (p *Pages) RemovePage(name string) *Pages { + hasFocus := p.HasFocus() + for index, page := range p.pages { + if page.Name == name { + p.pages = append(p.pages[:index], p.pages[index+1:]...) + if page.Visible && p.changed != nil { + p.changed() + } + break + } + } + if hasFocus { + p.Focus(p.setFocus) + } + return p +} + +// HasPage returns true if a page with the given name exists in this object. +func (p *Pages) HasPage(name string) bool { + for _, page := range p.pages { + if page.Name == name { + return true + } + } + return false +} + +// ShowPage sets a page's visibility to "true" (in addition to any other pages +// which are already visible). +func (p *Pages) ShowPage(name string) *Pages { + for _, page := range p.pages { + if page.Name == name { + page.Visible = true + if p.changed != nil { + p.changed() + } + break + } + } + if p.HasFocus() { + p.Focus(p.setFocus) + } + return p +} + +// HidePage sets a page's visibility to "false". +func (p *Pages) HidePage(name string) *Pages { + for _, page := range p.pages { + if page.Name == name { + page.Visible = false + if p.changed != nil { + p.changed() + } + break + } + } + if p.HasFocus() { + p.Focus(p.setFocus) + } + return p +} + +// SwitchToPage sets a page's visibility to "true" and all other pages' +// visibility to "false". +func (p *Pages) SwitchToPage(name string) *Pages { + for _, page := range p.pages { + if page.Name == name { + page.Visible = true + } else { + page.Visible = false + } + } + if p.changed != nil { + p.changed() + } + if p.HasFocus() { + p.Focus(p.setFocus) + } + return p +} + +// SendToFront changes the order of the pages such that the page with the given +// name comes last, causing it to be drawn last with the next update (if +// visible). +func (p *Pages) SendToFront(name string) *Pages { + for index, page := range p.pages { + if page.Name == name { + if index < len(p.pages)-1 { + p.pages = append(append(p.pages[:index], p.pages[index+1:]...), page) + } + if page.Visible && p.changed != nil { + p.changed() + } + break + } + } + if p.HasFocus() { + p.Focus(p.setFocus) + } + return p +} + +// SendToBack changes the order of the pages such that the page with the given +// name comes first, causing it to be drawn first with the next update (if +// visible). +func (p *Pages) SendToBack(name string) *Pages { + for index, pg := range p.pages { + if pg.Name == name { + if index > 0 { + p.pages = append(append([]*page{pg}, p.pages[:index]...), p.pages[index+1:]...) + } + if pg.Visible && p.changed != nil { + p.changed() + } + break + } + } + if p.HasFocus() { + p.Focus(p.setFocus) + } + return p +} + +// HasFocus returns whether or not this primitive has focus. +func (p *Pages) HasFocus() bool { + for _, page := range p.pages { + if page.Item.GetFocusable().HasFocus() { + return true + } + } + return false +} + +// Focus is called by the application when the primitive receives focus. +func (p *Pages) Focus(delegate func(p Primitive)) { + if delegate == nil { + return // We cannot delegate so we cannot focus. + } + p.setFocus = delegate + var topItem Primitive + for _, page := range p.pages { + if page.Visible { + topItem = page.Item + } + } + if topItem != nil { + delegate(topItem) + } +} + +// Draw draws this primitive onto the screen. +func (p *Pages) Draw(screen tcell.Screen) { + p.Box.Draw(screen) + for _, page := range p.pages { + if !page.Visible { + continue + } + if page.Resize { + x, y, width, height := p.GetInnerRect() + page.Item.SetRect(x, y, width, height) + } + page.Item.Draw(screen) + } +} diff --git a/vendor/github.com/rivo/tview/primitive.go b/vendor/github.com/rivo/tview/primitive.go new file mode 100644 index 00000000..88a9d466 --- /dev/null +++ b/vendor/github.com/rivo/tview/primitive.go @@ -0,0 +1,46 @@ +package tview + +import "github.com/gdamore/tcell" + +// Primitive is the top-most interface for all graphical primitives. +type Primitive interface { + // Draw draws this primitive onto the screen. Implementers can call the + // screen's ShowCursor() function but should only do so when they have focus. + // (They will need to keep track of this themselves.) + Draw(screen tcell.Screen) + + // GetRect returns the current position of the primitive, x, y, width, and + // height. + GetRect() (int, int, int, int) + + // SetRect sets a new position of the primitive. + SetRect(x, y, width, height int) + + // InputHandler returns a handler which receives key events when it has focus. + // It is called by the Application class. + // + // A value of nil may also be returned, in which case this primitive cannot + // receive focus and will not process any key events. + // + // The handler will receive the key event and a function that allows it to + // set the focus to a different primitive, so that future key events are sent + // to that primitive. + // + // The Application's Draw() function will be called automatically after the + // handler returns. + // + // The Box class provides functionality to intercept keyboard input. If you + // subclass from Box, it is recommended that you wrap your handler using + // Box.WrapInputHandler() so you inherit that functionality. + InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) + + // Focus is called by the application when the primitive receives focus. + // Implementers may call delegate() to pass the focus on to another primitive. + Focus(delegate func(p Primitive)) + + // Blur is called by the application when the primitive loses focus. + Blur() + + // GetFocusable returns the item's Focusable. + GetFocusable() Focusable +} diff --git a/vendor/github.com/rivo/tview/semigraphics.go b/vendor/github.com/rivo/tview/semigraphics.go new file mode 100644 index 00000000..3b66c5fc --- /dev/null +++ b/vendor/github.com/rivo/tview/semigraphics.go @@ -0,0 +1,296 @@ +package tview + +import "github.com/gdamore/tcell" + +// Semigraphics provides an easy way to access unicode characters for drawing. +// +// Named like the unicode characters, 'Semigraphics'-prefix used if unicode block +// isn't prefixed itself. +const ( + // Block: General Punctation U+2000-U+206F (http://unicode.org/charts/PDF/U2000.pdf) + SemigraphicsHorizontalEllipsis rune = '\u2026' // … + + // Block: Box Drawing U+2500-U+257F (http://unicode.org/charts/PDF/U2500.pdf) + BoxDrawingsLightHorizontal rune = '\u2500' // ─ + BoxDrawingsHeavyHorizontal rune = '\u2501' // ━ + BoxDrawingsLightVertical rune = '\u2502' // │ + BoxDrawingsHeavyVertical rune = '\u2503' // ┃ + BoxDrawingsLightTripleDashHorizontal rune = '\u2504' // ┄ + BoxDrawingsHeavyTripleDashHorizontal rune = '\u2505' // ┅ + BoxDrawingsLightTripleDashVertical rune = '\u2506' // ┆ + BoxDrawingsHeavyTripleDashVertical rune = '\u2507' // ┇ + BoxDrawingsLightQuadrupleDashHorizontal rune = '\u2508' // ┈ + BoxDrawingsHeavyQuadrupleDashHorizontal rune = '\u2509' // ┉ + BoxDrawingsLightQuadrupleDashVertical rune = '\u250a' // ┊ + BoxDrawingsHeavyQuadrupleDashVertical rune = '\u250b' // ┋ + BoxDrawingsLightDownAndRight rune = '\u250c' // ┌ + BoxDrawingsDownLighAndRightHeavy rune = '\u250d' // ┍ + BoxDrawingsDownHeavyAndRightLight rune = '\u250e' // ┎ + BoxDrawingsHeavyDownAndRight rune = '\u250f' // ┏ + BoxDrawingsLightDownAndLeft rune = '\u2510' // ┐ + BoxDrawingsDownLighAndLeftHeavy rune = '\u2511' // ┑ + BoxDrawingsDownHeavyAndLeftLight rune = '\u2512' // ┒ + BoxDrawingsHeavyDownAndLeft rune = '\u2513' // ┓ + BoxDrawingsLightUpAndRight rune = '\u2514' // └ + BoxDrawingsUpLightAndRightHeavy rune = '\u2515' // ┕ + BoxDrawingsUpHeavyAndRightLight rune = '\u2516' // ┖ + BoxDrawingsHeavyUpAndRight rune = '\u2517' // ┗ + BoxDrawingsLightUpAndLeft rune = '\u2518' // ┘ + BoxDrawingsUpLightAndLeftHeavy rune = '\u2519' // ┙ + BoxDrawingsUpHeavyAndLeftLight rune = '\u251a' // ┚ + BoxDrawingsHeavyUpAndLeft rune = '\u251b' // ┛ + BoxDrawingsLightVerticalAndRight rune = '\u251c' // ├ + BoxDrawingsVerticalLightAndRightHeavy rune = '\u251d' // ┝ + BoxDrawingsUpHeavyAndRightDownLight rune = '\u251e' // ┞ + BoxDrawingsDownHeacyAndRightUpLight rune = '\u251f' // ┟ + BoxDrawingsVerticalHeavyAndRightLight rune = '\u2520' // ┠ + BoxDrawingsDownLightAnbdRightUpHeavy rune = '\u2521' // ┡ + BoxDrawingsUpLightAndRightDownHeavy rune = '\u2522' // ┢ + BoxDrawingsHeavyVerticalAndRight rune = '\u2523' // ┣ + BoxDrawingsLightVerticalAndLeft rune = '\u2524' // ┤ + BoxDrawingsVerticalLightAndLeftHeavy rune = '\u2525' // ┥ + BoxDrawingsUpHeavyAndLeftDownLight rune = '\u2526' // ┦ + BoxDrawingsDownHeavyAndLeftUpLight rune = '\u2527' // ┧ + BoxDrawingsVerticalheavyAndLeftLight rune = '\u2528' // ┨ + BoxDrawingsDownLightAndLeftUpHeavy rune = '\u2529' // ┨ + BoxDrawingsUpLightAndLeftDownHeavy rune = '\u252a' // ┪ + BoxDrawingsHeavyVerticalAndLeft rune = '\u252b' // ┫ + BoxDrawingsLightDownAndHorizontal rune = '\u252c' // ┬ + BoxDrawingsLeftHeavyAndRightDownLight rune = '\u252d' // ┭ + BoxDrawingsRightHeavyAndLeftDownLight rune = '\u252e' // ┮ + BoxDrawingsDownLightAndHorizontalHeavy rune = '\u252f' // ┯ + BoxDrawingsDownHeavyAndHorizontalLight rune = '\u2530' // ┰ + BoxDrawingsRightLightAndLeftDownHeavy rune = '\u2531' // ┱ + BoxDrawingsLeftLightAndRightDownHeavy rune = '\u2532' // ┲ + BoxDrawingsHeavyDownAndHorizontal rune = '\u2533' // ┳ + BoxDrawingsLightUpAndHorizontal rune = '\u2534' // ┴ + BoxDrawingsLeftHeavyAndRightUpLight rune = '\u2535' // ┵ + BoxDrawingsRightHeavyAndLeftUpLight rune = '\u2536' // ┶ + BoxDrawingsUpLightAndHorizontalHeavy rune = '\u2537' // ┷ + BoxDrawingsUpHeavyAndHorizontalLight rune = '\u2538' // ┸ + BoxDrawingsRightLightAndLeftUpHeavy rune = '\u2539' // ┹ + BoxDrawingsLeftLightAndRightUpHeavy rune = '\u253a' // ┺ + BoxDrawingsHeavyUpAndHorizontal rune = '\u253b' // ┻ + BoxDrawingsLightVerticalAndHorizontal rune = '\u253c' // ┼ + BoxDrawingsLeftHeavyAndRightVerticalLight rune = '\u253d' // ┽ + BoxDrawingsRightHeavyAndLeftVerticalLight rune = '\u253e' // ┾ + BoxDrawingsVerticalLightAndHorizontalHeavy rune = '\u253f' // ┿ + BoxDrawingsUpHeavyAndDownHorizontalLight rune = '\u2540' // ╀ + BoxDrawingsDownHeavyAndUpHorizontalLight rune = '\u2541' // ╁ + BoxDrawingsVerticalHeavyAndHorizontalLight rune = '\u2542' // ╂ + BoxDrawingsLeftUpHeavyAndRightDownLight rune = '\u2543' // ╃ + BoxDrawingsRightUpHeavyAndLeftDownLight rune = '\u2544' // ╄ + BoxDrawingsLeftDownHeavyAndRightUpLight rune = '\u2545' // ╅ + BoxDrawingsRightDownHeavyAndLeftUpLight rune = '\u2546' // ╆ + BoxDrawingsDownLightAndUpHorizontalHeavy rune = '\u2547' // ╇ + BoxDrawingsUpLightAndDownHorizontalHeavy rune = '\u2548' // ╈ + BoxDrawingsRightLightAndLeftVerticalHeavy rune = '\u2549' // ╉ + BoxDrawingsLeftLightAndRightVerticalHeavy rune = '\u254a' // ╊ + BoxDrawingsHeavyVerticalAndHorizontal rune = '\u254b' // ╋ + BoxDrawingsLightDoubleDashHorizontal rune = '\u254c' // ╌ + BoxDrawingsHeavyDoubleDashHorizontal rune = '\u254d' // ╍ + BoxDrawingsLightDoubleDashVertical rune = '\u254e' // ╎ + BoxDrawingsHeavyDoubleDashVertical rune = '\u254f' // ╏ + BoxDrawingsDoubleHorizontal rune = '\u2550' // ═ + BoxDrawingsDoubleVertical rune = '\u2551' // ║ + BoxDrawingsDownSingleAndRightDouble rune = '\u2552' // ╒ + BoxDrawingsDownDoubleAndRightSingle rune = '\u2553' // ╓ + BoxDrawingsDoubleDownAndRight rune = '\u2554' // ╔ + BoxDrawingsDownSingleAndLeftDouble rune = '\u2555' // ╕ + BoxDrawingsDownDoubleAndLeftSingle rune = '\u2556' // ╖ + BoxDrawingsDoubleDownAndLeft rune = '\u2557' // ╗ + BoxDrawingsUpSingleAndRightDouble rune = '\u2558' // ╘ + BoxDrawingsUpDoubleAndRightSingle rune = '\u2559' // ╙ + BoxDrawingsDoubleUpAndRight rune = '\u255a' // ╚ + BoxDrawingsUpSingleAndLeftDouble rune = '\u255b' // ╛ + BoxDrawingsUpDobuleAndLeftSingle rune = '\u255c' // ╜ + BoxDrawingsDoubleUpAndLeft rune = '\u255d' // ╝ + BoxDrawingsVerticalSingleAndRightDouble rune = '\u255e' // ╞ + BoxDrawingsVerticalDoubleAndRightSingle rune = '\u255f' // ╟ + BoxDrawingsDoubleVerticalAndRight rune = '\u2560' // ╠ + BoxDrawingsVerticalSingleAndLeftDouble rune = '\u2561' // ╡ + BoxDrawingsVerticalDoubleAndLeftSingle rune = '\u2562' // ╢ + BoxDrawingsDoubleVerticalAndLeft rune = '\u2563' // ╣ + BoxDrawingsDownSingleAndHorizontalDouble rune = '\u2564' // ╤ + BoxDrawingsDownDoubleAndHorizontalSingle rune = '\u2565' // ╥ + BoxDrawingsDoubleDownAndHorizontal rune = '\u2566' // ╦ + BoxDrawingsUpSingleAndHorizontalDouble rune = '\u2567' // ╧ + BoxDrawingsUpDoubleAndHorizontalSingle rune = '\u2568' // ╨ + BoxDrawingsDoubleUpAndHorizontal rune = '\u2569' // ╩ + BoxDrawingsVerticalSingleAndHorizontalDouble rune = '\u256a' // ╪ + BoxDrawingsVerticalDoubleAndHorizontalSingle rune = '\u256b' // ╫ + BoxDrawingsDoubleVerticalAndHorizontal rune = '\u256c' // ╬ + BoxDrawingsLightArcDownAndRight rune = '\u256d' // ╭ + BoxDrawingsLightArcDownAndLeft rune = '\u256e' // ╮ + BoxDrawingsLightArcUpAndLeft rune = '\u256f' // ╯ + BoxDrawingsLightArcUpAndRight rune = '\u2570' // ╰ + BoxDrawingsLightDiagonalUpperRightToLowerLeft rune = '\u2571' // ╱ + BoxDrawingsLightDiagonalUpperLeftToLowerRight rune = '\u2572' // ╲ + BoxDrawingsLightDiagonalCross rune = '\u2573' // ╳ + BoxDrawingsLightLeft rune = '\u2574' // ╴ + BoxDrawingsLightUp rune = '\u2575' // ╵ + BoxDrawingsLightRight rune = '\u2576' // ╶ + BoxDrawingsLightDown rune = '\u2577' // ╷ + BoxDrawingsHeavyLeft rune = '\u2578' // ╸ + BoxDrawingsHeavyUp rune = '\u2579' // ╹ + BoxDrawingsHeavyRight rune = '\u257a' // ╺ + BoxDrawingsHeavyDown rune = '\u257b' // ╻ + BoxDrawingsLightLeftAndHeavyRight rune = '\u257c' // ╼ + BoxDrawingsLightUpAndHeavyDown rune = '\u257d' // ╽ + BoxDrawingsHeavyLeftAndLightRight rune = '\u257e' // ╾ + BoxDrawingsHeavyUpAndLightDown rune = '\u257f' // ╿ +) + +// SemigraphicJoints is a map for joining semigraphic (or otherwise) runes. +// So far only light lines are supported but if you want to change the border +// styling you need to provide the joints, too. +// The matching will be sorted ascending by rune value, so you don't need to +// provide all rune combinations, +// e.g. (─) + (│) = (┼) will also match (│) + (─) = (┼) +var SemigraphicJoints = map[string]rune{ + // (─) + (│) = (┼) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightVertical}): BoxDrawingsLightVerticalAndHorizontal, + // (─) + (┌) = (┬) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightDownAndRight}): BoxDrawingsLightDownAndHorizontal, + // (─) + (┐) = (┬) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightDownAndLeft}): BoxDrawingsLightDownAndHorizontal, + // (─) + (└) = (┴) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightUpAndRight}): BoxDrawingsLightUpAndHorizontal, + // (─) + (┘) = (┴) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightUpAndHorizontal, + // (─) + (├) = (┼) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndHorizontal, + // (─) + (┤) = (┼) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndHorizontal, + // (─) + (┬) = (┬) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightDownAndHorizontal, + // (─) + (┴) = (┴) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightUpAndHorizontal, + // (─) + (┼) = (┼) + string([]rune{BoxDrawingsLightHorizontal, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (│) + (┌) = (├) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightDownAndRight}): BoxDrawingsLightVerticalAndRight, + // (│) + (┐) = (┤) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightDownAndLeft}): BoxDrawingsLightVerticalAndLeft, + // (│) + (└) = (├) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightUpAndRight}): BoxDrawingsLightVerticalAndRight, + // (│) + (┘) = (┤) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightVerticalAndLeft, + // (│) + (├) = (├) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndRight, + // (│) + (┤) = (┤) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndLeft, + // (│) + (┬) = (┼) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (│) + (┴) = (┼) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (│) + (┼) = (┼) + string([]rune{BoxDrawingsLightVertical, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (┌) + (┐) = (┬) + string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightDownAndLeft}): BoxDrawingsLightDownAndHorizontal, + // (┌) + (└) = (├) + string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightUpAndRight}): BoxDrawingsLightVerticalAndRight, + // (┌) + (┘) = (┼) + string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightVerticalAndHorizontal, + // (┌) + (├) = (├) + string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndRight, + // (┌) + (┤) = (┼) + string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndHorizontal, + // (┌) + (┬) = (┬) + string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightDownAndHorizontal, + // (┌) + (┴) = (┼) + string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (┌) + (┴) = (┼) + string([]rune{BoxDrawingsLightDownAndRight, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (┐) + (└) = (┼) + string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightUpAndRight}): BoxDrawingsLightVerticalAndHorizontal, + // (┐) + (┘) = (┤) + string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightVerticalAndLeft, + // (┐) + (├) = (┼) + string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndHorizontal, + // (┐) + (┤) = (┤) + string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndLeft, + // (┐) + (┬) = (┬) + string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightDownAndHorizontal, + // (┐) + (┴) = (┼) + string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (┐) + (┼) = (┼) + string([]rune{BoxDrawingsLightDownAndLeft, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (└) + (┘) = (┴) + string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightUpAndLeft}): BoxDrawingsLightUpAndHorizontal, + // (└) + (├) = (├) + string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndRight, + // (└) + (┤) = (┼) + string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndHorizontal, + // (└) + (┬) = (┼) + string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (└) + (┴) = (┴) + string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightUpAndHorizontal, + // (└) + (┼) = (┼) + string([]rune{BoxDrawingsLightUpAndRight, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (┘) + (├) = (┼) + string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightVerticalAndRight}): BoxDrawingsLightVerticalAndHorizontal, + // (┘) + (┤) = (┤) + string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndLeft, + // (┘) + (┬) = (┼) + string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (┘) + (┴) = (┴) + string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightUpAndHorizontal, + // (┘) + (┼) = (┼) + string([]rune{BoxDrawingsLightUpAndLeft, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (├) + (┤) = (┼) + string([]rune{BoxDrawingsLightVerticalAndRight, BoxDrawingsLightVerticalAndLeft}): BoxDrawingsLightVerticalAndHorizontal, + // (├) + (┬) = (┼) + string([]rune{BoxDrawingsLightVerticalAndRight, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (├) + (┴) = (┼) + string([]rune{BoxDrawingsLightVerticalAndRight, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (├) + (┼) = (┼) + string([]rune{BoxDrawingsLightVerticalAndRight, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (┤) + (┬) = (┼) + string([]rune{BoxDrawingsLightVerticalAndLeft, BoxDrawingsLightDownAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (┤) + (┴) = (┼) + string([]rune{BoxDrawingsLightVerticalAndLeft, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (┤) + (┼) = (┼) + string([]rune{BoxDrawingsLightVerticalAndLeft, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (┬) + (┴) = (┼) + string([]rune{BoxDrawingsLightDownAndHorizontal, BoxDrawingsLightUpAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + // (┬) + (┼) = (┼) + string([]rune{BoxDrawingsLightDownAndHorizontal, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, + + // (┴) + (┼) = (┼) + string([]rune{BoxDrawingsLightUpAndHorizontal, BoxDrawingsLightVerticalAndHorizontal}): BoxDrawingsLightVerticalAndHorizontal, +} + +// PrintJoinedSemigraphics prints a semigraphics rune into the screen at the given +// position with the given color, joining it with any existing semigraphics +// rune. Background colors are preserved. At this point, only regular single +// line borders are supported. +func PrintJoinedSemigraphics(screen tcell.Screen, x, y int, ch rune, color tcell.Color) { + previous, _, style, _ := screen.GetContent(x, y) + style = style.Foreground(color) + + // What's the resulting rune? + var result rune + if ch == previous { + result = ch + } else { + if ch < previous { + previous, ch = ch, previous + } + result = SemigraphicJoints[string([]rune{previous, ch})] + } + if result == 0 { + result = ch + } + + // We only print something if we have something. + screen.SetContent(x, y, result, nil, style) +} diff --git a/vendor/github.com/rivo/tview/styles.go b/vendor/github.com/rivo/tview/styles.go new file mode 100644 index 00000000..dbd60ad0 --- /dev/null +++ b/vendor/github.com/rivo/tview/styles.go @@ -0,0 +1,34 @@ +package tview + +import "github.com/gdamore/tcell" + +// Styles defines various colors used when primitives are initialized. These +// may be changed to accommodate a different look and feel. +// +// The default is for applications with a black background and basic colors: +// black, white, yellow, green, and blue. +var Styles = struct { + PrimitiveBackgroundColor tcell.Color // Main background color for primitives. + ContrastBackgroundColor tcell.Color // Background color for contrasting elements. + MoreContrastBackgroundColor tcell.Color // Background color for even more contrasting elements. + BorderColor tcell.Color // Box borders. + TitleColor tcell.Color // Box titles. + GraphicsColor tcell.Color // Graphics. + PrimaryTextColor tcell.Color // Primary text. + SecondaryTextColor tcell.Color // Secondary text (e.g. labels). + TertiaryTextColor tcell.Color // Tertiary text (e.g. subtitles, notes). + InverseTextColor tcell.Color // Text on primary-colored backgrounds. + ContrastSecondaryTextColor tcell.Color // Secondary text on ContrastBackgroundColor-colored backgrounds. +}{ + PrimitiveBackgroundColor: tcell.ColorBlack, + ContrastBackgroundColor: tcell.ColorBlue, + MoreContrastBackgroundColor: tcell.ColorGreen, + BorderColor: tcell.ColorWhite, + TitleColor: tcell.ColorWhite, + GraphicsColor: tcell.ColorWhite, + PrimaryTextColor: tcell.ColorWhite, + SecondaryTextColor: tcell.ColorYellow, + TertiaryTextColor: tcell.ColorGreen, + InverseTextColor: tcell.ColorBlue, + ContrastSecondaryTextColor: tcell.ColorDarkCyan, +} diff --git a/vendor/github.com/rivo/tview/table.go b/vendor/github.com/rivo/tview/table.go new file mode 100644 index 00000000..10f83995 --- /dev/null +++ b/vendor/github.com/rivo/tview/table.go @@ -0,0 +1,1043 @@ +package tview + +import ( + "sort" + + "github.com/gdamore/tcell" + colorful "github.com/lucasb-eyer/go-colorful" +) + +// TableCell represents one cell inside a Table. You can instantiate this type +// directly but all colors (background and text) will be set to their default +// which is black. +type TableCell struct { + // The text to be displayed in the table cell. + Text string + + // The alignment of the cell text. One of AlignLeft (default), AlignCenter, + // or AlignRight. + Align int + + // The maximum width of the cell in screen space. This is used to give a + // column a maximum width. Any cell text whose screen width exceeds this width + // is cut off. Set to 0 if there is no maximum width. + MaxWidth int + + // If the total table width is less than the available width, this value is + // used to add extra width to a column. See SetExpansion() for details. + Expansion int + + // The color of the cell text. + Color tcell.Color + + // The background color of the cell. + BackgroundColor tcell.Color + + // The style attributes of the cell. + Attributes tcell.AttrMask + + // If set to true, this cell cannot be selected. + NotSelectable bool + + // The position and width of the cell the last time table was drawn. + x, y, width int +} + +// NewTableCell returns a new table cell with sensible defaults. That is, left +// aligned text with the primary text color (see Styles) and a transparent +// background (using the background of the Table). +func NewTableCell(text string) *TableCell { + return &TableCell{ + Text: text, + Align: AlignLeft, + Color: Styles.PrimaryTextColor, + BackgroundColor: tcell.ColorDefault, + } +} + +// SetText sets the cell's text. +func (c *TableCell) SetText(text string) *TableCell { + c.Text = text + return c +} + +// SetAlign sets the cell's text alignment, one of AlignLeft, AlignCenter, or +// AlignRight. +func (c *TableCell) SetAlign(align int) *TableCell { + c.Align = align + return c +} + +// SetMaxWidth sets maximum width of the cell in screen space. This is used to +// give a column a maximum width. Any cell text whose screen width exceeds this +// width is cut off. Set to 0 if there is no maximum width. +func (c *TableCell) SetMaxWidth(maxWidth int) *TableCell { + c.MaxWidth = maxWidth + return c +} + +// SetExpansion sets the value by which the column of this cell expands if the +// available width for the table is more than the table width (prior to applying +// this expansion value). This is a proportional value. The amount of unused +// horizontal space is divided into widths to be added to each column. How much +// extra width a column receives depends on the expansion value: A value of 0 +// (the default) will not cause the column to increase in width. Other values +// are proportional, e.g. a value of 2 will cause a column to grow by twice +// the amount of a column with a value of 1. +// +// Since this value affects an entire column, the maximum over all visible cells +// in that column is used. +// +// This function panics if a negative value is provided. +func (c *TableCell) SetExpansion(expansion int) *TableCell { + if expansion < 0 { + panic("Table cell expansion values may not be negative") + } + c.Expansion = expansion + return c +} + +// SetTextColor sets the cell's text color. +func (c *TableCell) SetTextColor(color tcell.Color) *TableCell { + c.Color = color + return c +} + +// SetBackgroundColor sets the cell's background color. Set to +// tcell.ColorDefault to use the table's background color. +func (c *TableCell) SetBackgroundColor(color tcell.Color) *TableCell { + c.BackgroundColor = color + return c +} + +// SetAttributes sets the cell's text attributes. You can combine different +// attributes using bitmask operations: +// +// cell.SetAttributes(tcell.AttrUnderline | tcell.AttrBold) +func (c *TableCell) SetAttributes(attr tcell.AttrMask) *TableCell { + c.Attributes = attr + return c +} + +// SetStyle sets the cell's style (foreground color, background color, and +// attributes) all at once. +func (c *TableCell) SetStyle(style tcell.Style) *TableCell { + c.Color, c.BackgroundColor, c.Attributes = style.Decompose() + return c +} + +// SetSelectable sets whether or not this cell can be selected by the user. +func (c *TableCell) SetSelectable(selectable bool) *TableCell { + c.NotSelectable = !selectable + return c +} + +// GetLastPosition returns the position of the table cell the last time it was +// drawn on screen. If the cell is not on screen, the return values are +// undefined. +// +// Because the Table class will attempt to keep selected cells on screen, this +// function is most useful in response to a "selected" event (see +// SetSelectedFunc()) or a "selectionChanged" event (see +// SetSelectionChangedFunc()). +func (c *TableCell) GetLastPosition() (x, y, width int) { + return c.x, c.y, c.width +} + +// Table visualizes two-dimensional data consisting of rows and columns. Each +// Table cell is defined via SetCell() by the TableCell type. They can be added +// dynamically to the table and changed any time. +// +// The most compact display of a table is without borders. Each row will then +// occupy one row on screen and columns are separated by the rune defined via +// SetSeparator() (a space character by default). +// +// When borders are turned on (via SetBorders()), each table cell is surrounded +// by lines. Therefore one table row will require two rows on screen. +// +// Columns will use as much horizontal space as they need. You can constrain +// their size with the MaxWidth parameter of the TableCell type. +// +// Fixed Columns +// +// You can define fixed rows and rolumns via SetFixed(). They will always stay +// in their place, even when the table is scrolled. Fixed rows are always the +// top rows. Fixed columns are always the leftmost columns. +// +// Selections +// +// You can call SetSelectable() to set columns and/or rows to "selectable". If +// the flag is set only for columns, entire columns can be selected by the user. +// If it is set only for rows, entire rows can be selected. If both flags are +// set, individual cells can be selected. The "selected" handler set via +// SetSelectedFunc() is invoked when the user presses Enter on a selection. +// +// Navigation +// +// If the table extends beyond the available space, it can be navigated with +// key bindings similar to Vim: +// +// - h, left arrow: Move left by one column. +// - l, right arrow: Move right by one column. +// - j, down arrow: Move down by one row. +// - k, up arrow: Move up by one row. +// - g, home: Move to the top. +// - G, end: Move to the bottom. +// - Ctrl-F, page down: Move down by one page. +// - Ctrl-B, page up: Move up by one page. +// +// When there is no selection, this affects the entire table (except for fixed +// rows and columns). When there is a selection, the user moves the selection. +// The class will attempt to keep the selection from moving out of the screen. +// +// Use SetInputCapture() to override or modify keyboard input. +// +// See https://github.com/rivo/tview/wiki/Table for an example. +type Table struct { + *Box + + // Whether or not this table has borders around each cell. + borders bool + + // The color of the borders or the separator. + bordersColor tcell.Color + + // If there are no borders, the column separator. + separator rune + + // The cells of the table. Rows first, then columns. + cells [][]*TableCell + + // The rightmost column in the data set. + lastColumn int + + // The number of fixed rows / columns. + fixedRows, fixedColumns int + + // Whether or not rows or columns can be selected. If both are set to true, + // cells can be selected. + rowsSelectable, columnsSelectable bool + + // The currently selected row and column. + selectedRow, selectedColumn int + + // The number of rows/columns by which the table is scrolled down/to the + // right. + rowOffset, columnOffset int + + // If set to true, the table's last row will always be visible. + trackEnd bool + + // The number of visible rows the last time the table was drawn. + visibleRows int + + // An optional function which gets called when the user presses Enter on a + // selected cell. If entire rows selected, the column value is undefined. + // Likewise for entire columns. + selected func(row, column int) + + // An optional function which gets called when the user changes the selection. + // If entire rows selected, the column value is undefined. + // Likewise for entire columns. + selectionChanged func(row, column int) + + // An optional function which gets called when the user presses Escape, Tab, + // or Backtab. Also when the user presses Enter if nothing is selectable. + done func(key tcell.Key) +} + +// NewTable returns a new table. +func NewTable() *Table { + return &Table{ + Box: NewBox(), + bordersColor: Styles.GraphicsColor, + separator: ' ', + lastColumn: -1, + } +} + +// Clear removes all table data. +func (t *Table) Clear() *Table { + t.cells = nil + t.lastColumn = -1 + return t +} + +// SetBorders sets whether or not each cell in the table is surrounded by a +// border. +func (t *Table) SetBorders(show bool) *Table { + t.borders = show + return t +} + +// SetBordersColor sets the color of the cell borders. +func (t *Table) SetBordersColor(color tcell.Color) *Table { + t.bordersColor = color + return t +} + +// SetSeparator sets the character used to fill the space between two +// neighboring cells. This is a space character ' ' per default but you may +// want to set it to Borders.Vertical (or any other rune) if the column +// separation should be more visible. If cell borders are activated, this is +// ignored. +// +// Separators have the same color as borders. +func (t *Table) SetSeparator(separator rune) *Table { + t.separator = separator + return t +} + +// SetFixed sets the number of fixed rows and columns which are always visible +// even when the rest of the cells are scrolled out of view. Rows are always the +// top-most ones. Columns are always the left-most ones. +func (t *Table) SetFixed(rows, columns int) *Table { + t.fixedRows, t.fixedColumns = rows, columns + return t +} + +// SetSelectable sets the flags which determine what can be selected in a table. +// There are three selection modi: +// +// - rows = false, columns = false: Nothing can be selected. +// - rows = true, columns = false: Rows can be selected. +// - rows = false, columns = true: Columns can be selected. +// - rows = true, columns = true: Individual cells can be selected. +func (t *Table) SetSelectable(rows, columns bool) *Table { + t.rowsSelectable, t.columnsSelectable = rows, columns + return t +} + +// GetSelectable returns what can be selected in a table. Refer to +// SetSelectable() for details. +func (t *Table) GetSelectable() (rows, columns bool) { + return t.rowsSelectable, t.columnsSelectable +} + +// GetSelection returns the position of the current selection. +// If entire rows are selected, the column index is undefined. +// Likewise for entire columns. +func (t *Table) GetSelection() (row, column int) { + return t.selectedRow, t.selectedColumn +} + +// Select sets the selected cell. Depending on the selection settings +// specified via SetSelectable(), this may be an entire row or column, or even +// ignored completely. +func (t *Table) Select(row, column int) *Table { + t.selectedRow, t.selectedColumn = row, column + return t +} + +// SetOffset sets how many rows and columns should be skipped when drawing the +// table. This is useful for large tables that do not fit on the screen. +// Navigating a selection can change these values. +// +// Fixed rows and columns are never skipped. +func (t *Table) SetOffset(row, column int) *Table { + t.rowOffset, t.columnOffset = row, column + return t +} + +// GetOffset returns the current row and column offset. This indicates how many +// rows and columns the table is scrolled down and to the right. +func (t *Table) GetOffset() (row, column int) { + return t.rowOffset, t.columnOffset +} + +// SetSelectedFunc sets a handler which is called whenever the user presses the +// Enter key on a selected cell/row/column. The handler receives the position of +// the selection and its cell contents. If entire rows are selected, the column +// index is undefined. Likewise for entire columns. +func (t *Table) SetSelectedFunc(handler func(row, column int)) *Table { + t.selected = handler + return t +} + +// SetSelectionChangedFunc sets a handler which is called whenever the user +// navigates to a new selection. The handler receives the position of the new +// selection. If entire rows are selected, the column index is undefined. +// Likewise for entire columns. +func (t *Table) SetSelectionChangedFunc(handler func(row, column int)) *Table { + t.selectionChanged = handler + return t +} + +// SetDoneFunc sets a handler which is called whenever the user presses the +// Escape, Tab, or Backtab key. If nothing is selected, it is also called when +// user presses the Enter key (because pressing Enter on a selection triggers +// the "selected" handler set via SetSelectedFunc()). +func (t *Table) SetDoneFunc(handler func(key tcell.Key)) *Table { + t.done = handler + return t +} + +// SetCell sets the content of a cell the specified position. It is ok to +// directly instantiate a TableCell object. If the cell has contain, at least +// the Text and Color fields should be set. +// +// Note that setting cells in previously unknown rows and columns will +// automatically extend the internal table representation, e.g. starting with +// a row of 100,000 will immediately create 100,000 empty rows. +// +// To avoid unnecessary garbage collection, fill columns from left to right. +func (t *Table) SetCell(row, column int, cell *TableCell) *Table { + if row >= len(t.cells) { + t.cells = append(t.cells, make([][]*TableCell, row-len(t.cells)+1)...) + } + rowLen := len(t.cells[row]) + if column >= rowLen { + t.cells[row] = append(t.cells[row], make([]*TableCell, column-rowLen+1)...) + for c := rowLen; c < column; c++ { + t.cells[row][c] = &TableCell{} + } + } + t.cells[row][column] = cell + if column > t.lastColumn { + t.lastColumn = column + } + return t +} + +// SetCellSimple calls SetCell() with the given text, left-aligned, in white. +func (t *Table) SetCellSimple(row, column int, text string) *Table { + t.SetCell(row, column, NewTableCell(text)) + return t +} + +// GetCell returns the contents of the cell at the specified position. A valid +// TableCell object is always returns but it will be uninitialized if the cell +// was not previously set. +func (t *Table) GetCell(row, column int) *TableCell { + if row >= len(t.cells) || column >= len(t.cells[row]) { + return &TableCell{} + } + return t.cells[row][column] +} + +// GetRowCount returns the number of rows in the table. +func (t *Table) GetRowCount() int { + return len(t.cells) +} + +// GetColumnCount returns the (maximum) number of columns in the table. +func (t *Table) GetColumnCount() int { + if len(t.cells) == 0 { + return 0 + } + return t.lastColumn + 1 +} + +// ScrollToBeginning scrolls the table to the beginning to that the top left +// corner of the table is shown. Note that this position may be corrected if +// there is a selection. +func (t *Table) ScrollToBeginning() *Table { + t.trackEnd = false + t.columnOffset = 0 + t.rowOffset = 0 + return t +} + +// ScrollToEnd scrolls the table to the beginning to that the bottom left corner +// of the table is shown. Adding more rows to the table will cause it to +// automatically scroll with the new data. Note that this position may be +// corrected if there is a selection. +func (t *Table) ScrollToEnd() *Table { + t.trackEnd = true + t.columnOffset = 0 + t.rowOffset = len(t.cells) + return t +} + +// Draw draws this primitive onto the screen. +func (t *Table) Draw(screen tcell.Screen) { + t.Box.Draw(screen) + + // What's our available screen space? + x, y, width, height := t.GetInnerRect() + if t.borders { + t.visibleRows = height / 2 + } else { + t.visibleRows = height + } + + // Return the cell at the specified position (nil if it doesn't exist). + getCell := func(row, column int) *TableCell { + if row < 0 || column < 0 || row >= len(t.cells) || column >= len(t.cells[row]) { + return nil + } + return t.cells[row][column] + } + + // If this cell is not selectable, find the next one. + if t.rowsSelectable || t.columnsSelectable { + if t.selectedColumn < 0 { + t.selectedColumn = 0 + } + if t.selectedRow < 0 { + t.selectedRow = 0 + } + for t.selectedRow < len(t.cells) { + cell := getCell(t.selectedRow, t.selectedColumn) + if cell == nil || !cell.NotSelectable { + break + } + t.selectedColumn++ + if t.selectedColumn > t.lastColumn { + t.selectedColumn = 0 + t.selectedRow++ + } + } + } + + // Clamp row offsets. + if t.rowsSelectable { + if t.selectedRow >= t.fixedRows && t.selectedRow < t.fixedRows+t.rowOffset { + t.rowOffset = t.selectedRow - t.fixedRows + t.trackEnd = false + } + if t.borders { + if 2*(t.selectedRow+1-t.rowOffset) >= height { + t.rowOffset = t.selectedRow + 1 - height/2 + t.trackEnd = false + } + } else { + if t.selectedRow+1-t.rowOffset >= height { + t.rowOffset = t.selectedRow + 1 - height + t.trackEnd = false + } + } + } + if t.borders { + if 2*(len(t.cells)-t.rowOffset) < height { + t.trackEnd = true + } + } else { + if len(t.cells)-t.rowOffset < height { + t.trackEnd = true + } + } + if t.trackEnd { + if t.borders { + t.rowOffset = len(t.cells) - height/2 + } else { + t.rowOffset = len(t.cells) - height + } + } + if t.rowOffset < 0 { + t.rowOffset = 0 + } + + // Clamp column offset. (Only left side here. The right side is more + // difficult and we'll do it below.) + if t.columnsSelectable && t.selectedColumn >= t.fixedColumns && t.selectedColumn < t.fixedColumns+t.columnOffset { + t.columnOffset = t.selectedColumn - t.fixedColumns + } + if t.columnOffset < 0 { + t.columnOffset = 0 + } + if t.selectedColumn < 0 { + t.selectedColumn = 0 + } + + // Determine the indices and widths of the columns and rows which fit on the + // screen. + var ( + columns, rows, widths []int + tableHeight, tableWidth int + ) + rowStep := 1 + if t.borders { + rowStep = 2 // With borders, every table row takes two screen rows. + tableWidth = 1 // We start at the second character because of the left table border. + } + indexRow := func(row int) bool { // Determine if this row is visible, store its index. + if tableHeight >= height { + return false + } + rows = append(rows, row) + tableHeight += rowStep + return true + } + for row := 0; row < t.fixedRows && row < len(t.cells); row++ { // Do the fixed rows first. + if !indexRow(row) { + break + } + } + for row := t.fixedRows + t.rowOffset; row < len(t.cells); row++ { // Then the remaining rows. + if !indexRow(row) { + break + } + } + var ( + skipped, lastTableWidth, expansionTotal int + expansions []int + ) +ColumnLoop: + for column := 0; ; column++ { + // If we've moved beyond the right border, we stop or skip a column. + for tableWidth-1 >= width { // -1 because we include one extra column if the separator falls on the right end of the box. + // We've moved beyond the available space. + if column < t.fixedColumns { + break ColumnLoop // We're in the fixed area. We're done. + } + if !t.columnsSelectable && skipped >= t.columnOffset { + break ColumnLoop // There is no selection and we've already reached the offset. + } + if t.columnsSelectable && t.selectedColumn-skipped == t.fixedColumns { + break ColumnLoop // The selected column reached the leftmost point before disappearing. + } + if t.columnsSelectable && skipped >= t.columnOffset && + (t.selectedColumn < column && lastTableWidth < width-1 && tableWidth < width-1 || t.selectedColumn < column-1) { + break ColumnLoop // We've skipped as many as requested and the selection is visible. + } + if len(columns) <= t.fixedColumns { + break // Nothing to skip. + } + + // We need to skip a column. + skipped++ + lastTableWidth -= widths[t.fixedColumns] + 1 + tableWidth -= widths[t.fixedColumns] + 1 + columns = append(columns[:t.fixedColumns], columns[t.fixedColumns+1:]...) + widths = append(widths[:t.fixedColumns], widths[t.fixedColumns+1:]...) + expansions = append(expansions[:t.fixedColumns], expansions[t.fixedColumns+1:]...) + } + + // What's this column's width (without expansion)? + maxWidth := -1 + expansion := 0 + for _, row := range rows { + if cell := getCell(row, column); cell != nil { + _, _, _, _, cellWidth := decomposeString(cell.Text) + if cell.MaxWidth > 0 && cell.MaxWidth < cellWidth { + cellWidth = cell.MaxWidth + } + if cellWidth > maxWidth { + maxWidth = cellWidth + } + if cell.Expansion > expansion { + expansion = cell.Expansion + } + } + } + if maxWidth < 0 { + break // No more cells found in this column. + } + + // Store new column info at the end. + columns = append(columns, column) + widths = append(widths, maxWidth) + lastTableWidth = tableWidth + tableWidth += maxWidth + 1 + expansions = append(expansions, expansion) + expansionTotal += expansion + } + t.columnOffset = skipped + + // If we have space left, distribute it. + if tableWidth < width { + toDistribute := width - tableWidth + for index, expansion := range expansions { + if expansionTotal <= 0 { + break + } + expWidth := toDistribute * expansion / expansionTotal + widths[index] += expWidth + tableWidth += expWidth + toDistribute -= expWidth + expansionTotal -= expansion + } + } + + // Helper function which draws border runes. + borderStyle := tcell.StyleDefault.Background(t.backgroundColor).Foreground(t.bordersColor) + drawBorder := func(colX, rowY int, ch rune) { + screen.SetContent(x+colX, y+rowY, ch, nil, borderStyle) + } + + // Draw the cells (and borders). + var columnX int + if !t.borders { + columnX-- + } + for columnIndex, column := range columns { + columnWidth := widths[columnIndex] + for rowY, row := range rows { + if t.borders { + // Draw borders. + rowY *= 2 + for pos := 0; pos < columnWidth && columnX+1+pos < width; pos++ { + drawBorder(columnX+pos+1, rowY, Borders.Horizontal) + } + ch := Borders.Cross + if columnIndex == 0 { + if rowY == 0 { + ch = Borders.TopLeft + } else { + ch = Borders.LeftT + } + } else if rowY == 0 { + ch = Borders.TopT + } + drawBorder(columnX, rowY, ch) + rowY++ + if rowY >= height { + break // No space for the text anymore. + } + drawBorder(columnX, rowY, Borders.Vertical) + } else if columnIndex > 0 { + // Draw separator. + drawBorder(columnX, rowY, t.separator) + } + + // Get the cell. + cell := getCell(row, column) + if cell == nil { + continue + } + + // Draw text. + finalWidth := columnWidth + if columnX+1+columnWidth >= width { + finalWidth = width - columnX - 1 + } + cell.x, cell.y, cell.width = x+columnX+1, y+rowY, finalWidth + _, printed := printWithStyle(screen, cell.Text, x+columnX+1, y+rowY, finalWidth, cell.Align, tcell.StyleDefault.Foreground(cell.Color)|tcell.Style(cell.Attributes)) + if StringWidth(cell.Text)-printed > 0 && printed > 0 { + _, _, style, _ := screen.GetContent(x+columnX+1+finalWidth-1, y+rowY) + printWithStyle(screen, string(SemigraphicsHorizontalEllipsis), x+columnX+1+finalWidth-1, y+rowY, 1, AlignLeft, style) + } + } + + // Draw bottom border. + if rowY := 2 * len(rows); t.borders && rowY < height { + for pos := 0; pos < columnWidth && columnX+1+pos < width; pos++ { + drawBorder(columnX+pos+1, rowY, Borders.Horizontal) + } + ch := Borders.BottomT + if columnIndex == 0 { + ch = Borders.BottomLeft + } + drawBorder(columnX, rowY, ch) + } + + columnX += columnWidth + 1 + } + + // Draw right border. + if t.borders && len(t.cells) > 0 && columnX < width { + for rowY := range rows { + rowY *= 2 + if rowY+1 < height { + drawBorder(columnX, rowY+1, Borders.Vertical) + } + ch := Borders.RightT + if rowY == 0 { + ch = Borders.TopRight + } + drawBorder(columnX, rowY, ch) + } + if rowY := 2 * len(rows); rowY < height { + drawBorder(columnX, rowY, Borders.BottomRight) + } + } + + // Helper function which colors the background of a box. + colorBackground := func(fromX, fromY, w, h int, backgroundColor, textColor tcell.Color, selected bool) { + for by := 0; by < h && fromY+by < y+height; by++ { + for bx := 0; bx < w && fromX+bx < x+width; bx++ { + m, c, style, _ := screen.GetContent(fromX+bx, fromY+by) + if selected { + fg, _, _ := style.Decompose() + if fg == textColor || fg == t.bordersColor { + fg = backgroundColor + } + if fg == tcell.ColorDefault { + fg = t.backgroundColor + } + style = style.Background(textColor).Foreground(fg) + } else { + if backgroundColor == tcell.ColorDefault { + continue + } + style = style.Background(backgroundColor) + } + screen.SetContent(fromX+bx, fromY+by, m, c, style) + } + } + } + + // Color the cell backgrounds. To avoid undesirable artefacts, we combine + // the drawing of a cell by background color, selected cells last. + cellsByBackgroundColor := make(map[tcell.Color][]*struct { + x, y, w, h int + text tcell.Color + selected bool + }) + var backgroundColors []tcell.Color + for rowY, row := range rows { + columnX := 0 + rowSelected := t.rowsSelectable && !t.columnsSelectable && row == t.selectedRow + for columnIndex, column := range columns { + columnWidth := widths[columnIndex] + cell := getCell(row, column) + if cell == nil { + continue + } + bx, by, bw, bh := x+columnX, y+rowY, columnWidth+1, 1 + if t.borders { + by = y + rowY*2 + bw++ + bh = 3 + } + columnSelected := t.columnsSelectable && !t.rowsSelectable && column == t.selectedColumn + cellSelected := !cell.NotSelectable && (columnSelected || rowSelected || t.rowsSelectable && t.columnsSelectable && column == t.selectedColumn && row == t.selectedRow) + entries, ok := cellsByBackgroundColor[cell.BackgroundColor] + cellsByBackgroundColor[cell.BackgroundColor] = append(entries, &struct { + x, y, w, h int + text tcell.Color + selected bool + }{ + x: bx, + y: by, + w: bw, + h: bh, + text: cell.Color, + selected: cellSelected, + }) + if !ok { + backgroundColors = append(backgroundColors, cell.BackgroundColor) + } + columnX += columnWidth + 1 + } + } + sort.Slice(backgroundColors, func(i int, j int) bool { + // Draw brightest colors last (i.e. on top). + r, g, b := backgroundColors[i].RGB() + c := colorful.Color{R: float64(r) / 255, G: float64(g) / 255, B: float64(b) / 255} + _, _, li := c.Hcl() + r, g, b = backgroundColors[j].RGB() + c = colorful.Color{R: float64(r) / 255, G: float64(g) / 255, B: float64(b) / 255} + _, _, lj := c.Hcl() + return li < lj + }) + for _, bgColor := range backgroundColors { + entries := cellsByBackgroundColor[bgColor] + for _, cell := range entries { + if cell.selected { + defer colorBackground(cell.x, cell.y, cell.w, cell.h, bgColor, cell.text, true) + } else { + colorBackground(cell.x, cell.y, cell.w, cell.h, bgColor, cell.text, false) + } + } + } +} + +// InputHandler returns the handler for this primitive. +func (t *Table) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { + key := event.Key() + + if (!t.rowsSelectable && !t.columnsSelectable && key == tcell.KeyEnter) || + key == tcell.KeyEscape || + key == tcell.KeyTab || + key == tcell.KeyBacktab { + if t.done != nil { + t.done(key) + } + return + } + + // Movement functions. + previouslySelectedRow, previouslySelectedColumn := t.selectedRow, t.selectedColumn + var ( + getCell = func(row, column int) *TableCell { + if row < 0 || column < 0 || row >= len(t.cells) || column >= len(t.cells[row]) { + return nil + } + return t.cells[row][column] + } + + previous = func() { + for t.selectedRow >= 0 { + cell := getCell(t.selectedRow, t.selectedColumn) + if cell == nil || !cell.NotSelectable { + return + } + t.selectedColumn-- + if t.selectedColumn < 0 { + t.selectedColumn = t.lastColumn + t.selectedRow-- + } + } + } + + next = func() { + if t.selectedColumn > t.lastColumn { + t.selectedColumn = 0 + t.selectedRow++ + if t.selectedRow >= len(t.cells) { + t.selectedRow = len(t.cells) - 1 + } + } + for t.selectedRow < len(t.cells) { + cell := getCell(t.selectedRow, t.selectedColumn) + if cell == nil || !cell.NotSelectable { + return + } + t.selectedColumn++ + if t.selectedColumn > t.lastColumn { + t.selectedColumn = 0 + t.selectedRow++ + } + } + t.selectedColumn = t.lastColumn + t.selectedRow = len(t.cells) - 1 + previous() + } + + home = func() { + if t.rowsSelectable { + t.selectedRow = 0 + t.selectedColumn = 0 + next() + } else { + t.trackEnd = false + t.rowOffset = 0 + t.columnOffset = 0 + } + } + + end = func() { + if t.rowsSelectable { + t.selectedRow = len(t.cells) - 1 + t.selectedColumn = t.lastColumn + previous() + } else { + t.trackEnd = true + t.columnOffset = 0 + } + } + + down = func() { + if t.rowsSelectable { + t.selectedRow++ + if t.selectedRow >= len(t.cells) { + t.selectedRow = len(t.cells) - 1 + } + next() + } else { + t.rowOffset++ + } + } + + up = func() { + if t.rowsSelectable { + t.selectedRow-- + if t.selectedRow < 0 { + t.selectedRow = 0 + } + previous() + } else { + t.trackEnd = false + t.rowOffset-- + } + } + + left = func() { + if t.columnsSelectable { + t.selectedColumn-- + if t.selectedColumn < 0 { + t.selectedColumn = 0 + } + previous() + } else { + t.columnOffset-- + } + } + + right = func() { + if t.columnsSelectable { + t.selectedColumn++ + if t.selectedColumn > t.lastColumn { + t.selectedColumn = t.lastColumn + } + next() + } else { + t.columnOffset++ + } + } + + pageDown = func() { + if t.rowsSelectable { + t.selectedRow += t.visibleRows + if t.selectedRow >= len(t.cells) { + t.selectedRow = len(t.cells) - 1 + } + next() + } else { + t.rowOffset += t.visibleRows + } + } + + pageUp = func() { + if t.rowsSelectable { + t.selectedRow -= t.visibleRows + if t.selectedRow < 0 { + t.selectedRow = 0 + } + previous() + } else { + t.trackEnd = false + t.rowOffset -= t.visibleRows + } + } + ) + + switch key { + case tcell.KeyRune: + switch event.Rune() { + case 'g': + home() + case 'G': + end() + case 'j': + down() + case 'k': + up() + case 'h': + left() + case 'l': + right() + } + case tcell.KeyHome: + home() + case tcell.KeyEnd: + end() + case tcell.KeyUp: + up() + case tcell.KeyDown: + down() + case tcell.KeyLeft: + left() + case tcell.KeyRight: + right() + case tcell.KeyPgDn, tcell.KeyCtrlF: + pageDown() + case tcell.KeyPgUp, tcell.KeyCtrlB: + pageUp() + case tcell.KeyEnter: + if (t.rowsSelectable || t.columnsSelectable) && t.selected != nil { + t.selected(t.selectedRow, t.selectedColumn) + } + } + + // If the selection has changed, notify the handler. + if t.selectionChanged != nil && + (t.rowsSelectable && previouslySelectedRow != t.selectedRow || + t.columnsSelectable && previouslySelectedColumn != t.selectedColumn) { + t.selectionChanged(t.selectedRow, t.selectedColumn) + } + }) +} diff --git a/vendor/github.com/rivo/tview/textview.go b/vendor/github.com/rivo/tview/textview.go new file mode 100644 index 00000000..d49e7bdd --- /dev/null +++ b/vendor/github.com/rivo/tview/textview.go @@ -0,0 +1,967 @@ +package tview + +import ( + "bytes" + "fmt" + "regexp" + "sync" + "unicode" + "unicode/utf8" + + "github.com/gdamore/tcell" + colorful "github.com/lucasb-eyer/go-colorful" + runewidth "github.com/mattn/go-runewidth" +) + +// TabSize is the number of spaces with which a tab character will be replaced. +var TabSize = 4 + +// textViewIndex contains information about each line displayed in the text +// view. +type textViewIndex struct { + Line int // The index into the "buffer" variable. + Pos int // The index into the "buffer" string (byte position). + NextPos int // The (byte) index of the next character in this buffer line. + Width int // The screen width of this line. + ForegroundColor string // The starting foreground color ("" = don't change, "-" = reset). + BackgroundColor string // The starting background color ("" = don't change, "-" = reset). + Attributes string // The starting attributes ("" = don't change, "-" = reset). + Region string // The starting region ID. +} + +// TextView is a box which displays text. It implements the io.Writer interface +// so you can stream text to it. This does not trigger a redraw automatically +// but if a handler is installed via SetChangedFunc(), you can cause it to be +// redrawn. +// +// Navigation +// +// If the text view is scrollable (the default), text is kept in a buffer which +// may be larger than the screen and can be navigated similarly to Vim: +// +// - h, left arrow: Move left. +// - l, right arrow: Move right. +// - j, down arrow: Move down. +// - k, up arrow: Move up. +// - g, home: Move to the top. +// - G, end: Move to the bottom. +// - Ctrl-F, page down: Move down by one page. +// - Ctrl-B, page up: Move up by one page. +// +// If the text is not scrollable, any text above the top visible line is +// discarded. +// +// Use SetInputCapture() to override or modify keyboard input. +// +// Colors +// +// If dynamic colors are enabled via SetDynamicColors(), text color can be +// changed dynamically by embedding color strings in square brackets. This works +// the same way as anywhere else. Please see the package documentation for more +// information. +// +// Regions and Highlights +// +// If regions are enabled via SetRegions(), you can define text regions within +// the text and assign region IDs to them. Text regions start with region tags. +// Region tags are square brackets that contain a region ID in double quotes, +// for example: +// +// We define a ["rg"]region[""] here. +// +// A text region ends with the next region tag. Tags with no region ID ([""]) +// don't start new regions. They can therefore be used to mark the end of a +// region. Region IDs must satisfy the following regular expression: +// +// [a-zA-Z0-9_,;: \-\.]+ +// +// Regions can be highlighted by calling the Highlight() function with one or +// more region IDs. This can be used to display search results, for example. +// +// The ScrollToHighlight() function can be used to jump to the currently +// highlighted region once when the text view is drawn the next time. +// +// See https://github.com/rivo/tview/wiki/TextView for an example. +type TextView struct { + sync.Mutex + *Box + + // The text buffer. + buffer []string + + // The last bytes that have been received but are not part of the buffer yet. + recentBytes []byte + + // The processed line index. This is nil if the buffer has changed and needs + // to be re-indexed. + index []*textViewIndex + + // The text alignment, one of AlignLeft, AlignCenter, or AlignRight. + align int + + // Indices into the "index" slice which correspond to the first line of the + // first highlight and the last line of the last highlight. This is calculated + // during re-indexing. Set to -1 if there is no current highlight. + fromHighlight, toHighlight int + + // A set of region IDs that are currently highlighted. + highlights map[string]struct{} + + // The last width for which the current table is drawn. + lastWidth int + + // The screen width of the longest line in the index (not the buffer). + longestLine int + + // The index of the first line shown in the text view. + lineOffset int + + // If set to true, the text view will always remain at the end of the content. + trackEnd bool + + // The number of characters to be skipped on each line (not in wrap mode). + columnOffset int + + // The height of the content the last time the text view was drawn. + pageSize int + + // If set to true, the text view will keep a buffer of text which can be + // navigated when the text is longer than what fits into the box. + scrollable bool + + // If set to true, lines that are longer than the available width are wrapped + // onto the next line. If set to false, any characters beyond the available + // width are discarded. + wrap bool + + // If set to true and if wrap is also true, lines are split at spaces or + // after punctuation characters. + wordWrap bool + + // The (starting) color of the text. + textColor tcell.Color + + // If set to true, the text color can be changed dynamically by piping color + // strings in square brackets to the text view. + dynamicColors bool + + // If set to true, region tags can be used to define regions. + regions bool + + // A temporary flag which, when true, will automatically bring the current + // highlight(s) into the visible screen. + scrollToHighlights bool + + // An optional function which is called when the content of the text view has + // changed. + changed func() + + // An optional function which is called when the user presses one of the + // following keys: Escape, Enter, Tab, Backtab. + done func(tcell.Key) +} + +// NewTextView returns a new text view. +func NewTextView() *TextView { + return &TextView{ + Box: NewBox(), + highlights: make(map[string]struct{}), + lineOffset: -1, + scrollable: true, + align: AlignLeft, + wrap: true, + textColor: Styles.PrimaryTextColor, + dynamicColors: false, + } +} + +// SetScrollable sets the flag that decides whether or not the text view is +// scrollable. If true, text is kept in a buffer and can be navigated. +func (t *TextView) SetScrollable(scrollable bool) *TextView { + t.scrollable = scrollable + if !scrollable { + t.trackEnd = true + } + return t +} + +// SetWrap sets the flag that, if true, leads to lines that are longer than the +// available width being wrapped onto the next line. If false, any characters +// beyond the available width are not displayed. +func (t *TextView) SetWrap(wrap bool) *TextView { + if t.wrap != wrap { + t.index = nil + } + t.wrap = wrap + return t +} + +// SetWordWrap sets the flag that, if true and if the "wrap" flag is also true +// (see SetWrap()), wraps the line at spaces or after punctuation marks. Note +// that trailing spaces will not be printed. +// +// This flag is ignored if the "wrap" flag is false. +func (t *TextView) SetWordWrap(wrapOnWords bool) *TextView { + if t.wordWrap != wrapOnWords { + t.index = nil + } + t.wordWrap = wrapOnWords + return t +} + +// SetTextAlign sets the text alignment within the text view. This must be +// either AlignLeft, AlignCenter, or AlignRight. +func (t *TextView) SetTextAlign(align int) *TextView { + if t.align != align { + t.index = nil + } + t.align = align + return t +} + +// SetTextColor sets the initial color of the text (which can be changed +// dynamically by sending color strings in square brackets to the text view if +// dynamic colors are enabled). +func (t *TextView) SetTextColor(color tcell.Color) *TextView { + t.textColor = color + return t +} + +// SetText sets the text of this text view to the provided string. Previously +// contained text will be removed. +func (t *TextView) SetText(text string) *TextView { + t.Clear() + fmt.Fprint(t, text) + return t +} + +// SetDynamicColors sets the flag that allows the text color to be changed +// dynamically. See class description for details. +func (t *TextView) SetDynamicColors(dynamic bool) *TextView { + if t.dynamicColors != dynamic { + t.index = nil + } + t.dynamicColors = dynamic + return t +} + +// SetRegions sets the flag that allows to define regions in the text. See class +// description for details. +func (t *TextView) SetRegions(regions bool) *TextView { + if t.regions != regions { + t.index = nil + } + t.regions = regions + return t +} + +// SetChangedFunc sets a handler function which is called when the text of the +// text view has changed. This is typically used to cause the application to +// redraw the screen. +func (t *TextView) SetChangedFunc(handler func()) *TextView { + t.changed = handler + return t +} + +// SetDoneFunc sets a handler which is called when the user presses on the +// following keys: Escape, Enter, Tab, Backtab. The key is passed to the +// handler. +func (t *TextView) SetDoneFunc(handler func(key tcell.Key)) *TextView { + t.done = handler + return t +} + +// ScrollTo scrolls to the specified row and column (both starting with 0). +func (t *TextView) ScrollTo(row, column int) *TextView { + if !t.scrollable { + return t + } + t.lineOffset = row + t.columnOffset = column + return t +} + +// ScrollToBeginning scrolls to the top left corner of the text if the text view +// is scrollable. +func (t *TextView) ScrollToBeginning() *TextView { + if !t.scrollable { + return t + } + t.trackEnd = false + t.lineOffset = 0 + t.columnOffset = 0 + return t +} + +// ScrollToEnd scrolls to the bottom left corner of the text if the text view +// is scrollable. Adding new rows to the end of the text view will cause it to +// scroll with the new data. +func (t *TextView) ScrollToEnd() *TextView { + if !t.scrollable { + return t + } + t.trackEnd = true + t.columnOffset = 0 + return t +} + +// Clear removes all text from the buffer. +func (t *TextView) Clear() *TextView { + t.buffer = nil + t.recentBytes = nil + t.index = nil + return t +} + +// Highlight specifies which regions should be highlighted. See class +// description for details on regions. Empty region strings are ignored. +// +// Text in highlighted regions will be drawn inverted, i.e. with their +// background and foreground colors swapped. +// +// Calling this function will remove any previous highlights. To remove all +// highlights, call this function without any arguments. +func (t *TextView) Highlight(regionIDs ...string) *TextView { + t.highlights = make(map[string]struct{}) + for _, id := range regionIDs { + if id == "" { + continue + } + t.highlights[id] = struct{}{} + } + t.index = nil + return t +} + +// GetHighlights returns the IDs of all currently highlighted regions. +func (t *TextView) GetHighlights() (regionIDs []string) { + for id := range t.highlights { + regionIDs = append(regionIDs, id) + } + return +} + +// ScrollToHighlight will cause the visible area to be scrolled so that the +// highlighted regions appear in the visible area of the text view. This +// repositioning happens the next time the text view is drawn. It happens only +// once so you will need to call this function repeatedly to always keep +// highlighted regions in view. +// +// Nothing happens if there are no highlighted regions or if the text view is +// not scrollable. +func (t *TextView) ScrollToHighlight() *TextView { + if len(t.highlights) == 0 || !t.scrollable || !t.regions { + return t + } + t.index = nil + t.scrollToHighlights = true + t.trackEnd = false + return t +} + +// GetRegionText returns the text of the region with the given ID. If dynamic +// colors are enabled, color tags are stripped from the text. Newlines are +// always returned as '\n' runes. +// +// If the region does not exist or if regions are turned off, an empty string +// is returned. +func (t *TextView) GetRegionText(regionID string) string { + if !t.regions || regionID == "" { + return "" + } + + var ( + buffer bytes.Buffer + currentRegionID string + ) + + for _, str := range t.buffer { + // Find all color tags in this line. + var colorTagIndices [][]int + if t.dynamicColors { + colorTagIndices = colorPattern.FindAllStringIndex(str, -1) + } + + // Find all regions in this line. + var ( + regionIndices [][]int + regions [][]string + ) + if t.regions { + regionIndices = regionPattern.FindAllStringIndex(str, -1) + regions = regionPattern.FindAllStringSubmatch(str, -1) + } + + // Analyze this line. + var currentTag, currentRegion int + for pos, ch := range str { + // Skip any color tags. + if currentTag < len(colorTagIndices) && pos >= colorTagIndices[currentTag][0] && pos < colorTagIndices[currentTag][1] { + if pos == colorTagIndices[currentTag][1]-1 { + currentTag++ + } + continue + } + + // Skip any regions. + if currentRegion < len(regionIndices) && pos >= regionIndices[currentRegion][0] && pos < regionIndices[currentRegion][1] { + if pos == regionIndices[currentRegion][1]-1 { + if currentRegionID == regionID { + // This is the end of the requested region. We're done. + return buffer.String() + } + currentRegionID = regions[currentRegion][1] + currentRegion++ + } + continue + } + + // Add this rune. + if currentRegionID == regionID { + buffer.WriteRune(ch) + } + } + + // Add newline. + if currentRegionID == regionID { + buffer.WriteRune('\n') + } + } + + return escapePattern.ReplaceAllString(buffer.String(), `[$1$2]`) +} + +// Write lets us implement the io.Writer interface. Tab characters will be +// replaced with TabSize space characters. A "\n" or "\r\n" will be interpreted +// as a new line. +func (t *TextView) Write(p []byte) (n int, err error) { + // Notify at the end. + if t.changed != nil { + defer t.changed() + } + + t.Lock() + defer t.Unlock() + + // Copy data over. + newBytes := append(t.recentBytes, p...) + t.recentBytes = nil + + // If we have a trailing invalid UTF-8 byte, we'll wait. + if r, _ := utf8.DecodeLastRune(p); r == utf8.RuneError { + t.recentBytes = newBytes + return len(p), nil + } + + // If we have a trailing open dynamic color, exclude it. + if t.dynamicColors { + openColor := regexp.MustCompile(`\[([a-zA-Z]*|#[0-9a-zA-Z]*)$`) + location := openColor.FindIndex(newBytes) + if location != nil { + t.recentBytes = newBytes[location[0]:] + newBytes = newBytes[:location[0]] + } + } + + // If we have a trailing open region, exclude it. + if t.regions { + openRegion := regexp.MustCompile(`\["[a-zA-Z0-9_,;: \-\.]*"?$`) + location := openRegion.FindIndex(newBytes) + if location != nil { + t.recentBytes = newBytes[location[0]:] + newBytes = newBytes[:location[0]] + } + } + + // Transform the new bytes into strings. + newLine := regexp.MustCompile(`\r?\n`) + newBytes = bytes.Replace(newBytes, []byte{'\t'}, bytes.Repeat([]byte{' '}, TabSize), -1) + for index, line := range newLine.Split(string(newBytes), -1) { + if index == 0 { + if len(t.buffer) == 0 { + t.buffer = []string{line} + } else { + t.buffer[len(t.buffer)-1] += line + } + } else { + t.buffer = append(t.buffer, line) + } + } + + // Reset the index. + t.index = nil + + return len(p), nil +} + +// reindexBuffer re-indexes the buffer such that we can use it to easily draw +// the buffer onto the screen. Each line in the index will contain a pointer +// into the buffer from which on we will print text. It will also contain the +// color with which the line starts. +func (t *TextView) reindexBuffer(width int) { + if t.index != nil { + return // Nothing has changed. We can still use the current index. + } + t.index = nil + t.fromHighlight, t.toHighlight = -1, -1 + + // If there's no space, there's no index. + if width < 1 { + return + } + + // Initial states. + regionID := "" + var highlighted bool + + // Go through each line in the buffer. + for bufferIndex, str := range t.buffer { + // Find all color tags in this line. Then remove them. + var ( + colorTagIndices [][]int + colorTags [][]string + escapeIndices [][]int + ) + if t.dynamicColors { + colorTagIndices, colorTags, escapeIndices, str, _ = decomposeString(str) + } + + // Find all regions in this line. Then remove them. + var ( + regionIndices [][]int + regions [][]string + ) + if t.regions { + regionIndices = regionPattern.FindAllStringIndex(str, -1) + regions = regionPattern.FindAllStringSubmatch(str, -1) + str = regionPattern.ReplaceAllString(str, "") + if !t.dynamicColors { + // We haven't detected escape tags yet. Do it now. + escapeIndices = escapePattern.FindAllStringIndex(str, -1) + str = escapePattern.ReplaceAllString(str, "[$1$2]") + } + } + + // Split the line if required. + var splitLines []string + if t.wrap && len(str) > 0 { + for len(str) > 0 { + extract := runewidth.Truncate(str, width, "") + if t.wordWrap && len(extract) < len(str) { + // Add any spaces from the next line. + if spaces := spacePattern.FindStringIndex(str[len(extract):]); spaces != nil && spaces[0] == 0 { + extract = str[:len(extract)+spaces[1]] + } + + // Can we split before the mandatory end? + matches := boundaryPattern.FindAllStringIndex(extract, -1) + if len(matches) > 0 { + // Yes. Let's split there. + extract = extract[:matches[len(matches)-1][1]] + } + } + splitLines = append(splitLines, extract) + str = str[len(extract):] + } + } else { + // No need to split the line. + splitLines = []string{str} + } + + // Create index from split lines. + var ( + originalPos, colorPos, regionPos, escapePos int + foregroundColor, backgroundColor, attributes string + ) + for _, splitLine := range splitLines { + line := &textViewIndex{ + Line: bufferIndex, + Pos: originalPos, + ForegroundColor: foregroundColor, + BackgroundColor: backgroundColor, + Attributes: attributes, + Region: regionID, + } + + // Shift original position with tags. + lineLength := len(splitLine) + for { + if colorPos < len(colorTagIndices) && colorTagIndices[colorPos][0] <= originalPos+lineLength { + // Process color tags. + originalPos += colorTagIndices[colorPos][1] - colorTagIndices[colorPos][0] + foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colorTags[colorPos]) + colorPos++ + } else if regionPos < len(regionIndices) && regionIndices[regionPos][0] <= originalPos+lineLength { + // Process region tags. + originalPos += regionIndices[regionPos][1] - regionIndices[regionPos][0] + regionID = regions[regionPos][1] + _, highlighted = t.highlights[regionID] + + // Update highlight range. + if highlighted { + line := len(t.index) + if t.fromHighlight < 0 { + t.fromHighlight, t.toHighlight = line, line + } else if line > t.toHighlight { + t.toHighlight = line + } + } + + regionPos++ + } else if escapePos < len(escapeIndices) && escapeIndices[escapePos][0] <= originalPos+lineLength { + // Process escape tags. + originalPos++ + escapePos++ + } else { + break + } + } + + // Advance to next line. + originalPos += lineLength + + // Append this line. + line.NextPos = originalPos + line.Width = runewidth.StringWidth(splitLine) + t.index = append(t.index, line) + } + + // Word-wrapped lines may have trailing whitespace. Remove it. + if t.wrap && t.wordWrap { + for _, line := range t.index { + str := t.buffer[line.Line][line.Pos:line.NextPos] + spaces := spacePattern.FindAllStringIndex(str, -1) + if spaces != nil && spaces[len(spaces)-1][1] == len(str) { + oldNextPos := line.NextPos + line.NextPos -= spaces[len(spaces)-1][1] - spaces[len(spaces)-1][0] + line.Width -= runewidth.StringWidth(t.buffer[line.Line][line.NextPos:oldNextPos]) + } + } + } + } + + // Calculate longest line. + t.longestLine = 0 + for _, line := range t.index { + if line.Width > t.longestLine { + t.longestLine = line.Width + } + } +} + +// Draw draws this primitive onto the screen. +func (t *TextView) Draw(screen tcell.Screen) { + t.Lock() + defer t.Unlock() + t.Box.Draw(screen) + + // Get the available size. + x, y, width, height := t.GetInnerRect() + t.pageSize = height + + // If the width has changed, we need to reindex. + if width != t.lastWidth && t.wrap { + t.index = nil + } + t.lastWidth = width + + // Re-index. + t.reindexBuffer(width) + + // If we don't have an index, there's nothing to draw. + if t.index == nil { + return + } + + // Move to highlighted regions. + if t.regions && t.scrollToHighlights && t.fromHighlight >= 0 { + // Do we fit the entire height? + if t.toHighlight-t.fromHighlight+1 < height { + // Yes, let's center the highlights. + t.lineOffset = (t.fromHighlight + t.toHighlight - height) / 2 + } else { + // No, let's move to the start of the highlights. + t.lineOffset = t.fromHighlight + } + } + t.scrollToHighlights = false + + // Adjust line offset. + if t.lineOffset+height > len(t.index) { + t.trackEnd = true + } + if t.trackEnd { + t.lineOffset = len(t.index) - height + } + if t.lineOffset < 0 { + t.lineOffset = 0 + } + + // Adjust column offset. + if t.align == AlignLeft { + if t.columnOffset+width > t.longestLine { + t.columnOffset = t.longestLine - width + } + if t.columnOffset < 0 { + t.columnOffset = 0 + } + } else if t.align == AlignRight { + if t.columnOffset-width < -t.longestLine { + t.columnOffset = width - t.longestLine + } + if t.columnOffset > 0 { + t.columnOffset = 0 + } + } else { // AlignCenter. + half := (t.longestLine - width) / 2 + if half > 0 { + if t.columnOffset > half { + t.columnOffset = half + } + if t.columnOffset < -half { + t.columnOffset = -half + } + } else { + t.columnOffset = 0 + } + } + + // Draw the buffer. + defaultStyle := tcell.StyleDefault.Foreground(t.textColor) + for line := t.lineOffset; line < len(t.index); line++ { + // Are we done? + if line-t.lineOffset >= height { + break + } + + // Get the text for this line. + index := t.index[line] + text := t.buffer[index.Line][index.Pos:index.NextPos] + foregroundColor := index.ForegroundColor + backgroundColor := index.BackgroundColor + attributes := index.Attributes + regionID := index.Region + + // Get color tags. + var ( + colorTagIndices [][]int + colorTags [][]string + escapeIndices [][]int + ) + if t.dynamicColors { + colorTagIndices, colorTags, escapeIndices, _, _ = decomposeString(text) + } + + // Get regions. + var ( + regionIndices [][]int + regions [][]string + ) + if t.regions { + regionIndices = regionPattern.FindAllStringIndex(text, -1) + regions = regionPattern.FindAllStringSubmatch(text, -1) + if !t.dynamicColors { + escapeIndices = escapePattern.FindAllStringIndex(text, -1) + } + } + + // Calculate the position of the line. + var skip, posX int + if t.align == AlignLeft { + posX = -t.columnOffset + } else if t.align == AlignRight { + posX = width - index.Width - t.columnOffset + } else { // AlignCenter. + posX = (width-index.Width)/2 - t.columnOffset + } + if posX < 0 { + skip = -posX + posX = 0 + } + + // Print the line. + var currentTag, currentRegion, currentEscapeTag, skipped, runeSeqWidth int + runeSequence := make([]rune, 0, 10) + flush := func() { + if len(runeSequence) == 0 { + return + } + + // Mix the existing style with the new style. + _, _, existingStyle, _ := screen.GetContent(x+posX, y+line-t.lineOffset) + _, background, _ := existingStyle.Decompose() + style := overlayStyle(background, defaultStyle, foregroundColor, backgroundColor, attributes) + + // Do we highlight this character? + var highlighted bool + if len(regionID) > 0 { + if _, ok := t.highlights[regionID]; ok { + highlighted = true + } + } + if highlighted { + fg, bg, _ := style.Decompose() + if bg == tcell.ColorDefault { + r, g, b := fg.RGB() + c := colorful.Color{R: float64(r) / 255, G: float64(g) / 255, B: float64(b) / 255} + _, _, li := c.Hcl() + if li < .5 { + bg = tcell.ColorWhite + } else { + bg = tcell.ColorBlack + } + } + style = style.Background(fg).Foreground(bg) + } + + // Draw the character. + var comb []rune + if len(runeSequence) > 1 && !unicode.IsControl(runeSequence[1]) { + // Allocate space for the combining characters only when necessary. + comb = make([]rune, len(runeSequence)-1) + copy(comb, runeSequence[1:]) + } + for offset := 0; offset < runeSeqWidth; offset++ { + screen.SetContent(x+posX+offset, y+line-t.lineOffset, runeSequence[0], comb, style) + } + + // Advance. + posX += runeSeqWidth + runeSequence = runeSequence[:0] + runeSeqWidth = 0 + } + for pos, ch := range text { + // Get the color. + if currentTag < len(colorTags) && pos >= colorTagIndices[currentTag][0] && pos < colorTagIndices[currentTag][1] { + flush() + if pos == colorTagIndices[currentTag][1]-1 { + foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colorTags[currentTag]) + currentTag++ + } + continue + } + + // Get the region. + if currentRegion < len(regionIndices) && pos >= regionIndices[currentRegion][0] && pos < regionIndices[currentRegion][1] { + flush() + if pos == regionIndices[currentRegion][1]-1 { + regionID = regions[currentRegion][1] + currentRegion++ + } + continue + } + + // Skip the second-to-last character of an escape tag. + if currentEscapeTag < len(escapeIndices) && pos >= escapeIndices[currentEscapeTag][0] && pos < escapeIndices[currentEscapeTag][1] { + flush() + if pos == escapeIndices[currentEscapeTag][1]-1 { + currentEscapeTag++ + } else if pos == escapeIndices[currentEscapeTag][1]-2 { + continue + } + } + + // Determine the width of this rune. + chWidth := runewidth.RuneWidth(ch) + if chWidth == 0 { + // If this is not a modifier, we treat it as a space character. + if len(runeSequence) == 0 { + ch = ' ' + chWidth = 1 + } else { + runeSequence = append(runeSequence, ch) + continue + } + } + + // Skip to the right. + if !t.wrap && skipped < skip { + skipped += chWidth + continue + } + + // Stop at the right border. + if posX+runeSeqWidth+chWidth > width { + break + } + + // Flush the rune sequence. + flush() + + // Queue this rune. + runeSequence = append(runeSequence, ch) + runeSeqWidth += chWidth + } + if posX+runeSeqWidth <= width { + flush() + } + } + + // If this view is not scrollable, we'll purge the buffer of lines that have + // scrolled out of view. + if !t.scrollable && t.lineOffset > 0 { + t.buffer = t.buffer[t.index[t.lineOffset].Line:] + t.index = nil + } +} + +// InputHandler returns the handler for this primitive. +func (t *TextView) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { + return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { + key := event.Key() + + if key == tcell.KeyEscape || key == tcell.KeyEnter || key == tcell.KeyTab || key == tcell.KeyBacktab { + if t.done != nil { + t.done(key) + } + return + } + + if !t.scrollable { + return + } + + switch key { + case tcell.KeyRune: + switch event.Rune() { + case 'g': // Home. + t.trackEnd = false + t.lineOffset = 0 + t.columnOffset = 0 + case 'G': // End. + t.trackEnd = true + t.columnOffset = 0 + case 'j': // Down. + t.lineOffset++ + case 'k': // Up. + t.trackEnd = false + t.lineOffset-- + case 'h': // Left. + t.columnOffset-- + case 'l': // Right. + t.columnOffset++ + } + case tcell.KeyHome: + t.trackEnd = false + t.lineOffset = 0 + t.columnOffset = 0 + case tcell.KeyEnd: + t.trackEnd = true + t.columnOffset = 0 + case tcell.KeyUp: + t.trackEnd = false + t.lineOffset-- + case tcell.KeyDown: + t.lineOffset++ + case tcell.KeyLeft: + t.columnOffset-- + case tcell.KeyRight: + t.columnOffset++ + case tcell.KeyPgDn, tcell.KeyCtrlF: + t.lineOffset += t.pageSize + case tcell.KeyPgUp, tcell.KeyCtrlB: + t.trackEnd = false + t.lineOffset -= t.pageSize + } + }) +} diff --git a/vendor/github.com/rivo/tview/tview.gif b/vendor/github.com/rivo/tview/tview.gif new file mode 100644 index 00000000..0583d7b9 Binary files /dev/null and b/vendor/github.com/rivo/tview/tview.gif differ diff --git a/vendor/github.com/rivo/tview/util.go b/vendor/github.com/rivo/tview/util.go new file mode 100644 index 00000000..7ac8f74f --- /dev/null +++ b/vendor/github.com/rivo/tview/util.go @@ -0,0 +1,534 @@ +package tview + +import ( + "fmt" + "math" + "regexp" + "strconv" + "strings" + "unicode" + + "github.com/gdamore/tcell" + runewidth "github.com/mattn/go-runewidth" +) + +// Text alignment within a box. +const ( + AlignLeft = iota + AlignCenter + AlignRight +) + +// Common regular expressions. +var ( + colorPattern = regexp.MustCompile(`\[([a-zA-Z]+|#[0-9a-zA-Z]{6}|\-)?(:([a-zA-Z]+|#[0-9a-zA-Z]{6}|\-)?(:([lbdru]+|\-)?)?)?\]`) + regionPattern = regexp.MustCompile(`\["([a-zA-Z0-9_,;: \-\.]*)"\]`) + escapePattern = regexp.MustCompile(`\[([a-zA-Z0-9_,;: \-\."#]+)\[(\[*)\]`) + nonEscapePattern = regexp.MustCompile(`(\[[a-zA-Z0-9_,;: \-\."#]+\[*)\]`) + boundaryPattern = regexp.MustCompile("([[:punct:]]\\s*|\\s+)") + spacePattern = regexp.MustCompile(`\s+`) +) + +// Positions of substrings in regular expressions. +const ( + colorForegroundPos = 1 + colorBackgroundPos = 3 + colorFlagPos = 5 +) + +// Predefined InputField acceptance functions. +var ( + // InputFieldInteger accepts integers. + InputFieldInteger func(text string, ch rune) bool + + // InputFieldFloat accepts floating-point numbers. + InputFieldFloat func(text string, ch rune) bool + + // InputFieldMaxLength returns an input field accept handler which accepts + // input strings up to a given length. Use it like this: + // + // inputField.SetAcceptanceFunc(InputFieldMaxLength(10)) // Accept up to 10 characters. + InputFieldMaxLength func(maxLength int) func(text string, ch rune) bool +) + +// Package initialization. +func init() { + // Initialize the predefined input field handlers. + InputFieldInteger = func(text string, ch rune) bool { + if text == "-" { + return true + } + _, err := strconv.Atoi(text) + return err == nil + } + InputFieldFloat = func(text string, ch rune) bool { + if text == "-" || text == "." || text == "-." { + return true + } + _, err := strconv.ParseFloat(text, 64) + return err == nil + } + InputFieldMaxLength = func(maxLength int) func(text string, ch rune) bool { + return func(text string, ch rune) bool { + return len([]rune(text)) <= maxLength + } + } +} + +// styleFromTag takes the given style, defined by a foreground color (fgColor), +// a background color (bgColor), and style attributes, and modifies it based on +// the substrings (tagSubstrings) extracted by the regular expression for color +// tags. The new colors and attributes are returned where empty strings mean +// "don't modify" and a dash ("-") means "reset to default". +func styleFromTag(fgColor, bgColor, attributes string, tagSubstrings []string) (newFgColor, newBgColor, newAttributes string) { + if tagSubstrings[colorForegroundPos] != "" { + color := tagSubstrings[colorForegroundPos] + if color == "-" { + fgColor = "-" + } else if color != "" { + fgColor = color + } + } + + if tagSubstrings[colorBackgroundPos-1] != "" { + color := tagSubstrings[colorBackgroundPos] + if color == "-" { + bgColor = "-" + } else if color != "" { + bgColor = color + } + } + + if tagSubstrings[colorFlagPos-1] != "" { + flags := tagSubstrings[colorFlagPos] + if flags == "-" { + attributes = "-" + } else if flags != "" { + attributes = flags + } + } + + return fgColor, bgColor, attributes +} + +// overlayStyle mixes a background color with a foreground color (fgColor), +// a (possibly new) background color (bgColor), and style attributes, and +// returns the resulting style. For a definition of the colors and attributes, +// see styleFromTag(). Reset instructions cause the corresponding part of the +// default style to be used. +func overlayStyle(background tcell.Color, defaultStyle tcell.Style, fgColor, bgColor, attributes string) tcell.Style { + defFg, defBg, defAttr := defaultStyle.Decompose() + style := defaultStyle.Background(background) + + if fgColor == "-" { + style = style.Foreground(defFg) + } else if fgColor != "" { + style = style.Foreground(tcell.GetColor(fgColor)) + } + + if bgColor == "-" { + style = style.Background(defBg) + } else if bgColor != "" { + style = style.Background(tcell.GetColor(bgColor)) + } + + if attributes == "-" { + style = style.Bold(defAttr&tcell.AttrBold > 0) + style = style.Blink(defAttr&tcell.AttrBlink > 0) + style = style.Reverse(defAttr&tcell.AttrReverse > 0) + style = style.Underline(defAttr&tcell.AttrUnderline > 0) + style = style.Dim(defAttr&tcell.AttrDim > 0) + } else if attributes != "" { + style = style.Normal() + for _, flag := range attributes { + switch flag { + case 'l': + style = style.Blink(true) + case 'b': + style = style.Bold(true) + case 'd': + style = style.Dim(true) + case 'r': + style = style.Reverse(true) + case 'u': + style = style.Underline(true) + } + } + } + + return style +} + +// decomposeString returns information about a string which may contain color +// tags. It returns the indices of the color tags (as returned by +// re.FindAllStringIndex()), the color tags themselves (as returned by +// re.FindAllStringSubmatch()), the indices of an escaped tags, the string +// stripped by any color tags and escaped, and the screen width of the stripped +// string. +func decomposeString(text string) (colorIndices [][]int, colors [][]string, escapeIndices [][]int, stripped string, width int) { + // Get positions of color and escape tags. + colorIndices = colorPattern.FindAllStringIndex(text, -1) + colors = colorPattern.FindAllStringSubmatch(text, -1) + escapeIndices = escapePattern.FindAllStringIndex(text, -1) + + // Because the color pattern detects empty tags, we need to filter them out. + for i := len(colorIndices) - 1; i >= 0; i-- { + if colorIndices[i][1]-colorIndices[i][0] == 2 { + colorIndices = append(colorIndices[:i], colorIndices[i+1:]...) + colors = append(colors[:i], colors[i+1:]...) + } + } + + // Remove the color tags from the original string. + var from int + buf := make([]byte, 0, len(text)) + for _, indices := range colorIndices { + buf = append(buf, []byte(text[from:indices[0]])...) + from = indices[1] + } + buf = append(buf, text[from:]...) + + // Escape string. + stripped = string(escapePattern.ReplaceAll(buf, []byte("[$1$2]"))) + + // Get the width of the stripped string. + width = runewidth.StringWidth(stripped) + + return +} + +// Print prints text onto the screen into the given box at (x,y,maxWidth,1), +// not exceeding that box. "align" is one of AlignLeft, AlignCenter, or +// AlignRight. The screen's background color will not be changed. +// +// You can change the colors and text styles mid-text by inserting a color tag. +// See the package description for details. +// +// Returns the number of actual runes printed (not including color tags) and the +// actual width used for the printed runes. +func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tcell.Color) (int, int) { + return printWithStyle(screen, text, x, y, maxWidth, align, tcell.StyleDefault.Foreground(color)) +} + +// printWithStyle works like Print() but it takes a style instead of just a +// foreground color. +func printWithStyle(screen tcell.Screen, text string, x, y, maxWidth, align int, style tcell.Style) (int, int) { + if maxWidth <= 0 || len(text) == 0 { + return 0, 0 + } + + // Decompose the text. + colorIndices, colors, escapeIndices, strippedText, _ := decomposeString(text) + + // We deal with runes, not with bytes. + runes := []rune(strippedText) + + // This helper function takes positions for a substring of "runes" and returns + // a new string corresponding to this substring, making sure printing that + // substring will observe color tags. + substring := func(from, to int) string { + var ( + colorPos, escapePos, runePos, startPos int + foregroundColor, backgroundColor, attributes string + ) + if from >= len(runes) { + return "" + } + for pos := range text { + // Handle color tags. + if colorPos < len(colorIndices) && pos >= colorIndices[colorPos][0] && pos < colorIndices[colorPos][1] { + if pos == colorIndices[colorPos][1]-1 { + if runePos <= from { + foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colors[colorPos]) + } + colorPos++ + } + continue + } + + // Handle escape tags. + if escapePos < len(escapeIndices) && pos >= escapeIndices[escapePos][0] && pos < escapeIndices[escapePos][1] { + if pos == escapeIndices[escapePos][1]-1 { + escapePos++ + } else if pos == escapeIndices[escapePos][1]-2 { + continue + } + } + + // Check boundaries. + if runePos == from { + startPos = pos + } else if runePos >= to { + return fmt.Sprintf(`[%s:%s:%s]%s`, foregroundColor, backgroundColor, attributes, text[startPos:pos]) + } + + runePos++ + } + + return fmt.Sprintf(`[%s:%s:%s]%s`, foregroundColor, backgroundColor, attributes, text[startPos:]) + } + + // We want to reduce everything to AlignLeft. + if align == AlignRight { + width := 0 + start := len(runes) + for index := start - 1; index >= 0; index-- { + w := runewidth.RuneWidth(runes[index]) + if width+w > maxWidth { + break + } + width += w + start = index + } + for start < len(runes) && runewidth.RuneWidth(runes[start]) == 0 { + start++ + } + return printWithStyle(screen, substring(start, len(runes)), x+maxWidth-width, y, width, AlignLeft, style) + } else if align == AlignCenter { + width := runewidth.StringWidth(strippedText) + if width == maxWidth { + // Use the exact space. + return printWithStyle(screen, text, x, y, maxWidth, AlignLeft, style) + } else if width < maxWidth { + // We have more space than we need. + half := (maxWidth - width) / 2 + return printWithStyle(screen, text, x+half, y, maxWidth-half, AlignLeft, style) + } else { + // Chop off runes until we have a perfect fit. + var choppedLeft, choppedRight, leftIndex, rightIndex int + rightIndex = len(runes) - 1 + for rightIndex > leftIndex && width-choppedLeft-choppedRight > maxWidth { + if choppedLeft < choppedRight { + leftWidth := runewidth.RuneWidth(runes[leftIndex]) + choppedLeft += leftWidth + leftIndex++ + for leftIndex < len(runes) && leftIndex < rightIndex && runewidth.RuneWidth(runes[leftIndex]) == 0 { + leftIndex++ + } + } else { + rightWidth := runewidth.RuneWidth(runes[rightIndex]) + choppedRight += rightWidth + rightIndex-- + } + } + return printWithStyle(screen, substring(leftIndex, rightIndex), x, y, maxWidth, AlignLeft, style) + } + } + + // Draw text. + drawn := 0 + drawnWidth := 0 + var ( + colorPos, escapePos int + foregroundColor, backgroundColor, attributes string + ) + runeSequence := make([]rune, 0, 10) + runeSeqWidth := 0 + flush := func() { + if len(runeSequence) == 0 { + return // Nothing to flush. + } + + // Print the rune sequence. + finalX := x + drawnWidth + _, _, finalStyle, _ := screen.GetContent(finalX, y) + _, background, _ := finalStyle.Decompose() + finalStyle = overlayStyle(background, style, foregroundColor, backgroundColor, attributes) + var comb []rune + if len(runeSequence) > 1 && !unicode.IsControl(runeSequence[1]) { + // Allocate space for the combining characters only when necessary. + comb = make([]rune, len(runeSequence)-1) + copy(comb, runeSequence[1:]) + } + for offset := 0; offset < runeSeqWidth; offset++ { + // To avoid undesired effects, we place the same character in all cells. + screen.SetContent(finalX+offset, y, runeSequence[0], comb, finalStyle) + } + + // Advance and reset. + drawn += len(runeSequence) + drawnWidth += runeSeqWidth + runeSequence = runeSequence[:0] + runeSeqWidth = 0 + } + for pos, ch := range text { + // Handle color tags. + if colorPos < len(colorIndices) && pos >= colorIndices[colorPos][0] && pos < colorIndices[colorPos][1] { + flush() + if pos == colorIndices[colorPos][1]-1 { + foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colors[colorPos]) + colorPos++ + } + continue + } + + // Handle escape tags. + if escapePos < len(escapeIndices) && pos >= escapeIndices[escapePos][0] && pos < escapeIndices[escapePos][1] { + flush() + if pos == escapeIndices[escapePos][1]-1 { + escapePos++ + } else if pos == escapeIndices[escapePos][1]-2 { + continue + } + } + + // Check if we have enough space for this rune. + chWidth := runewidth.RuneWidth(ch) + if drawnWidth+chWidth > maxWidth { + break // No. We're done then. + } + + // Put this rune in the queue. + if chWidth == 0 { + // If this is not a modifier, we treat it as a space character. + if len(runeSequence) == 0 { + ch = ' ' + chWidth = 1 + } + } else { + // We have a character. Flush all previous runes. + flush() + } + runeSequence = append(runeSequence, ch) + runeSeqWidth += chWidth + } + if drawnWidth+runeSeqWidth <= maxWidth { + flush() + } + + return drawn, drawnWidth +} + +// PrintSimple prints white text to the screen at the given position. +func PrintSimple(screen tcell.Screen, text string, x, y int) { + Print(screen, text, x, y, math.MaxInt32, AlignLeft, Styles.PrimaryTextColor) +} + +// StringWidth returns the width of the given string needed to print it on +// screen. The text may contain color tags which are not counted. +func StringWidth(text string) int { + _, _, _, _, width := decomposeString(text) + return width +} + +// WordWrap splits a text such that each resulting line does not exceed the +// given screen width. Possible split points are after any punctuation or +// whitespace. Whitespace after split points will be dropped. +// +// This function considers color tags to have no width. +// +// Text is always split at newline characters ('\n'). +func WordWrap(text string, width int) (lines []string) { + colorTagIndices, _, escapeIndices, strippedText, _ := decomposeString(text) + + // Find candidate breakpoints. + breakPoints := boundaryPattern.FindAllStringIndex(strippedText, -1) + + // This helper function adds a new line to the result slice. The provided + // positions are in stripped index space. + addLine := func(from, to int) { + // Shift indices back to original index space. + var colorTagIndex, escapeIndex int + for colorTagIndex < len(colorTagIndices) && to >= colorTagIndices[colorTagIndex][0] || + escapeIndex < len(escapeIndices) && to >= escapeIndices[escapeIndex][0] { + past := 0 + if colorTagIndex < len(colorTagIndices) { + tagWidth := colorTagIndices[colorTagIndex][1] - colorTagIndices[colorTagIndex][0] + if colorTagIndices[colorTagIndex][0] < from { + from += tagWidth + to += tagWidth + colorTagIndex++ + } else if colorTagIndices[colorTagIndex][0] < to { + to += tagWidth + colorTagIndex++ + } else { + past++ + } + } else { + past++ + } + if escapeIndex < len(escapeIndices) { + tagWidth := escapeIndices[escapeIndex][1] - escapeIndices[escapeIndex][0] + if escapeIndices[escapeIndex][0] < from { + from += tagWidth + to += tagWidth + escapeIndex++ + } else if escapeIndices[escapeIndex][0] < to { + to += tagWidth + escapeIndex++ + } else { + past++ + } + } else { + past++ + } + if past == 2 { + break // All other indices are beyond the requested string. + } + } + lines = append(lines, text[from:to]) + } + + // Determine final breakpoints. + var start, lastEnd, newStart, breakPoint int + for { + // What's our candidate string? + var candidate string + if breakPoint < len(breakPoints) { + candidate = text[start:breakPoints[breakPoint][1]] + } else { + candidate = text[start:] + } + candidate = strings.TrimRightFunc(candidate, unicode.IsSpace) + + if runewidth.StringWidth(candidate) >= width { + // We're past the available width. + if lastEnd > start { + // Use the previous candidate. + addLine(start, lastEnd) + start = newStart + } else { + // We have no previous candidate. Make a hard break. + var lineWidth int + for index, ch := range text { + if index < start { + continue + } + chWidth := runewidth.RuneWidth(ch) + if lineWidth > 0 && lineWidth+chWidth >= width { + addLine(start, index) + start = index + break + } + lineWidth += chWidth + } + } + } else { + // We haven't hit the right border yet. + if breakPoint >= len(breakPoints) { + // It's the last line. We're done. + if len(candidate) > 0 { + addLine(start, len(strippedText)) + } + break + } else { + // We have a new candidate. + lastEnd = start + len(candidate) + newStart = breakPoints[breakPoint][1] + breakPoint++ + } + } + } + + return +} + +// Escape escapes the given text such that color and/or region tags are not +// recognized and substituted by the print functions of this package. For +// example, to include a tag-like string in a box title or in a TextView: +// +// box.SetTitle(tview.Escape("[squarebrackets]")) +// fmt.Fprint(textView, tview.Escape(`["quoted"]`)) +func Escape(text string) string { + return nonEscapePattern.ReplaceAllString(text, "$1[]") +} diff --git a/vendor/github.com/xanzy/go-gitlab/.gitignore b/vendor/github.com/xanzy/go-gitlab/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/xanzy/go-gitlab/.travis.yml b/vendor/github.com/xanzy/go-gitlab/.travis.yml new file mode 100644 index 00000000..26203291 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/.travis.yml @@ -0,0 +1,27 @@ +language: go + +go: + - 1.8.x + - 1.9.x + - 1.10.x + - master + +stages: + - lint + - test + +jobs: + include: + - stage: lint + script: + - go get github.com/golang/lint/golint + - golint -set_exit_status + - go vet -v + - stage: test + script: + - go test -v + +matrix: + allow_failures: + - go: master + fast_finish: true diff --git a/vendor/github.com/xanzy/go-gitlab/CHANGELOG.md b/vendor/github.com/xanzy/go-gitlab/CHANGELOG.md new file mode 100644 index 00000000..29e93fff --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/CHANGELOG.md @@ -0,0 +1,27 @@ +go-github CHANGELOG +=================== + +0.6.0 +----- +- Add support for the V4 Gitlab API. This means the older V3 API is no longer fully supported + with this version. If you still need that version, please use the `f-api-v3` branch. + +0.4.0 +----- +- Add support to use [`sudo`](https://docs.gitlab.com/ce/api/README.html#sudo) for all API calls. +- Add support for the Notification Settings API. +- Add support for the Time Tracking API. +- Make sure that the error response correctly outputs any returned errors. +- And a reasonable number of smaller enhanchements and bugfixes. + +0.3.0 +----- +- Moved the tags related API calls to their own service, following the Gitlab API structure. + +0.2.0 +----- +- Convert all Option structs to use pointers for their fields. + +0.1.0 +----- +- Initial release. diff --git a/vendor/github.com/xanzy/go-gitlab/LICENSE b/vendor/github.com/xanzy/go-gitlab/LICENSE new file mode 100644 index 00000000..e06d2081 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/vendor/github.com/xanzy/go-gitlab/README.md b/vendor/github.com/xanzy/go-gitlab/README.md new file mode 100644 index 00000000..dc793162 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/README.md @@ -0,0 +1,171 @@ +# go-gitlab + +A GitLab API client enabling Go programs to interact with GitLab in a simple and uniform way + +[![Build Status](https://travis-ci.org/xanzy/go-gitlab.svg?branch=master)](https://travis-ci.org/xanzy/go-gitlab) +[![GitHub license](https://img.shields.io/github/license/xanzy/go-gitlab.svg)](https://github.com/xanzy/go-gitlab/blob/master/LICENSE) +[![Sourcegraph](https://sourcegraph.com/github.com/xanzy/go-gitlab/-/badge.svg)](https://sourcegraph.com/github.com/xanzy/go-gitlab?badge) +[![GoDoc](https://godoc.org/github.com/xanzy/go-gitlab?status.svg)](https://godoc.org/github.com/xanzy/go-gitlab) +[![Go Report Card](https://goreportcard.com/badge/github.com/xanzy/go-gitlab)](https://goreportcard.com/report/github.com/xanzy/go-gitlab) +[![GitHub issues](https://img.shields.io/github/issues/xanzy/go-gitlab.svg)](https://github.com/xanzy/go-gitlab/issues) + +## NOTE + +Release v0.6.0 (released on 25-08-2017) no longer supports the older V3 Gitlab API. If +you need V3 support, please use the `f-api-v3` branch. This release contains some backwards +incompatible changes that were needed to fully support the V4 Gitlab API. + +## Coverage + +This API client package covers most of the existing Gitlab API calls and is updated regularly +to add new and/or missing endpoints. Currently the following services are supported: + +- [x] Award Emojis +- [x] Branches +- [x] Broadcast Messages +- [ ] Project-level Variables +- [ ] Group-level Variables +- [x] Commits +- [ ] Custom Attributes +- [x] Deployments +- [x] Deploy Keys +- [x] Environments +- [ ] Epics +- [ ] Epic Issues +- [x] Events +- [x] Feature flags +- [ ] Geo Nodes +- [x] Gitignores templates +- [ ] GitLab CI Config templates +- [x] Groups +- [ ] Group Access Requests +- [x] Group Members +- [x] Issues +- [x] Issue Boards +- [x] Jobs +- [ ] Keys +- [x] Labels +- [ ] License +- [x] Merge Requests +- [x] Merge Request Approvals +- [x] Project Milestones +- [ ] Group Milestones +- [x] Namespaces +- [x] Notes (comments) +- [ ] Discussions (threaded comments) +- [x] Notification settings +- [ ] Open source license templates +- [x] Pages Domains +- [x] Pipelines +- [x] Pipeline Triggers +- [x] Pipeline Schedules +- [x] Projects (including setting Webhooks) +- [ ] Project Access Requests +- [ ] Project badges +- [ ] Project import/export +- [x] Project Members +- [x] Project Snippets +- [x] Protected Branches +- [x] Repositories +- [x] Repository Files +- [x] Runners +- [ ] Search +- [x] Services +- [x] Settings +- [x] Sidekiq metrics +- [x] Session +- [x] System Hooks +- [x] Tags +- [x] Todos +- [x] Users +- [x] Validate CI configuration +- [x] Version +- [x] Wikis + +## Usage + +```go +import "github.com/xanzy/go-gitlab" +``` + +Construct a new GitLab client, then use the various services on the client to +access different parts of the GitLab API. For example, to list all +users: + +```go +git := gitlab.NewClient(nil, "yourtokengoeshere") +//git.SetBaseURL("https://git.mydomain.com/api/v3") +users, _, err := git.Users.ListUsers() +``` + +Some API methods have optional parameters that can be passed. For example, +to list all projects for user "svanharmelen": + +```go +git := gitlab.NewClient(nil) +opt := &ListProjectsOptions{Search: gitlab.String("svanharmelen")} +projects, _, err := git.Projects.ListProjects(opt) +``` + +### Examples + +The [examples](https://github.com/xanzy/go-gitlab/tree/master/examples) directory +contains a couple for clear examples, of which one is partially listed here as well: + +```go +package main + +import ( + "log" + + "github.com/xanzy/go-gitlab" +) + +func main() { + git := gitlab.NewClient(nil, "yourtokengoeshere") + + // Create new project + p := &gitlab.CreateProjectOptions{ + Name: gitlab.String("My Project"), + Description: gitlab.String("Just a test project to play with"), + MergeRequestsEnabled: gitlab.Bool(true), + SnippetsEnabled: gitlab.Bool(true), + Visibility: gitlab.Visibility(gitlab.PublicVisibility), + } + project, _, err := git.Projects.CreateProject(p) + if err != nil { + log.Fatal(err) + } + + // Add a new snippet + s := &gitlab.CreateProjectSnippetOptions{ + Title: gitlab.String("Dummy Snippet"), + FileName: gitlab.String("snippet.go"), + Code: gitlab.String("package main...."), + Visibility: gitlab.Visibility(gitlab.PublicVisibility), + } + _, _, err = git.ProjectSnippets.CreateSnippet(project.ID, s) + if err != nil { + log.Fatal(err) + } +} + +``` + +For complete usage of go-gitlab, see the full [package docs](https://godoc.org/github.com/xanzy/go-gitlab). + +## ToDo + +- The biggest thing this package still needs is tests :disappointed: + +## Issues + +- If you have an issue: report it on the [issue tracker](https://github.com/xanzy/go-gitlab/issues) + +## Author + +Sander van Harmelen () + +## License + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/vendor/github.com/xanzy/go-gitlab/award_emojis.go b/vendor/github.com/xanzy/go-gitlab/award_emojis.go new file mode 100644 index 00000000..b12a662f --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/award_emojis.go @@ -0,0 +1,460 @@ +// +// Copyright 2017, Arkbriar +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// AwardEmojiService handles communication with the emoji awards related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/award_emoji.html +type AwardEmojiService struct { + client *Client +} + +// AwardEmoji represents a GitLab Award Emoji. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/award_emoji.html +type AwardEmoji struct { + ID int `json:"id"` + Name string `json:"name"` + User struct { + Name string `json:"name"` + Username string `json:"username"` + ID int `json:"id"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"user"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + AwardableID int `json:"awardable_id"` + AwardableType string `json:"awardable_type"` +} + +const ( + awardMergeRequest = "merge_requests" + awardIssue = "issues" + awardSnippets = "snippets" +) + +// ListEmojiAwardsOptions represents the available options for listing emoji +// for each resources +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html +type ListEmojiAwardsOptions ListOptions + +// ListMergeRequestAwardEmoji gets a list of all award emoji on the merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#list-an-awardable-39-s-award-emoji +func (s *AwardEmojiService) ListMergeRequestAwardEmoji(pid interface{}, mergeRequestIID int, opt *ListEmojiAwardsOptions, options ...OptionFunc) ([]*AwardEmoji, *Response, error) { + return s.listAwardEmoji(pid, awardMergeRequest, mergeRequestIID, opt, options...) +} + +// ListIssueAwardEmoji gets a list of all award emoji on the issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#list-an-awardable-39-s-award-emoji +func (s *AwardEmojiService) ListIssueAwardEmoji(pid interface{}, issueIID int, opt *ListEmojiAwardsOptions, options ...OptionFunc) ([]*AwardEmoji, *Response, error) { + return s.listAwardEmoji(pid, awardIssue, issueIID, opt, options...) +} + +// ListSnippetAwardEmoji gets a list of all award emoji on the snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#list-an-awardable-39-s-award-emoji +func (s *AwardEmojiService) ListSnippetAwardEmoji(pid interface{}, snippetID int, opt *ListEmojiAwardsOptions, options ...OptionFunc) ([]*AwardEmoji, *Response, error) { + return s.listAwardEmoji(pid, awardSnippets, snippetID, opt, options...) +} + +func (s *AwardEmojiService) listAwardEmoji(pid interface{}, resource string, resourceID int, opt *ListEmojiAwardsOptions, options ...OptionFunc) ([]*AwardEmoji, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/award_emoji", + url.QueryEscape(project), + resource, + resourceID, + ) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var as []*AwardEmoji + resp, err := s.client.Do(req, &as) + if err != nil { + return nil, resp, err + } + + return as, resp, err +} + +// GetMergeRequestAwardEmoji get an award emoji from merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#list-an-awardable-39-s-award-emoji +func (s *AwardEmojiService) GetMergeRequestAwardEmoji(pid interface{}, mergeRequestIID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.getAwardEmoji(pid, awardMergeRequest, mergeRequestIID, awardID, options...) +} + +// GetIssueAwardEmoji get an award emoji from issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#list-an-awardable-39-s-award-emoji +func (s *AwardEmojiService) GetIssueAwardEmoji(pid interface{}, issueIID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.getAwardEmoji(pid, awardIssue, issueIID, awardID, options...) +} + +// GetSnippetAwardEmoji get an award emoji from snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#list-an-awardable-39-s-award-emoji +func (s *AwardEmojiService) GetSnippetAwardEmoji(pid interface{}, snippetID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.getAwardEmoji(pid, awardSnippets, snippetID, awardID, options...) +} + +func (s *AwardEmojiService) getAwardEmoji(pid interface{}, resource string, resourceID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/award_emoji/%d", + url.QueryEscape(project), + resource, + resourceID, + awardID, + ) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + a := new(AwardEmoji) + resp, err := s.client.Do(req, &a) + if err != nil { + return nil, resp, err + } + + return a, resp, err +} + +// CreateMergeRequestAwardEmoji get an award emoji from merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-a-new-emoji +func (s *AwardEmojiService) CreateMergeRequestAwardEmoji(pid interface{}, mergeRequestIID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.createAwardEmoji(pid, awardMergeRequest, mergeRequestIID, awardID, options...) +} + +// CreateIssueAwardEmoji get an award emoji from issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-a-new-emoji +func (s *AwardEmojiService) CreateIssueAwardEmoji(pid interface{}, issueIID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.createAwardEmoji(pid, awardIssue, issueIID, awardID, options...) +} + +// CreateSnippetAwardEmoji get an award emoji from snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-a-new-emoji +func (s *AwardEmojiService) CreateSnippetAwardEmoji(pid interface{}, snippetID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.createAwardEmoji(pid, awardSnippets, snippetID, awardID, options...) +} + +func (s *AwardEmojiService) createAwardEmoji(pid interface{}, resource string, resourceID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/award_emoji/%d", + url.QueryEscape(project), + resource, + resourceID, + awardID, + ) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + a := new(AwardEmoji) + resp, err := s.client.Do(req, &a) + if err != nil { + return nil, resp, err + } + + return a, resp, err +} + +// DeleteIssueAwardEmoji delete award emoji on an issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-a-new-emoji-on-a-note +func (s *AwardEmojiService) DeleteIssueAwardEmoji(pid interface{}, issueIID, awardID int, options ...OptionFunc) (*Response, error) { + return s.deleteAwardEmoji(pid, awardMergeRequest, issueIID, awardID, options...) +} + +// DeleteMergeRequestAwardEmoji delete award emoji on a merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-a-new-emoji-on-a-note +func (s *AwardEmojiService) DeleteMergeRequestAwardEmoji(pid interface{}, mergeRequestIID, awardID int, options ...OptionFunc) (*Response, error) { + return s.deleteAwardEmoji(pid, awardMergeRequest, mergeRequestIID, awardID, options...) +} + +// DeleteSnippetAwardEmoji delete award emoji on a snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-a-new-emoji-on-a-note +func (s *AwardEmojiService) DeleteSnippetAwardEmoji(pid interface{}, snippetID, awardID int, options ...OptionFunc) (*Response, error) { + return s.deleteAwardEmoji(pid, awardMergeRequest, snippetID, awardID, options...) +} + +// DeleteAwardEmoji Delete an award emoji on the specified resource. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#delete-an-award-emoji +func (s *AwardEmojiService) deleteAwardEmoji(pid interface{}, resource string, resourceID, awardID int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/award_emoji/%d", url.QueryEscape(project), resource, + resourceID, awardID) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + return s.client.Do(req, nil) +} + +// ListIssuesAwardEmojiOnNote gets a list of all award emoji on a note from the +// issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) ListIssuesAwardEmojiOnNote(pid interface{}, issueID, noteID int, opt *ListEmojiAwardsOptions, options ...OptionFunc) ([]*AwardEmoji, *Response, error) { + return s.listAwardEmojiOnNote(pid, awardIssue, issueID, noteID, opt, options...) +} + +// ListMergeRequestAwardEmojiOnNote gets a list of all award emoji on a note +// from the merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) ListMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID int, opt *ListEmojiAwardsOptions, options ...OptionFunc) ([]*AwardEmoji, *Response, error) { + return s.listAwardEmojiOnNote(pid, awardMergeRequest, mergeRequestIID, noteID, opt, options...) +} + +// ListSnippetAwardEmojiOnNote gets a list of all award emoji on a note from the +// snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) ListSnippetAwardEmojiOnNote(pid interface{}, snippetIID, noteID int, opt *ListEmojiAwardsOptions, options ...OptionFunc) ([]*AwardEmoji, *Response, error) { + return s.listAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, opt, options...) +} + +func (s *AwardEmojiService) listAwardEmojiOnNote(pid interface{}, resources string, ressourceID, noteID int, opt *ListEmojiAwardsOptions, options ...OptionFunc) ([]*AwardEmoji, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/notes/%d/award_emoji", url.QueryEscape(project), resources, + ressourceID, noteID) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var as []*AwardEmoji + resp, err := s.client.Do(req, &as) + if err != nil { + return nil, resp, err + } + + return as, resp, err +} + +// GetIssuesAwardEmojiOnNote gets an award emoji on a note from an issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) GetIssuesAwardEmojiOnNote(pid interface{}, issueID, noteID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.getSingleNoteAwardEmoji(pid, awardIssue, issueID, noteID, awardID, options...) +} + +// GetMergeRequestAwardEmojiOnNote gets an award emoji on a note from a +// merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) GetMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.getSingleNoteAwardEmoji(pid, awardMergeRequest, mergeRequestIID, noteID, awardID, + options...) +} + +// GetSnippetAwardEmojiOnNote gets an award emoji on a note from a snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) GetSnippetAwardEmojiOnNote(pid interface{}, snippetIID, noteID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.getSingleNoteAwardEmoji(pid, awardSnippets, snippetIID, noteID, awardID, options...) +} + +func (s *AwardEmojiService) getSingleNoteAwardEmoji(pid interface{}, ressource string, resourceID, noteID, awardID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/notes/%d/award_emoji/%d", + url.QueryEscape(project), + ressource, + resourceID, + noteID, + awardID, + ) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + a := new(AwardEmoji) + resp, err := s.client.Do(req, &a) + if err != nil { + return nil, resp, err + } + + return a, resp, err +} + +// CreateIssuesAwardEmojiOnNote gets an award emoji on a note from an issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) CreateIssuesAwardEmojiOnNote(pid interface{}, issueID, noteID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.createAwardEmojiOnNote(pid, awardIssue, issueID, noteID, options...) +} + +// CreateMergeRequestAwardEmojiOnNote gets an award emoji on a note from a +// merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) CreateMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.createAwardEmojiOnNote(pid, awardMergeRequest, mergeRequestIID, noteID, options...) +} + +// CreateSnippetAwardEmojiOnNote gets an award emoji on a note from a snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) CreateSnippetAwardEmojiOnNote(pid interface{}, snippetIID, noteID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + return s.createAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, options...) +} + +// CreateAwardEmojiOnNote award emoji on a note. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-a-new-emoji-on-a-note +func (s *AwardEmojiService) createAwardEmojiOnNote(pid interface{}, resource string, resourceID, noteID int, options ...OptionFunc) (*AwardEmoji, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/notes/%d/award_emoji", + url.QueryEscape(project), + resource, + resourceID, + noteID, + ) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + a := new(AwardEmoji) + resp, err := s.client.Do(req, &a) + if err != nil { + return nil, resp, err + } + + return a, resp, err +} + +// DeleteIssuesAwardEmojiOnNote deletes an award emoji on a note from an issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) DeleteIssuesAwardEmojiOnNote(pid interface{}, issueID, noteID, awardID int, options ...OptionFunc) (*Response, error) { + return s.deleteAwardEmojiOnNote(pid, awardIssue, issueID, noteID, awardID, options...) +} + +// DeleteMergeRequestAwardEmojiOnNote deletes an award emoji on a note from a +// merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) DeleteMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID, awardID int, options ...OptionFunc) (*Response, error) { + return s.deleteAwardEmojiOnNote(pid, awardMergeRequest, mergeRequestIID, noteID, awardID, + options...) +} + +// DeleteSnippetAwardEmojiOnNote deletes an award emoji on a note from a snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/award_emoji.html#award-emoji-on-notes +func (s *AwardEmojiService) DeleteSnippetAwardEmojiOnNote(pid interface{}, snippetIID, noteID, awardID int, options ...OptionFunc) (*Response, error) { + return s.deleteAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, awardID, options...) +} + +func (s *AwardEmojiService) deleteAwardEmojiOnNote(pid interface{}, resource string, resourceID, noteID, awardID int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/notes/%d/award_emoji/%d", + url.QueryEscape(project), + resource, + resourceID, + noteID, + awardID, + ) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/boards.go b/vendor/github.com/xanzy/go-gitlab/boards.go new file mode 100644 index 00000000..7579a5bd --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/boards.go @@ -0,0 +1,261 @@ +// +// Copyright 2015, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// IssueBoardsService handles communication with the issue board related +// methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html +type IssueBoardsService struct { + client *Client +} + +// IssueBoard represents a GitLab issue board. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html +type IssueBoard struct { + ID int `json:"id"` + Name string `json:"name"` + Project *Project `json:"project"` + Milestone *Milestone `json:"milestone"` + Lists []*BoardList `json:"lists"` +} + +func (b IssueBoard) String() string { + return Stringify(b) +} + +// BoardList represents a GitLab board list. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html +type BoardList struct { + ID int `json:"id"` + Labels []*Label `json:"labels"` + Position int `json:"position"` +} + +func (b BoardList) String() string { + return Stringify(b) +} + +// ListIssueBoardsOptions represents the available ListIssueBoards() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#project-board +type ListIssueBoardsOptions ListOptions + +// ListIssueBoards gets a list of all issue boards in a project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#project-board +func (s *IssueBoardsService) ListIssueBoards(pid interface{}, opt *ListIssueBoardsOptions, options ...OptionFunc) ([]*IssueBoard, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/boards", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var is []*IssueBoard + resp, err := s.client.Do(req, &is) + if err != nil { + return nil, resp, err + } + + return is, resp, err +} + +// GetIssueBoard gets a single issue board of a project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#single-board +func (s *IssueBoardsService) GetIssueBoard(pid interface{}, board int, options ...OptionFunc) (*IssueBoard, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/boards/%d", url.QueryEscape(project), board) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + ib := new(IssueBoard) + resp, err := s.client.Do(req, ib) + if err != nil { + return nil, resp, err + } + + return ib, resp, err +} + +// GetIssueBoardListsOptions represents the available GetIssueBoardLists() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#list-board-lists +type GetIssueBoardListsOptions ListOptions + +// GetIssueBoardLists gets a list of the issue board's lists. Does not include +// backlog and closed lists. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#list-board-lists +func (s *IssueBoardsService) GetIssueBoardLists(pid interface{}, board int, opt *GetIssueBoardListsOptions, options ...OptionFunc) ([]*BoardList, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/boards/%d/lists", url.QueryEscape(project), board) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var bl []*BoardList + resp, err := s.client.Do(req, &bl) + if err != nil { + return nil, resp, err + } + + return bl, resp, err +} + +// GetIssueBoardList gets a single issue board list. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#single-board-list +func (s *IssueBoardsService) GetIssueBoardList(pid interface{}, board, list int, options ...OptionFunc) (*BoardList, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/boards/%d/lists/%d", + url.QueryEscape(project), + board, + list, + ) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + bl := new(BoardList) + resp, err := s.client.Do(req, bl) + if err != nil { + return nil, resp, err + } + + return bl, resp, err +} + +// CreateIssueBoardListOptions represents the available CreateIssueBoardList() +// options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#new-board-list +type CreateIssueBoardListOptions struct { + LabelID *int `url:"label_id" json:"label_id"` +} + +// CreateIssueBoardList creates a new issue board list. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#new-board-list +func (s *IssueBoardsService) CreateIssueBoardList(pid interface{}, board int, opt *CreateIssueBoardListOptions, options ...OptionFunc) (*BoardList, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/boards/%d/lists", url.QueryEscape(project), board) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + bl := new(BoardList) + resp, err := s.client.Do(req, bl) + if err != nil { + return nil, resp, err + } + + return bl, resp, err +} + +// UpdateIssueBoardListOptions represents the available UpdateIssueBoardList() +// options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#edit-board-list +type UpdateIssueBoardListOptions struct { + Position *int `url:"position" json:"position"` +} + +// UpdateIssueBoardList updates the position of an existing issue board list. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/boards.html#edit-board-list +func (s *IssueBoardsService) UpdateIssueBoardList(pid interface{}, board, list int, opt *UpdateIssueBoardListOptions, options ...OptionFunc) (*BoardList, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/boards/%d/lists/%d", + url.QueryEscape(project), + board, + list, + ) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + bl := new(BoardList) + resp, err := s.client.Do(req, bl) + if err != nil { + return nil, resp, err + } + + return bl, resp, err +} + +// DeleteIssueBoardList soft deletes an issue board list. Only for admins and +// project owners. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/boards.html#delete-a-board-list +func (s *IssueBoardsService) DeleteIssueBoardList(pid interface{}, board, list int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/boards/%d/lists/%d", + url.QueryEscape(project), + board, + list, + ) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/branches.go b/vendor/github.com/xanzy/go-gitlab/branches.go new file mode 100644 index 00000000..3f7bd0cd --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/branches.go @@ -0,0 +1,238 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// BranchesService handles communication with the branch related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/branches.html +type BranchesService struct { + client *Client +} + +// Branch represents a GitLab branch. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/branches.html +type Branch struct { + Commit *Commit `json:"commit"` + Name string `json:"name"` + Protected bool `json:"protected"` + Merged bool `json:"merged"` + DevelopersCanPush bool `json:"developers_can_push"` + DevelopersCanMerge bool `json:"developers_can_merge"` +} + +func (b Branch) String() string { + return Stringify(b) +} + +// ListBranchesOptions represents the available ListBranches() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#list-repository-branches +type ListBranchesOptions ListOptions + +// ListBranches gets a list of repository branches from a project, sorted by +// name alphabetically. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#list-repository-branches +func (s *BranchesService) ListBranches(pid interface{}, opts *ListBranchesOptions, options ...OptionFunc) ([]*Branch, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/branches", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opts, options) + if err != nil { + return nil, nil, err + } + + var b []*Branch + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b, resp, err +} + +// GetBranch gets a single project repository branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#get-single-repository-branch +func (s *BranchesService) GetBranch(pid interface{}, branch string, options ...OptionFunc) (*Branch, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/branches/%s", url.QueryEscape(project), url.QueryEscape(branch)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + b := new(Branch) + resp, err := s.client.Do(req, b) + if err != nil { + return nil, resp, err + } + + return b, resp, err +} + +// ProtectBranchOptions represents the available ProtectBranch() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#protect-repository-branch +type ProtectBranchOptions struct { + DevelopersCanPush *bool `url:"developers_can_push,omitempty" json:"developers_can_push,omitempty"` + DevelopersCanMerge *bool `url:"developers_can_merge,omitempty" json:"developers_can_merge,omitempty"` +} + +// ProtectBranch protects a single project repository branch. This is an +// idempotent function, protecting an already protected repository branch +// still returns a 200 OK status code. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#protect-repository-branch +func (s *BranchesService) ProtectBranch(pid interface{}, branch string, opts *ProtectBranchOptions, options ...OptionFunc) (*Branch, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/branches/%s/protect", url.QueryEscape(project), url.QueryEscape(branch)) + + req, err := s.client.NewRequest("PUT", u, opts, options) + if err != nil { + return nil, nil, err + } + + b := new(Branch) + resp, err := s.client.Do(req, b) + if err != nil { + return nil, resp, err + } + + return b, resp, err +} + +// UnprotectBranch unprotects a single project repository branch. This is an +// idempotent function, unprotecting an already unprotected repository branch +// still returns a 200 OK status code. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#unprotect-repository-branch +func (s *BranchesService) UnprotectBranch(pid interface{}, branch string, options ...OptionFunc) (*Branch, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/branches/%s/unprotect", url.QueryEscape(project), url.QueryEscape(branch)) + + req, err := s.client.NewRequest("PUT", u, nil, options) + if err != nil { + return nil, nil, err + } + + b := new(Branch) + resp, err := s.client.Do(req, b) + if err != nil { + return nil, resp, err + } + + return b, resp, err +} + +// CreateBranchOptions represents the available CreateBranch() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#create-repository-branch +type CreateBranchOptions struct { + Branch *string `url:"branch,omitempty" json:"branch,omitempty"` + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` +} + +// CreateBranch creates branch from commit SHA or existing branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#create-repository-branch +func (s *BranchesService) CreateBranch(pid interface{}, opt *CreateBranchOptions, options ...OptionFunc) (*Branch, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/branches", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + b := new(Branch) + resp, err := s.client.Do(req, b) + if err != nil { + return nil, resp, err + } + + return b, resp, err +} + +// DeleteBranch deletes an existing branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#delete-repository-branch +func (s *BranchesService) DeleteBranch(pid interface{}, branch string, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/repository/branches/%s", url.QueryEscape(project), url.QueryEscape(branch)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteMergedBranches deletes all branches that are merged into the project's default branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/branches.html#delete-merged-branches +func (s *BranchesService) DeleteMergedBranches(pid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/repository/merged_branches", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/broadcast_messages.go b/vendor/github.com/xanzy/go-gitlab/broadcast_messages.go new file mode 100644 index 00000000..aee852d4 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/broadcast_messages.go @@ -0,0 +1,172 @@ +// +// Copyright 2018, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "time" +) + +// BroadcastMessagesService handles communication with the broadcast +// messages methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/broadcast_messages.html +type BroadcastMessagesService struct { + client *Client +} + +// BroadcastMessage represents a GitLab issue board. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#get-all-broadcast-messages +type BroadcastMessage struct { + Message string `json:"message"` + StartsAt *time.Time `json:"starts_at"` + EndsAt *time.Time `json:"ends_at"` + Color string `json:"color"` + Font string `json:"font"` + ID int `json:"id"` + Active bool `json:"active"` +} + +// ListBroadcastMessagesOptions represents the available ListBroadcastMessages() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#get-all-broadcast-messages +type ListBroadcastMessagesOptions ListOptions + +// ListBroadcastMessages gets a list of all broadcasted messages. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#get-all-broadcast-messages +func (s *BroadcastMessagesService) ListBroadcastMessages(opt *ListBroadcastMessagesOptions, options ...OptionFunc) ([]*BroadcastMessage, *Response, error) { + req, err := s.client.NewRequest("GET", "broadcast_messages", opt, options) + if err != nil { + return nil, nil, err + } + + var bs []*BroadcastMessage + resp, err := s.client.Do(req, &bs) + if err != nil { + return nil, resp, err + } + + return bs, resp, err +} + +// GetBroadcastMessage gets a single broadcast message. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#get-a-specific-broadcast-message +func (s *BroadcastMessagesService) GetBroadcastMessage(broadcast int, options ...OptionFunc) (*BroadcastMessage, *Response, error) { + u := fmt.Sprintf("broadcast_messages/%d", broadcast) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + b := new(BroadcastMessage) + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b, resp, err +} + +// CreateBroadcastMessageOptions represents the available CreateBroadcastMessage() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#create-a-broadcast-message +type CreateBroadcastMessageOptions struct { + Message *string `url:"message" json:"message"` + StartsAt *time.Time `url:"starts_at,omitempty" json:"starts_at,omitempty"` + EndsAt *time.Time `url:"ends_at,omitempty" json:"ends_at,omitempty"` + Color *string `url:"color,omitempty" json:"color,omitempty"` + Font *string `url:"font,omitempty" json:"font,omitempty"` +} + +// CreateBroadcastMessage creates a message to broadcast. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#create-a-broadcast-message +func (s *BroadcastMessagesService) CreateBroadcastMessage(opt *CreateBroadcastMessageOptions, options ...OptionFunc) (*BroadcastMessage, *Response, error) { + req, err := s.client.NewRequest("POST", "broadcast_messages", opt, options) + if err != nil { + return nil, nil, err + } + + b := new(BroadcastMessage) + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b, resp, err +} + +// UpdateBroadcastMessageOptions represents the available CreateBroadcastMessage() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#update-a-broadcast-message +type UpdateBroadcastMessageOptions struct { + Message *string `url:"message,omitempty" json:"message,omitempty"` + StartsAt *time.Time `url:"starts_at,omitempty" json:"starts_at,omitempty"` + EndsAt *time.Time `url:"ends_at,omitempty" json:"ends_at,omitempty"` + Color *string `url:"color,omitempty" json:"color,omitempty"` + Font *string `url:"font,omitempty" json:"font,omitempty"` +} + +// UpdateBroadcastMessage update a broadcasted message. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#update-a-broadcast-message +func (s *BroadcastMessagesService) UpdateBroadcastMessage(broadcast int, opt *UpdateBroadcastMessageOptions, options ...OptionFunc) (*BroadcastMessage, *Response, error) { + u := fmt.Sprintf("broadcast_messages/%d", broadcast) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + b := new(BroadcastMessage) + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b, resp, err +} + +// DeleteBroadcastMessage deletes a broadcasted message. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/broadcast_messages.html#delete-a-broadcast-message +func (s *BroadcastMessagesService) DeleteBroadcastMessage(broadcast int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("broadcast_messages/%d", broadcast) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/build_variables.go b/vendor/github.com/xanzy/go-gitlab/build_variables.go new file mode 100644 index 00000000..8a6c8cdd --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/build_variables.go @@ -0,0 +1,173 @@ +package gitlab + +import ( + "fmt" + "net/url" +) + +// BuildVariablesService handles communication with the project variables related methods +// of the Gitlab API +// +// Gitlab API Docs : https://docs.gitlab.com/ce/api/build_variables.html +type BuildVariablesService struct { + client *Client +} + +// BuildVariable represents a variable available for each build of the given project +// +// Gitlab API Docs : https://docs.gitlab.com/ce/api/build_variables.html +type BuildVariable struct { + Key string `json:"key"` + Value string `json:"value"` + Protected bool `json:"protected"` +} + +func (v BuildVariable) String() string { + return Stringify(v) +} + +// ListBuildVariablesOptions are the parameters to ListBuildVariables() +// +// Gitlab API Docs: +// https://docs.gitlab.com/ce/api/build_variables.html#list-project-variables +type ListBuildVariablesOptions ListOptions + +// ListBuildVariables gets the a list of project variables in a project +// +// Gitlab API Docs: +// https://docs.gitlab.com/ce/api/build_variables.html#list-project-variables +func (s *BuildVariablesService) ListBuildVariables(pid interface{}, opts *ListBuildVariablesOptions, options ...OptionFunc) ([]*BuildVariable, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/variables", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opts, options) + if err != nil { + return nil, nil, err + } + + var v []*BuildVariable + resp, err := s.client.Do(req, &v) + if err != nil { + return nil, resp, err + } + + return v, resp, err +} + +// GetBuildVariable gets a single project variable of a project +// +// Gitlab API Docs: +// https://docs.gitlab.com/ce/api/build_variables.html#show-variable-details +func (s *BuildVariablesService) GetBuildVariable(pid interface{}, key string, options ...OptionFunc) (*BuildVariable, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + v := new(BuildVariable) + resp, err := s.client.Do(req, v) + if err != nil { + return nil, resp, err + } + + return v, resp, err +} + +// CreateBuildVariableOptions are the parameters to CreateBuildVariable() +// +// Gitlab API Docs: +// https://docs.gitlab.com/ce/api/build_variables.html#create-variable +type CreateBuildVariableOptions struct { + Key *string `url:"key" json:"key"` + Value *string `url:"value" json:"value"` + Protected *bool `url:"protected,omitempty" json:"protected,omitempty"` +} + +// CreateBuildVariable creates a variable for a given project +// +// Gitlab API Docs: +// https://docs.gitlab.com/ce/api/build_variables.html#create-variable +func (s *BuildVariablesService) CreateBuildVariable(pid interface{}, opt *CreateBuildVariableOptions, options ...OptionFunc) (*BuildVariable, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/variables", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + v := new(BuildVariable) + resp, err := s.client.Do(req, v) + if err != nil { + return nil, resp, err + } + + return v, resp, err +} + +// UpdateBuildVariableOptions are the parameters to UpdateBuildVariable() +// +// Gitlab API Docs: +// https://docs.gitlab.com/ce/api/build_variables.html#update-variable +type UpdateBuildVariableOptions struct { + Key *string `url:"key" json:"key"` + Value *string `url:"value" json:"value"` + Protected *bool `url:"protected,omitempty" json:"protected,omitempty"` +} + +// UpdateBuildVariable updates an existing project variable +// The variable key must exist +// +// Gitlab API Docs: +// https://docs.gitlab.com/ce/api/build_variables.html#update-variable +func (s *BuildVariablesService) UpdateBuildVariable(pid interface{}, key string, opt *UpdateBuildVariableOptions, options ...OptionFunc) (*BuildVariable, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + v := new(BuildVariable) + resp, err := s.client.Do(req, v) + if err != nil { + return nil, resp, err + } + + return v, resp, err +} + +// RemoveBuildVariable removes a project variable of a given project identified by its key +// +// Gitlab API Docs: +// https://docs.gitlab.com/ce/api/build_variables.html#remove-variable +func (s *BuildVariablesService) RemoveBuildVariable(pid interface{}, key string, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/variables/%s", url.QueryEscape(project), key) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/commits.go b/vendor/github.com/xanzy/go-gitlab/commits.go new file mode 100644 index 00000000..5b5dc2a7 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/commits.go @@ -0,0 +1,448 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// CommitsService handles communication with the commit related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html +type CommitsService struct { + client *Client +} + +// Commit represents a GitLab commit. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html +type Commit struct { + ID string `json:"id"` + ShortID string `json:"short_id"` + Title string `json:"title"` + AuthorName string `json:"author_name"` + AuthorEmail string `json:"author_email"` + AuthoredDate *time.Time `json:"authored_date"` + CommitterName string `json:"committer_name"` + CommitterEmail string `json:"committer_email"` + CommittedDate *time.Time `json:"committed_date"` + CreatedAt *time.Time `json:"created_at"` + Message string `json:"message"` + ParentIDs []string `json:"parent_ids"` + Stats *CommitStats `json:"stats"` + Status *BuildStateValue `json:"status"` +} + +// CommitStats represents the number of added and deleted files in a commit. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html +type CommitStats struct { + Additions int `json:"additions"` + Deletions int `json:"deletions"` + Total int `json:"total"` +} + +func (c Commit) String() string { + return Stringify(c) +} + +// ListCommitsOptions represents the available ListCommits() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#list-repository-commits +type ListCommitsOptions struct { + ListOptions + RefName *string `url:"ref_name,omitempty" json:"ref_name,omitempty"` + Since *time.Time `url:"since,omitempty" json:"since,omitempty"` + Until *time.Time `url:"until,omitempty" json:"until,omitempty"` + Path *string `url:"path,omitempty" json:"path,omitempty"` + All *bool `url:"all,omitempty" json:"all,omitempty"` +} + +// ListCommits gets a list of repository commits in a project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#list-commits +func (s *CommitsService) ListCommits(pid interface{}, opt *ListCommitsOptions, options ...OptionFunc) ([]*Commit, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/commits", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var c []*Commit + resp, err := s.client.Do(req, &c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} + +// FileAction represents the available actions that can be performed on a file. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions +type FileAction string + +// The available file actions. +const ( + FileCreate FileAction = "create" + FileDelete FileAction = "delete" + FileMove FileAction = "move" + FileUpdate FileAction = "update" +) + +// CommitAction represents a single file action within a commit. +type CommitAction struct { + Action FileAction `url:"action" json:"action"` + FilePath string `url:"file_path" json:"file_path"` + PreviousPath string `url:"previous_path,omitempty" json:"previous_path,omitempty"` + Content string `url:"content,omitempty" json:"content,omitempty"` + Encoding string `url:"encoding,omitempty" json:"encoding,omitempty"` +} + +// GetCommit gets a specific commit identified by the commit hash or name of a +// branch or tag. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#get-a-single-commit +func (s *CommitsService) GetCommit(pid interface{}, sha string, options ...OptionFunc) (*Commit, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/commits/%s", url.QueryEscape(project), sha) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + c := new(Commit) + resp, err := s.client.Do(req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} + +// CreateCommitOptions represents the available options for a new commit. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions +type CreateCommitOptions struct { + Branch *string `url:"branch" json:"branch"` + CommitMessage *string `url:"commit_message" json:"commit_message"` + StartBranch *string `url:"start_branch,omitempty" json:"start_branch,omitempty"` + Actions []*CommitAction `url:"actions" json:"actions"` + AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"` + AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"` +} + +// CreateCommit creates a commit with multiple files and actions. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions +func (s *CommitsService) CreateCommit(pid interface{}, opt *CreateCommitOptions, options ...OptionFunc) (*Commit, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/commits", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + var c *Commit + resp, err := s.client.Do(req, &c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} + +// Diff represents a GitLab diff. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html +type Diff struct { + Diff string `json:"diff"` + NewPath string `json:"new_path"` + OldPath string `json:"old_path"` + AMode string `json:"a_mode"` + BMode string `json:"b_mode"` + NewFile bool `json:"new_file"` + RenamedFile bool `json:"renamed_file"` + DeletedFile bool `json:"deleted_file"` +} + +func (d Diff) String() string { + return Stringify(d) +} + +// GetCommitDiffOptions represents the available GetCommitDiff() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/commits.html#get-the-diff-of-a-commit +type GetCommitDiffOptions ListOptions + +// GetCommitDiff gets the diff of a commit in a project.. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/commits.html#get-the-diff-of-a-commit +func (s *CommitsService) GetCommitDiff(pid interface{}, sha string, opt *GetCommitDiffOptions, options ...OptionFunc) ([]*Diff, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/commits/%s/diff", url.QueryEscape(project), sha) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var d []*Diff + resp, err := s.client.Do(req, &d) + if err != nil { + return nil, resp, err + } + + return d, resp, err +} + +// CommitComment represents a GitLab commit comment. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html +type CommitComment struct { + Note string `json:"note"` + Path string `json:"path"` + Line int `json:"line"` + LineType string `json:"line_type"` + Author Author `json:"author"` +} + +// Author represents a GitLab commit author +type Author struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + Blocked bool `json:"blocked"` + CreatedAt *time.Time `json:"created_at"` +} + +func (c CommitComment) String() string { + return Stringify(c) +} + +// GetCommitCommentsOptions represents the available GetCommitComments() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/commits.html#get-the-comments-of-a-commit +type GetCommitCommentsOptions ListOptions + +// GetCommitComments gets the comments of a commit in a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/commits.html#get-the-comments-of-a-commit +func (s *CommitsService) GetCommitComments(pid interface{}, sha string, opt *GetCommitCommentsOptions, options ...OptionFunc) ([]*CommitComment, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/commits/%s/comments", url.QueryEscape(project), sha) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var c []*CommitComment + resp, err := s.client.Do(req, &c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} + +// PostCommitCommentOptions represents the available PostCommitComment() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/commits.html#post-comment-to-commit +type PostCommitCommentOptions struct { + Note *string `url:"note,omitempty" json:"note,omitempty"` + Path *string `url:"path" json:"path"` + Line *int `url:"line" json:"line"` + LineType *string `url:"line_type" json:"line_type"` +} + +// PostCommitComment adds a comment to a commit. Optionally you can post +// comments on a specific line of a commit. Therefor both path, line_new and +// line_old are required. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/commits.html#post-comment-to-commit +func (s *CommitsService) PostCommitComment(pid interface{}, sha string, opt *PostCommitCommentOptions, options ...OptionFunc) (*CommitComment, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/commits/%s/comments", url.QueryEscape(project), sha) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + c := new(CommitComment) + resp, err := s.client.Do(req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} + +// GetCommitStatusesOptions represents the available GetCommitStatuses() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#get-the-status-of-a-commit +type GetCommitStatusesOptions struct { + ListOptions + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` + Stage *string `url:"stage,omitempty" json:"stage,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + All *bool `url:"all,omitempty" json:"all,omitempty"` +} + +// CommitStatus represents a GitLab commit status. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#get-the-status-of-a-commit +type CommitStatus struct { + ID int `json:"id"` + SHA string `json:"sha"` + Ref string `json:"ref"` + Status string `json:"status"` + Name string `json:"name"` + TargetURL string `json:"target_url"` + Description string `json:"description"` + CreatedAt *time.Time `json:"created_at"` + StartedAt *time.Time `json:"started_at"` + FinishedAt *time.Time `json:"finished_at"` + Author Author `json:"author"` +} + +// GetCommitStatuses gets the statuses of a commit in a project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#get-the-status-of-a-commit +func (s *CommitsService) GetCommitStatuses(pid interface{}, sha string, opt *GetCommitStatusesOptions, options ...OptionFunc) ([]*CommitStatus, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/commits/%s/statuses", url.QueryEscape(project), sha) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var cs []*CommitStatus + resp, err := s.client.Do(req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, err +} + +// SetCommitStatusOptions represents the available SetCommitStatus() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#post-the-status-to-commit +type SetCommitStatusOptions struct { + State BuildStateValue `url:"state" json:"state"` + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + Context *string `url:"context,omitempty" json:"context,omitempty"` + TargetURL *string `url:"target_url,omitempty" json:"target_url,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` +} + +// SetCommitStatus sets the status of a commit in a project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#post-the-status-to-commit +func (s *CommitsService) SetCommitStatus(pid interface{}, sha string, opt *SetCommitStatusOptions, options ...OptionFunc) (*CommitStatus, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/statuses/%s", url.QueryEscape(project), sha) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + var cs *CommitStatus + resp, err := s.client.Do(req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, err +} + +// CherryPickCommitOptions represents the available options for cherry-picking a commit. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#cherry-pick-a-commit +type CherryPickCommitOptions struct { + TargetBranch *string `url:"branch" json:"branch,omitempty"` +} + +// CherryPickCommit sherry picks a commit to a given branch. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/commits.html#cherry-pick-a-commit +func (s *CommitsService) CherryPickCommit(pid interface{}, sha string, opt *CherryPickCommitOptions, options ...OptionFunc) (*Commit, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/commits/%s/cherry_pick", + url.QueryEscape(project), url.QueryEscape(sha)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + var c *Commit + resp, err := s.client.Do(req, &c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/deploy_keys.go b/vendor/github.com/xanzy/go-gitlab/deploy_keys.go new file mode 100644 index 00000000..76444592 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/deploy_keys.go @@ -0,0 +1,201 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// DeployKeysService handles communication with the keys related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/deploy_keys.html +type DeployKeysService struct { + client *Client +} + +// DeployKey represents a GitLab deploy key. +type DeployKey struct { + ID int `json:"id"` + Title string `json:"title"` + Key string `json:"key"` + CanPush *bool `json:"can_push"` + CreatedAt *time.Time `json:"created_at"` +} + +func (k DeployKey) String() string { + return Stringify(k) +} + +// ListAllDeployKeys gets a list of all deploy keys +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deploy_keys.html#list-all-deploy-keys +func (s *DeployKeysService) ListAllDeployKeys(options ...OptionFunc) ([]*DeployKey, *Response, error) { + req, err := s.client.NewRequest("GET", "deploy_keys", nil, options) + if err != nil { + return nil, nil, err + } + + var ks []*DeployKey + resp, err := s.client.Do(req, &ks) + if err != nil { + return nil, resp, err + } + + return ks, resp, err +} + +// ListProjectDeployKeysOptions represents the available ListProjectDeployKeys() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deploy_keys.html#list-project-deploy-keys +type ListProjectDeployKeysOptions ListOptions + +// ListProjectDeployKeys gets a list of a project's deploy keys +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deploy_keys.html#list-project-deploy-keys +func (s *DeployKeysService) ListProjectDeployKeys(pid interface{}, opt *ListProjectDeployKeysOptions, options ...OptionFunc) ([]*DeployKey, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/deploy_keys", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var ks []*DeployKey + resp, err := s.client.Do(req, &ks) + if err != nil { + return nil, resp, err + } + + return ks, resp, err +} + +// GetDeployKey gets a single deploy key. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deploy_keys.html#single-deploy-key +func (s *DeployKeysService) GetDeployKey(pid interface{}, deployKey int, options ...OptionFunc) (*DeployKey, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/deploy_keys/%d", url.QueryEscape(project), deployKey) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + k := new(DeployKey) + resp, err := s.client.Do(req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, err +} + +// AddDeployKeyOptions represents the available ADDDeployKey() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deploy_keys.html#add-deploy-key +type AddDeployKeyOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Key *string `url:"key,omitempty" json:"key,omitempty"` + CanPush *bool `url:"can_push,omitempty" json:"can_push,omitempty"` +} + +// AddDeployKey creates a new deploy key for a project. If deploy key already +// exists in another project - it will be joined to project but only if +// original one was is accessible by same user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deploy_keys.html#add-deploy-key +func (s *DeployKeysService) AddDeployKey(pid interface{}, opt *AddDeployKeyOptions, options ...OptionFunc) (*DeployKey, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/deploy_keys", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + k := new(DeployKey) + resp, err := s.client.Do(req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, err +} + +// DeleteDeployKey deletes a deploy key from a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deploy_keys.html#delete-deploy-key +func (s *DeployKeysService) DeleteDeployKey(pid interface{}, deployKey int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/deploy_keys/%d", url.QueryEscape(project), deployKey) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// EnableDeployKey enables a deploy key. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deploy_keys.html#enable-deploy-key +func (s *DeployKeysService) EnableDeployKey(pid interface{}, deployKey int, options ...OptionFunc) (*DeployKey, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/deploy_keys/%d/enable", url.QueryEscape(project), deployKey) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + k := new(DeployKey) + resp, err := s.client.Do(req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/deployments.go b/vendor/github.com/xanzy/go-gitlab/deployments.go new file mode 100644 index 00000000..a648605e --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/deployments.go @@ -0,0 +1,121 @@ +// +// Copyright 2018, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// DeploymentsService handles communication with the deployment related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/deployments.html +type DeploymentsService struct { + client *Client +} + +// Deployment represents the Gitlab deployment +type Deployment struct { + ID int `json:"id"` + IID int `json:"iid"` + Ref string `json:"ref"` + Sha string `json:"sha"` + CreatedAt *time.Time `json:"created_at"` + User *ProjectUser `json:"user"` + Environment *Environment `json:"environment"` + Deployable struct { + ID int `json:"id"` + Status string `json:"status"` + Stage string `json:"stage"` + Name string `json:"name"` + Ref string `json:"ref"` + Tag bool `json:"tag"` + Coverage float64 `json:"coverage"` + CreatedAt *time.Time `json:"created_at"` + StartedAt *time.Time `json:"started_at"` + FinishedAt *time.Time `json:"finished_at"` + Duration float64 `json:"duration"` + User *User `json:"user"` + Commit *Commit `json:"commit"` + Pipeline struct { + ID int `json:"id"` + Sha string `json:"sha"` + Ref string `json:"ref"` + Status string `json:"status"` + } `json:"pipeline"` + Runner *Runner `json:"runner"` + } `json:"deployable"` +} + +// ListProjectDeploymentsOptions represents the available ListProjectDeployments() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/deployments.html#list-project-deployments +type ListProjectDeploymentsOptions struct { + ListOptions + OrderBy *OrderByValue `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` +} + +// ListProjectDeployments gets a list of deployments in a project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/deployments.html#list-project-deployments +func (s *DeploymentsService) ListProjectDeployments(pid interface{}, opts *ListProjectDeploymentsOptions, options ...OptionFunc) ([]*Deployment, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/deployments", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opts, options) + if err != nil { + return nil, nil, err + } + + var ds []*Deployment + resp, err := s.client.Do(req, &ds) + if err != nil { + return nil, resp, err + } + + return ds, resp, err +} + +// GetProjectDeployment get a deployment for a project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/deployments.html#get-a-specific-deployment +func (s *DeploymentsService) GetProjectDeployment(pid interface{}, deployment int, options ...OptionFunc) (*Deployment, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/deployments/%d", url.QueryEscape(project), deployment) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + d := new(Deployment) + resp, err := s.client.Do(req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/environments.go b/vendor/github.com/xanzy/go-gitlab/environments.go new file mode 100644 index 00000000..c2305ee9 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/environments.go @@ -0,0 +1,166 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// EnvironmentsService handles communication with the environment related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/environments.html +type EnvironmentsService struct { + client *Client +} + +// Environment represents a GitLab environment. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/environments.html +type Environment struct { + ID int `json:"id"` + Name string `json:"name"` + Slug string `json:"slug"` + ExternalURL string `json:"external_url"` +} + +func (env Environment) String() string { + return Stringify(env) +} + +// ListEnvironmentsOptions represents the available ListEnvironments() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/environments.html#list-environments +type ListEnvironmentsOptions ListOptions + +// ListEnvironments gets a list of environments from a project, sorted by name +// alphabetically. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/environments.html#list-environments +func (s *EnvironmentsService) ListEnvironments(pid interface{}, opts *ListEnvironmentsOptions, options ...OptionFunc) ([]*Environment, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/environments", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opts, options) + if err != nil { + return nil, nil, err + } + + var envs []*Environment + resp, err := s.client.Do(req, &envs) + if err != nil { + return nil, resp, err + } + + return envs, resp, err +} + +// CreateEnvironmentOptions represents the available CreateEnvironment() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/environments.html#create-a-new-environment +type CreateEnvironmentOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` +} + +// CreateEnvironment adds a environment to a project. This is an idempotent +// method and can be called multiple times with the same parameters. Createing +// an environment that is already a environment does not affect the +// existing environmentship. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/environments.html#create-a-new-environment +func (s *EnvironmentsService) CreateEnvironment(pid interface{}, opt *CreateEnvironmentOptions, options ...OptionFunc) (*Environment, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/environments", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + env := new(Environment) + resp, err := s.client.Do(req, env) + if err != nil { + return nil, resp, err + } + + return env, resp, err +} + +// EditEnvironmentOptions represents the available EditEnvironment() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/environments.html#edit-an-existing-environment +type EditEnvironmentOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` +} + +// EditEnvironment updates a project team environment to a specified access level.. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/environments.html#edit-an-existing-environment +func (s *EnvironmentsService) EditEnvironment(pid interface{}, environment int, opt *EditEnvironmentOptions, options ...OptionFunc) (*Environment, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/environments/%d", url.QueryEscape(project), environment) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + env := new(Environment) + resp, err := s.client.Do(req, env) + if err != nil { + return nil, resp, err + } + + return env, resp, err +} + +// DeleteEnvironment removes a environment from a project team. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/environments.html#remove-a-environment-from-a-group-or-project +func (s *EnvironmentsService) DeleteEnvironment(pid interface{}, environment int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/environments/%d", url.QueryEscape(project), environment) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/event_types.go b/vendor/github.com/xanzy/go-gitlab/event_types.go new file mode 100644 index 00000000..f051726e --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/event_types.go @@ -0,0 +1,649 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "time" +) + +// PushEvent represents a push event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#push-events +type PushEvent struct { + ObjectKind string `json:"object_kind"` + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` + CheckoutSha string `json:"checkout_sha"` + UserID int `json:"user_id"` + UserName string `json:"user_name"` + UserEmail string `json:"user_email"` + UserAvatar string `json:"user_avatar"` + ProjectID int `json:"project_id"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + Repository *Repository `json:"repository"` + Commits []*struct { + ID string `json:"id"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"author"` + Added []string `json:"added"` + Modified []string `json:"modified"` + Removed []string `json:"removed"` + } `json:"commits"` + TotalCommitsCount int `json:"total_commits_count"` +} + +// TagEvent represents a tag event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#tag-events +type TagEvent struct { + ObjectKind string `json:"object_kind"` + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` + CheckoutSha string `json:"checkout_sha"` + UserID int `json:"user_id"` + UserName string `json:"user_name"` + UserAvatar string `json:"user_avatar"` + ProjectID int `json:"project_id"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + Repository *Repository `json:"repository"` + Commits []*struct { + ID string `json:"id"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"author"` + Added []string `json:"added"` + Modified []string `json:"modified"` + Removed []string `json:"removed"` + } `json:"commits"` + TotalCommitsCount int `json:"total_commits_count"` +} + +// IssueEvent represents a issue event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#issues-events +type IssueEvent struct { + ObjectKind string `json:"object_kind"` + User *User `json:"user"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + Repository *Repository `json:"repository"` + ObjectAttributes struct { + ID int `json:"id"` + Title string `json:"title"` + AssigneeID int `json:"assignee_id"` + AuthorID int `json:"author_id"` + ProjectID int `json:"project_id"` + CreatedAt string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468) + UpdatedAt string `json:"updated_at"` // Should be *time.Time (see Gitlab issue #21468) + Position int `json:"position"` + BranchName string `json:"branch_name"` + Description string `json:"description"` + MilestoneID int `json:"milestone_id"` + State string `json:"state"` + IID int `json:"iid"` + URL string `json:"url"` + Action string `json:"action"` + } `json:"object_attributes"` + Assignee struct { + Name string `json:"name"` + Username string `json:"username"` + AvatarURL string `json:"avatar_url"` + } `json:"assignee"` +} + +// CommitCommentEvent represents a comment on a commit event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#comment-on-commit +type CommitCommentEvent struct { + ObjectKind string `json:"object_kind"` + User *User `json:"user"` + ProjectID int `json:"project_id"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + Repository *Repository `json:"repository"` + ObjectAttributes struct { + ID int `json:"id"` + Note string `json:"note"` + NoteableType string `json:"noteable_type"` + AuthorID int `json:"author_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ProjectID int `json:"project_id"` + Attachment string `json:"attachment"` + LineCode string `json:"line_code"` + CommitID string `json:"commit_id"` + NoteableID int `json:"noteable_id"` + System bool `json:"system"` + StDiff struct { + Diff string `json:"diff"` + NewPath string `json:"new_path"` + OldPath string `json:"old_path"` + AMode string `json:"a_mode"` + BMode string `json:"b_mode"` + NewFile bool `json:"new_file"` + RenamedFile bool `json:"renamed_file"` + DeletedFile bool `json:"deleted_file"` + } `json:"st_diff"` + } `json:"object_attributes"` + Commit *struct { + ID string `json:"id"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"author"` + } `json:"commit"` +} + +// MergeCommentEvent represents a comment on a merge event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#comment-on-merge-request +type MergeCommentEvent struct { + ObjectKind string `json:"object_kind"` + User *User `json:"user"` + ProjectID int `json:"project_id"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + ObjectAttributes struct { + ID int `json:"id"` + Note string `json:"note"` + NoteableType string `json:"noteable_type"` + AuthorID int `json:"author_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ProjectID int `json:"project_id"` + Attachment string `json:"attachment"` + LineCode string `json:"line_code"` + CommitID string `json:"commit_id"` + NoteableID int `json:"noteable_id"` + System bool `json:"system"` + StDiff *Diff `json:"st_diff"` + URL string `json:"url"` + } `json:"object_attributes"` + Repository *Repository `json:"repository"` + MergeRequest struct { + ID int `json:"id"` + TargetBranch string `json:"target_branch"` + SourceBranch string `json:"source_branch"` + SourceProjectID int `json:"source_project_id"` + AuthorID int `json:"author_id"` + AssigneeID int `json:"assignee_id"` + Title string `json:"title"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + MilestoneID int `json:"milestone_id"` + State string `json:"state"` + MergeStatus string `json:"merge_status"` + TargetProjectID int `json:"target_project_id"` + IID int `json:"iid"` + Description string `json:"description"` + Position int `json:"position"` + LockedAt string `json:"locked_at"` + UpdatedByID int `json:"updated_by_id"` + MergeError string `json:"merge_error"` + MergeParams struct { + ForceRemoveSourceBranch string `json:"force_remove_source_branch"` + } `json:"merge_params"` + MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` + MergeUserID int `json:"merge_user_id"` + MergeCommitSha string `json:"merge_commit_sha"` + DeletedAt string `json:"deleted_at"` + InProgressMergeCommitSha string `json:"in_progress_merge_commit_sha"` + LockVersion int `json:"lock_version"` + ApprovalsBeforeMerge string `json:"approvals_before_merge"` + RebaseCommitSha string `json:"rebase_commit_sha"` + TimeEstimate int `json:"time_estimate"` + Squash bool `json:"squash"` + LastEditedAt string `json:"last_edited_at"` + LastEditedByID int `json:"last_edited_by_id"` + Source *Repository `json:"source"` + Target *Repository `json:"target"` + LastCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"author"` + } `json:"last_commit"` + WorkInProgress bool `json:"work_in_progress"` + TotalTimeSpent int `json:"total_time_spent"` + } `json:"merge_request"` +} + +// IssueCommentEvent represents a comment on an issue event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#comment-on-issue +type IssueCommentEvent struct { + ObjectKind string `json:"object_kind"` + User *User `json:"user"` + ProjectID int `json:"project_id"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + Repository *Repository `json:"repository"` + ObjectAttributes struct { + ID int `json:"id"` + Note string `json:"note"` + NoteableType string `json:"noteable_type"` + AuthorID int `json:"author_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ProjectID int `json:"project_id"` + Attachment string `json:"attachment"` + LineCode string `json:"line_code"` + CommitID string `json:"commit_id"` + NoteableID int `json:"noteable_id"` + System bool `json:"system"` + StDiff []*Diff `json:"st_diff"` + URL string `json:"url"` + } `json:"object_attributes"` + Issue *Issue `json:"issue"` +} + +// SnippetCommentEvent represents a comment on a snippet event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#comment-on-code-snippet +type SnippetCommentEvent struct { + ObjectKind string `json:"object_kind"` + User *User `json:"user"` + ProjectID int `json:"project_id"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + Repository *Repository `json:"repository"` + ObjectAttributes struct { + ID int `json:"id"` + Note string `json:"note"` + NoteableType string `json:"noteable_type"` + AuthorID int `json:"author_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ProjectID int `json:"project_id"` + Attachment string `json:"attachment"` + LineCode string `json:"line_code"` + CommitID string `json:"commit_id"` + NoteableID int `json:"noteable_id"` + System bool `json:"system"` + StDiff *Diff `json:"st_diff"` + URL string `json:"url"` + } `json:"object_attributes"` + Snippet *Snippet `json:"snippet"` +} + +// MergeEvent represents a merge event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#merge-request-events +type MergeEvent struct { + ObjectKind string `json:"object_kind"` + User *User `json:"user"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + ObjectAttributes struct { + ID int `json:"id"` + TargetBranch string `json:"target_branch"` + SourceBranch string `json:"source_branch"` + SourceProjectID int `json:"source_project_id"` + AuthorID int `json:"author_id"` + AssigneeID int `json:"assignee_id"` + Title string `json:"title"` + CreatedAt string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468) + UpdatedAt string `json:"updated_at"` // Should be *time.Time (see Gitlab issue #21468) + StCommits []*Commit `json:"st_commits"` + StDiffs []*Diff `json:"st_diffs"` + MilestoneID int `json:"milestone_id"` + State string `json:"state"` + MergeStatus string `json:"merge_status"` + TargetProjectID int `json:"target_project_id"` + IID int `json:"iid"` + Description string `json:"description"` + Position int `json:"position"` + LockedAt string `json:"locked_at"` + UpdatedByID int `json:"updated_by_id"` + MergeError string `json:"merge_error"` + MergeParams struct { + ForceRemoveSourceBranch string `json:"force_remove_source_branch"` + } `json:"merge_params"` + MergeWhenBuildSucceeds bool `json:"merge_when_build_succeeds"` + MergeUserID int `json:"merge_user_id"` + MergeCommitSha string `json:"merge_commit_sha"` + DeletedAt string `json:"deleted_at"` + ApprovalsBeforeMerge string `json:"approvals_before_merge"` + RebaseCommitSha string `json:"rebase_commit_sha"` + InProgressMergeCommitSha string `json:"in_progress_merge_commit_sha"` + LockVersion int `json:"lock_version"` + TimeEstimate int `json:"time_estimate"` + Source *Repository `json:"source"` + Target *Repository `json:"target"` + LastCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"author"` + } `json:"last_commit"` + WorkInProgress bool `json:"work_in_progress"` + URL string `json:"url"` + Action string `json:"action"` + Assignee struct { + Name string `json:"name"` + Username string `json:"username"` + AvatarURL string `json:"avatar_url"` + } `json:"assignee"` + } `json:"object_attributes"` + Repository *Repository `json:"repository"` + Assignee struct { + Name string `json:"name"` + Username string `json:"username"` + AvatarURL string `json:"avatar_url"` + } `json:"assignee"` +} + +// WikiPageEvent represents a wiki page event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#wiki-page-events +type WikiPageEvent struct { + ObjectKind string `json:"object_kind"` + User *User `json:"user"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + Wiki struct { + WebURL string `json:"web_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + } `json:"wiki"` + ObjectAttributes struct { + Title string `json:"title"` + Content string `json:"content"` + Format string `json:"format"` + Message string `json:"message"` + Slug string `json:"slug"` + URL string `json:"url"` + Action string `json:"action"` + } `json:"object_attributes"` +} + +// PipelineEvent represents a pipeline event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#pipeline-events +type PipelineEvent struct { + ObjectKind string `json:"object_kind"` + ObjectAttributes struct { + ID int `json:"id"` + Ref string `json:"ref"` + Tag bool `json:"tag"` + Sha string `json:"sha"` + BeforeSha string `json:"before_sha"` + Status string `json:"status"` + Stages []string `json:"stages"` + CreatedAt string `json:"created_at"` + FinishedAt string `json:"finished_at"` + Duration int `json:"duration"` + } `json:"object_attributes"` + User struct { + Name string `json:"name"` + Username string `json:"username"` + AvatarURL string `json:"avatar_url"` + } `json:"user"` + Project struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` + } `json:"project"` + Commit struct { + ID string `json:"id"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"author"` + } `json:"commit"` + Builds []struct { + ID int `json:"id"` + Stage string `json:"stage"` + Name string `json:"name"` + Status string `json:"status"` + CreatedAt string `json:"created_at"` + StartedAt string `json:"started_at"` + FinishedAt string `json:"finished_at"` + When string `json:"when"` + Manual bool `json:"manual"` + User struct { + Name string `json:"name"` + Username string `json:"username"` + AvatarURL string `json:"avatar_url"` + } `json:"user"` + Runner struct { + ID int `json:"id"` + Description string `json:"description"` + Active bool `json:"active"` + IsShared bool `json:"is_shared"` + } `json:"runner"` + ArtifactsFile struct { + Filename string `json:"filename"` + Size int `json:"size"` + } `json:"artifacts_file"` + } `json:"builds"` +} + +//BuildEvent represents a build event +// +// GitLab API docs: +// https://docs.gitlab.com/ce/web_hooks/web_hooks.html#build-events +type BuildEvent struct { + ObjectKind string `json:"object_kind"` + Ref string `json:"ref"` + Tag bool `json:"tag"` + BeforeSha string `json:"before_sha"` + Sha string `json:"sha"` + BuildID int `json:"build_id"` + BuildName string `json:"build_name"` + BuildStage string `json:"build_stage"` + BuildStatus string `json:"build_status"` + BuildStartedAt string `json:"build_started_at"` + BuildFinishedAt string `json:"build_finished_at"` + BuildDuration float64 `json:"build_duration"` + BuildAllowFailure bool `json:"build_allow_failure"` + ProjectID int `json:"project_id"` + ProjectName string `json:"project_name"` + User struct { + ID int `json:"id"` + Name string `json:"name"` + Email string `json:"email"` + } `json:"user"` + Commit struct { + ID int `json:"id"` + Sha string `json:"sha"` + Message string `json:"message"` + AuthorName string `json:"author_name"` + AuthorEmail string `json:"author_email"` + Status string `json:"status"` + Duration int `json:"duration"` + StartedAt string `json:"started_at"` + FinishedAt string `json:"finished_at"` + } `json:"commit"` + Repository *Repository `json:"repository"` +} diff --git a/vendor/github.com/xanzy/go-gitlab/events.go b/vendor/github.com/xanzy/go-gitlab/events.go new file mode 100644 index 00000000..4740e4ab --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/events.go @@ -0,0 +1,147 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// EventsService handles communication with the event related methods of +// the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/events.html +type EventsService struct { + client *Client +} + +// ContributionEvent represents a user's contribution +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/events.html#get-user-contribution-events +type ContributionEvent struct { + Title string `json:"title"` + ProjectID int `json:"project_id"` + ActionName string `json:"action_name"` + TargetID int `json:"target_id"` + TargetIID int `json:"target_iid"` + TargetType string `json:"target_type"` + AuthorID int `json:"author_id"` + TargetTitle string `json:"target_title"` + CreatedAt *time.Time `json:"created_at"` + PushData struct { + CommitCount int `json:"commit_count"` + Action string `json:"action"` + RefType string `json:"ref_type"` + CommitFrom string `json:"commit_from"` + CommitTo string `json:"commit_to"` + Ref string `json:"ref"` + CommitTitle string `json:"commit_title"` + } `json:"push_data"` + Note *Note `json:"note"` + Author struct { + Name string `json:"name"` + Username string `json:"username"` + ID int `json:"id"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"author"` + AuthorUsername string `json:"author_username"` +} + +// ListContributionEventsOptions represents the options for GetUserContributionEvents +// +// GitLap API docs: +// https://docs.gitlab.com/ce/api/events.html#get-user-contribution-events +type ListContributionEventsOptions struct { + ListOptions + Action *EventTypeValue `json:"action,omitempty"` + TargetType *EventTargetTypeValue `json:"target_type,omitempty"` + Before *ISOTime `json:"before,omitempty"` + After *ISOTime `json:"after,omitempty"` + Sort *string `json:"sort,omitempty"` +} + +// ListUserContributionEvents retrieves user contribution events +// for the specified user, sorted from newest to oldest. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/events.html#get-user-contribution-events +func (s *UsersService) ListUserContributionEvents(uid interface{}, opt *ListContributionEventsOptions, options ...OptionFunc) ([]*ContributionEvent, *Response, error) { + user, err := parseID(uid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("users/%s/events", user) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var cs []*ContributionEvent + resp, err := s.client.Do(req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, err +} + +// ListCurrentUserContributionEvents gets a list currently authenticated user's events +// +// GitLab API docs: https://docs.gitlab.com/ce/api/events.html#list-currently-authenticated-user-39-s-events +func (s *EventsService) ListCurrentUserContributionEvents(opt *ListContributionEventsOptions, options ...OptionFunc) ([]*ContributionEvent, *Response, error) { + req, err := s.client.NewRequest("GET", "events", opt, options) + if err != nil { + return nil, nil, err + } + + var cs []*ContributionEvent + resp, err := s.client.Do(req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, err +} + +// ListProjectContributionEvents gets a list currently authenticated user's events +// +// GitLab API docs: https://docs.gitlab.com/ce/api/events.html#list-a-project-39-s-visible-events +func (s *EventsService) ListProjectContributionEvents(pid interface{}, opt *ListContributionEventsOptions, options ...OptionFunc) ([]*ContributionEvent, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("%s/events", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var cs []*ContributionEvent + resp, err := s.client.Do(req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/feature_flags.go b/vendor/github.com/xanzy/go-gitlab/feature_flags.go new file mode 100644 index 00000000..b6380ab0 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/feature_flags.go @@ -0,0 +1,79 @@ +package gitlab + +import ( + "fmt" + "net/url" +) + +// FeaturesService handles the communication with the application FeaturesService +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/features.html +type FeaturesService struct { + client *Client +} + +// Feature represents a GitLab feature flag. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/features.html +type Feature struct { + Name string `json:"name"` + State string `json:"state"` + Gates []Gate +} + +// Gate represents a gate of a GitLab feature flag. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/features.html +type Gate struct { + Key string `json:"key"` + Value interface{} `json:"value"` +} + +func (f Feature) String() string { + return Stringify(f) +} + +// ListFeatures gets a list of feature flags +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/features.html#list-all-features +func (s *FeaturesService) ListFeatures(options ...OptionFunc) ([]*Feature, *Response, error) { + req, err := s.client.NewRequest("GET", "features", nil, options) + if err != nil { + return nil, nil, err + } + + var f []*Feature + resp, err := s.client.Do(req, &f) + if err != nil { + return nil, resp, err + } + return f, resp, err +} + +// SetFeatureFlag sets or creates a feature flag gate +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/features.html#set-or-create-a-feature +func (s *FeaturesService) SetFeatureFlag(name string, value interface{}, options ...OptionFunc) (*Feature, *Response, error) { + u := fmt.Sprintf("features/%s", url.QueryEscape(name)) + + opt := struct { + Value interface{} `url:"value" json:"value"` + }{ + value, + } + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + f := &Feature{} + resp, err := s.client.Do(req, f) + if err != nil { + return nil, resp, err + } + return f, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/gitignore_templates.go b/vendor/github.com/xanzy/go-gitlab/gitignore_templates.go new file mode 100644 index 00000000..5c911f45 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/gitignore_templates.go @@ -0,0 +1,84 @@ +// +// Copyright 2018, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// GitIgnoreTemplatesService handles communication with the gitignore +// templates related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/templates/gitignores.html +type GitIgnoreTemplatesService struct { + client *Client +} + +// GitIgnoreTemplate represents a GitLab gitignore template. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/templates/gitignores.html +type GitIgnoreTemplate struct { + Name string `json:"name"` + Content string `json:"content"` +} + +// ListTemplatesOptions represents the available ListAllTemplates() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/templates/gitignores.html#list-gitignore-templates +type ListTemplatesOptions ListOptions + +// ListTemplates get a list of available git ignore templates +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/templates/gitignores.html#list-gitignore-templates +func (s *GitIgnoreTemplatesService) ListTemplates(opt *ListTemplatesOptions, options ...OptionFunc) ([]*GitIgnoreTemplate, *Response, error) { + req, err := s.client.NewRequest("GET", "templates/gitignores", opt, options) + if err != nil { + return nil, nil, err + } + + var gs []*GitIgnoreTemplate + resp, err := s.client.Do(req, &gs) + if err != nil { + return nil, resp, err + } + + return gs, resp, err +} + +// GetTemplate get a git ignore template +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/templates/gitignores.html#single-gitignore-template +func (s *GitIgnoreTemplatesService) GetTemplate(key string, options ...OptionFunc) (*GitIgnoreTemplate, *Response, error) { + u := fmt.Sprintf("templates/gitignores/%s", url.QueryEscape(key)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + g := new(GitIgnoreTemplate) + resp, err := s.client.Do(req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/gitlab.go b/vendor/github.com/xanzy/go-gitlab/gitlab.go new file mode 100644 index 00000000..6019d87a --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/gitlab.go @@ -0,0 +1,857 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "time" + + "github.com/google/go-querystring/query" + "golang.org/x/oauth2" +) + +const ( + defaultBaseURL = "https://gitlab.com/" + apiVersionPath = "api/v4/" + userAgent = "go-gitlab" +) + +// authType represents an authentication type within GitLab. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/ +type authType int + +// List of available authentication types. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/ +const ( + basicAuth authType = iota + oAuthToken + privateToken +) + +// AccessLevelValue represents a permission level within GitLab. +// +// GitLab API docs: https://docs.gitlab.com/ce/permissions/permissions.html +type AccessLevelValue int + +// List of available access levels +// +// GitLab API docs: https://docs.gitlab.com/ce/permissions/permissions.html +const ( + NoPermissions AccessLevelValue = 0 + GuestPermissions AccessLevelValue = 10 + ReporterPermissions AccessLevelValue = 20 + DeveloperPermissions AccessLevelValue = 30 + MasterPermissions AccessLevelValue = 40 + OwnerPermission AccessLevelValue = 50 +) + +// BuildStateValue represents a GitLab build state. +type BuildStateValue string + +// These constants represent all valid build states. +const ( + Pending BuildStateValue = "pending" + Running BuildStateValue = "running" + Success BuildStateValue = "success" + Failed BuildStateValue = "failed" + Canceled BuildStateValue = "canceled" + Skipped BuildStateValue = "skipped" +) + +// ISOTime represents an ISO 8601 formatted date +type ISOTime time.Time + +// ISO 8601 date format +const iso8601 = "2006-01-02" + +// MarshalJSON implements the json.Marshaler interface +func (t ISOTime) MarshalJSON() ([]byte, error) { + if y := time.Time(t).Year(); y < 0 || y >= 10000 { + // ISO 8901 uses 4 digits for the years + return nil, errors.New("ISOTime.MarshalJSON: year outside of range [0,9999]") + } + + b := make([]byte, 0, len(iso8601)+2) + b = append(b, '"') + b = time.Time(t).AppendFormat(b, iso8601) + b = append(b, '"') + + return b, nil +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (t *ISOTime) UnmarshalJSON(data []byte) error { + // Ignore null, like in the main JSON package + if string(data) == "null" { + return nil + } + + isotime, err := time.Parse(`"`+iso8601+`"`, string(data)) + *t = ISOTime(isotime) + + return err +} + +// String implements the Stringer interface +func (t ISOTime) String() string { + return time.Time(t).Format(iso8601) +} + +// NotificationLevelValue represents a notification level. +type NotificationLevelValue int + +// String implements the fmt.Stringer interface. +func (l NotificationLevelValue) String() string { + return notificationLevelNames[l] +} + +// MarshalJSON implements the json.Marshaler interface. +func (l NotificationLevelValue) MarshalJSON() ([]byte, error) { + return json.Marshal(l.String()) +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (l *NotificationLevelValue) UnmarshalJSON(data []byte) error { + var raw interface{} + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + + switch raw := raw.(type) { + case float64: + *l = NotificationLevelValue(raw) + case string: + *l = notificationLevelTypes[raw] + case nil: + // No action needed. + default: + return fmt.Errorf("json: cannot unmarshal %T into Go value of type %T", raw, *l) + } + + return nil +} + +// List of valid notification levels. +const ( + DisabledNotificationLevel NotificationLevelValue = iota + ParticipatingNotificationLevel + WatchNotificationLevel + GlobalNotificationLevel + MentionNotificationLevel + CustomNotificationLevel +) + +var notificationLevelNames = [...]string{ + "disabled", + "participating", + "watch", + "global", + "mention", + "custom", +} + +var notificationLevelTypes = map[string]NotificationLevelValue{ + "disabled": DisabledNotificationLevel, + "participating": ParticipatingNotificationLevel, + "watch": WatchNotificationLevel, + "global": GlobalNotificationLevel, + "mention": MentionNotificationLevel, + "custom": CustomNotificationLevel, +} + +// OrderByValue represent in which order to sort the item +type OrderByValue string + +// These constants represent all valid order by values. +const ( + OrderByCreatedAt OrderByValue = "created_at" + OrderByID OrderByValue = "id" + OrderByIID OrderByValue = "iid" + OrderByRef OrderByValue = "ref" + OrderByStatus OrderByValue = "status" + OrderByUserID OrderByValue = "user_id" +) + +// VisibilityValue represents a visibility level within GitLab. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/ +type VisibilityValue string + +// List of available visibility levels +// +// GitLab API docs: https://docs.gitlab.com/ce/api/ +const ( + PrivateVisibility VisibilityValue = "private" + InternalVisibility VisibilityValue = "internal" + PublicVisibility VisibilityValue = "public" +) + +// MergeMethodValue represents a project merge type within GitLab. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#project-merge-method +type MergeMethodValue string + +// List of available merge type +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#project-merge-method +const ( + NoFastForwardMerge MergeMethodValue = "merge" + FastForwardMerge MergeMethodValue = "ff" + RebaseMerge MergeMethodValue = "rebase_merge" +) + +// EventTypeValue represents actions type for contribution events +type EventTypeValue string + +// List of available action type +// +// GitLab API docs: https://docs.gitlab.com/ce/api/events.html#action-types +const ( + CreatedEventType EventTypeValue = "created" + UpdatedEventType EventTypeValue = "updated" + ClosedEventType EventTypeValue = "closed" + ReopenedEventType EventTypeValue = "reopened" + PushedEventType EventTypeValue = "pushed" + CommentedEventType EventTypeValue = "commented" + MergedEventType EventTypeValue = "merged" + JoinedEventType EventTypeValue = "joined" + LeftEventType EventTypeValue = "left" + DestroyedEventType EventTypeValue = "destroyed" + ExpiredEventType EventTypeValue = "expired" +) + +// EventTargetTypeValue represents actions type value for contribution events +type EventTargetTypeValue string + +// List of available action type +// +// GitLab API docs: https://docs.gitlab.com/ce/api/events.html#target-types +const ( + IssueEventTargetType EventTargetTypeValue = "issue" + MilestoneEventTargetType EventTargetTypeValue = "milestone" + MergeRequestEventTargetType EventTargetTypeValue = "merge_request" + NoteEventTargetType EventTargetTypeValue = "note" + ProjectEventTargetType EventTargetTypeValue = "project" + SnippetEventTargetType EventTargetTypeValue = "snippet" + UserEventTargetType EventTargetTypeValue = "user" +) + +// A Client manages communication with the GitLab API. +type Client struct { + // HTTP client used to communicate with the API. + client *http.Client + + // Base URL for API requests. Defaults to the public GitLab API, but can be + // set to a domain endpoint to use with a self hosted GitLab server. baseURL + // should always be specified with a trailing slash. + baseURL *url.URL + + // Token type used to make authenticated API calls. + authType authType + + // Username and password used for basix authentication. + username, password string + + // Token used to make authenticated API calls. + token string + + // User agent used when communicating with the GitLab API. + UserAgent string + + // Services used for talking to different parts of the GitLab API. + AwardEmoji *AwardEmojiService + Branches *BranchesService + BuildVariables *BuildVariablesService + BroadcastMessage *BroadcastMessagesService + Commits *CommitsService + DeployKeys *DeployKeysService + Deployments *DeploymentsService + Environments *EnvironmentsService + Events *EventsService + Features *FeaturesService + GitIgnoreTemplates *GitIgnoreTemplatesService + Groups *GroupsService + GroupMembers *GroupMembersService + GroupMilestones *GroupMilestonesService + Issues *IssuesService + IssueLinks *IssueLinksService + Jobs *JobsService + Boards *IssueBoardsService + Labels *LabelsService + MergeRequests *MergeRequestsService + MergeRequestApprovals *MergeRequestApprovalsService + Milestones *MilestonesService + Namespaces *NamespacesService + Notes *NotesService + NotificationSettings *NotificationSettingsService + PagesDomains *PagesDomainsService + Pipelines *PipelinesService + PipelineSchedules *PipelineSchedulesService + PipelineTriggers *PipelineTriggersService + Projects *ProjectsService + ProjectMembers *ProjectMembersService + ProjectSnippets *ProjectSnippetsService + ProtectedBranches *ProtectedBranchesService + Repositories *RepositoriesService + RepositoryFiles *RepositoryFilesService + Runners *RunnersService + Search *SearchService + Services *ServicesService + Session *SessionService + Settings *SettingsService + Sidekiq *SidekiqService + Snippets *SnippetsService + SystemHooks *SystemHooksService + Tags *TagsService + Todos *TodosService + Users *UsersService + Validate *ValidateService + Version *VersionService + Wikis *WikisService +} + +// ListOptions specifies the optional parameters to various List methods that +// support pagination. +type ListOptions struct { + // For paginated result sets, page of results to retrieve. + Page int `url:"page,omitempty" json:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty" json:"per_page,omitempty"` +} + +// NewClient returns a new GitLab API client. If a nil httpClient is +// provided, http.DefaultClient will be used. To use API methods which require +// authentication, provide a valid private or personal token. +func NewClient(httpClient *http.Client, token string) *Client { + client := newClient(httpClient) + client.authType = privateToken + client.token = token + return client +} + +// NewBasicAuthClient returns a new GitLab API client. If a nil httpClient is +// provided, http.DefaultClient will be used. To use API methods which require +// authentication, provide a valid username and password. +func NewBasicAuthClient(httpClient *http.Client, endpoint, username, password string) (*Client, error) { + client := newClient(httpClient) + client.authType = basicAuth + client.username = username + client.password = password + client.SetBaseURL(endpoint) + + err := client.requestOAuthToken(context.TODO()) + if err != nil { + return nil, err + } + + return client, nil +} + +func (c *Client) requestOAuthToken(ctx context.Context) error { + config := &oauth2.Config{ + Endpoint: oauth2.Endpoint{ + AuthURL: fmt.Sprintf("%s://%s/oauth/authorize", c.BaseURL().Scheme, c.BaseURL().Host), + TokenURL: fmt.Sprintf("%s://%s/oauth/token", c.BaseURL().Scheme, c.BaseURL().Host), + }, + } + ctx = context.WithValue(ctx, oauth2.HTTPClient, c.client) + t, err := config.PasswordCredentialsToken(ctx, c.username, c.password) + if err != nil { + return err + } + c.token = t.AccessToken + return nil +} + +// NewOAuthClient returns a new GitLab API client. If a nil httpClient is +// provided, http.DefaultClient will be used. To use API methods which require +// authentication, provide a valid oauth token. +func NewOAuthClient(httpClient *http.Client, token string) *Client { + client := newClient(httpClient) + client.authType = oAuthToken + client.token = token + return client +} + +func newClient(httpClient *http.Client) *Client { + if httpClient == nil { + httpClient = http.DefaultClient + } + + c := &Client{client: httpClient, UserAgent: userAgent} + if err := c.SetBaseURL(defaultBaseURL); err != nil { + // Should never happen since defaultBaseURL is our constant. + panic(err) + } + + // Create the internal timeStats service. + timeStats := &timeStatsService{client: c} + + // Create all the public services. + c.AwardEmoji = &AwardEmojiService{client: c} + c.Branches = &BranchesService{client: c} + c.BuildVariables = &BuildVariablesService{client: c} + c.BroadcastMessage = &BroadcastMessagesService{client: c} + c.Commits = &CommitsService{client: c} + c.DeployKeys = &DeployKeysService{client: c} + c.Deployments = &DeploymentsService{client: c} + c.Environments = &EnvironmentsService{client: c} + c.Events = &EventsService{client: c} + c.Features = &FeaturesService{client: c} + c.GitIgnoreTemplates = &GitIgnoreTemplatesService{client: c} + c.Groups = &GroupsService{client: c} + c.GroupMembers = &GroupMembersService{client: c} + c.GroupMilestones = &GroupMilestonesService{client: c} + c.Issues = &IssuesService{client: c, timeStats: timeStats} + c.IssueLinks = &IssueLinksService{client: c} + c.Jobs = &JobsService{client: c} + c.Boards = &IssueBoardsService{client: c} + c.Labels = &LabelsService{client: c} + c.MergeRequests = &MergeRequestsService{client: c, timeStats: timeStats} + c.MergeRequestApprovals = &MergeRequestApprovalsService{client: c} + c.Milestones = &MilestonesService{client: c} + c.Namespaces = &NamespacesService{client: c} + c.Notes = &NotesService{client: c} + c.NotificationSettings = &NotificationSettingsService{client: c} + c.PagesDomains = &PagesDomainsService{client: c} + c.Pipelines = &PipelinesService{client: c} + c.PipelineSchedules = &PipelineSchedulesService{client: c} + c.PipelineTriggers = &PipelineTriggersService{client: c} + c.Projects = &ProjectsService{client: c} + c.ProjectMembers = &ProjectMembersService{client: c} + c.ProjectSnippets = &ProjectSnippetsService{client: c} + c.ProtectedBranches = &ProtectedBranchesService{client: c} + c.Repositories = &RepositoriesService{client: c} + c.RepositoryFiles = &RepositoryFilesService{client: c} + c.Runners = &RunnersService{client: c} + c.Services = &ServicesService{client: c} + c.Search = &SearchService{client: c} + c.Session = &SessionService{client: c} + c.Settings = &SettingsService{client: c} + c.Sidekiq = &SidekiqService{client: c} + c.Snippets = &SnippetsService{client: c} + c.SystemHooks = &SystemHooksService{client: c} + c.Tags = &TagsService{client: c} + c.Todos = &TodosService{client: c} + c.Users = &UsersService{client: c} + c.Validate = &ValidateService{client: c} + c.Version = &VersionService{client: c} + c.Wikis = &WikisService{client: c} + + return c +} + +// BaseURL return a copy of the baseURL. +func (c *Client) BaseURL() *url.URL { + u := *c.baseURL + return &u +} + +// SetBaseURL sets the base URL for API requests to a custom endpoint. urlStr +// should always be specified with a trailing slash. +func (c *Client) SetBaseURL(urlStr string) error { + // Make sure the given URL end with a slash + if !strings.HasSuffix(urlStr, "/") { + urlStr += "/" + } + + baseURL, err := url.Parse(urlStr) + if err != nil { + return err + } + + if !strings.HasSuffix(baseURL.Path, apiVersionPath) { + baseURL.Path += apiVersionPath + } + + // Update the base URL of the client. + c.baseURL = baseURL + + return nil +} + +// NewRequest creates an API request. A relative URL path can be provided in +// urlStr, in which case it is resolved relative to the base URL of the Client. +// Relative URL paths should always be specified without a preceding slash. If +// specified, the value pointed to by body is JSON encoded and included as the +// request body. +func (c *Client) NewRequest(method, path string, opt interface{}, options []OptionFunc) (*http.Request, error) { + u := *c.baseURL + // Set the encoded opaque data + u.Opaque = c.baseURL.Path + path + + if opt != nil { + q, err := query.Values(opt) + if err != nil { + return nil, err + } + u.RawQuery = q.Encode() + } + + req := &http.Request{ + Method: method, + URL: &u, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: make(http.Header), + Host: u.Host, + } + + for _, fn := range options { + if fn == nil { + continue + } + + if err := fn(req); err != nil { + return nil, err + } + } + + if method == "POST" || method == "PUT" { + bodyBytes, err := json.Marshal(opt) + if err != nil { + return nil, err + } + bodyReader := bytes.NewReader(bodyBytes) + + u.RawQuery = "" + req.Body = ioutil.NopCloser(bodyReader) + req.ContentLength = int64(bodyReader.Len()) + req.Header.Set("Content-Type", "application/json") + } + + req.Header.Set("Accept", "application/json") + + switch c.authType { + case basicAuth, oAuthToken: + req.Header.Set("Authorization", "Bearer "+c.token) + case privateToken: + req.Header.Set("PRIVATE-TOKEN", c.token) + } + + if c.UserAgent != "" { + req.Header.Set("User-Agent", c.UserAgent) + } + + return req, nil +} + +// Response is a GitLab API response. This wraps the standard http.Response +// returned from GitLab and provides convenient access to things like +// pagination links. +type Response struct { + *http.Response + + // These fields provide the page values for paginating through a set of + // results. Any or all of these may be set to the zero value for + // responses that are not part of a paginated set, or for which there + // are no additional pages. + TotalItems int + TotalPages int + ItemsPerPage int + CurrentPage int + NextPage int + PreviousPage int +} + +// newResponse creates a new Response for the provided http.Response. +func newResponse(r *http.Response) *Response { + response := &Response{Response: r} + response.populatePageValues() + return response +} + +const ( + xTotal = "X-Total" + xTotalPages = "X-Total-Pages" + xPerPage = "X-Per-Page" + xPage = "X-Page" + xNextPage = "X-Next-Page" + xPrevPage = "X-Prev-Page" +) + +// populatePageValues parses the HTTP Link response headers and populates the +// various pagination link values in the Response. +func (r *Response) populatePageValues() { + if totalItems := r.Response.Header.Get(xTotal); totalItems != "" { + r.TotalItems, _ = strconv.Atoi(totalItems) + } + if totalPages := r.Response.Header.Get(xTotalPages); totalPages != "" { + r.TotalPages, _ = strconv.Atoi(totalPages) + } + if itemsPerPage := r.Response.Header.Get(xPerPage); itemsPerPage != "" { + r.ItemsPerPage, _ = strconv.Atoi(itemsPerPage) + } + if currentPage := r.Response.Header.Get(xPage); currentPage != "" { + r.CurrentPage, _ = strconv.Atoi(currentPage) + } + if nextPage := r.Response.Header.Get(xNextPage); nextPage != "" { + r.NextPage, _ = strconv.Atoi(nextPage) + } + if previousPage := r.Response.Header.Get(xPrevPage); previousPage != "" { + r.PreviousPage, _ = strconv.Atoi(previousPage) + } +} + +// Do sends an API request and returns the API response. The API response is +// JSON decoded and stored in the value pointed to by v, or returned as an +// error if an API error has occurred. If v implements the io.Writer +// interface, the raw response body will be written to v, without attempting to +// first decode it. +func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) { + resp, err := c.client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode == http.StatusUnauthorized && c.authType == basicAuth { + err = c.requestOAuthToken(req.Context()) + if err != nil { + return nil, err + } + return c.Do(req, v) + } + + response := newResponse(resp) + + err = CheckResponse(resp) + if err != nil { + // even though there was an error, we still return the response + // in case the caller wants to inspect it further + return response, err + } + + if v != nil { + if w, ok := v.(io.Writer); ok { + _, err = io.Copy(w, resp.Body) + } else { + err = json.NewDecoder(resp.Body).Decode(v) + } + } + + return response, err +} + +// Helper function to accept and format both the project ID or name as project +// identifier for all API calls. +func parseID(id interface{}) (string, error) { + switch v := id.(type) { + case int: + return strconv.Itoa(v), nil + case string: + return v, nil + default: + return "", fmt.Errorf("invalid ID type %#v, the ID must be an int or a string", id) + } +} + +// An ErrorResponse reports one or more errors caused by an API request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/README.html#data-validation-and-error-reporting +type ErrorResponse struct { + Body []byte + Response *http.Response + Message string +} + +func (e *ErrorResponse) Error() string { + path, _ := url.QueryUnescape(e.Response.Request.URL.Opaque) + u := fmt.Sprintf("%s://%s%s", e.Response.Request.URL.Scheme, e.Response.Request.URL.Host, path) + return fmt.Sprintf("%s %s: %d %s", e.Response.Request.Method, u, e.Response.StatusCode, e.Message) +} + +// CheckResponse checks the API response for errors, and returns them if present. +func CheckResponse(r *http.Response) error { + switch r.StatusCode { + case 200, 201, 202, 204, 304: + return nil + } + + errorResponse := &ErrorResponse{Response: r} + data, err := ioutil.ReadAll(r.Body) + if err == nil && data != nil { + errorResponse.Body = data + + var raw interface{} + if err := json.Unmarshal(data, &raw); err != nil { + errorResponse.Message = "failed to parse unknown error format" + } else { + errorResponse.Message = parseError(raw) + } + } + + return errorResponse +} + +// Format: +// { +// "message": { +// "": [ +// "", +// "", +// ... +// ], +// "": { +// "": [ +// "", +// "", +// ... +// ], +// } +// }, +// "error": "" +// } +func parseError(raw interface{}) string { + switch raw := raw.(type) { + case string: + return raw + + case []interface{}: + var errs []string + for _, v := range raw { + errs = append(errs, parseError(v)) + } + return fmt.Sprintf("[%s]", strings.Join(errs, ", ")) + + case map[string]interface{}: + var errs []string + for k, v := range raw { + errs = append(errs, fmt.Sprintf("{%s: %s}", k, parseError(v))) + } + sort.Strings(errs) + return strings.Join(errs, ", ") + + default: + return fmt.Sprintf("failed to parse unexpected error type: %T", raw) + } +} + +// OptionFunc can be passed to all API requests to make the API call as if you were +// another user, provided your private token is from an administrator account. +// +// GitLab docs: https://docs.gitlab.com/ce/api/README.html#sudo +type OptionFunc func(*http.Request) error + +// WithSudo takes either a username or user ID and sets the SUDO request header +func WithSudo(uid interface{}) OptionFunc { + return func(req *http.Request) error { + user, err := parseID(uid) + if err != nil { + return err + } + req.Header.Set("SUDO", user) + return nil + } +} + +// WithContext runs the request with the provided context +func WithContext(ctx context.Context) OptionFunc { + return func(req *http.Request) error { + *req = *req.WithContext(ctx) + return nil + } +} + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { + p := new(bool) + *p = v + return p +} + +// Int is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it, but unlike Int32 +// its argument value is an int. +func Int(v int) *int { + p := new(int) + *p = v + return p +} + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { + p := new(string) + *p = v + return p +} + +// AccessLevel is a helper routine that allocates a new AccessLevelValue +// to store v and returns a pointer to it. +func AccessLevel(v AccessLevelValue) *AccessLevelValue { + p := new(AccessLevelValue) + *p = v + return p +} + +// BuildState is a helper routine that allocates a new BuildStateValue +// to store v and returns a pointer to it. +func BuildState(v BuildStateValue) *BuildStateValue { + p := new(BuildStateValue) + *p = v + return p +} + +// NotificationLevel is a helper routine that allocates a new NotificationLevelValue +// to store v and returns a pointer to it. +func NotificationLevel(v NotificationLevelValue) *NotificationLevelValue { + p := new(NotificationLevelValue) + *p = v + return p +} + +// OrderBy is a helper routine that allocates a new OrderByValue +// to store v and returns a pointer to it. +func OrderBy(v OrderByValue) *OrderByValue { + p := new(OrderByValue) + *p = v + return p +} + +// Visibility is a helper routine that allocates a new VisibilityValue +// to store v and returns a pointer to it. +func Visibility(v VisibilityValue) *VisibilityValue { + p := new(VisibilityValue) + *p = v + return p +} + +// MergeMethod is a helper routine that allocates a new MergeMethod +// to sotre v and returns a pointer to it. +func MergeMethod(v MergeMethodValue) *MergeMethodValue { + p := new(MergeMethodValue) + *p = v + return p +} diff --git a/vendor/github.com/xanzy/go-gitlab/group_members.go b/vendor/github.com/xanzy/go-gitlab/group_members.go new file mode 100644 index 00000000..9423ff68 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/group_members.go @@ -0,0 +1,195 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// GroupMembersService handles communication with the group members +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/members.html +type GroupMembersService struct { + client *Client +} + +// GroupMember represents a GitLab group member. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/members.html +type GroupMember struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + AccessLevel AccessLevelValue `json:"access_level"` + ExpiresAt *ISOTime `json:"expires_at"` +} + +// ListGroupMembersOptions represents the available ListGroupMembers() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project +type ListGroupMembersOptions struct { + ListOptions + Query *string `url:"query,omitempty" json:"query,omitempty"` +} + +// ListGroupMembers get a list of group members viewable by the authenticated +// user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project +func (s *GroupsService) ListGroupMembers(gid interface{}, opt *ListGroupMembersOptions, options ...OptionFunc) ([]*GroupMember, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/members", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var gm []*GroupMember + resp, err := s.client.Do(req, &gm) + if err != nil { + return nil, resp, err + } + + return gm, resp, err +} + +// AddGroupMemberOptions represents the available AddGroupMember() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#add-a-member-to-a-group-or-project +type AddGroupMemberOptions struct { + UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` + AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` + ExpiresAt *string `url:"expires_at,omitempty" json:"expires_at"` +} + +// GetGroupMember gets a member of a group. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#get-a-member-of-a-group-or-project +func (s *GroupMembersService) GetGroupMember(gid interface{}, user int, options ...OptionFunc) (*GroupMember, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/members/%d", url.QueryEscape(group), user) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + gm := new(GroupMember) + resp, err := s.client.Do(req, gm) + if err != nil { + return nil, resp, err + } + + return gm, resp, err +} + +// AddGroupMember adds a user to the list of group members. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#add-a-member-to-a-group-or-project +func (s *GroupMembersService) AddGroupMember(gid interface{}, opt *AddGroupMemberOptions, options ...OptionFunc) (*GroupMember, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/members", url.QueryEscape(group)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + gm := new(GroupMember) + resp, err := s.client.Do(req, gm) + if err != nil { + return nil, resp, err + } + + return gm, resp, err +} + +// EditGroupMemberOptions represents the available EditGroupMember() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project +type EditGroupMemberOptions struct { + AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` + ExpiresAt *string `url:"expires_at,omitempty" json:"expires_at"` +} + +// EditGroupMember updates a member of a group. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project +func (s *GroupMembersService) EditGroupMember(gid interface{}, user int, opt *EditGroupMemberOptions, options ...OptionFunc) (*GroupMember, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/members/%d", url.QueryEscape(group), user) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + gm := new(GroupMember) + resp, err := s.client.Do(req, gm) + if err != nil { + return nil, resp, err + } + + return gm, resp, err +} + +// RemoveGroupMember removes user from user team. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#remove-a-member-from-a-group-or-project +func (s *GroupMembersService) RemoveGroupMember(gid interface{}, user int, options ...OptionFunc) (*Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("groups/%s/members/%d", url.QueryEscape(group), user) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/group_milestones.go b/vendor/github.com/xanzy/go-gitlab/group_milestones.go new file mode 100644 index 00000000..8335a47b --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/group_milestones.go @@ -0,0 +1,250 @@ +// +// Copyright 2018, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// GroupMilestonesService handles communication with the milestone related +// methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/group_milestones.html +type GroupMilestonesService struct { + client *Client +} + +// GroupMilestone represents a GitLab milestone. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/group_milestones.html +type GroupMilestone struct { + ID int `json:"id"` + IID int `json:"iid"` + GroupID int `json:"group_id"` + Title string `json:"title"` + Description string `json:"description"` + StartDate *ISOTime `json:"start_date"` + DueDate *ISOTime `json:"due_date"` + State string `json:"state"` + UpdatedAt *time.Time `json:"updated_at"` + CreatedAt *time.Time `json:"created_at"` +} + +func (m GroupMilestone) String() string { + return Stringify(m) +} + +// ListGroupMilestonesOptions represents the available +// ListGroupMilestones() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#list-group-milestones +type ListGroupMilestonesOptions struct { + ListOptions + IIDs []int `url:"iids,omitempty" json:"iids,omitempty"` + State string `url:"state,omitempty" json:"state,omitempty"` + Search string `url:"search,omitempty" json:"search,omitempty"` +} + +// ListGroupMilestones returns a list of group milestones. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#list-group-milestones +func (s *GroupMilestonesService) ListGroupMilestones(gid interface{}, opt *ListGroupMilestonesOptions, options ...OptionFunc) ([]*GroupMilestone, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/milestones", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var m []*GroupMilestone + resp, err := s.client.Do(req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// GetGroupMilestone gets a single group milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#get-single-milestone +func (s *GroupMilestonesService) GetGroupMilestone(gid interface{}, milestone int, options ...OptionFunc) (*GroupMilestone, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/milestones/%d", url.QueryEscape(group), milestone) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + m := new(GroupMilestone) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// CreateGroupMilestoneOptions represents the available CreateGroupMilestone() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#create-new-milestone +type CreateGroupMilestoneOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"` + DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` +} + +// CreateGroupMilestone creates a new group milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#create-new-milestone +func (s *GroupMilestonesService) CreateGroupMilestone(gid interface{}, opt *CreateGroupMilestoneOptions, options ...OptionFunc) (*GroupMilestone, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/milestones", url.QueryEscape(group)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + m := new(GroupMilestone) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// UpdateGroupMilestoneOptions represents the available UpdateGroupMilestone() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#edit-milestone +type UpdateGroupMilestoneOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"` + DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` + StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"` +} + +// UpdateGroupMilestone updates an existing group milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#edit-milestone +func (s *GroupMilestonesService) UpdateGroupMilestone(gid interface{}, milestone int, opt *UpdateGroupMilestoneOptions, options ...OptionFunc) (*GroupMilestone, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/milestones/%d", url.QueryEscape(group), milestone) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + m := new(GroupMilestone) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// GetGroupMilestoneIssuesOptions represents the available GetGroupMilestoneIssues() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#get-all-issues-assigned-to-a-single-milestone +type GetGroupMilestoneIssuesOptions ListOptions + +// GetGroupMilestoneIssues gets all issues assigned to a single group milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#get-all-issues-assigned-to-a-single-milestone +func (s *GroupMilestonesService) GetGroupMilestoneIssues(gid interface{}, milestone int, opt *GetGroupMilestoneIssuesOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/milestones/%d/issues", url.QueryEscape(group), milestone) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var i []*Issue + resp, err := s.client.Do(req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// GetGroupMilestoneMergeRequestsOptions represents the available +// GetGroupMilestoneMergeRequests() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#get-all-merge-requests-assigned-to-a-single-milestone +type GetGroupMilestoneMergeRequestsOptions ListOptions + +// GetGroupMilestoneMergeRequests gets all merge requests assigned to a +// single group milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/group_milestones.html#get-all-merge-requests-assigned-to-a-single-milestone +func (s *GroupMilestonesService) GetGroupMilestoneMergeRequests(gid interface{}, milestone int, opt *GetGroupMilestoneMergeRequestsOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/milestones/%d/merge_requests", url.QueryEscape(group), milestone) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var mr []*MergeRequest + resp, err := s.client.Do(req, &mr) + if err != nil { + return nil, resp, err + } + + return mr, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/groups.go b/vendor/github.com/xanzy/go-gitlab/groups.go new file mode 100644 index 00000000..d379915c --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/groups.go @@ -0,0 +1,307 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// GroupsService handles communication with the group related methods of +// the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html +type GroupsService struct { + client *Client +} + +// Group represents a GitLab group. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html +type Group struct { + ID int `json:"id"` + Name string `json:"name"` + Path string `json:"path"` + Description string `json:"description"` + Visibility *VisibilityValue `json:"visibility"` + LFSEnabled bool `json:"lfs_enabled"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + RequestAccessEnabled bool `json:"request_access_enabled"` + FullName string `json:"full_name"` + FullPath string `json:"full_path"` + ParentID int `json:"parent_id"` + Projects []*Project `json:"projects"` + Statistics *StorageStatistics `json:"statistics"` +} + +// ListGroupsOptions represents the available ListGroups() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#list-project-groups +type ListGroupsOptions struct { + ListOptions + AllAvailable *bool `url:"all_available,omitempty" json:"all_available,omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Owned *bool `url:"owned,omitempty" json:"owned,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"` +} + +// ListGroups gets a list of groups (as user: my groups, as admin: all groups). +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/groups.html#list-project-groups +func (s *GroupsService) ListGroups(opt *ListGroupsOptions, options ...OptionFunc) ([]*Group, *Response, error) { + req, err := s.client.NewRequest("GET", "groups", opt, options) + if err != nil { + return nil, nil, err + } + + var g []*Group + resp, err := s.client.Do(req, &g) + if err != nil { + return nil, resp, err + } + + return g, resp, err +} + +// GetGroup gets all details of a group. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#details-of-a-group +func (s *GroupsService) GetGroup(gid interface{}, options ...OptionFunc) (*Group, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + g := new(Group) + resp, err := s.client.Do(req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, err +} + +// CreateGroupOptions represents the available CreateGroup() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#new-group +type CreateGroupOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + Path *string `url:"path,omitempty" json:"path,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` + LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"` + RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"` + ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"` +} + +// CreateGroup creates a new project group. Available only for users who can +// create groups. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#new-group +func (s *GroupsService) CreateGroup(opt *CreateGroupOptions, options ...OptionFunc) (*Group, *Response, error) { + req, err := s.client.NewRequest("POST", "groups", opt, options) + if err != nil { + return nil, nil, err + } + + g := new(Group) + resp, err := s.client.Do(req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, err +} + +// TransferGroup transfers a project to the Group namespace. Available only +// for admin. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/groups.html#transfer-project-to-group +func (s *GroupsService) TransferGroup(gid interface{}, pid interface{}, options ...OptionFunc) (*Group, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + + u := fmt.Sprintf("groups/%s/projects/%s", url.QueryEscape(group), + url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + g := new(Group) + resp, err := s.client.Do(req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, err +} + +// UpdateGroupOptions represents the set of available options to update a Group; +// as of today these are exactly the same available when creating a new Group. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#update-group +type UpdateGroupOptions CreateGroupOptions + +// UpdateGroup updates an existing group; only available to group owners and +// administrators. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#update-group +func (s *GroupsService) UpdateGroup(gid interface{}, opt *UpdateGroupOptions, options ...OptionFunc) (*Group, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s", url.QueryEscape(group)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + g := new(Group) + resp, err := s.client.Do(req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, err +} + +// DeleteGroup removes group with all projects inside. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#remove-group +func (s *GroupsService) DeleteGroup(gid interface{}, options ...OptionFunc) (*Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("groups/%s", url.QueryEscape(group)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// SearchGroup get all groups that match your string in their name or path. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#search-for-group +func (s *GroupsService) SearchGroup(query string, options ...OptionFunc) ([]*Group, *Response, error) { + var q struct { + Search string `url:"search,omitempty" json:"search,omitempty"` + } + q.Search = query + + req, err := s.client.NewRequest("GET", "groups", &q, options) + if err != nil { + return nil, nil, err + } + + var g []*Group + resp, err := s.client.Do(req, &g) + if err != nil { + return nil, resp, err + } + + return g, resp, err +} + +// ListGroupProjectsOptions represents the available ListGroupProjects() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/groups.html#list-a-group-39-s-projects +type ListGroupProjectsOptions ListProjectsOptions + +// ListGroupProjects get a list of group projects +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/groups.html#list-a-group-39-s-projects +func (s *GroupsService) ListGroupProjects(gid interface{}, opt *ListGroupProjectsOptions, options ...OptionFunc) ([]*Project, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/projects", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var p []*Project + resp, err := s.client.Do(req, &p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// ListSubgroupsOptions represents the available ListSubgroupsOptions() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/groups.html#list-a-groups-s-subgroups +type ListSubgroupsOptions ListGroupsOptions + +// ListSubgroups gets a list of subgroups for a given project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/groups.html#list-a-groups-s-subgroups +func (s *GroupsService) ListSubgroups(gid interface{}, opt *ListSubgroupsOptions, options ...OptionFunc) ([]*Group, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/subgroups", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var g []*Group + resp, err := s.client.Do(req, &g) + if err != nil { + return nil, resp, err + } + + return g, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/issue_links.go b/vendor/github.com/xanzy/go-gitlab/issue_links.go new file mode 100644 index 00000000..5dfd76aa --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/issue_links.go @@ -0,0 +1,128 @@ +// +// Copyright 2017, Arkbriar +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// IssueLinksService handles communication with the issue relations related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html +type IssueLinksService struct { + client *Client +} + +// IssueLink represents a two-way relation between two issues. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html +type IssueLink struct { + SourceIssue *Issue `json:"source_issue"` + TargetIssue *Issue `json:"target_issue"` +} + +// ListIssueRelations gets a list of related issues of a given issue, +// sorted by the relationship creation datetime (ascending). +// +// Issues will be filtered according to the user authorizations. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/issue_links.html#list-issue-relations +func (s *IssueLinksService) ListIssueRelations(pid interface{}, issueIID int, options ...OptionFunc) ([]*Issue, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d/links", url.QueryEscape(project), issueIID) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var is []*Issue + resp, err := s.client.Do(req, &is) + if err != nil { + return nil, resp, err + } + + return is, resp, err +} + +// CreateIssueLinkOptions represents the available CreateIssueLink() options. +// +// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html +type CreateIssueLinkOptions struct { + TargetProjectID *string `json:"target_project_id"` + TargetIssueIID *string `json:"target_issue_iid"` +} + +// CreateIssueLink creates a two-way relation between two issues. +// User must be allowed to update both issues in order to succeed. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/issue_links.html#create-an-issue-link +func (s *IssueLinksService) CreateIssueLink(pid interface{}, issueIID int, opt *CreateIssueLinkOptions, options ...OptionFunc) (*IssueLink, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d/links", url.QueryEscape(project), issueIID) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + i := new(IssueLink) + resp, err := s.client.Do(req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// DeleteIssueLink deletes an issue link, thus removes the two-way relationship. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/issue_links.html#delete-an-issue-link +func (s *IssueLinksService) DeleteIssueLink(pid interface{}, issueIID, issueLinkID int, options ...OptionFunc) (*IssueLink, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d/links/%d", + url.QueryEscape(project), + issueIID, + issueLinkID) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, nil, err + } + + i := new(IssueLink) + resp, err := s.client.Do(req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/issues.go b/vendor/github.com/xanzy/go-gitlab/issues.go new file mode 100644 index 00000000..411146a3 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/issues.go @@ -0,0 +1,436 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "encoding/json" + "fmt" + "net/url" + "strings" + "time" +) + +// IssuesService handles communication with the issue related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html +type IssuesService struct { + client *Client + timeStats *timeStatsService +} + +// Issue represents a GitLab issue. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html +type Issue struct { + ID int `json:"id"` + IID int `json:"iid"` + ProjectID int `json:"project_id"` + Milestone *Milestone `json:"milestone"` + Author struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + } `json:"author"` + Description string `json:"description"` + State string `json:"state"` + Assignees []struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + } `json:"assignees"` + Assignee struct { + ID int `json:"id"` + Name string `json:"name"` + Username string `json:"username"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"assignee"` + Upvotes int `json:"upvotes"` + Downvotes int `json:"downvotes"` + Labels []string `json:"labels"` + Title string `json:"title"` + UpdatedAt *time.Time `json:"updated_at"` + CreatedAt *time.Time `json:"created_at"` + ClosedAt *time.Time `json:"closed_at"` + Subscribed bool `json:"subscribed"` + UserNotesCount int `json:"user_notes_count"` + DueDate *ISOTime `json:"due_date"` + WebURL string `json:"web_url"` + TimeStats *TimeStats `json:"time_stats"` + Confidential bool `json:"confidential"` + Weight int `json:"weight"` + DiscussionLocked bool `json:"discussion_locked"` + Links struct { + Self string `json:"self"` + Notes string `json:"notes"` + AwardEmoji string `json:"award_emoji"` + Project string `json:"project"` + } `json:"_links"` + IssueLinkID int `json:"issue_link_id"` +} + +func (i Issue) String() string { + return Stringify(i) +} + +// Labels is a custom type with specific marshaling characteristics. +type Labels []string + +// MarshalJSON implements the json.Marshaler interface. +func (l *Labels) MarshalJSON() ([]byte, error) { + return json.Marshal(strings.Join(*l, ",")) +} + +// ListIssuesOptions represents the available ListIssues() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#list-issues +type ListIssuesOptions struct { + ListOptions + State *string `url:"state,omitempty" json:"state,omitempty"` + Labels Labels `url:"labels,comma,omitempty" json:"labels,omitempty"` + Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` + AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` + IIDs []int `url:"iids[],omitempty" json:"iids,omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` + CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` + CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` + UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` + UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` +} + +// ListIssues gets all issues created by authenticated user. This function +// takes pagination parameters page and per_page to restrict the list of issues. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#list-issues +func (s *IssuesService) ListIssues(opt *ListIssuesOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + req, err := s.client.NewRequest("GET", "issues", opt, options) + if err != nil { + return nil, nil, err + } + + var i []*Issue + resp, err := s.client.Do(req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// ListGroupIssuesOptions represents the available ListGroupIssues() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#list-group-issues +type ListGroupIssuesOptions struct { + ListOptions + State *string `url:"state,omitempty" json:"state,omitempty"` + Labels Labels `url:"labels,comma,omitempty" json:"labels,omitempty"` + IIDs []int `url:"iids[],omitempty" json:"iids,omitempty"` + Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` + AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` + CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` + CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` + UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` + UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` +} + +// ListGroupIssues gets a list of group issues. This function accepts +// pagination parameters page and per_page to return the list of group issues. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#list-group-issues +func (s *IssuesService) ListGroupIssues(pid interface{}, opt *ListGroupIssuesOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + group, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/issues", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var i []*Issue + resp, err := s.client.Do(req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// ListProjectIssuesOptions represents the available ListProjectIssues() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#list-project-issues +type ListProjectIssuesOptions struct { + ListOptions + IIDs []int `url:"iids[],omitempty" json:"iids,omitempty"` + State *string `url:"state,omitempty" json:"state,omitempty"` + Labels Labels `url:"labels,comma,omitempty" json:"labels,omitempty"` + Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` + AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` + CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` + CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` + UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` + UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` +} + +// ListProjectIssues gets a list of project issues. This function accepts +// pagination parameters page and per_page to return the list of project issues. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#list-project-issues +func (s *IssuesService) ListProjectIssues(pid interface{}, opt *ListProjectIssuesOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var i []*Issue + resp, err := s.client.Do(req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// GetIssue gets a single project issue. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#single-issues +func (s *IssuesService) GetIssue(pid interface{}, issue int, options ...OptionFunc) (*Issue, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d", url.QueryEscape(project), issue) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// CreateIssueOptions represents the available CreateIssue() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#new-issues +type CreateIssueOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` + AssigneeIDs []int `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` + MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + Labels Labels `url:"labels,comma,omitempty" json:"labels,omitempty"` + CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` + DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` + MergeRequestToResolveDiscussionsOf *int `url:"merge_request_to_resolve_discussions_of,omitempty" json:"merge_request_to_resolve_discussions_of,omitempty"` + DiscussionToResolve *string `url:"discussion_to_resolve,omitempty" json:"discussion_to_resolve,omitempty"` + Weight *int `url:"weight,omitempty" json:"weight,omitempty"` +} + +// CreateIssue creates a new project issue. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#new-issues +func (s *IssuesService) CreateIssue(pid interface{}, opt *CreateIssueOptions, options ...OptionFunc) (*Issue, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// UpdateIssueOptions represents the available UpdateIssue() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#edit-issues +type UpdateIssueOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` + AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + Labels Labels `url:"labels,comma,omitempty" json:"labels,omitempty"` + StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"` + UpdatedAt *time.Time `url:"updated_at,omitempty" json:"updated_at,omitempty"` + DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` + DiscussionLocked *bool `url:"discussion_locked,omitempty" json:"discussion_locked,omitempty"` +} + +// UpdateIssue updates an existing project issue. This function is also used +// to mark an issue as closed. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#edit-issues +func (s *IssuesService) UpdateIssue(pid interface{}, issue int, opt *UpdateIssueOptions, options ...OptionFunc) (*Issue, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d", url.QueryEscape(project), issue) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// DeleteIssue deletes a single project issue. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/issues.html#delete-an-issue +func (s *IssuesService) DeleteIssue(pid interface{}, issue int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d", url.QueryEscape(project), issue) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ListMergeRequestsClosingIssueOptions represents the available +// ListMergeRequestsClosingIssue() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/issues.html#list-merge-requests-that-will-close-issue-on-merge +type ListMergeRequestsClosingIssueOptions ListOptions + +// ListMergeRequestsClosingIssue gets all the merge requests that will close +// issue when merged. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/issues.html#list-merge-requests-that-will-close-issue-on-merge +func (s *IssuesService) ListMergeRequestsClosingIssue(pid interface{}, issue int, opt *ListMergeRequestsClosingIssueOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("/projects/%s/issues/%d/closed_by", url.QueryEscape(project), issue) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var m []*MergeRequest + resp, err := s.client.Do(req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// SetTimeEstimate sets the time estimate for a single project issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/issues.html#set-a-time-estimate-for-an-issue +func (s *IssuesService) SetTimeEstimate(pid interface{}, issue int, opt *SetTimeEstimateOptions, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.setTimeEstimate(pid, "issues", issue, opt, options...) +} + +// ResetTimeEstimate resets the time estimate for a single project issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/issues.html#reset-the-time-estimate-for-an-issue +func (s *IssuesService) ResetTimeEstimate(pid interface{}, issue int, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.resetTimeEstimate(pid, "issues", issue, options...) +} + +// AddSpentTime adds spent time for a single project issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/issues.html#add-spent-time-for-an-issue +func (s *IssuesService) AddSpentTime(pid interface{}, issue int, opt *AddSpentTimeOptions, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.addSpentTime(pid, "issues", issue, opt, options...) +} + +// ResetSpentTime resets the spent time for a single project issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/issues.html#reset-spent-time-for-an-issue +func (s *IssuesService) ResetSpentTime(pid interface{}, issue int, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.resetSpentTime(pid, "issues", issue, options...) +} + +// GetTimeSpent gets the spent time for a single project issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/issues.html#get-time-tracking-stats +func (s *IssuesService) GetTimeSpent(pid interface{}, issue int, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.getTimeSpent(pid, "issues", issue, options...) +} diff --git a/vendor/github.com/xanzy/go-gitlab/jobs.go b/vendor/github.com/xanzy/go-gitlab/jobs.go new file mode 100644 index 00000000..669f96dd --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/jobs.go @@ -0,0 +1,350 @@ +// +// Copyright 2017, Arkbriar +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "bytes" + "fmt" + "io" + "net/url" + "time" +) + +// JobsService handles communication with the ci builds related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/jobs.html +type JobsService struct { + client *Client +} + +// Job represents a ci build. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/jobs.html +type Job struct { + Commit *Commit `json:"commit"` + CreatedAt *time.Time `json:"created_at"` + Coverage float64 `json:"coverage"` + ArtifactsFile struct { + Filename string `json:"filename"` + Size int `json:"size"` + } `json:"artifacts_file"` + FinishedAt *time.Time `json:"finished_at"` + ID int `json:"id"` + Name string `json:"name"` + Ref string `json:"ref"` + Runner struct { + ID int `json:"id"` + Description string `json:"description"` + Active bool `json:"active"` + IsShared bool `json:"is_shared"` + Name string `json:"name"` + } `json:"runner"` + Stage string `json:"stage"` + StartedAt *time.Time `json:"started_at"` + Status string `json:"status"` + Tag bool `json:"tag"` + User *User `json:"user"` +} + +// ListJobsOptions are options for two list apis +type ListJobsOptions struct { + ListOptions + Scope []BuildStateValue `url:"scope,omitempty" json:"scope,omitempty"` +} + +// ListProjectJobs gets a list of jobs in a project. +// +// The scope of jobs to show, one or array of: created, pending, running, +// failed, success, canceled, skipped; showing all jobs if none provided +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#list-project-jobs +func (s *JobsService) ListProjectJobs(pid interface{}, opts *ListJobsOptions, options ...OptionFunc) ([]Job, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opts, options) + if err != nil { + return nil, nil, err + } + + var jobs []Job + resp, err := s.client.Do(req, &jobs) + if err != nil { + return nil, resp, err + } + + return jobs, resp, err +} + +// ListPipelineJobs gets a list of jobs for specific pipeline in a +// project. If the pipeline ID is not found, it will respond with 404. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#list-pipeline-jobs +func (s *JobsService) ListPipelineJobs(pid interface{}, pipelineID int, opts *ListJobsOptions, options ...OptionFunc) ([]*Job, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipelines/%d/jobs", url.QueryEscape(project), pipelineID) + + req, err := s.client.NewRequest("GET", u, opts, options) + if err != nil { + return nil, nil, err + } + + var jobs []*Job + resp, err := s.client.Do(req, &jobs) + if err != nil { + return nil, resp, err + } + + return jobs, resp, err +} + +// GetJob gets a single job of a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#get-a-single-job +func (s *JobsService) GetJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/%d", url.QueryEscape(project), jobID) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + job := new(Job) + resp, err := s.client.Do(req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, err +} + +// GetJobArtifacts get jobs artifacts of a project +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#get-job-artifacts +func (s *JobsService) GetJobArtifacts(pid interface{}, jobID int, options ...OptionFunc) (io.Reader, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/%d/artifacts", url.QueryEscape(project), jobID) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + artifactsBuf := new(bytes.Buffer) + resp, err := s.client.Do(req, artifactsBuf) + if err != nil { + return nil, resp, err + } + + return artifactsBuf, resp, err +} + +// DownloadArtifactsFile download the artifacts file from the given +// reference name and job provided the job finished successfully. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#download-the-artifacts-file +func (s *JobsService) DownloadArtifactsFile(pid interface{}, refName string, job string, options ...OptionFunc) (io.Reader, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/artifacts/%s/download?job=%s", url.QueryEscape(project), refName, job) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + artifactsBuf := new(bytes.Buffer) + resp, err := s.client.Do(req, artifactsBuf) + if err != nil { + return nil, resp, err + } + + return artifactsBuf, resp, err +} + +// GetTraceFile gets a trace of a specific job of a project +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#get-a-trace-file +func (s *JobsService) GetTraceFile(pid interface{}, jobID int, options ...OptionFunc) (io.Reader, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/%d/trace", url.QueryEscape(project), jobID) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + traceBuf := new(bytes.Buffer) + resp, err := s.client.Do(req, traceBuf) + if err != nil { + return nil, resp, err + } + + return traceBuf, resp, err +} + +// CancelJob cancels a single job of a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#cancel-a-job +func (s *JobsService) CancelJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/%d/cancel", url.QueryEscape(project), jobID) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + job := new(Job) + resp, err := s.client.Do(req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, err +} + +// RetryJob retries a single job of a project +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#retry-a-job +func (s *JobsService) RetryJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/%d/retry", url.QueryEscape(project), jobID) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + job := new(Job) + resp, err := s.client.Do(req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, err +} + +// EraseJob erases a single job of a project, removes a job +// artifacts and a job trace. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#erase-a-job +func (s *JobsService) EraseJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/%d/erase", url.QueryEscape(project), jobID) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + job := new(Job) + resp, err := s.client.Do(req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, err +} + +// KeepArtifacts prevents artifacts from being deleted when +// expiration is set. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#keep-artifacts +func (s *JobsService) KeepArtifacts(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/%d/artifacts/keep", url.QueryEscape(project), jobID) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + job := new(Job) + resp, err := s.client.Do(req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, err +} + +// PlayJob triggers a manual action to start a job. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/jobs.html#play-a-job +func (s *JobsService) PlayJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/jobs/%d/play", url.QueryEscape(project), jobID) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + job := new(Job) + resp, err := s.client.Do(req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/labels.go b/vendor/github.com/xanzy/go-gitlab/labels.go new file mode 100644 index 00000000..2f8307d2 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/labels.go @@ -0,0 +1,228 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// LabelsService handles communication with the label related methods of the +// GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html +type LabelsService struct { + client *Client +} + +// Label represents a GitLab label. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html +type Label struct { + ID int `json:"id"` + Name string `json:"name"` + Color string `json:"color"` + Description string `json:"description"` + OpenIssuesCount int `json:"open_issues_count"` + ClosedIssuesCount int `json:"closed_issues_count"` + OpenMergeRequestsCount int `json:"open_merge_requests_count"` + Subscribed bool `json:"subscribed"` + Priority int `json:"priority"` +} + +func (l Label) String() string { + return Stringify(l) +} + +// ListLabelsOptions represents the available ListLabels() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#list-labels +type ListLabelsOptions ListOptions + +// ListLabels gets all labels for given project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#list-labels +func (s *LabelsService) ListLabels(pid interface{}, opt *ListLabelsOptions, options ...OptionFunc) ([]*Label, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/labels", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var l []*Label + resp, err := s.client.Do(req, &l) + if err != nil { + return nil, resp, err + } + + return l, resp, err +} + +// CreateLabelOptions represents the available CreateLabel() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#create-a-new-label +type CreateLabelOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + Color *string `url:"color,omitempty" json:"color,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` +} + +// CreateLabel creates a new label for given repository with given name and +// color. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#create-a-new-label +func (s *LabelsService) CreateLabel(pid interface{}, opt *CreateLabelOptions, options ...OptionFunc) (*Label, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/labels", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + l := new(Label) + resp, err := s.client.Do(req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, err +} + +// DeleteLabelOptions represents the available DeleteLabel() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#delete-a-label +type DeleteLabelOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` +} + +// DeleteLabel deletes a label given by its name. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#delete-a-label +func (s *LabelsService) DeleteLabel(pid interface{}, opt *DeleteLabelOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/labels", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// UpdateLabelOptions represents the available UpdateLabel() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#delete-a-label +type UpdateLabelOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + NewName *string `url:"new_name,omitempty" json:"new_name,omitempty"` + Color *string `url:"color,omitempty" json:"color,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` +} + +// UpdateLabel updates an existing label with new name or now color. At least +// one parameter is required, to update the label. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/labels.html#edit-an-existing-label +func (s *LabelsService) UpdateLabel(pid interface{}, opt *UpdateLabelOptions, options ...OptionFunc) (*Label, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/labels", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + l := new(Label) + resp, err := s.client.Do(req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, err +} + +// SubscribeToLabel subscribes the authenticated user to a label to receive +// notifications. If the user is already subscribed to the label, the status +// code 304 is returned. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/labels.html#subscribe-to-a-label +func (s *LabelsService) SubscribeToLabel(pid interface{}, labelID interface{}, options ...OptionFunc) (*Label, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + label, err := parseID(labelID) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/labels/%s/subscribe", url.QueryEscape(project), label) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + l := new(Label) + resp, err := s.client.Do(req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, err +} + +// UnsubscribeFromLabel unsubscribes the authenticated user from a label to not +// receive notifications from it. If the user is not subscribed to the label, the +// status code 304 is returned. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/labels.html#unsubscribe-from-a-label +func (s *LabelsService) UnsubscribeFromLabel(pid interface{}, labelID interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + label, err := parseID(labelID) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/labels/%s/unsubscribe", url.QueryEscape(project), label) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/merge_request_approvals.go b/vendor/github.com/xanzy/go-gitlab/merge_request_approvals.go new file mode 100644 index 00000000..e03cb618 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/merge_request_approvals.go @@ -0,0 +1,125 @@ +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// MergeRequestApprovalsService handles communication with the merge request +// approvals related methods of the GitLab API. This includes reading/updating +// approval settings and approve/unapproving merge requests +// +// GitLab API docs: https://docs.gitlab.com/ee/api/merge_request_approvals.html +type MergeRequestApprovalsService struct { + client *Client +} + +// MergeRequestApprovals represents GitLab merge request approvals. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/merge_request_approvals.html#merge-request-level-mr-approvals +type MergeRequestApprovals struct { + ID int `json:"id"` + ProjectID int `json:"project_id"` + Title string `json:"title"` + Description string `json:"description"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + MergeStatus string `json:"merge_status"` + ApprovalsRequired int `json:"approvals_required"` + ApprovalsLeft int `json:"approvals_left"` + ApprovedBy []struct { + User struct { + ID int `json:"id"` + Name string `json:"name"` + Username string `json:"username"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"user"` + } `json:"approved_by"` + Approvers []struct { + User struct { + ID int `json:"id"` + Name string `json:"name"` + Username string `json:"username"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"user"` + } `json:"approvers"` + ApproverGroups []struct { + Group struct { + ID int `json:"id"` + Name string `json:"name"` + Path string `json:"path"` + Description string `json:"description"` + Visibility string `json:"visibility"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + FullName string `json:"full_name"` + FullPath string `json:"full_path"` + LFSEnabled bool `json:"lfs_enabled"` + RequestAccessEnabled bool `json:"request_access_enabled"` + } `json:"group"` + } `json:"approver_group"` +} + +func (m MergeRequestApprovals) String() string { + return Stringify(m) +} + +// ApproveMergeRequestOptions represents the available ApproveMergeRequest() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/merge_request_approvals.html#approve-merge-request +type ApproveMergeRequestOptions struct { + Sha *string `url:"sha,omitempty" json:"sha,omitempty"` +} + +// ApproveMergeRequest approves a merge request on GitLab. If a non-empty sha +// is provided then it must match the sha at the HEAD of the MR. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/merge_request_approvals.html#approve-merge-request +func (s *MergeRequestApprovalsService) ApproveMergeRequest(pid interface{}, mr int, opt *ApproveMergeRequestOptions, options ...OptionFunc) (*MergeRequestApprovals, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/approve", url.QueryEscape(project), mr) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequestApprovals) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// UnapproveMergeRequest unapproves a previously approved merge request on GitLab. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/merge_request_approvals.html#unapprove-merge-request +func (s *MergeRequestApprovalsService) UnapproveMergeRequest(pid interface{}, mr int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/unapprove", url.QueryEscape(project), mr) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/merge_requests.go b/vendor/github.com/xanzy/go-gitlab/merge_requests.go new file mode 100644 index 00000000..daddd623 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/merge_requests.go @@ -0,0 +1,743 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// MergeRequestsService handles communication with the merge requests related +// methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/merge_requests.html +type MergeRequestsService struct { + client *Client + timeStats *timeStatsService +} + +// MergeRequest represents a GitLab merge request. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/merge_requests.html +type MergeRequest struct { + ID int `json:"id"` + IID int `json:"iid"` + TargetBranch string `json:"target_branch"` + SourceBranch string `json:"source_branch"` + ProjectID int `json:"project_id"` + Title string `json:"title"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + Upvotes int `json:"upvotes"` + Downvotes int `json:"downvotes"` + Author struct { + ID int `json:"id"` + Username string `json:"username"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + } `json:"author"` + Assignee struct { + ID int `json:"id"` + Username string `json:"username"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + } `json:"assignee"` + SourceProjectID int `json:"source_project_id"` + TargetProjectID int `json:"target_project_id"` + Labels []string `json:"labels"` + Description string `json:"description"` + WorkInProgress bool `json:"work_in_progress"` + Milestone *Milestone `json:"milestone"` + MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` + MergeStatus string `json:"merge_status"` + MergedBy struct { + ID int `json:"id"` + Username string `json:"username"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + } `json:"merged_by"` + MergedAt *time.Time `json:"merged_at"` + ClosedBy struct { + ID int `json:"id"` + Username string `json:"username"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + } `json:"closed_by"` + ClosedAt *time.Time `json:"closed_at"` + Subscribed bool `json:"subscribed"` + SHA string `json:"sha"` + MergeCommitSHA string `json:"merge_commit_sha"` + UserNotesCount int `json:"user_notes_count"` + ChangesCount string `json:"changes_count"` + ShouldRemoveSourceBranch bool `json:"should_remove_source_branch"` + ForceRemoveSourceBranch bool `json:"force_remove_source_branch"` + WebURL string `json:"web_url"` + DiscussionLocked bool `json:"discussion_locked"` + Changes []struct { + OldPath string `json:"old_path"` + NewPath string `json:"new_path"` + AMode string `json:"a_mode"` + BMode string `json:"b_mode"` + Diff string `json:"diff"` + NewFile bool `json:"new_file"` + RenamedFile bool `json:"renamed_file"` + DeletedFile bool `json:"deleted_file"` + } `json:"changes"` + TimeStats *TimeStats `json:"time_stats"` + Squash bool `json:"squash"` + Pipeline struct { + ID int `json:"id"` + Ref string `json:"ref"` + SHA string `json:"sha"` + Status string `json:"status"` + } `json:"pipeline"` +} + +func (m MergeRequest) String() string { + return Stringify(m) +} + +// MergeRequestDiffVersion represents Gitlab merge request version. +// +// Gitlab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-a-single-mr-diff-version +type MergeRequestDiffVersion struct { + ID int `json:"id"` + HeadCommitSHA string `json:"head_commit_sha,omitempty"` + BaseCommitSHA string `json:"base_commit_sha,omitempty"` + StartCommitSHA string `json:"start_commit_sha,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + MergeRequestID int `json:"merge_request_id,omitempty"` + State string `json:"state,omitempty"` + RealSize string `json:"real_size,omitempty"` + Commits []*Commit `json:"commits,omitempty"` + Diffs []*Diff `json:"diffs,omitempty"` +} + +func (m MergeRequestDiffVersion) String() string { + return Stringify(m) +} + +// ListMergeRequestsOptions represents the available ListMergeRequests() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#list-merge-requests +type ListMergeRequestsOptions struct { + ListOptions + State *string `url:"state,omitempty" json:"state,omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` + View *string `url:"view,omitempty" json:"view,omitempty"` + Labels Labels `url:"labels,omitempty" json:"labels,omitempty"` + CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` + CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` + AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` +} + +// ListMergeRequests gets all merge requests. The state parameter can be used +// to get only merge requests with a given state (opened, closed, or merged) +// or all of them (all). The pagination parameters page and per_page can be +// used to restrict the list of merge requests. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#list-merge-requests +func (s *MergeRequestsService) ListMergeRequests(opt *ListMergeRequestsOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) { + req, err := s.client.NewRequest("GET", "merge_requests", opt, options) + if err != nil { + return nil, nil, err + } + + var m []*MergeRequest + resp, err := s.client.Do(req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// ListProjectMergeRequestsOptions represents the available ListMergeRequests() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#list-project-merge-requests +type ListProjectMergeRequestsOptions struct { + ListOptions + IIDs []int `url:"iids[],omitempty" json:"iids,omitempty"` + State *string `url:"state,omitempty" json:"state,omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` + View *string `url:"view,omitempty" json:"view,omitempty"` + Labels Labels `url:"labels,omitempty" json:"labels,omitempty"` + CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` + CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` + AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` +} + +// ListProjectMergeRequests gets all merge requests for this project. The state +// parameter can be used to get only merge requests with a given state (opened, +// closed, or merged) or all of them (all). The pagination parameters page and +// per_page can be used to restrict the list of merge requests. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#list-merge-requests +func (s *MergeRequestsService) ListProjectMergeRequests(pid interface{}, opt *ListProjectMergeRequestsOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var m []*MergeRequest + resp, err := s.client.Do(req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// GetMergeRequest shows information about a single merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-single-mr +func (s *MergeRequestsService) GetMergeRequest(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequest) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// GetMergeRequestApprovals gets information about a merge requests approvals +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/merge_request_approvals.html#merge-request-level-mr-approvals +func (s *MergeRequestsService) GetMergeRequestApprovals(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequestApprovals, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/approvals", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + a := new(MergeRequestApprovals) + resp, err := s.client.Do(req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, err +} + +// GetMergeRequestCommitsOptions represents the available GetMergeRequestCommits() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-single-mr-commits +type GetMergeRequestCommitsOptions ListOptions + +// GetMergeRequestCommits gets a list of merge request commits. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-single-mr-commits +func (s *MergeRequestsService) GetMergeRequestCommits(pid interface{}, mergeRequest int, opt *GetMergeRequestCommitsOptions, options ...OptionFunc) ([]*Commit, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/commits", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var c []*Commit + resp, err := s.client.Do(req, &c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} + +// GetMergeRequestChanges shows information about the merge request including +// its files and changes. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-single-mr-changes +func (s *MergeRequestsService) GetMergeRequestChanges(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/changes", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequest) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// ListMergeRequestPipelines gets all pipelines for the provided merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#list-mr-pipelines +func (s *MergeRequestsService) ListMergeRequestPipelines(pid interface{}, mergeRequest int, options ...OptionFunc) (PipelineList, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/pipelines", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var p PipelineList + resp, err := s.client.Do(req, &p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// GetIssuesClosedOnMergeOptions represents the available GetIssuesClosedOnMerge() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#list-issues-that-will-close-on-merge +type GetIssuesClosedOnMergeOptions ListOptions + +// GetIssuesClosedOnMerge gets all the issues that would be closed by merging the +// provided merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#list-issues-that-will-close-on-merge +func (s *MergeRequestsService) GetIssuesClosedOnMerge(pid interface{}, mergeRequest int, opt *GetIssuesClosedOnMergeOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("/projects/%s/merge_requests/%d/closes_issues", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var i []*Issue + resp, err := s.client.Do(req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// CreateMergeRequestOptions represents the available CreateMergeRequest() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#create-mr +type CreateMergeRequestOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"` + TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"` + AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + TargetProjectID *int `url:"target_project_id,omitempty" json:"target_project_id,omitempty"` +} + +// CreateMergeRequest creates a new merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#create-mr +func (s *MergeRequestsService) CreateMergeRequest(pid interface{}, opt *CreateMergeRequestOptions, options ...OptionFunc) (*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequest) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// UpdateMergeRequestOptions represents the available UpdateMergeRequest() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#update-mr +type UpdateMergeRequestOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"` + AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + Labels Labels `url:"labels,comma,omitempty" json:"labels,omitempty"` + MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"` +} + +// UpdateMergeRequest updates an existing project milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#update-mr +func (s *MergeRequestsService) UpdateMergeRequest(pid interface{}, mergeRequest int, opt *UpdateMergeRequestOptions, options ...OptionFunc) (*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequest) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// DeleteMergeRequest deletes a merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#delete-a-merge-request +func (s *MergeRequestsService) DeleteMergeRequest(pid interface{}, mergeRequest int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// AcceptMergeRequestOptions represents the available AcceptMergeRequest() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#accept-mr +type AcceptMergeRequestOptions struct { + MergeCommitMessage *string `url:"merge_commit_message,omitempty" json:"merge_commit_message,omitempty"` + ShouldRemoveSourceBranch *bool `url:"should_remove_source_branch,omitempty" json:"should_remove_source_branch,omitempty"` + MergeWhenPipelineSucceeds *bool `url:"merge_when_pipeline_succeeds,omitempty" json:"merge_when_pipeline_succeeds,omitempty"` + Sha *string `url:"sha,omitempty" json:"sha,omitempty"` +} + +// AcceptMergeRequest merges changes submitted with MR using this API. If merge +// success you get 200 OK. If it has some conflicts and can not be merged - you +// get 405 and error message 'Branch cannot be merged'. If merge request is +// already merged or closed - you get 405 and error message 'Method Not Allowed' +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#accept-mr +func (s *MergeRequestsService) AcceptMergeRequest(pid interface{}, mergeRequest int, opt *AcceptMergeRequestOptions, options ...OptionFunc) (*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/merge", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequest) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// CancelMergeWhenPipelineSucceeds cancels a merge when pipeline succeeds. If +// you don't have permissions to accept this merge request - you'll get a 401. +// If the merge request is already merged or closed - you get 405 and error +// message 'Method Not Allowed'. In case the merge request is not set to be +// merged when the pipeline succeeds, you'll also get a 406 error. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#cancel-merge-when-pipeline-succeeds +func (s *MergeRequestsService) CancelMergeWhenPipelineSucceeds(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/cancel_merge_when_pipeline_succeeds", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("PUT", u, nil, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequest) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// GetMergeRequestDiffVersionsOptions represents the available +// GetMergeRequestDiffVersions() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-mr-diff-versions +type GetMergeRequestDiffVersionsOptions ListOptions + +// GetMergeRequestDiffVersions get a list of merge request diff versions. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-mr-diff-versions +func (s *MergeRequestsService) GetMergeRequestDiffVersions(pid interface{}, mergeRequest int, opt *GetMergeRequestDiffVersionsOptions, options ...OptionFunc) ([]*MergeRequestDiffVersion, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/versions", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var v []*MergeRequestDiffVersion + resp, err := s.client.Do(req, &v) + if err != nil { + return nil, resp, err + } + + return v, resp, err +} + +// GetSingleMergeRequestDiffVersion get a single MR diff version +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-a-single-mr-diff-version +func (s *MergeRequestsService) GetSingleMergeRequestDiffVersion(pid interface{}, mergeRequest, version int, options ...OptionFunc) (*MergeRequestDiffVersion, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/versions/%d", url.QueryEscape(project), mergeRequest, version) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var v = new(MergeRequestDiffVersion) + resp, err := s.client.Do(req, v) + if err != nil { + return nil, resp, err + } + + return v, resp, err +} + +// SubscribeToMergeRequest subscribes the authenticated user to the given merge request +// to receive notifications. If the user is already subscribed to the +// merge request, the status code 304 is returned. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#subscribe-to-a-merge-request +func (s *MergeRequestsService) SubscribeToMergeRequest(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/subscribe", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequest) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// UnsubscribeFromMergeRequest unsubscribes the authenticated user from the given merge request +// to not receive notifications from that merge request. If the user is +// not subscribed to the merge request, status code 304 is returned. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#unsubscribe-from-a-merge-request +func (s *MergeRequestsService) UnsubscribeFromMergeRequest(pid interface{}, mergeRequest int, options ...OptionFunc) (*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/unsubscribe", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + m := new(MergeRequest) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// CreateTodo manually creates a todo for the current user on a merge request. +// If there already exists a todo for the user on that merge request, +// status code 304 is returned. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#create-a-todo +func (s *MergeRequestsService) CreateTodo(pid interface{}, mergeRequest int, options ...OptionFunc) (*Todo, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/todo", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + t := new(Todo) + resp, err := s.client.Do(req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// SetTimeEstimate sets the time estimate for a single project merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#set-a-time-estimate-for-a-merge-request +func (s *MergeRequestsService) SetTimeEstimate(pid interface{}, mergeRequest int, opt *SetTimeEstimateOptions, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.setTimeEstimate(pid, "merge_requests", mergeRequest, opt, options...) +} + +// ResetTimeEstimate resets the time estimate for a single project merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#reset-the-time-estimate-for-a-merge-request +func (s *MergeRequestsService) ResetTimeEstimate(pid interface{}, mergeRequest int, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.resetTimeEstimate(pid, "merge_requests", mergeRequest, options...) +} + +// AddSpentTime adds spent time for a single project merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#add-spent-time-for-a-merge-request +func (s *MergeRequestsService) AddSpentTime(pid interface{}, mergeRequest int, opt *AddSpentTimeOptions, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.addSpentTime(pid, "merge_requests", mergeRequest, opt, options...) +} + +// ResetSpentTime resets the spent time for a single project merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#reset-spent-time-for-a-merge-request +func (s *MergeRequestsService) ResetSpentTime(pid interface{}, mergeRequest int, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.resetSpentTime(pid, "merge_requests", mergeRequest, options...) +} + +// GetTimeSpent gets the spent time for a single project merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/merge_requests.html#get-time-tracking-stats +func (s *MergeRequestsService) GetTimeSpent(pid interface{}, mergeRequest int, options ...OptionFunc) (*TimeStats, *Response, error) { + return s.timeStats.getTimeSpent(pid, "merge_requests", mergeRequest, options...) +} diff --git a/vendor/github.com/xanzy/go-gitlab/milestones.go b/vendor/github.com/xanzy/go-gitlab/milestones.go new file mode 100644 index 00000000..c1a69f93 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/milestones.go @@ -0,0 +1,267 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// MilestonesService handles communication with the milestone related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/milestones.html +type MilestonesService struct { + client *Client +} + +// Milestone represents a GitLab milestone. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/milestones.html +type Milestone struct { + ID int `json:"id"` + IID int `json:"iid"` + ProjectID int `json:"project_id"` + Title string `json:"title"` + Description string `json:"description"` + StartDate *ISOTime `json:"start_date"` + DueDate *ISOTime `json:"due_date"` + State string `json:"state"` + UpdatedAt *time.Time `json:"updated_at"` + CreatedAt *time.Time `json:"created_at"` +} + +func (m Milestone) String() string { + return Stringify(m) +} + +// ListMilestonesOptions represents the available ListMilestones() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#list-project-milestones +type ListMilestonesOptions struct { + ListOptions + IIDs []int `url:"iids,omitempty" json:"iids,omitempty"` + State string `url:"state,omitempty" json:"state,omitempty"` + Search string `url:"search,omitempty" json:"search,omitempty"` +} + +// ListMilestones returns a list of project milestones. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#list-project-milestones +func (s *MilestonesService) ListMilestones(pid interface{}, opt *ListMilestonesOptions, options ...OptionFunc) ([]*Milestone, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/milestones", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var m []*Milestone + resp, err := s.client.Do(req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// GetMilestone gets a single project milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#get-single-milestone +func (s *MilestonesService) GetMilestone(pid interface{}, milestone int, options ...OptionFunc) (*Milestone, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + m := new(Milestone) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// CreateMilestoneOptions represents the available CreateMilestone() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#create-new-milestone +type CreateMilestoneOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"` + DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` +} + +// CreateMilestone creates a new project milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#create-new-milestone +func (s *MilestonesService) CreateMilestone(pid interface{}, opt *CreateMilestoneOptions, options ...OptionFunc) (*Milestone, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/milestones", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + m := new(Milestone) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// UpdateMilestoneOptions represents the available UpdateMilestone() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#edit-milestone +type UpdateMilestoneOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"` + DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` + StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"` +} + +// UpdateMilestone updates an existing project milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#edit-milestone +func (s *MilestonesService) UpdateMilestone(pid interface{}, milestone int, opt *UpdateMilestoneOptions, options ...OptionFunc) (*Milestone, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + m := new(Milestone) + resp, err := s.client.Do(req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, err +} + +// DeleteMilestone deletes a specified project milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#delete-project-milestone +func (s *MilestonesService) DeleteMilestone(pid interface{}, milestone int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + return s.client.Do(req, nil) +} + +// GetMilestoneIssuesOptions represents the available GetMilestoneIssues() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone +type GetMilestoneIssuesOptions ListOptions + +// GetMilestoneIssues gets all issues assigned to a single project milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone +func (s *MilestonesService) GetMilestoneIssues(pid interface{}, milestone int, opt *GetMilestoneIssuesOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/milestones/%d/issues", url.QueryEscape(project), milestone) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var i []*Issue + resp, err := s.client.Do(req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, err +} + +// GetMilestoneMergeRequestsOptions represents the available +// GetMilestoneMergeRequests() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#get-all-merge-requests-assigned-to-a-single-milestone +type GetMilestoneMergeRequestsOptions ListOptions + +// GetMilestoneMergeRequests gets all merge requests assigned to a single +// project milestone. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/milestones.html#get-all-merge-requests-assigned-to-a-single-milestone +func (s *MilestonesService) GetMilestoneMergeRequests(pid interface{}, milestone int, opt *GetMilestoneMergeRequestsOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/milestones/%d/merge_requests", url.QueryEscape(project), milestone) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var mr []*MergeRequest + resp, err := s.client.Do(req, &mr) + if err != nil { + return nil, resp, err + } + + return mr, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/namespaces.go b/vendor/github.com/xanzy/go-gitlab/namespaces.go new file mode 100644 index 00000000..9add6449 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/namespaces.go @@ -0,0 +1,122 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" +) + +// NamespacesService handles communication with the namespace related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/namespaces.html +type NamespacesService struct { + client *Client +} + +// Namespace represents a GitLab namespace. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/namespaces.html +type Namespace struct { + ID int `json:"id"` + Name string `json:"name"` + Path string `json:"path"` + Kind string `json:"kind"` + FullPath string `json:"full_path"` + ParentID int `json:"parent_id"` + MembersCountWithDescendants int `json:"members_count_with_descendants"` +} + +func (n Namespace) String() string { + return Stringify(n) +} + +// ListNamespacesOptions represents the available ListNamespaces() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/namespaces.html#list-namespaces +type ListNamespacesOptions struct { + ListOptions + Search *string `url:"search,omitempty" json:"search,omitempty"` +} + +// ListNamespaces gets a list of projects accessible by the authenticated user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/namespaces.html#list-namespaces +func (s *NamespacesService) ListNamespaces(opt *ListNamespacesOptions, options ...OptionFunc) ([]*Namespace, *Response, error) { + req, err := s.client.NewRequest("GET", "namespaces", opt, options) + if err != nil { + return nil, nil, err + } + + var n []*Namespace + resp, err := s.client.Do(req, &n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// SearchNamespace gets all namespaces that match your string in their name +// or path. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/namespaces.html#search-for-namespace +func (s *NamespacesService) SearchNamespace(query string, options ...OptionFunc) ([]*Namespace, *Response, error) { + var q struct { + Search string `url:"search,omitempty" json:"search,omitempty"` + } + q.Search = query + + req, err := s.client.NewRequest("GET", "namespaces", &q, options) + if err != nil { + return nil, nil, err + } + + var n []*Namespace + resp, err := s.client.Do(req, &n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// GetNamespace gets a namespace by id. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/namespaces.html#get-namespace-by-id +func (s *NamespacesService) GetNamespace(id interface{}, options ...OptionFunc) (*Namespace, *Response, error) { + namespace, err := parseID(id) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("namespaces/%s", namespace) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + n := new(Namespace) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/notes.go b/vendor/github.com/xanzy/go-gitlab/notes.go new file mode 100644 index 00000000..2ad7f9d4 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/notes.go @@ -0,0 +1,490 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// NotesService handles communication with the notes related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/notes.html +type NotesService struct { + client *Client +} + +// Note represents a GitLab note. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/notes.html +type Note struct { + ID int `json:"id"` + Body string `json:"body"` + Attachment string `json:"attachment"` + Title string `json:"title"` + FileName string `json:"file_name"` + Author struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"author"` + System bool `json:"system"` + ExpiresAt *time.Time `json:"expires_at"` + UpdatedAt *time.Time `json:"updated_at"` + CreatedAt *time.Time `json:"created_at"` + NoteableID int `json:"noteable_id"` + NoteableType string `json:"noteable_type"` + NoteableIID int `json:"noteable_iid"` +} + +func (n Note) String() string { + return Stringify(n) +} + +// ListIssueNotesOptions represents the available ListIssueNotes() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#list-project-issue-notes +type ListIssueNotesOptions ListOptions + +// ListIssueNotes gets a list of all notes for a single issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#list-project-issue-notes +func (s *NotesService) ListIssueNotes(pid interface{}, issue int, opt *ListIssueNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d/notes", url.QueryEscape(project), issue) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var n []*Note + resp, err := s.client.Do(req, &n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// GetIssueNote returns a single note for a specific project issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#get-single-issue-note +func (s *NotesService) GetIssueNote(pid interface{}, issue, note int, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", url.QueryEscape(project), issue, note) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// CreateIssueNoteOptions represents the available CreateIssueNote() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#create-new-issue-note +type CreateIssueNoteOptions struct { + Body *string `url:"body,omitempty" json:"body,omitempty"` +} + +// CreateIssueNote creates a new note to a single project issue. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#create-new-issue-note +func (s *NotesService) CreateIssueNote(pid interface{}, issue int, opt *CreateIssueNoteOptions, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d/notes", url.QueryEscape(project), issue) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// UpdateIssueNoteOptions represents the available UpdateIssueNote() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#modify-existing-issue-note +type UpdateIssueNoteOptions struct { + Body *string `url:"body,omitempty" json:"body,omitempty"` +} + +// UpdateIssueNote modifies existing note of an issue. +// +// https://docs.gitlab.com/ce/api/notes.html#modify-existing-issue-note +func (s *NotesService) UpdateIssueNote(pid interface{}, issue, note int, opt *UpdateIssueNoteOptions, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", url.QueryEscape(project), issue, note) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// DeleteIssueNote deletes an existing note of an issue. +// +// https://docs.gitlab.com/ce/api/notes.html#delete-an-issue-note +func (s *NotesService) DeleteIssueNote(pid interface{}, issue, note int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", url.QueryEscape(project), issue, note) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ListSnippetNotesOptions represents the available ListSnippetNotes() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#list-all-snippet-notes +type ListSnippetNotesOptions ListOptions + +// ListSnippetNotes gets a list of all notes for a single snippet. Snippet +// notes are comments users can post to a snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#list-all-snippet-notes +func (s *NotesService) ListSnippetNotes(pid interface{}, snippet int, opt *ListSnippetNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d/notes", url.QueryEscape(project), snippet) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var n []*Note + resp, err := s.client.Do(req, &n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// GetSnippetNote returns a single note for a given snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#get-single-snippet-note +func (s *NotesService) GetSnippetNote(pid interface{}, snippet, note int, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", url.QueryEscape(project), snippet, note) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// CreateSnippetNoteOptions represents the available CreateSnippetNote() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#create-new-snippet-note +type CreateSnippetNoteOptions struct { + Body *string `url:"body,omitempty" json:"body,omitempty"` +} + +// CreateSnippetNote creates a new note for a single snippet. Snippet notes are +// comments users can post to a snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#create-new-snippet-note +func (s *NotesService) CreateSnippetNote(pid interface{}, snippet int, opt *CreateSnippetNoteOptions, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d/notes", url.QueryEscape(project), snippet) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// UpdateSnippetNoteOptions represents the available UpdateSnippetNote() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#modify-existing-snippet-note +type UpdateSnippetNoteOptions struct { + Body *string `url:"body,omitempty" json:"body,omitempty"` +} + +// UpdateSnippetNote modifies existing note of a snippet. +// +// https://docs.gitlab.com/ce/api/notes.html#modify-existing-snippet-note +func (s *NotesService) UpdateSnippetNote(pid interface{}, snippet, note int, opt *UpdateSnippetNoteOptions, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", url.QueryEscape(project), snippet, note) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// DeleteSnippetNote deletes an existing note of a snippet. +// +// https://docs.gitlab.com/ce/api/notes.html#delete-a-snippet-note +func (s *NotesService) DeleteSnippetNote(pid interface{}, snippet, note int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", url.QueryEscape(project), snippet, note) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ListMergeRequestNotesOptions represents the available ListMergeRequestNotes() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#list-all-merge-request-notes +type ListMergeRequestNotesOptions ListOptions + +// ListMergeRequestNotes gets a list of all notes for a single merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#list-all-merge-request-notes +func (s *NotesService) ListMergeRequestNotes(pid interface{}, mergeRequest int, opt *ListMergeRequestNotesOptions, options ...OptionFunc) ([]*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var n []*Note + resp, err := s.client.Do(req, &n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// GetMergeRequestNote returns a single note for a given merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#get-single-merge-request-note +func (s *NotesService) GetMergeRequestNote(pid interface{}, mergeRequest, note int, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/notes/%d", url.QueryEscape(project), mergeRequest, note) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// CreateMergeRequestNoteOptions represents the available +// CreateMergeRequestNote() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#create-new-merge-request-note +type CreateMergeRequestNoteOptions struct { + Body *string `url:"body,omitempty" json:"body,omitempty"` +} + +// CreateMergeRequestNote creates a new note for a single merge request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#create-new-merge-request-note +func (s *NotesService) CreateMergeRequestNote(pid interface{}, mergeRequest int, opt *CreateMergeRequestNoteOptions, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", url.QueryEscape(project), mergeRequest) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// UpdateMergeRequestNoteOptions represents the available +// UpdateMergeRequestNote() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note +type UpdateMergeRequestNoteOptions struct { + Body *string `url:"body,omitempty" json:"body,omitempty"` +} + +// UpdateMergeRequestNote modifies existing note of a merge request. +// +// https://docs.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note +func (s *NotesService) UpdateMergeRequestNote(pid interface{}, mergeRequest, note int, opt *UpdateMergeRequestNoteOptions, options ...OptionFunc) (*Note, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf( + "projects/%s/merge_requests/%d/notes/%d", url.QueryEscape(project), mergeRequest, note) + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + n := new(Note) + resp, err := s.client.Do(req, n) + if err != nil { + return nil, resp, err + } + + return n, resp, err +} + +// DeleteMergeRequestNote deletes an existing note of a merge request. +// +// https://docs.gitlab.com/ce/api/notes.html#delete-a-merge-request-note +func (s *NotesService) DeleteMergeRequestNote(pid interface{}, mergeRequest, note int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf( + "projects/%s/merge_requests/%d/notes/%d", url.QueryEscape(project), mergeRequest, note) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/notifications.go b/vendor/github.com/xanzy/go-gitlab/notifications.go new file mode 100644 index 00000000..a5501dd7 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/notifications.go @@ -0,0 +1,214 @@ +package gitlab + +import ( + "errors" + "fmt" + "net/url" +) + +// NotificationSettingsService handles communication with the notification settings +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/notification_settings.html +type NotificationSettingsService struct { + client *Client +} + +// NotificationSettings represents the Gitlab notification setting. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notification_settings.html#notification-settings +type NotificationSettings struct { + Level NotificationLevelValue `json:"level"` + NotificationEmail string `json:"notification_email"` + Events *NotificationEvents `json:"events"` +} + +// NotificationEvents represents the available notification setting events. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notification_settings.html#notification-settings +type NotificationEvents struct { + CloseIssue bool `json:"close_issue"` + CloseMergeRequest bool `json:"close_merge_request"` + FailedPipeline bool `json:"failed_pipeline"` + MergeMergeRequest bool `json:"merge_merge_request"` + NewIssue bool `json:"new_issue"` + NewMergeRequest bool `json:"new_merge_request"` + NewNote bool `json:"new_note"` + ReassignIssue bool `json:"reassign_issue"` + ReassignMergeRequest bool `json:"reassign_merge_request"` + ReopenIssue bool `json:"reopen_issue"` + ReopenMergeRequest bool `json:"reopen_merge_request"` + SuccessPipeline bool `json:"success_pipeline"` +} + +func (ns NotificationSettings) String() string { + return Stringify(ns) +} + +// GetGlobalSettings returns current notification settings and email address. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notification_settings.html#global-notification-settings +func (s *NotificationSettingsService) GetGlobalSettings(options ...OptionFunc) (*NotificationSettings, *Response, error) { + u := "notification_settings" + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + ns := new(NotificationSettings) + resp, err := s.client.Do(req, ns) + if err != nil { + return nil, resp, err + } + + return ns, resp, err +} + +// NotificationSettingsOptions represents the available options that can be passed +// to the API when updating the notification settings. +type NotificationSettingsOptions struct { + Level *NotificationLevelValue `url:"level,omitempty" json:"level,omitempty"` + NotificationEmail *string `url:"notification_email,omitempty" json:"notification_email,omitempty"` + CloseIssue *bool `url:"close_issue,omitempty" json:"close_issue,omitempty"` + CloseMergeRequest *bool `url:"close_merge_request,omitempty" json:"close_merge_request,omitempty"` + FailedPipeline *bool `url:"failed_pipeline,omitempty" json:"failed_pipeline,omitempty"` + MergeMergeRequest *bool `url:"merge_merge_request,omitempty" json:"merge_merge_request,omitempty"` + NewIssue *bool `url:"new_issue,omitempty" json:"new_issue,omitempty"` + NewMergeRequest *bool `url:"new_merge_request,omitempty" json:"new_merge_request,omitempty"` + NewNote *bool `url:"new_note,omitempty" json:"new_note,omitempty"` + ReassignIssue *bool `url:"reassign_issue,omitempty" json:"reassign_issue,omitempty"` + ReassignMergeRequest *bool `url:"reassign_merge_request,omitempty" json:"reassign_merge_request,omitempty"` + ReopenIssue *bool `url:"reopen_issue,omitempty" json:"reopen_issue,omitempty"` + ReopenMergeRequest *bool `url:"reopen_merge_request,omitempty" json:"reopen_merge_request,omitempty"` + SuccessPipeline *bool `url:"success_pipeline,omitempty" json:"success_pipeline,omitempty"` +} + +// UpdateGlobalSettings updates current notification settings and email address. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notification_settings.html#update-global-notification-settings +func (s *NotificationSettingsService) UpdateGlobalSettings(opt *NotificationSettingsOptions, options ...OptionFunc) (*NotificationSettings, *Response, error) { + if opt.Level != nil && *opt.Level == GlobalNotificationLevel { + return nil, nil, errors.New( + "notification level 'global' is not valid for global notification settings") + } + + u := "notification_settings" + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + ns := new(NotificationSettings) + resp, err := s.client.Do(req, ns) + if err != nil { + return nil, resp, err + } + + return ns, resp, err +} + +// GetSettingsForGroup returns current group notification settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notification_settings.html#group-project-level-notification-settings +func (s *NotificationSettingsService) GetSettingsForGroup(gid interface{}, options ...OptionFunc) (*NotificationSettings, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/notification_settings", url.QueryEscape(group)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + ns := new(NotificationSettings) + resp, err := s.client.Do(req, ns) + if err != nil { + return nil, resp, err + } + + return ns, resp, err +} + +// GetSettingsForProject returns current project notification settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notification_settings.html#group-project-level-notification-settings +func (s *NotificationSettingsService) GetSettingsForProject(pid interface{}, options ...OptionFunc) (*NotificationSettings, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/notification_settings", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + ns := new(NotificationSettings) + resp, err := s.client.Do(req, ns) + if err != nil { + return nil, resp, err + } + + return ns, resp, err +} + +// UpdateSettingsForGroup updates current group notification settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notification_settings.html#update-group-project-level-notification-settings +func (s *NotificationSettingsService) UpdateSettingsForGroup(gid interface{}, opt *NotificationSettingsOptions, options ...OptionFunc) (*NotificationSettings, *Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("groups/%s/notification_settings", url.QueryEscape(group)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + ns := new(NotificationSettings) + resp, err := s.client.Do(req, ns) + if err != nil { + return nil, resp, err + } + + return ns, resp, err +} + +// UpdateSettingsForProject updates current project notification settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/notification_settings.html#update-group-project-level-notification-settings +func (s *NotificationSettingsService) UpdateSettingsForProject(pid interface{}, opt *NotificationSettingsOptions, options ...OptionFunc) (*NotificationSettings, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/notification_settings", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + ns := new(NotificationSettings) + resp, err := s.client.Do(req, ns) + if err != nil { + return nil, resp, err + } + + return ns, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/pages_domains.go b/vendor/github.com/xanzy/go-gitlab/pages_domains.go new file mode 100644 index 00000000..3cd72e21 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/pages_domains.go @@ -0,0 +1,175 @@ +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// PagesDomainsService handles communication with the pages domains +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pages_domains.html +type PagesDomainsService struct { + client *Client +} + +// PagesDomain represents a pages domain. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pages_domains.html +type PagesDomain struct { + Domain string `json:"domain"` + URL string `json:"url"` + ProjectID int `json:"project_id"` + Verified bool `json:"verified"` + VerificationCode string `json:"verification_code"` + EnabledUntil *time.Time `json:"enabled_until"` + Certificate struct { + Expired bool `json:"expired"` + Expiration *time.Time `json:"expiration"` + } `json:"certificate"` +} + +// ListPagesDomainsOptions represents the available ListPagesDomains() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pages_domains.html#list-pages-domains +type ListPagesDomainsOptions ListOptions + +// ListPagesDomains gets a list of project pages domains. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pages_domains.html#list-pages-domains +func (s *PagesDomainsService) ListPagesDomains(pid interface{}, opt *ListPagesDomainsOptions, options ...OptionFunc) ([]*PagesDomain, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pages/domains", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var pd []*PagesDomain + resp, err := s.client.Do(req, &pd) + if err != nil { + return nil, resp, err + } + + return pd, resp, err +} + +// GetPagesDomain get a specific pages domain for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pages_domains.html#single-pages-domain +func (s *PagesDomainsService) GetPagesDomain(pid interface{}, domain string, options ...OptionFunc) (*PagesDomain, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pages/domains/%s", url.QueryEscape(project), domain) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + pd := new(PagesDomain) + resp, err := s.client.Do(req, pd) + if err != nil { + return nil, resp, err + } + + return pd, resp, err +} + +// CreatePagesDomainOptions represents the available CreatePagesDomain() options. +// +// GitLab API docs: +// // https://docs.gitlab.com/ce/api/pages_domains.html#create-new-pages-domain +type CreatePagesDomainOptions struct { + Domain *string `url:"domain,omitempty" json:"domain,omitempty"` + Certificate *string `url:"certifiate,omitempty" json:"certifiate,omitempty"` + Key *string `url:"key,omitempty" json:"key,omitempty"` +} + +// CreatePagesDomain creates a new project pages domain. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pages_domains.html#create-new-pages-domain +func (s *PagesDomainsService) CreatePagesDomain(pid interface{}, opt *CreatePagesDomainOptions, options ...OptionFunc) (*PagesDomain, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pages/domains", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + pd := new(PagesDomain) + resp, err := s.client.Do(req, pd) + if err != nil { + return nil, resp, err + } + + return pd, resp, err +} + +// UpdatePagesDomainOptions represents the available UpdatePagesDomain() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pages_domains.html#update-pages-domain +type UpdatePagesDomainOptions struct { + Cerificate *string `url:"certifiate" json:"certifiate"` + Key *string `url:"key" json:"key"` +} + +// UpdatePagesDomain updates an existing project pages domain. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pages_domains.html#update-pages-domain +func (s *PagesDomainsService) UpdatePagesDomain(pid interface{}, domain string, opt *UpdatePagesDomainOptions, options ...OptionFunc) (*PagesDomain, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pages/domains/%s", url.QueryEscape(project), domain) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + pd := new(PagesDomain) + resp, err := s.client.Do(req, pd) + if err != nil { + return nil, resp, err + } + + return pd, resp, err +} + +// DeletePagesDomain deletes an existing prject pages domain. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pages_domains.html#delete-pages-domain +func (s *PagesDomainsService) DeletePagesDomain(pid interface{}, domain string, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/pages/domains/%s", url.QueryEscape(project), domain) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/pipeline_schedules.go b/vendor/github.com/xanzy/go-gitlab/pipeline_schedules.go new file mode 100644 index 00000000..bb935835 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/pipeline_schedules.go @@ -0,0 +1,341 @@ +// +// Copyright 2018, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// PipelineSchedulesService handles communication with the pipeline +// schedules related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipeline_schedules.html +type PipelineSchedulesService struct { + client *Client +} + +// PipelineVariable represents a pipeline schedule variable. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#pipeline-schedule-variable +type PipelineVariable struct { + Key string `json:"key"` + Value string `json:"value"` +} + +// PipelineSchedule represents a pipeline schedule. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html +type PipelineSchedule struct { + ID int `json:"id"` + Description string `json:"description"` + Ref string `json:"ref"` + Cron string `json:"cron"` + CronTimezone string `json:"cron_timezone"` + NextRunAt *time.Time `json:"next_run_at"` + Active bool `json:"active"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + Owner *User `json:"owner"` + LastPipeline struct { + ID int `json:"id"` + Sha string `json:"sha"` + Ref string `json:"ref"` + Status string `json:"status"` + } `json:"last_pipeline"` + Variables []*PipelineVariable `json:"variables"` +} + +// ListPipelineSchedulesOptions represents the available ListPipelineTriggers() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#list-project-triggers +type ListPipelineSchedulesOptions ListOptions + +// ListPipelineSchedules gets a list of project triggers. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html +func (s *PipelineSchedulesService) ListPipelineSchedules(pid interface{}, opt *ListPipelineSchedulesOptions, options ...OptionFunc) ([]*PipelineSchedule, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var ps []*PipelineSchedule + resp, err := s.client.Do(req, &ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// GetPipelineSchedule gets a pipeline schedule. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html +func (s *PipelineSchedulesService) GetPipelineSchedule(pid interface{}, schedule int, options ...OptionFunc) (*PipelineSchedule, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", url.QueryEscape(project), schedule) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(PipelineSchedule) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// CreatePipelineScheduleOptions represents the available +// CreatePipelineSchedule() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule +type CreatePipelineScheduleOptions struct { + Description *string `url:"description" json:"description"` + Ref *string `url:"ref" json:"ref"` + Cron *string `url:"cron" json:"cron"` + CronTimezone *string `url:"cron_timezone,omitempty" json:"cron_timezone,omitempty"` + Active *bool `url:"active,omitempty" json:"active,omitempty"` +} + +// CreatePipelineSchedule creates a pipeline schedule. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule +func (s *PipelineSchedulesService) CreatePipelineSchedule(pid interface{}, opt *CreatePipelineScheduleOptions, options ...OptionFunc) (*PipelineSchedule, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + p := new(PipelineSchedule) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// EditPipelineScheduleOptions represents the available +// EditPipelineSchedule() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule +type EditPipelineScheduleOptions struct { + Description *string `url:"description,omitempty" json:"description,omitempty"` + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` + Cron *string `url:"cron,omitempty" json:"cron,omitempty"` + CronTimezone *string `url:"cron_timezone,omitempty" json:"cron_timezone,omitempty"` + Active *bool `url:"active,omitempty" json:"active,omitempty"` +} + +// EditPipelineSchedule edits a pipeline schedule. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#edit-a-pipeline-schedule +func (s *PipelineSchedulesService) EditPipelineSchedule(pid interface{}, schedule int, opt *EditPipelineScheduleOptions, options ...OptionFunc) (*PipelineSchedule, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", url.QueryEscape(project), schedule) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + p := new(PipelineSchedule) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// TakeOwnershipOfPipelineSchedule sets the owner of the specified +// pipeline schedule to the user issuing the request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#take-ownership-of-a-pipeline-schedule +func (s *PipelineSchedulesService) TakeOwnershipOfPipelineSchedule(pid interface{}, schedule int, options ...OptionFunc) (*PipelineSchedule, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/take_ownership", url.QueryEscape(project), schedule) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(PipelineSchedule) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// DeletePipelineSchedule deletes a pipeline schedule. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#delete-a-pipeline-schedule +func (s *PipelineSchedulesService) DeletePipelineSchedule(pid interface{}, schedule int, options ...OptionFunc) (*PipelineSchedule, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", url.QueryEscape(project), schedule) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(PipelineSchedule) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// CreatePipelineScheduleVariableOptions represents the available +// CreatePipelineScheduleVariable() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule +type CreatePipelineScheduleVariableOptions struct { + Key *string `url:"key" json:"key"` + Value *string `url:"value" json:"value"` +} + +// CreatePipelineScheduleVariable creates a pipeline schedule variable. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule +func (s *PipelineSchedulesService) CreatePipelineScheduleVariable(pid interface{}, schedule int, opt *CreatePipelineScheduleVariableOptions, options ...OptionFunc) (*PipelineVariable, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables", url.QueryEscape(project), schedule) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + p := new(PipelineVariable) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// EditPipelineScheduleVariableOptions represents the available +// EditPipelineScheduleVariable() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#edit-a-pipeline-schedule-variable +type EditPipelineScheduleVariableOptions struct { + Value *string `url:"value" json:"value"` +} + +// EditPipelineScheduleVariable creates a pipeline schedule variable. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#edit-a-pipeline-schedule-variable +func (s *PipelineSchedulesService) EditPipelineScheduleVariable(pid interface{}, schedule int, key string, opt *EditPipelineScheduleVariableOptions, options ...OptionFunc) (*PipelineVariable, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables/%s", url.QueryEscape(project), schedule, key) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + p := new(PipelineVariable) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// DeletePipelineScheduleVariable creates a pipeline schedule variable. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_schedules.html#delete-a-pipeline-schedule-variable +func (s *PipelineSchedulesService) DeletePipelineScheduleVariable(pid interface{}, schedule int, key string, options ...OptionFunc) (*PipelineVariable, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables/%s", url.QueryEscape(project), schedule, key) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(PipelineVariable) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/pipeline_triggers.go b/vendor/github.com/xanzy/go-gitlab/pipeline_triggers.go new file mode 100644 index 00000000..6e8dfb8a --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/pipeline_triggers.go @@ -0,0 +1,232 @@ +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// PipelineTriggersService handles Project pipeline triggers. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html +type PipelineTriggersService struct { + client *Client +} + +// PipelineTrigger represents a project pipeline trigger. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#pipeline-triggers +type PipelineTrigger struct { + ID int `json:"id"` + Description string `json:"description"` + CreatedAt *time.Time `json:"created_at"` + DeletedAt *time.Time `json:"deleted_at"` + LastUsed *time.Time `json:"last_used"` + Token string `json:"token"` + UpdatedAt *time.Time `json:"updated_at"` + Owner *User `json:"owner"` +} + +// ListPipelineTriggersOptions represents the available ListPipelineTriggers() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#list-project-triggers +type ListPipelineTriggersOptions ListOptions + +// ListPipelineTriggers gets a list of project triggers. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#list-project-triggers +func (s *PipelineTriggersService) ListPipelineTriggers(pid interface{}, opt *ListPipelineTriggersOptions, options ...OptionFunc) ([]*PipelineTrigger, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/triggers", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var pt []*PipelineTrigger + resp, err := s.client.Do(req, &pt) + if err != nil { + return nil, resp, err + } + + return pt, resp, err +} + +// GetPipelineTrigger gets a specific pipeline trigger for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#get-trigger-details +func (s *PipelineTriggersService) GetPipelineTrigger(pid interface{}, trigger int, options ...OptionFunc) (*PipelineTrigger, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/triggers/%d", url.QueryEscape(project), trigger) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + pt := new(PipelineTrigger) + resp, err := s.client.Do(req, pt) + if err != nil { + return nil, resp, err + } + + return pt, resp, err +} + +// AddPipelineTriggerOptions represents the available AddPipelineTrigger() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#create-a-project-trigger +type AddPipelineTriggerOptions struct { + Description *string `url:"description,omitempty" json:"description,omitempty"` +} + +// AddPipelineTrigger adds a pipeline trigger to a specified project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#create-a-project-trigger +func (s *PipelineTriggersService) AddPipelineTrigger(pid interface{}, opt *AddPipelineTriggerOptions, options ...OptionFunc) (*PipelineTrigger, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/triggers", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + pt := new(PipelineTrigger) + resp, err := s.client.Do(req, pt) + if err != nil { + return nil, resp, err + } + + return pt, resp, err +} + +// EditPipelineTriggerOptions represents the available EditPipelineTrigger() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#update-a-project-trigger +type EditPipelineTriggerOptions struct { + Description *string `url:"description,omitempty" json:"description,omitempty"` +} + +// EditPipelineTrigger edits a trigger for a specified project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#update-a-project-trigger +func (s *PipelineTriggersService) EditPipelineTrigger(pid interface{}, trigger int, opt *EditPipelineTriggerOptions, options ...OptionFunc) (*PipelineTrigger, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/triggers/%d", url.QueryEscape(project), trigger) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + pt := new(PipelineTrigger) + resp, err := s.client.Do(req, pt) + if err != nil { + return nil, resp, err + } + + return pt, resp, err +} + +// TakeOwnershipOfPipelineTrigger sets the owner of the specified +// pipeline trigger to the user issuing the request. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#take-ownership-of-a-project-trigger +func (s *PipelineTriggersService) TakeOwnershipOfPipelineTrigger(pid interface{}, trigger int, options ...OptionFunc) (*PipelineTrigger, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/triggers/%d/take_ownership", url.QueryEscape(project), trigger) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + pt := new(PipelineTrigger) + resp, err := s.client.Do(req, pt) + if err != nil { + return nil, resp, err + } + + return pt, resp, err +} + +// DeletePipelineTrigger removes a trigger from a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipeline_triggers.html#remove-a-project-trigger +func (s *PipelineTriggersService) DeletePipelineTrigger(pid interface{}, trigger int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/triggers/%d", url.QueryEscape(project), trigger) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// RunPipelineTriggerOptions represents the available RunPipelineTrigger() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/ci/triggers/README.html#triggering-a-pipeline +type RunPipelineTriggerOptions struct { + Ref *string `url:"ref" json:"ref"` + Token *string `url:"token" json:"token"` + Variables map[string]string `url:"variables,omitempty" json:"variables,omitempty"` +} + +// RunPipelineTrigger starts a trigger from a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/ci/triggers/README.html#triggering-a-pipeline +func (s *PipelineTriggersService) RunPipelineTrigger(pid interface{}, opt *RunPipelineTriggerOptions, options ...OptionFunc) (*Pipeline, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/trigger/pipeline", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + pt := new(Pipeline) + resp, err := s.client.Do(req, pt) + if err != nil { + return nil, resp, err + } + + return pt, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/pipelines.go b/vendor/github.com/xanzy/go-gitlab/pipelines.go new file mode 100644 index 00000000..0c736dd2 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/pipelines.go @@ -0,0 +1,220 @@ +// +// Copyright 2017, Igor Varavko +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// PipelinesService handles communication with the repositories related +// methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html +type PipelinesService struct { + client *Client +} + +// Pipeline represents a GitLab pipeline. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html +type Pipeline struct { + ID int `json:"id"` + Status string `json:"status"` + Ref string `json:"ref"` + Sha string `json:"sha"` + BeforeSha string `json:"before_sha"` + Tag bool `json:"tag"` + YamlErrors string `json:"yaml_errors"` + User struct { + Name string `json:"name"` + Username string `json:"username"` + ID int `json:"id"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } + UpdatedAt *time.Time `json:"updated_at"` + CreatedAt *time.Time `json:"created_at"` + StartedAt *time.Time `json:"started_at"` + FinishedAt *time.Time `json:"finished_at"` + CommittedAt *time.Time `json:"committed_at"` + Duration int `json:"duration"` + Coverage string `json:"coverage"` +} + +func (i Pipeline) String() string { + return Stringify(i) +} + +// PipelineList represents a GitLab list project pipelines +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#list-project-pipelines +type PipelineList []struct { + ID int `json:"id"` + Status string `json:"status"` + Ref string `json:"ref"` + Sha string `json:"sha"` +} + +func (i PipelineList) String() string { + return Stringify(i) +} + +// ListProjectPipelinesOptions represents the available ListProjectPipelines() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#list-project-pipelines +type ListProjectPipelinesOptions struct { + ListOptions + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` + Status *BuildStateValue `url:"status,omitempty" json:"status,omitempty"` + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` + YamlErrors *bool `url:"yaml_errors,omitempty" json:"yaml_errors,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + OrderBy *OrderByValue `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` +} + +// ListProjectPipelines gets a list of project piplines. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#list-project-pipelines +func (s *PipelinesService) ListProjectPipelines(pid interface{}, opt *ListProjectPipelinesOptions, options ...OptionFunc) (PipelineList, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipelines", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var p PipelineList + resp, err := s.client.Do(req, &p) + if err != nil { + return nil, resp, err + } + return p, resp, err +} + +// GetPipeline gets a single project pipeline. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#get-a-single-pipeline +func (s *PipelinesService) GetPipeline(pid interface{}, pipeline int, options ...OptionFunc) (*Pipeline, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipelines/%d", url.QueryEscape(project), pipeline) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Pipeline) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// CreatePipelineOptions represents the available CreatePipeline() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#create-a-new-pipeline +type CreatePipelineOptions struct { + Ref *string `url:"ref,omitempty" json:"ref"` +} + +// CreatePipeline creates a new project pipeline. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#create-a-new-pipeline +func (s *PipelinesService) CreatePipeline(pid interface{}, opt *CreatePipelineOptions, options ...OptionFunc) (*Pipeline, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipeline", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + p := new(Pipeline) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// RetryPipelineBuild retries failed builds in a pipeline +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/pipelines.html#retry-failed-builds-in-a-pipeline +func (s *PipelinesService) RetryPipelineBuild(pid interface{}, pipelineID int, options ...OptionFunc) (*Pipeline, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipelines/%d/retry", project, pipelineID) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Pipeline) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// CancelPipelineBuild cancels a pipeline builds +// +// GitLab API docs: +//https://docs.gitlab.com/ce/api/pipelines.html#cancel-a-pipelines-builds +func (s *PipelinesService) CancelPipelineBuild(pid interface{}, pipelineID int, options ...OptionFunc) (*Pipeline, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/pipelines/%d/cancel", project, pipelineID) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Pipeline) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/project_members.go b/vendor/github.com/xanzy/go-gitlab/project_members.go new file mode 100644 index 00000000..70beb72d --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/project_members.go @@ -0,0 +1,179 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// ProjectMembersService handles communication with the project members +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/members.html +type ProjectMembersService struct { + client *Client +} + +// ListProjectMembersOptions represents the available ListProjectMembers() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project +type ListProjectMembersOptions struct { + ListOptions + Query *string `url:"query,omitempty" json:"query,omitempty"` +} + +// ListProjectMembers gets a list of a project's team members. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project +func (s *ProjectMembersService) ListProjectMembers(pid interface{}, opt *ListProjectMembersOptions, options ...OptionFunc) ([]*ProjectMember, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/members", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var pm []*ProjectMember + resp, err := s.client.Do(req, &pm) + if err != nil { + return nil, resp, err + } + + return pm, resp, err +} + +// GetProjectMember gets a project team member. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#get-a-member-of-a-group-or-project +func (s *ProjectMembersService) GetProjectMember(pid interface{}, user int, options ...OptionFunc) (*ProjectMember, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/members/%d", url.QueryEscape(project), user) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + pm := new(ProjectMember) + resp, err := s.client.Do(req, pm) + if err != nil { + return nil, resp, err + } + + return pm, resp, err +} + +// AddProjectMemberOptions represents the available AddProjectMember() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#add-a-member-to-a-group-or-project +type AddProjectMemberOptions struct { + UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` + AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` +} + +// AddProjectMember adds a user to a project team. This is an idempotent +// method and can be called multiple times with the same parameters. Adding +// team membership to a user that is already a member does not affect the +// existing membership. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#add-a-member-to-a-group-or-project +func (s *ProjectMembersService) AddProjectMember(pid interface{}, opt *AddProjectMemberOptions, options ...OptionFunc) (*ProjectMember, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/members", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + pm := new(ProjectMember) + resp, err := s.client.Do(req, pm) + if err != nil { + return nil, resp, err + } + + return pm, resp, err +} + +// EditProjectMemberOptions represents the available EditProjectMember() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project +type EditProjectMemberOptions struct { + AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` +} + +// EditProjectMember updates a project team member to a specified access level.. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project +func (s *ProjectMembersService) EditProjectMember(pid interface{}, user int, opt *EditProjectMemberOptions, options ...OptionFunc) (*ProjectMember, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/members/%d", url.QueryEscape(project), user) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + pm := new(ProjectMember) + resp, err := s.client.Do(req, pm) + if err != nil { + return nil, resp, err + } + + return pm, resp, err +} + +// DeleteProjectMember removes a user from a project team. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/members.html#remove-a-member-from-a-group-or-project +func (s *ProjectMembersService) DeleteProjectMember(pid interface{}, user int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/members/%d", url.QueryEscape(project), user) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/project_snippets.go b/vendor/github.com/xanzy/go-gitlab/project_snippets.go new file mode 100644 index 00000000..00428196 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/project_snippets.go @@ -0,0 +1,207 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "bytes" + "fmt" + "net/url" +) + +// ProjectSnippetsService handles communication with the project snippets +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/project_snippets.html +type ProjectSnippetsService struct { + client *Client +} + +// ListProjectSnippetsOptions represents the available ListSnippets() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/project_snippets.html#list-snippets +type ListProjectSnippetsOptions ListOptions + +// ListSnippets gets a list of project snippets. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/project_snippets.html#list-snippets +func (s *ProjectSnippetsService) ListSnippets(pid interface{}, opt *ListProjectSnippetsOptions, options ...OptionFunc) ([]*Snippet, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var ps []*Snippet + resp, err := s.client.Do(req, &ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// GetSnippet gets a single project snippet +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/project_snippets.html#single-snippet +func (s *ProjectSnippetsService) GetSnippet(pid interface{}, snippet int, options ...OptionFunc) (*Snippet, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d", url.QueryEscape(project), snippet) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + ps := new(Snippet) + resp, err := s.client.Do(req, ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// CreateProjectSnippetOptions represents the available CreateSnippet() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/project_snippets.html#create-new-snippet +type CreateProjectSnippetOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + FileName *string `url:"file_name,omitempty" json:"file_name,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Code *string `url:"code,omitempty" json:"code,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` +} + +// CreateSnippet creates a new project snippet. The user must have permission +// to create new snippets. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/project_snippets.html#create-new-snippet +func (s *ProjectSnippetsService) CreateSnippet(pid interface{}, opt *CreateProjectSnippetOptions, options ...OptionFunc) (*Snippet, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + ps := new(Snippet) + resp, err := s.client.Do(req, ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// UpdateProjectSnippetOptions represents the available UpdateSnippet() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/project_snippets.html#update-snippet +type UpdateProjectSnippetOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + FileName *string `url:"file_name,omitempty" json:"file_name,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Code *string `url:"code,omitempty" json:"code,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` +} + +// UpdateSnippet updates an existing project snippet. The user must have +// permission to change an existing snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/project_snippets.html#update-snippet +func (s *ProjectSnippetsService) UpdateSnippet(pid interface{}, snippet int, opt *UpdateProjectSnippetOptions, options ...OptionFunc) (*Snippet, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d", url.QueryEscape(project), snippet) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + ps := new(Snippet) + resp, err := s.client.Do(req, ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// DeleteSnippet deletes an existing project snippet. This is an idempotent +// function and deleting a non-existent snippet still returns a 200 OK status +// code. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/project_snippets.html#delete-snippet +func (s *ProjectSnippetsService) DeleteSnippet(pid interface{}, snippet int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d", url.QueryEscape(project), snippet) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// SnippetContent returns the raw project snippet as plain text. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/project_snippets.html#snippet-content +func (s *ProjectSnippetsService) SnippetContent(pid interface{}, snippet int, options ...OptionFunc) ([]byte, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/snippets/%d/raw", url.QueryEscape(project), snippet) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var b bytes.Buffer + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b.Bytes(), resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/projects.go b/vendor/github.com/xanzy/go-gitlab/projects.go new file mode 100644 index 00000000..4a252a99 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/projects.go @@ -0,0 +1,997 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "mime/multipart" + "net/url" + "os" + "time" +) + +// ProjectsService handles communication with the repositories related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html +type ProjectsService struct { + client *Client +} + +// Project represents a GitLab project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html +type Project struct { + ID int `json:"id"` + Description string `json:"description"` + DefaultBranch string `json:"default_branch"` + Public bool `json:"public"` + Visibility VisibilityValue `json:"visibility"` + SSHURLToRepo string `json:"ssh_url_to_repo"` + HTTPURLToRepo string `json:"http_url_to_repo"` + WebURL string `json:"web_url"` + TagList []string `json:"tag_list"` + Owner *User `json:"owner"` + Name string `json:"name"` + NameWithNamespace string `json:"name_with_namespace"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` + IssuesEnabled bool `json:"issues_enabled"` + OpenIssuesCount int `json:"open_issues_count"` + MergeRequestsEnabled bool `json:"merge_requests_enabled"` + ApprovalsBeforeMerge int `json:"approvals_before_merge"` + JobsEnabled bool `json:"jobs_enabled"` + WikiEnabled bool `json:"wiki_enabled"` + SnippetsEnabled bool `json:"snippets_enabled"` + ContainerRegistryEnabled bool `json:"container_registry_enabled"` + CreatedAt *time.Time `json:"created_at,omitempty"` + LastActivityAt *time.Time `json:"last_activity_at,omitempty"` + CreatorID int `json:"creator_id"` + Namespace *ProjectNamespace `json:"namespace"` + ImportStatus string `json:"import_status"` + ImportError string `json:"import_error"` + Permissions *Permissions `json:"permissions"` + Archived bool `json:"archived"` + AvatarURL string `json:"avatar_url"` + SharedRunnersEnabled bool `json:"shared_runners_enabled"` + ForksCount int `json:"forks_count"` + StarCount int `json:"star_count"` + RunnersToken string `json:"runners_token"` + PublicJobs bool `json:"public_jobs"` + OnlyAllowMergeIfPipelineSucceeds bool `json:"only_allow_merge_if_pipeline_succeeds"` + OnlyAllowMergeIfAllDiscussionsAreResolved bool `json:"only_allow_merge_if_all_discussions_are_resolved"` + LFSEnabled bool `json:"lfs_enabled"` + RequestAccessEnabled bool `json:"request_access_enabled"` + MergeMethod string `json:"merge_method"` + ForkedFromProject *ForkParent `json:"forked_from_project"` + SharedWithGroups []struct { + GroupID int `json:"group_id"` + GroupName string `json:"group_name"` + GroupAccessLevel int `json:"group_access_level"` + } `json:"shared_with_groups"` + Statistics *ProjectStatistics `json:"statistics"` + Links *Links `json:"_links,omitempty"` + CIConfigPath *string `json:"ci_config_path"` +} + +// Repository represents a repository. +type Repository struct { + Name string `json:"name"` + Description string `json:"description"` + WebURL string `json:"web_url"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + Visibility VisibilityValue `json:"visibility"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` +} + +// ProjectNamespace represents a project namespace. +type ProjectNamespace struct { + ID int `json:"id"` + Name string `json:"name"` + Path string `json:"path"` + Kind string `json:"kind"` + FullPath string `json:"full_path"` +} + +// StorageStatistics represents a statistics record for a group or project. +type StorageStatistics struct { + StorageSize int64 `json:"storage_size"` + RepositorySize int64 `json:"repository_size"` + LfsObjectsSize int64 `json:"lfs_objects_size"` + JobArtifactsSize int64 `json:"job_artifacts_size"` +} + +// ProjectStatistics represents a statistics record for a project. +type ProjectStatistics struct { + StorageStatistics + CommitCount int `json:"commit_count"` +} + +// Permissions represents permissions. +type Permissions struct { + ProjectAccess *ProjectAccess `json:"project_access"` + GroupAccess *GroupAccess `json:"group_access"` +} + +// ProjectAccess represents project access. +type ProjectAccess struct { + AccessLevel AccessLevelValue `json:"access_level"` + NotificationLevel NotificationLevelValue `json:"notification_level"` +} + +// GroupAccess represents group access. +type GroupAccess struct { + AccessLevel AccessLevelValue `json:"access_level"` + NotificationLevel NotificationLevelValue `json:"notification_level"` +} + +// ForkParent represents the parent project when this is a fork. +type ForkParent struct { + HTTPURLToRepo string `json:"http_url_to_repo"` + ID int `json:"id"` + Name string `json:"name"` + NameWithNamespace string `json:"name_with_namespace"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` + WebURL string `json:"web_url"` +} + +// Links represents a project web links for self, issues, merge_requests, +// repo_branches, labels, events, members. +type Links struct { + Self string `json:"self"` + Issues string `json:"issues"` + MergeRequests string `json:"merge_requests"` + RepoBranches string `json:"repo_branches"` + Labels string `json:"labels"` + Events string `json:"events"` + Members string `json:"members"` +} + +func (s Project) String() string { + return Stringify(s) +} + +// ListProjectsOptions represents the available ListProjects() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#list-projects +type ListProjectsOptions struct { + ListOptions + Archived *bool `url:"archived,omitempty" json:"archived,omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` + Simple *bool `url:"simple,omitempty" json:"simple,omitempty"` + Owned *bool `url:"owned,omitempty" json:"owned,omitempty"` + Membership *bool `url:"membership,omitempty" json:"membership,omitempty"` + Starred *bool `url:"starred,omitempty" json:"starred,omitempty"` + Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` + WithIssuesEnabled *bool `url:"with_issues_enabled,omitempty" json:"with_issues_enabled,omitempty"` + WithMergeRequestsEnabled *bool `url:"with_merge_requests_enabled,omitempty" json:"with_merge_requests_enabled,omitempty"` +} + +// ListProjects gets a list of projects accessible by the authenticated user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#list-projects +func (s *ProjectsService) ListProjects(opt *ListProjectsOptions, options ...OptionFunc) ([]*Project, *Response, error) { + req, err := s.client.NewRequest("GET", "projects", opt, options) + if err != nil { + return nil, nil, err + } + + var p []*Project + resp, err := s.client.Do(req, &p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// ListUserProjects gets a list of projects for the given user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#list-user-projects +func (s *ProjectsService) ListUserProjects(uid interface{}, opt *ListProjectsOptions, options ...OptionFunc) ([]*Project, *Response, error) { + user, err := parseID(uid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("users/%s/projects", user) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var p []*Project + resp, err := s.client.Do(req, &p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// ProjectUser represents a GitLab project user. +type ProjectUser struct { + ID int `json:"id"` + Name string `json:"name"` + Username string `json:"username"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` +} + +// ListProjectUserOptions represents the available ListProjectsUsers() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#get-project-users +type ListProjectUserOptions struct { + ListOptions + Search *string `url:"search,omitempty" json:"search,omitempty"` +} + +// ListProjectsUsers gets a list of users for the given project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#get-project-users +func (s *ProjectsService) ListProjectsUsers(pid interface{}, opt *ListProjectUserOptions, options ...OptionFunc) ([]*ProjectUser, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/users", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var p []*ProjectUser + resp, err := s.client.Do(req, &p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// GetProject gets a specific project, identified by project ID or +// NAMESPACE/PROJECT_NAME, which is owned by the authenticated user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#get-single-project +func (s *ProjectsService) GetProject(pid interface{}, options ...OptionFunc) (*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// ProjectEvent represents a GitLab project event. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#get-project-events +type ProjectEvent struct { + Title interface{} `json:"title"` + ProjectID int `json:"project_id"` + ActionName string `json:"action_name"` + TargetID interface{} `json:"target_id"` + TargetType interface{} `json:"target_type"` + AuthorID int `json:"author_id"` + AuthorUsername string `json:"author_username"` + Data struct { + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` + UserID int `json:"user_id"` + UserName string `json:"user_name"` + Repository *Repository `json:"repository"` + Commits []*Commit `json:"commits"` + TotalCommitsCount int `json:"total_commits_count"` + } `json:"data"` + TargetTitle interface{} `json:"target_title"` +} + +func (s ProjectEvent) String() string { + return Stringify(s) +} + +// GetProjectEventsOptions represents the available GetProjectEvents() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#get-project-events +type GetProjectEventsOptions ListOptions + +// GetProjectEvents gets the events for the specified project. Sorted from +// newest to latest. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#get-project-events +func (s *ProjectsService) GetProjectEvents(pid interface{}, opt *GetProjectEventsOptions, options ...OptionFunc) ([]*ProjectEvent, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/events", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var p []*ProjectEvent + resp, err := s.client.Do(req, &p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// CreateProjectOptions represents the available CreateProjects() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#create-project +type CreateProjectOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + Path *string `url:"path,omitempty" json:"path,omitempty"` + DefaultBranch *string `url:"default_branch,omitempty" json:"default_branch,omitempty"` + NamespaceID *int `url:"namespace_id,omitempty" json:"namespace_id,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + IssuesEnabled *bool `url:"issues_enabled,omitempty" json:"issues_enabled,omitempty"` + MergeRequestsEnabled *bool `url:"merge_requests_enabled,omitempty" json:"merge_requests_enabled,omitempty"` + JobsEnabled *bool `url:"jobs_enabled,omitempty" json:"jobs_enabled,omitempty"` + WikiEnabled *bool `url:"wiki_enabled,omitempty" json:"wiki_enabled,omitempty"` + SnippetsEnabled *bool `url:"snippets_enabled,omitempty" json:"snippets_enabled,omitempty"` + ResolveOutdatedDiffDiscussions *bool `url:"resolve_outdated_diff_discussions,omitempty" json:"resolve_outdated_diff_discussions,omitempty"` + ContainerRegistryEnabled *bool `url:"container_registry_enabled,omitempty" json:"container_registry_enabled,omitempty"` + SharedRunnersEnabled *bool `url:"shared_runners_enabled,omitempty" json:"shared_runners_enabled,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` + ImportURL *string `url:"import_url,omitempty" json:"import_url,omitempty"` + PublicJobs *bool `url:"public_jobs,omitempty" json:"public_jobs,omitempty"` + OnlyAllowMergeIfPipelineSucceeds *bool `url:"only_allow_merge_if_pipeline_succeeds,omitempty" json:"only_allow_merge_if_pipeline_succeeds,omitempty"` + OnlyAllowMergeIfAllDiscussionsAreResolved *bool `url:"only_allow_merge_if_all_discussions_are_resolved,omitempty" json:"only_allow_merge_if_all_discussions_are_resolved,omitempty"` + MergeMethod *MergeMethodValue `url:"merge_method,omitempty" json:"merge_method,omitempty"` + LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"` + RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"` + TagList *[]string `url:"tag_list,omitempty" json:"tag_list,omitempty"` + PrintingMergeRequestLinkEnabled *bool `url:"printing_merge_request_link_enabled,omitempty" json:"printing_merge_request_link_enabled,omitempty"` + CIConfigPath *string `url:"ci_config_path,omitempty" json:"ci_config_path,omitempty"` +} + +// CreateProject creates a new project owned by the authenticated user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#create-project +func (s *ProjectsService) CreateProject(opt *CreateProjectOptions, options ...OptionFunc) (*Project, *Response, error) { + req, err := s.client.NewRequest("POST", "projects", opt, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// CreateProjectForUserOptions represents the available CreateProjectForUser() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#create-project-for-user +type CreateProjectForUserOptions CreateProjectOptions + +// CreateProjectForUser creates a new project owned by the specified user. +// Available only for admins. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#create-project-for-user +func (s *ProjectsService) CreateProjectForUser(user int, opt *CreateProjectForUserOptions, options ...OptionFunc) (*Project, *Response, error) { + u := fmt.Sprintf("projects/user/%d", user) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// EditProjectOptions represents the available EditProject() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#edit-project +type EditProjectOptions CreateProjectOptions + +// EditProject updates an existing project. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#edit-project +func (s *ProjectsService) EditProject(pid interface{}, opt *EditProjectOptions, options ...OptionFunc) (*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// ForkProject forks a project into the user namespace of the authenticated +// user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#fork-project +func (s *ProjectsService) ForkProject(pid interface{}, options ...OptionFunc) (*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/fork", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// StarProject stars a given the project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#star-a-project +func (s *ProjectsService) StarProject(pid interface{}, options ...OptionFunc) (*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/star", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// UnstarProject unstars a given project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#unstar-a-project +func (s *ProjectsService) UnstarProject(pid interface{}, options ...OptionFunc) (*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/unstar", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// ArchiveProject archives the project if the user is either admin or the +// project owner of this project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#archive-a-project +func (s *ProjectsService) ArchiveProject(pid interface{}, options ...OptionFunc) (*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/archive", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// UnarchiveProject unarchives the project if the user is either admin or +// the project owner of this project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#unarchive-a-project +func (s *ProjectsService) UnarchiveProject(pid interface{}, options ...OptionFunc) (*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/unarchive", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// DeleteProject removes a project including all associated resources +// (issues, merge requests etc.) +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#remove-project +func (s *ProjectsService) DeleteProject(pid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ShareWithGroupOptions represents options to share project with groups +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#share-project-with-group +type ShareWithGroupOptions struct { + GroupID *int `url:"group_id" json:"group_id"` + GroupAccess *AccessLevelValue `url:"group_access" json:"group_access"` + ExpiresAt *string `url:"expires_at" json:"expires_at"` +} + +// ShareProjectWithGroup allows to share a project with a group. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#share-project-with-group +func (s *ProjectsService) ShareProjectWithGroup(pid interface{}, opt *ShareWithGroupOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/share", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteSharedProjectFromGroup allows to unshare a project from a group. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#delete-a-shared-project-link-within-a-group +func (s *ProjectsService) DeleteSharedProjectFromGroup(pid interface{}, groupID int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/share/%d", url.QueryEscape(project), groupID) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ProjectMember represents a project member. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#list-project-team-members +type ProjectMember struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + AccessLevel AccessLevelValue `json:"access_level"` +} + +// ProjectHook represents a project hook. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#list-project-hooks +type ProjectHook struct { + ID int `json:"id"` + URL string `json:"url"` + ProjectID int `json:"project_id"` + PushEvents bool `json:"push_events"` + IssuesEvents bool `json:"issues_events"` + ConfidentialIssuesEvents bool `json:"confidential_issues_events"` + MergeRequestsEvents bool `json:"merge_requests_events"` + TagPushEvents bool `json:"tag_push_events"` + NoteEvents bool `json:"note_events"` + JobEvents bool `json:"job_events"` + PipelineEvents bool `json:"pipeline_events"` + WikiPageEvents bool `json:"wiki_page_events"` + EnableSSLVerification bool `json:"enable_ssl_verification"` + CreatedAt *time.Time `json:"created_at"` +} + +// ListProjectHooksOptions represents the available ListProjectHooks() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#list-project-hooks +type ListProjectHooksOptions ListOptions + +// ListProjectHooks gets a list of project hooks. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#list-project-hooks +func (s *ProjectsService) ListProjectHooks(pid interface{}, opt *ListProjectHooksOptions, options ...OptionFunc) ([]*ProjectHook, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/hooks", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var ph []*ProjectHook + resp, err := s.client.Do(req, &ph) + if err != nil { + return nil, resp, err + } + + return ph, resp, err +} + +// GetProjectHook gets a specific hook for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#get-project-hook +func (s *ProjectsService) GetProjectHook(pid interface{}, hook int, options ...OptionFunc) (*ProjectHook, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/hooks/%d", url.QueryEscape(project), hook) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + ph := new(ProjectHook) + resp, err := s.client.Do(req, ph) + if err != nil { + return nil, resp, err + } + + return ph, resp, err +} + +// AddProjectHookOptions represents the available AddProjectHook() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#add-project-hook +type AddProjectHookOptions struct { + URL *string `url:"url,omitempty" json:"url,omitempty"` + PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` + IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"` + ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"` + MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"` + TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` + NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"` + JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"` + PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` + EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"` + Token *string `url:"token,omitempty" json:"token,omitempty"` +} + +// AddProjectHook adds a hook to a specified project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#add-project-hook +func (s *ProjectsService) AddProjectHook(pid interface{}, opt *AddProjectHookOptions, options ...OptionFunc) (*ProjectHook, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/hooks", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + ph := new(ProjectHook) + resp, err := s.client.Do(req, ph) + if err != nil { + return nil, resp, err + } + + return ph, resp, err +} + +// EditProjectHookOptions represents the available EditProjectHook() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#edit-project-hook +type EditProjectHookOptions struct { + URL *string `url:"url,omitempty" json:"url,omitempty"` + PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` + IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"` + ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"` + MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"` + TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` + NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"` + JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"` + PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` + EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"` + Token *string `url:"token,omitempty" json:"token,omitempty"` +} + +// EditProjectHook edits a hook for a specified project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#edit-project-hook +func (s *ProjectsService) EditProjectHook(pid interface{}, hook int, opt *EditProjectHookOptions, options ...OptionFunc) (*ProjectHook, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/hooks/%d", url.QueryEscape(project), hook) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + ph := new(ProjectHook) + resp, err := s.client.Do(req, ph) + if err != nil { + return nil, resp, err + } + + return ph, resp, err +} + +// DeleteProjectHook removes a hook from a project. This is an idempotent +// method and can be called multiple times. Either the hook is available or not. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#delete-project-hook +func (s *ProjectsService) DeleteProjectHook(pid interface{}, hook int, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/hooks/%d", url.QueryEscape(project), hook) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ProjectForkRelation represents a project fork relationship. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#admin-fork-relation +type ProjectForkRelation struct { + ID int `json:"id"` + ForkedToProjectID int `json:"forked_to_project_id"` + ForkedFromProjectID int `json:"forked_from_project_id"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` +} + +// CreateProjectForkRelation creates a forked from/to relation between +// existing projects. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#create-a-forked-fromto-relation-between-existing-projects. +func (s *ProjectsService) CreateProjectForkRelation(pid int, fork int, options ...OptionFunc) (*ProjectForkRelation, *Response, error) { + u := fmt.Sprintf("projects/%d/fork/%d", pid, fork) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + pfr := new(ProjectForkRelation) + resp, err := s.client.Do(req, pfr) + if err != nil { + return nil, resp, err + } + + return pfr, resp, err +} + +// DeleteProjectForkRelation deletes an existing forked from relationship. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#delete-an-existing-forked-from-relationship +func (s *ProjectsService) DeleteProjectForkRelation(pid int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("projects/%d/fork", pid) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ProjectFile represents an uploaded project file +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#upload-a-file +type ProjectFile struct { + Alt string `json:"alt"` + URL string `json:"url"` + Markdown string `json:"markdown"` +} + +// UploadFile upload a file from disk +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#upload-a-file +func (s *ProjectsService) UploadFile(pid interface{}, file string, options ...OptionFunc) (*ProjectFile, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/uploads", url.QueryEscape(project)) + + f, err := os.Open(file) + if err != nil { + return nil, nil, err + } + defer f.Close() + + b := &bytes.Buffer{} + w := multipart.NewWriter(b) + + fw, err := w.CreateFormFile("file", file) + if err != nil { + return nil, nil, err + } + + _, err = io.Copy(fw, f) + if err != nil { + return nil, nil, err + } + w.Close() + + req, err := s.client.NewRequest("", u, nil, options) + if err != nil { + return nil, nil, err + } + + req.Body = ioutil.NopCloser(b) + req.ContentLength = int64(b.Len()) + req.Header.Set("Content-Type", w.FormDataContentType()) + req.Method = "POST" + + uf := &ProjectFile{} + resp, err := s.client.Do(req, uf) + if err != nil { + return nil, resp, err + } + + return uf, resp, nil +} + +// ListProjectForks gets a list of project forks. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/projects.html#list-forks-of-a-project +func (s *ProjectsService) ListProjectForks(pid interface{}, opt *ListProjectsOptions, options ...OptionFunc) ([]*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/forks", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var forks []*Project + resp, err := s.client.Do(req, &forks) + if err != nil { + return nil, resp, err + } + + return forks, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/protected_branches.go b/vendor/github.com/xanzy/go-gitlab/protected_branches.go new file mode 100644 index 00000000..0a56241e --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/protected_branches.go @@ -0,0 +1,165 @@ +// +// Copyright 2017, Sander van Harmelen, Michael Lihs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// ProtectedBranchesService handles communication with the protected branch +// related methods of the GitLab API. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#protected-branches-api +type ProtectedBranchesService struct { + client *Client +} + +// BranchAccessDescription represents the access description for a protected +// branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#protected-branches-api +type BranchAccessDescription struct { + AccessLevel AccessLevelValue `json:"access_level"` + AccessLevelDescription string `json:"access_level_description"` +} + +// ProtectedBranch represents a protected branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#list-protected-branches +type ProtectedBranch struct { + Name string `json:"name"` + PushAccessLevels []*BranchAccessDescription `json:"push_access_levels"` + MergeAccessLevels []*BranchAccessDescription `json:"merge_access_levels"` +} + +// ListProtectedBranchesOptions represents the available ListProtectedBranches() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#list-protected-branches +type ListProtectedBranchesOptions ListOptions + +// ListProtectedBranches gets a list of protected branches from a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#list-protected-branches +func (s *ProtectedBranchesService) ListProtectedBranches(pid interface{}, opt *ListProtectedBranchesOptions, options ...OptionFunc) ([]*ProtectedBranch, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/protected_branches", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var p []*ProtectedBranch + resp, err := s.client.Do(req, &p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// GetProtectedBranch gets a single protected branch or wildcard protected branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#get-a-single-protected-branch-or-wildcard-protected-branch +func (s *ProtectedBranchesService) GetProtectedBranch(pid interface{}, branch string, options ...OptionFunc) (*ProtectedBranch, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/protected_branches/%s", url.QueryEscape(project), branch) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + p := new(ProtectedBranch) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// ProtectRepositoryBranchesOptions represents the available +// ProtectRepositoryBranches() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#protect-repository-branches +type ProtectRepositoryBranchesOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + PushAccessLevel *AccessLevelValue `url:"push_access_level,omitempty" json:"push_access_level,omitempty"` + MergeAccessLevel *AccessLevelValue `url:"merge_access_level,omitempty" json:"merge_access_level,omitempty"` +} + +// ProtectRepositoryBranches protects a single repository branch or several +// project repository branches using a wildcard protected branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#protect-repository-branches +func (s *ProtectedBranchesService) ProtectRepositoryBranches(pid interface{}, opt *ProtectRepositoryBranchesOptions, options ...OptionFunc) (*ProtectedBranch, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/protected_branches", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + p := new(ProtectedBranch) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// UnprotectRepositoryBranches unprotects the given protected branch or wildcard +// protected branch. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/protected_branches.html#unprotect-repository-branches +func (s *ProtectedBranchesService) UnprotectRepositoryBranches(pid interface{}, branch string, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/protected_branches/%s", url.QueryEscape(project), branch) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/repositories.go b/vendor/github.com/xanzy/go-gitlab/repositories.go new file mode 100644 index 00000000..7d109974 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/repositories.go @@ -0,0 +1,260 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "bytes" + "fmt" + "net/url" +) + +// RepositoriesService handles communication with the repositories related +// methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html +type RepositoriesService struct { + client *Client +} + +// TreeNode represents a GitLab repository file or directory. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html +type TreeNode struct { + ID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Path string `json:"path"` + Mode string `json:"mode"` +} + +func (t TreeNode) String() string { + return Stringify(t) +} + +// ListTreeOptions represents the available ListTree() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#list-repository-tree +type ListTreeOptions struct { + ListOptions + Path *string `url:"path,omitempty" json:"path,omitempty"` + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` + Recursive *bool `url:"recursive,omitempty" json:"recursive,omitempty"` +} + +// ListTree gets a list of repository files and directories in a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#list-repository-tree +func (s *RepositoriesService) ListTree(pid interface{}, opt *ListTreeOptions, options ...OptionFunc) ([]*TreeNode, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/tree", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var t []*TreeNode + resp, err := s.client.Do(req, &t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// RawFileContent gets the raw file contents for a file by commit SHA and path +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#raw-file-content +func (s *RepositoriesService) RawFileContent(pid interface{}, sha string, options ...OptionFunc) ([]byte, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/blobs/%s", url.QueryEscape(project), sha) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var b bytes.Buffer + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b.Bytes(), resp, err +} + +// RawBlobContent gets the raw file contents for a blob by blob SHA. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#raw-blob-content +func (s *RepositoriesService) RawBlobContent(pid interface{}, sha string, options ...OptionFunc) ([]byte, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/blobs/%s/raw", url.QueryEscape(project), sha) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var b bytes.Buffer + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b.Bytes(), resp, err +} + +// ArchiveOptions represents the available Archive() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#get-file-archive +type ArchiveOptions struct { + SHA *string `url:"sha,omitempty" json:"sha,omitempty"` +} + +// Archive gets an archive of the repository. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#get-file-archive +func (s *RepositoriesService) Archive(pid interface{}, opt *ArchiveOptions, options ...OptionFunc) ([]byte, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/archive", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var b bytes.Buffer + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b.Bytes(), resp, err +} + +// Compare represents the result of a comparison of branches, tags or commits. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits +type Compare struct { + Commit *Commit `json:"commit"` + Commits []*Commit `json:"commits"` + Diffs []*Diff `json:"diffs"` + CompareTimeout bool `json:"compare_timeout"` + CompareSameRef bool `json:"compare_same_ref"` +} + +func (c Compare) String() string { + return Stringify(c) +} + +// CompareOptions represents the available Compare() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits +type CompareOptions struct { + From *string `url:"from,omitempty" json:"from,omitempty"` + To *string `url:"to,omitempty" json:"to,omitempty"` +} + +// Compare compares branches, tags or commits. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits +func (s *RepositoriesService) Compare(pid interface{}, opt *CompareOptions, options ...OptionFunc) (*Compare, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/compare", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + c := new(Compare) + resp, err := s.client.Do(req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} + +// Contributor represents a GitLap contributor. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html#contributors +type Contributor struct { + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Commits int `json:"commits,omitempty"` + Additions int `json:"additions,omitempty"` + Deletions int `json:"deletions,omitempty"` +} + +func (c Contributor) String() string { + return Stringify(c) +} + +// ListContributorsOptions represents the available ListContributorsOptions() +// options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html#contributors +type ListContributorsOptions ListOptions + +// Contributors gets the repository contributors list. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html#contributors +func (s *RepositoriesService) Contributors(pid interface{}, opt *ListContributorsOptions, options ...OptionFunc) ([]*Contributor, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/contributors", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var c []*Contributor + resp, err := s.client.Do(req, &c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/repository_files.go b/vendor/github.com/xanzy/go-gitlab/repository_files.go new file mode 100644 index 00000000..473128a3 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/repository_files.go @@ -0,0 +1,235 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "bytes" + "fmt" + "net/url" +) + +// RepositoryFilesService handles communication with the repository files +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/repository_files.html +type RepositoryFilesService struct { + client *Client +} + +// File represents a GitLab repository file. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/repository_files.html +type File struct { + FileName string `json:"file_name"` + FilePath string `json:"file_path"` + Size int `json:"size"` + Encoding string `json:"encoding"` + Content string `json:"content"` + Ref string `json:"ref"` + BlobID string `json:"blob_id"` + CommitID string `json:"commit_id"` +} + +func (r File) String() string { + return Stringify(r) +} + +// GetFileOptions represents the available GetFile() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#get-file-from-repository +type GetFileOptions struct { + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` +} + +// GetFile allows you to receive information about a file in repository like +// name, size, content. Note that file content is Base64 encoded. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#get-file-from-repository +func (s *RepositoryFilesService) GetFile(pid interface{}, fileName string, opt *GetFileOptions, options ...OptionFunc) (*File, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/files/%s", url.QueryEscape(project), url.QueryEscape(fileName)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + f := new(File) + resp, err := s.client.Do(req, f) + if err != nil { + return nil, resp, err + } + + return f, resp, err +} + +// GetRawFileOptions represents the available GetRawFile() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#get-raw-file-from-repository +type GetRawFileOptions struct { + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` +} + +// GetRawFile allows you to receive the raw file in repository. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#get-raw-file-from-repository +func (s *RepositoryFilesService) GetRawFile(pid interface{}, fileName string, opt *GetRawFileOptions, options ...OptionFunc) ([]byte, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/files/%s/raw", url.QueryEscape(project), url.QueryEscape(fileName)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var f bytes.Buffer + resp, err := s.client.Do(req, &f) + if err != nil { + return nil, resp, err + } + + return f.Bytes(), resp, err +} + +// FileInfo represents file details of a GitLab repository file. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/repository_files.html +type FileInfo struct { + FilePath string `json:"file_path"` + Branch string `json:"branch"` +} + +func (r FileInfo) String() string { + return Stringify(r) +} + +// CreateFileOptions represents the available CreateFile() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#create-new-file-in-repository +type CreateFileOptions struct { + Branch *string `url:"branch,omitempty" json:"branch,omitempty"` + Encoding *string `url:"encoding,omitempty" json:"encoding,omitempty"` + AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"` + AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"` + Content *string `url:"content,omitempty" json:"content,omitempty"` + CommitMessage *string `url:"commit_message,omitempty" json:"commit_message,omitempty"` +} + +// CreateFile creates a new file in a repository. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#create-new-file-in-repository +func (s *RepositoryFilesService) CreateFile(pid interface{}, fileName string, opt *CreateFileOptions, options ...OptionFunc) (*FileInfo, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/files/%s", url.QueryEscape(project), url.QueryEscape(fileName)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + f := new(FileInfo) + resp, err := s.client.Do(req, f) + if err != nil { + return nil, resp, err + } + + return f, resp, err +} + +// UpdateFileOptions represents the available UpdateFile() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#update-existing-file-in-repository +type UpdateFileOptions struct { + Branch *string `url:"branch,omitempty" json:"branch,omitempty"` + Encoding *string `url:"encoding,omitempty" json:"encoding,omitempty"` + AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"` + AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"` + Content *string `url:"content,omitempty" json:"content,omitempty"` + CommitMessage *string `url:"commit_message,omitempty" json:"commit_message,omitempty"` + LastCommitID *string `url:"last_commit_id,omitempty" json:"last_commit_id,omitempty"` +} + +// UpdateFile updates an existing file in a repository +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#update-existing-file-in-repository +func (s *RepositoryFilesService) UpdateFile(pid interface{}, fileName string, opt *UpdateFileOptions, options ...OptionFunc) (*FileInfo, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/files/%s", url.QueryEscape(project), url.QueryEscape(fileName)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + f := new(FileInfo) + resp, err := s.client.Do(req, f) + if err != nil { + return nil, resp, err + } + + return f, resp, err +} + +// DeleteFileOptions represents the available DeleteFile() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#delete-existing-file-in-repository +type DeleteFileOptions struct { + Branch *string `url:"branch,omitempty" json:"branch,omitempty"` + AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"` + AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"` + CommitMessage *string `url:"commit_message,omitempty" json:"commit_message,omitempty"` +} + +// DeleteFile deletes an existing file in a repository +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/repository_files.html#delete-existing-file-in-repository +func (s *RepositoryFilesService) DeleteFile(pid interface{}, fileName string, opt *DeleteFileOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/repository/files/%s", url.QueryEscape(project), url.QueryEscape(fileName)) + + req, err := s.client.NewRequest("DELETE", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/runners.go b/vendor/github.com/xanzy/go-gitlab/runners.go new file mode 100644 index 00000000..4ffef038 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/runners.go @@ -0,0 +1,326 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// RunnersService handles communication with the runner related methods of the +// GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/runners.html +type RunnersService struct { + client *Client +} + +// Runner represents a GitLab CI Runner. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/runners.html +type Runner struct { + ID int `json:"id"` + Description string `json:"description"` + Active bool `json:"active"` + IsShared bool `json:"is_shared"` + Name string `json:"name"` + Online bool `json:"online"` + Status string `json:"status"` +} + +// RunnerDetails represents the GitLab CI runner details. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/runners.html +type RunnerDetails struct { + Active bool `json:"active"` + Architecture string `json:"architecture"` + Description string `json:"description"` + ID int `json:"id"` + IsShared bool `json:"is_shared"` + ContactedAt *time.Time `json:"contacted_at,omitempty"` + Name string `json:"name"` + Online bool `json:"online"` + Status string `json:"status"` + Platform string `json:"platform,omitempty"` + Projects []struct { + ID int `json:"id"` + Name string `json:"name"` + NameWithNamespace string `json:"name_with_namespace"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` + } `json:"projects"` + Token string `json:"Token"` + Revision string `json:"revision,omitempty"` + TagList []string `json:"tag_list"` + Version string `json:"version,omitempty"` + AccessLevel string `json:"access_level"` +} + +// ListRunnersOptions represents the available ListRunners() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#list-owned-runners +type ListRunnersOptions struct { + ListOptions + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` +} + +// ListRunners gets a list of runners accessible by the authenticated user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#list-owned-runners +func (s *RunnersService) ListRunners(opt *ListRunnersOptions, options ...OptionFunc) ([]*Runner, *Response, error) { + req, err := s.client.NewRequest("GET", "runners", opt, options) + if err != nil { + return nil, nil, err + } + + var rs []*Runner + resp, err := s.client.Do(req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, err +} + +// ListAllRunners gets a list of all runners in the GitLab instance. Access is +// restricted to users with admin privileges. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#list-all-runners +func (s *RunnersService) ListAllRunners(opt *ListRunnersOptions, options ...OptionFunc) ([]*Runner, *Response, error) { + req, err := s.client.NewRequest("GET", "runners/all", opt, options) + if err != nil { + return nil, nil, err + } + + var rs []*Runner + resp, err := s.client.Do(req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, err +} + +// GetRunnerDetails returns details for given runner. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#get-runner-39-s-details +func (s *RunnersService) GetRunnerDetails(rid interface{}, options ...OptionFunc) (*RunnerDetails, *Response, error) { + runner, err := parseID(rid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("runners/%s", runner) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var rs *RunnerDetails + resp, err := s.client.Do(req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, err +} + +// UpdateRunnerDetailsOptions represents the available UpdateRunnerDetails() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#update-runner-39-s-details +type UpdateRunnerDetailsOptions struct { + Description *string `url:"description,omitempty" json:"description,omitempty"` + Active *bool `url:"active,omitempty" json:"active,omitempty"` + TagList []string `url:"tag_list[],omitempty" json:"tag_list,omitempty"` + RunUntagged *bool `url:"run_untagged,omitempty" json:"run_untagged,omitempty"` + Locked *bool `url:"locked,omitempty" json:"locked,omitempty"` + AccessLevel *string `url:"access_level,omitempty" json:"access_level,omitempty"` +} + +// UpdateRunnerDetails updates details for a given runner. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#update-runner-39-s-details +func (s *RunnersService) UpdateRunnerDetails(rid interface{}, opt *UpdateRunnerDetailsOptions, options ...OptionFunc) (*RunnerDetails, *Response, error) { + runner, err := parseID(rid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("runners/%s", runner) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + var rs *RunnerDetails + resp, err := s.client.Do(req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, err +} + +// RemoveRunner removes a runner. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#remove-a-runner +func (s *RunnersService) RemoveRunner(rid interface{}, options ...OptionFunc) (*Response, error) { + runner, err := parseID(rid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("runners/%s", runner) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ListRunnerJobsOptions represents the available ListRunnerJobs() +// options. Status can be one of: running, success, failed, canceled. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#list-runner-39-s-jobs +type ListRunnerJobsOptions struct { + ListOptions + Status *string `url:"status,omitempty" json:"status,omitempty"` +} + +// ListRunnerJobs gets a list of jobs that are being processed or were processed by specified Runner. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#list-runner-39-s-jobs +func (s *RunnersService) ListRunnerJobs(rid interface{}, opt *ListRunnerJobsOptions, options ...OptionFunc) ([]*Job, *Response, error) { + runner, err := parseID(rid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("runners/%s/jobs", runner) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var rs []*Job + resp, err := s.client.Do(req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, err +} + +// ListProjectRunnersOptions represents the available ListProjectRunners() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#list-project-s-runners +type ListProjectRunnersOptions ListRunnersOptions + +// ListProjectRunners gets a list of runners accessible by the authenticated user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#list-project-s-runners +func (s *RunnersService) ListProjectRunners(pid interface{}, opt *ListProjectRunnersOptions, options ...OptionFunc) ([]*Runner, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/runners", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var rs []*Runner + resp, err := s.client.Do(req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, err +} + +// EnableProjectRunnerOptions represents the available EnableProjectRunner() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#enable-a-runner-in-project +type EnableProjectRunnerOptions struct { + RunnerID int `json:"runner_id"` +} + +// EnableProjectRunner enables an available specific runner in the project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#enable-a-runner-in-project +func (s *RunnersService) EnableProjectRunner(pid interface{}, opt *EnableProjectRunnerOptions, options ...OptionFunc) (*Runner, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/runners", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + var r *Runner + resp, err := s.client.Do(req, &r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} + +// DisableProjectRunner disables a specific runner from project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/runners.html#disable-a-runner-from-project +func (s *RunnersService) DisableProjectRunner(pid interface{}, rid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + runner, err := parseID(rid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/runners/%s", url.QueryEscape(project), url.QueryEscape(runner)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/search.go b/vendor/github.com/xanzy/go-gitlab/search.go new file mode 100644 index 00000000..99c2f020 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/search.go @@ -0,0 +1,326 @@ +// +// Copyright 2018, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// SearchService handles communication with the search related methods of the +// GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html +type SearchService struct { + client *Client +} + +// SearchOptions represents the available options for all search methods. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html +type SearchOptions ListOptions + +type searchOptions struct { + SearchOptions + Scope string `url:"scope" json:"scope"` + Search string `url:"search" json:"search"` +} + +// Projects searches the expression within projects +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-projects +func (s *SearchService) Projects(query string, opt *SearchOptions, options ...OptionFunc) ([]*Project, *Response, error) { + var ps []*Project + resp, err := s.search("projects", query, &ps, opt, options...) + return ps, resp, err +} + +// ProjectsByGroup searches the expression within projects for +// the specified group +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#group-search-api +func (s *SearchService) ProjectsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Project, *Response, error) { + var ps []*Project + resp, err := s.searchByGroup(gid, "projects", query, &ps, opt, options...) + return ps, resp, err +} + +// Issues searches the expression within issues +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-issues +func (s *SearchService) Issues(query string, opt *SearchOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + var is []*Issue + resp, err := s.search("issues", query, &is, opt, options...) + return is, resp, err +} + +// IssuesByGroup searches the expression within issues for +// the specified group +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-issues +func (s *SearchService) IssuesByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + var is []*Issue + resp, err := s.searchByGroup(gid, "issues", query, &is, opt, options...) + return is, resp, err +} + +// IssuesByProject searches the expression within issues for +// the specified project +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-issues +func (s *SearchService) IssuesByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Issue, *Response, error) { + var is []*Issue + resp, err := s.searchByProject(pid, "issues", query, &is, opt, options...) + return is, resp, err +} + +// MergeRequests searches the expression within merge requests +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/search.html#scope-merge_requests +func (s *SearchService) MergeRequests(query string, opt *SearchOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) { + var ms []*MergeRequest + resp, err := s.search("merge_requests", query, &ms, opt, options...) + return ms, resp, err +} + +// MergeRequestsByGroup searches the expression within merge requests for +// the specified group +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/search.html#scope-merge_requests +func (s *SearchService) MergeRequestsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) { + var ms []*MergeRequest + resp, err := s.searchByGroup(gid, "merge_requests", query, &ms, opt, options...) + return ms, resp, err +} + +// MergeRequestsByProject searches the expression within merge requests for +// the specified project +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/search.html#scope-merge_requests +func (s *SearchService) MergeRequestsByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*MergeRequest, *Response, error) { + var ms []*MergeRequest + resp, err := s.searchByProject(pid, "merge_requests", query, &ms, opt, options...) + return ms, resp, err +} + +// Milestones searches the expression within milestones +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-milestones +func (s *SearchService) Milestones(query string, opt *SearchOptions, options ...OptionFunc) ([]*Milestone, *Response, error) { + var ms []*Milestone + resp, err := s.search("milestones", query, &ms, opt, options...) + return ms, resp, err +} + +// MilestonesByGroup searches the expression within milestones for +// the specified group +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-milestones +func (s *SearchService) MilestonesByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Milestone, *Response, error) { + var ms []*Milestone + resp, err := s.searchByGroup(gid, "milestones", query, &ms, opt, options...) + return ms, resp, err +} + +// MilestonesByProject searches the expression within milestones for +// the specified project +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-milestones +func (s *SearchService) MilestonesByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Milestone, *Response, error) { + var ms []*Milestone + resp, err := s.searchByProject(pid, "milestones", query, &ms, opt, options...) + return ms, resp, err +} + +// SnippetTitles searches the expression within snippet titles +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/search.html#scope-snippet_titles +func (s *SearchService) SnippetTitles(query string, opt *SearchOptions, options ...OptionFunc) ([]*Snippet, *Response, error) { + var ss []*Snippet + resp, err := s.search("snippet_titles", query, &ss, opt, options...) + return ss, resp, err +} + +// SnippetBlobs searches the expression within snippet blobs +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/search.html#scope-snippet_blobs +func (s *SearchService) SnippetBlobs(query string, opt *SearchOptions, options ...OptionFunc) ([]*Snippet, *Response, error) { + var ss []*Snippet + resp, err := s.search("snippet_blobs", query, &ss, opt, options...) + return ss, resp, err +} + +// NotesByProject searches the expression within notes for the specified +// project +// +// GitLab API docs: // https://docs.gitlab.com/ce/api/search.html#scope-notes +func (s *SearchService) NotesByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Note, *Response, error) { + var ns []*Note + resp, err := s.searchByProject(pid, "notes", query, &ns, opt, options...) + return ns, resp, err +} + +// WikiBlobs searches the expression within all wiki blobs +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/search.html#scope-wiki_blobs +func (s *SearchService) WikiBlobs(query string, opt *SearchOptions, options ...OptionFunc) ([]*Wiki, *Response, error) { + var ws []*Wiki + resp, err := s.search("wiki_blobs", query, &ws, opt, options...) + return ws, resp, err +} + +// WikiBlobsByGroup searches the expression within wiki blobs for +// specified group +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/search.html#scope-wiki_blobs +func (s *SearchService) WikiBlobsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Wiki, *Response, error) { + var ws []*Wiki + resp, err := s.searchByGroup(gid, "wiki_blobs", query, &ws, opt, options...) + return ws, resp, err +} + +// WikiBlobsByProject searches the expression within wiki blobs for +// the specified project +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/search.html#scope-wiki_blobs +func (s *SearchService) WikiBlobsByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Wiki, *Response, error) { + var ws []*Wiki + resp, err := s.searchByProject(pid, "wiki_blobs", query, &ws, opt, options...) + return ws, resp, err +} + +// Commits searches the expression within all commits +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-commits +func (s *SearchService) Commits(query string, opt *SearchOptions, options ...OptionFunc) ([]*Commit, *Response, error) { + var cs []*Commit + resp, err := s.search("commits", query, &cs, opt, options...) + return cs, resp, err +} + +// CommitsByGroup searches the expression within commits for the specified +// group +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-commits +func (s *SearchService) CommitsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Commit, *Response, error) { + var cs []*Commit + resp, err := s.searchByGroup(gid, "commits", query, &cs, opt, options...) + return cs, resp, err +} + +// CommitsByProject searches the expression within commits for the +// specified project +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-commits +func (s *SearchService) CommitsByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Commit, *Response, error) { + var cs []*Commit + resp, err := s.searchByProject(pid, "commits", query, &cs, opt, options...) + return cs, resp, err +} + +// Blob represents a single blob. +type Blob struct { + Basename string `json:"basename"` + Data string `json:"data"` + Filename string `json:"filename"` + ID int `json:"id"` + Ref string `json:"ref"` + Startline int `json:"startline"` + ProjectID int `json:"project_id"` +} + +// Blobs searches the expression within all blobs +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-blobs +func (s *SearchService) Blobs(query string, opt *SearchOptions, options ...OptionFunc) ([]*Blob, *Response, error) { + var bs []*Blob + resp, err := s.search("blobs", query, &bs, opt, options...) + return bs, resp, err +} + +// BlobsByGroup searches the expression within blobs for the specified +// group +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-blobs +func (s *SearchService) BlobsByGroup(gid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Blob, *Response, error) { + var bs []*Blob + resp, err := s.searchByGroup(gid, "blobs", query, &bs, opt, options...) + return bs, resp, err +} + +// BlobsByProject searches the expression within blobs for the specified +// project +// +// GitLab API docs: https://docs.gitlab.com/ce/api/search.html#scope-blobs +func (s *SearchService) BlobsByProject(pid interface{}, query string, opt *SearchOptions, options ...OptionFunc) ([]*Blob, *Response, error) { + var bs []*Blob + resp, err := s.searchByProject(pid, "blobs", query, &bs, opt, options...) + return bs, resp, err +} + +func (s *SearchService) search(scope, query string, result interface{}, opt *SearchOptions, options ...OptionFunc) (*Response, error) { + opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query} + + req, err := s.client.NewRequest("GET", "search", opts, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, result) +} + +func (s *SearchService) searchByGroup(gid interface{}, scope, query string, result interface{}, opt *SearchOptions, options ...OptionFunc) (*Response, error) { + group, err := parseID(gid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("groups/%s/-/search", url.QueryEscape(group)) + + opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query} + + req, err := s.client.NewRequest("GET", u, opts, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, result) +} + +func (s *SearchService) searchByProject(pid interface{}, scope, query string, result interface{}, opt *SearchOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/-/search", url.QueryEscape(project)) + + opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query} + + req, err := s.client.NewRequest("GET", u, opts, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, result) +} diff --git a/vendor/github.com/xanzy/go-gitlab/services.go b/vendor/github.com/xanzy/go-gitlab/services.go new file mode 100644 index 00000000..e93ae600 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/services.go @@ -0,0 +1,515 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" + "time" +) + +// ServicesService handles communication with the services related methods of +// the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/services.html +type ServicesService struct { + client *Client +} + +// Service represents a GitLab service. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/services.html +type Service struct { + ID int `json:"id"` + Title string `json:"title"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + Active bool `json:"active"` + PushEvents bool `json:"push_events"` + IssuesEvents bool `json:"issues_events"` + ConfidentialIssuesEvents bool `json:"confidential_issues_events"` + MergeRequestsEvents bool `json:"merge_requests_events"` + TagPushEvents bool `json:"tag_push_events"` + NoteEvents bool `json:"note_events"` + PipelineEvents bool `json:"pipeline_events"` + JobEvents bool `json:"job_events"` +} + +// SetGitLabCIServiceOptions represents the available SetGitLabCIService() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#edit-gitlab-ci-service +type SetGitLabCIServiceOptions struct { + Token *string `url:"token,omitempty" json:"token,omitempty"` + ProjectURL *string `url:"project_url,omitempty" json:"project_url,omitempty"` +} + +// SetGitLabCIService sets GitLab CI service for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#edit-gitlab-ci-service +func (s *ServicesService) SetGitLabCIService(pid interface{}, opt *SetGitLabCIServiceOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/gitlab-ci", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteGitLabCIService deletes GitLab CI service settings for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#delete-gitlab-ci-service +func (s *ServicesService) DeleteGitLabCIService(pid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/gitlab-ci", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// SetHipChatServiceOptions represents the available SetHipChatService() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#edit-hipchat-service +type SetHipChatServiceOptions struct { + Token *string `url:"token,omitempty" json:"token,omitempty" ` + Room *string `url:"room,omitempty" json:"room,omitempty"` +} + +// SetHipChatService sets HipChat service for a project +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#edit-hipchat-service +func (s *ServicesService) SetHipChatService(pid interface{}, opt *SetHipChatServiceOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/hipchat", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteHipChatService deletes HipChat service for project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#delete-hipchat-service +func (s *ServicesService) DeleteHipChatService(pid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/hipchat", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DroneCIService represents Drone CI service settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#drone-ci +type DroneCIService struct { + Service + Properties *DroneCIServiceProperties `json:"properties"` +} + +// DroneCIServiceProperties represents Drone CI specific properties. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#drone-ci +type DroneCIServiceProperties struct { + Token string `json:"token"` + DroneURL string `json:"drone_url"` + EnableSSLVerification bool `json:"enable_ssl_verification"` +} + +// GetDroneCIService gets Drone CI service settings for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#get-drone-ci-service-settings +func (s *ServicesService) GetDroneCIService(pid interface{}, options ...OptionFunc) (*DroneCIService, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/services/drone-ci", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + svc := new(DroneCIService) + resp, err := s.client.Do(req, svc) + if err != nil { + return nil, resp, err + } + + return svc, resp, err +} + +// SetDroneCIServiceOptions represents the available SetDroneCIService() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#createedit-drone-ci-service +type SetDroneCIServiceOptions struct { + Token *string `url:"token" json:"token" ` + DroneURL *string `url:"drone_url" json:"drone_url"` + EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"` +} + +// SetDroneCIService sets Drone CI service for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#createedit-drone-ci-service +func (s *ServicesService) SetDroneCIService(pid interface{}, opt *SetDroneCIServiceOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/drone-ci", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteDroneCIService deletes Drone CI service settings for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#delete-drone-ci-service +func (s *ServicesService) DeleteDroneCIService(pid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/drone-ci", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// SlackService represents Slack service settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#slack +type SlackService struct { + Service + Properties *SlackServiceProperties `json:"properties"` +} + +// SlackServiceProperties represents Slack specific properties. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#slack +type SlackServiceProperties struct { + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines"` +} + +// GetSlackService gets Slack service settings for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#get-slack-service-settings +func (s *ServicesService) GetSlackService(pid interface{}, options ...OptionFunc) (*SlackService, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/services/slack", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + svc := new(SlackService) + resp, err := s.client.Do(req, svc) + if err != nil { + return nil, resp, err + } + + return svc, resp, err +} + +// SetSlackServiceOptions represents the available SetSlackService() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#edit-slack-service +type SetSlackServiceOptions struct { + WebHook *string `url:"webhook,omitempty" json:"webhook,omitempty" ` + Username *string `url:"username,omitempty" json:"username,omitempty" ` + Channel *string `url:"channel,omitempty" json:"channel,omitempty"` +} + +// SetSlackService sets Slack service for a project +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#edit-slack-service +func (s *ServicesService) SetSlackService(pid interface{}, opt *SetSlackServiceOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/slack", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteSlackService deletes Slack service for project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#delete-slack-service +func (s *ServicesService) DeleteSlackService(pid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/slack", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// JiraService represents Jira service settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#jira +type JiraService struct { + Service + Properties *JiraServiceProperties `json:"properties"` +} + +// JiraServiceProperties represents Jira specific properties. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#jira +type JiraServiceProperties struct { + URL *string `url:"url,omitempty" json:"url,omitempty"` + ProjectKey *string `url:"project_key,omitempty" json:"project_key,omitempty" ` + Username *string `url:"username,omitempty" json:"username,omitempty" ` + Password *string `url:"password,omitempty" json:"password,omitempty" ` + JiraIssueTransitionID *string `url:"jira_issue_transition_id,omitempty" json:"jira_issue_transition_id,omitempty"` +} + +// GetJiraService gets Jira service settings for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#get-jira-service-settings +func (s *ServicesService) GetJiraService(pid interface{}, options ...OptionFunc) (*JiraService, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/services/jira", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + svc := new(JiraService) + resp, err := s.client.Do(req, svc) + if err != nil { + return nil, resp, err + } + + return svc, resp, err +} + +// SetJiraServiceOptions represents the available SetJiraService() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#edit-jira-service +type SetJiraServiceOptions JiraServiceProperties + +// SetJiraService sets Jira service for a project +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#edit-jira-service +func (s *ServicesService) SetJiraService(pid interface{}, opt *SetJiraServiceOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/jira", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteJiraService deletes Jira service for project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#delete-jira-service +func (s *ServicesService) DeleteJiraService(pid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/jira", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// JenkinsCIService represents Jenkins CI service settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/services.html#jenkins-ci +type JenkinsCIService struct { + Service + Properties *JenkinsCIServiceProperties `json:"properties"` +} + +// JenkinsCIServiceProperties represents Jenkins CI specific properties. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/services.html#jenkins-ci +type JenkinsCIServiceProperties struct { + URL *string `url:"jenkins_url,omitempty" json:"jenkins_url,omitempty"` + ProjectName *string `url:"project_name,omitempty" json:"project_name,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` +} + +// GetJenkinsCIService gets Jenkins CI service settings for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/services.html#get-jenkins-ci-service-settings +func (s *ServicesService) GetJenkinsCIService(pid interface{}, options ...OptionFunc) (*JenkinsCIService, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/services/jenkins", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + svc := new(JenkinsCIService) + resp, err := s.client.Do(req, svc) + if err != nil { + return nil, resp, err + } + + return svc, resp, err +} + +// SetJenkinsCIServiceOptions represents the available SetJenkinsCIService() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/services.html#jenkins-ci +type SetJenkinsCIServiceOptions struct { + URL *string `url:"jenkins_url,omitempty" json:"jenkins_url,omitempty"` + ProjectName *string `url:"project_name,omitempty" json:"project_name,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + Password *string `url:"password,omitempty" json:"password,omitempty"` +} + +// SetJenkinsCIService sets Jenkins service for a project +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/services.html#create-edit-jenkins-ci-service +func (s *ServicesService) SetJenkinsCIService(pid interface{}, opt *SetJenkinsCIServiceOptions, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/jenkins", url.QueryEscape(project)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteJenkinsCIService deletes Jenkins CI service for project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/services.html#delete-jira-service +func (s *ServicesService) DeleteJenkinsCIService(pid interface{}, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/services/jenkins", url.QueryEscape(project)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/session.go b/vendor/github.com/xanzy/go-gitlab/session.go new file mode 100644 index 00000000..f89fdbe5 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/session.go @@ -0,0 +1,78 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import "time" + +// SessionService handles communication with the session related methods of +// the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/session.html +type SessionService struct { + client *Client +} + +// Session represents a GitLab session. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/session.html#session +type Session struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + PrivateToken string `json:"private_token"` + Blocked bool `json:"blocked"` + CreatedAt *time.Time `json:"created_at"` + Bio interface{} `json:"bio"` + Skype string `json:"skype"` + Linkedin string `json:"linkedin"` + Twitter string `json:"twitter"` + WebsiteURL string `json:"website_url"` + DarkScheme bool `json:"dark_scheme"` + ThemeID int `json:"theme_id"` + IsAdmin bool `json:"is_admin"` + CanCreateGroup bool `json:"can_create_group"` + CanCreateTeam bool `json:"can_create_team"` + CanCreateProject bool `json:"can_create_project"` +} + +// GetSessionOptions represents the available Session() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/session.html#session +type GetSessionOptions struct { + Login *string `url:"login,omitempty" json:"login,omitempty"` + Email *string `url:"email,omitempty" json:"email,omitempty"` + Password *string `url:"password,omitempty" json:"password,omitempty"` +} + +// GetSession logs in to get private token. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/session.html#session +func (s *SessionService) GetSession(opt *GetSessionOptions, options ...OptionFunc) (*Session, *Response, error) { + req, err := s.client.NewRequest("POST", "session", opt, options) + if err != nil { + return nil, nil, err + } + + session := new(Session) + resp, err := s.client.Do(req, session) + if err != nil { + return nil, resp, err + } + + return session, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/settings.go b/vendor/github.com/xanzy/go-gitlab/settings.go new file mode 100644 index 00000000..fde9910f --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/settings.go @@ -0,0 +1,265 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import "time" + +// SettingsService handles communication with the application SettingsService +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/settings.html +type SettingsService struct { + client *Client +} + +// Settings represents the GitLab application settings. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/settings.html +type Settings struct { + ID int `json:"id"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + AdminNotificationEmail string `json:"admin_notification_email"` + AfterSignOutPath string `json:"after_sign_out_path"` + AfterSignUpText string `json:"after_sign_up_text"` + AkismetAPIKey string `json:"akismet_api_key"` + AkismetEnabled bool `json:"akismet_enabled"` + CircuitbreakerAccessRetries int `json:"circuitbreaker_access_retries"` + CircuitbreakerBackoffThreshold int `json:"circuitbreaker_backoff_threshold"` + CircuitbreakerFailureCountThreshold int `json:"circuitbreaker_failure_count_threshold"` + CircuitbreakerFailureResetTime int `json:"circuitbreaker_failure_reset_time"` + CircuitbreakerFailureWaitTime int `json:"circuitbreaker_failure_wait_time"` + CircuitbreakerStorageTimeout int `json:"circuitbreaker_storage_timeout"` + ClientsideSentryDSN string `json:"clientside_sentry_dsn"` + ClientsideSentryEnabled bool `json:"clientside_sentry_enabled"` + ContainerRegistryTokenExpireDelay int `json:"container_registry_token_expire_delay"` + DefaultArtifactsExpireIn string `json:"default_artifacts_expire_in"` + DefaultBranchProtection int `json:"default_branch_protection"` + DefaultGroupVisibility string `json:"default_group_visibility"` + DefaultProjectVisibility string `json:"default_project_visibility"` + DefaultProjectsLimit int `json:"default_projects_limit"` + DefaultSnippetVisibility string `json:"default_snippet_visibility"` + DisabledOauthSignInSources []string `json:"disabled_oauth_sign_in_sources"` + DomainBlacklistEnabled bool `json:"domain_blacklist_enabled"` + DomainBlacklist []string `json:"domain_blacklist"` + DomainWhitelist []string `json:"domain_whitelist"` + DSAKeyRestriction int `json:"dsa_key_restriction"` + ECDSAKeyRestriction int `json:"ecdsa_key_restriction"` + Ed25519KeyRestriction int `json:"ed25519_key_restriction"` + EmailAuthorInBody bool `json:"email_author_in_body"` + EnabledGitAccessProtocol string `json:"enabled_git_access_protocol"` + GravatarEnabled bool `json:"gravatar_enabled"` + HelpPageHideCommercialContent bool `json:"help_page_hide_commercial_content"` + HelpPageSupportURL string `json:"help_page_support_url"` + HomePageURL string `json:"home_page_url"` + HousekeepingBitmapsEnabled bool `json:"housekeeping_bitmaps_enabled"` + HousekeepingEnabled bool `json:"housekeeping_enabled"` + HousekeepingFullRepackPeriod int `json:"housekeeping_full_repack_period"` + HousekeepingGcPeriod int `json:"housekeeping_gc_period"` + HousekeepingIncrementalRepackPeriod int `json:"housekeeping_incremental_repack_period"` + HTMLEmailsEnabled bool `json:"html_emails_enabled"` + ImportSources []string `json:"import_sources"` + KodingEnabled bool `json:"koding_enabled"` + KodingURL string `json:"koding_url"` + MaxArtifactsSize int `json:"max_artifacts_size"` + MaxAttachmentSize int `json:"max_attachment_size"` + MaxPagesSize int `json:"max_pages_size"` + MetricsEnabled bool `json:"metrics_enabled"` + MetricsHost string `json:"metrics_host"` + MetricsMethodCallThreshold int `json:"metrics_method_call_threshold"` + MetricsPacketSize int `json:"metrics_packet_size"` + MetricsPoolSize int `json:"metrics_pool_size"` + MetricsPort int `json:"metrics_port"` + MetricsSampleInterval int `json:"metrics_sample_interval"` + MetricsTimeout int `json:"metrics_timeout"` + PasswordAuthenticationEnabledForWeb bool `json:"password_authentication_enabled_for_web"` + PasswordAuthenticationEnabledForGit bool `json:"password_authentication_enabled_for_git"` + PerformanceBarAllowedGroupID string `json:"performance_bar_allowed_group_id"` + PerformanceBarEnabled bool `json:"performance_bar_enabled"` + PlantumlEnabled bool `json:"plantuml_enabled"` + PlantumlURL string `json:"plantuml_url"` + PollingIntervalMultiplier float64 `json:"polling_interval_multiplier"` + ProjectExportEnabled bool `json:"project_export_enabled"` + PrometheusMetricsEnabled bool `json:"prometheus_metrics_enabled"` + RecaptchaEnabled bool `json:"recaptcha_enabled"` + RecaptchaPrivateKey string `json:"recaptcha_private_key"` + RecaptchaSiteKey string `json:"recaptcha_site_key"` + RepositoryChecksEnabled bool `json:"repository_checks_enabled"` + RepositoryStorages []string `json:"repository_storages"` + RequireTwoFactorAuthentication bool `json:"require_two_factor_authentication"` + RestrictedVisibilityLevels []VisibilityValue `json:"restricted_visibility_levels"` + RsaKeyRestriction int `json:"rsa_key_restriction"` + SendUserConfirmationEmail bool `json:"send_user_confirmation_email"` + SentryDSN string `json:"sentry_dsn"` + SentryEnabled bool `json:"sentry_enabled"` + SessionExpireDelay int `json:"session_expire_delay"` + SharedRunnersEnabled bool `json:"shared_runners_enabled"` + SharedRunnersText string `json:"shared_runners_text"` + SidekiqThrottlingEnabled bool `json:"sidekiq_throttling_enabled"` + SidekiqThrottlingFactor float64 `json:"sidekiq_throttling_factor"` + SidekiqThrottlingQueues []string `json:"sidekiq_throttling_queues"` + SignInText string `json:"sign_in_text"` + SignupEnabled bool `json:"signup_enabled"` + TerminalMaxSessionTime int `json:"terminal_max_session_time"` + TwoFactorGracePeriod int `json:"two_factor_grace_period"` + UniqueIPsLimitEnabled bool `json:"unique_ips_limit_enabled"` + UniqueIPsLimitPerUser int `json:"unique_ips_limit_per_user"` + UniqueIPsLimitTimeWindow int `json:"unique_ips_limit_time_window"` + UsagePingEnabled bool `json:"usage_ping_enabled"` + UserDefaultExternal bool `json:"user_default_external"` + UserOauthApplications bool `json:"user_oauth_applications"` + VersionCheckEnabled bool `json:"version_check_enabled"` +} + +func (s Settings) String() string { + return Stringify(s) +} + +// GetSettings gets the current application settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/settings.html#get-current-application.settings +func (s *SettingsService) GetSettings(options ...OptionFunc) (*Settings, *Response, error) { + req, err := s.client.NewRequest("GET", "application/settings", nil, options) + if err != nil { + return nil, nil, err + } + + as := new(Settings) + resp, err := s.client.Do(req, as) + if err != nil { + return nil, resp, err + } + + return as, resp, err +} + +// UpdateSettingsOptions represents the available UpdateSettings() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/settings.html#change-application.settings +type UpdateSettingsOptions struct { + AdminNotificationEmail *string `url:"admin_notification_email,omitempty" json:"admin_notification_email,omitempty"` + AfterSignOutPath *string `url:"after_sign_out_path,omitempty" json:"after_sign_out_path,omitempty"` + AfterSignUpText *string `url:"after_sign_up_text,omitempty" json:"after_sign_up_text,omitempty"` + AkismetAPIKey *string `url:"akismet_api_key,omitempty" json:"akismet_api_key,omitempty"` + AkismetEnabled *bool `url:"akismet_enabled,omitempty" json:"akismet_enabled,omitempty"` + CircuitbreakerAccessRetries *int `url:"circuitbreaker_access_retries,omitempty" json:"circuitbreaker_access_retries,omitempty"` + CircuitbreakerBackoffThreshold *int `url:"circuitbreaker_backoff_threshold,omitempty" json:"circuitbreaker_backoff_threshold,omitempty"` + CircuitbreakerFailureCountThreshold *int `url:"circuitbreaker_failure_count_threshold,omitempty" json:"circuitbreaker_failure_count_threshold,omitempty"` + CircuitbreakerFailureResetTime *int `url:"circuitbreaker_failure_reset_time,omitempty" json:"circuitbreaker_failure_reset_time,omitempty"` + CircuitbreakerFailureWaitTime *int `url:"circuitbreaker_failure_wait_time,omitempty" json:"circuitbreaker_failure_wait_time,omitempty"` + CircuitbreakerStorageTimeout *int `url:"circuitbreaker_storage_timeout,omitempty" json:"circuitbreaker_storage_timeout,omitempty"` + ClientsideSentryDSN *string `url:"clientside_sentry_dsn,omitempty" json:"clientside_sentry_dsn,omitempty"` + ClientsideSentryEnabled *bool `url:"clientside_sentry_enabled,omitempty" json:"clientside_sentry_enabled,omitempty"` + ContainerRegistryTokenExpireDelay *int `url:"container_registry_token_expire_delay,omitempty" json:"container_registry_token_expire_delay,omitempty"` + DefaultArtifactsExpireIn *string `url:"default_artifacts_expire_in,omitempty" json:"default_artifacts_expire_in,omitempty"` + DefaultBranchProtection *int `url:"default_branch_protection,omitempty" json:"default_branch_protection,omitempty"` + DefaultGroupVisibility *string `url:"default_group_visibility,omitempty" json:"default_group_visibility,omitempty"` + DefaultProjectVisibility *string `url:"default_project_visibility,omitempty" json:"default_project_visibility,omitempty"` + DefaultProjectsLimit *int `url:"default_projects_limit,omitempty" json:"default_projects_limit,omitempty"` + DefaultSnippetVisibility *string `url:"default_snippet_visibility,omitempty" json:"default_snippet_visibility,omitempty"` + DisabledOauthSignInSources []string `url:"disabled_oauth_sign_in_sources,omitempty" json:"disabled_oauth_sign_in_sources,omitempty"` + DomainBlacklistEnabled *bool `url:"domain_blacklist_enabled,omitempty" json:"domain_blacklist_enabled,omitempty"` + DomainBlacklist []string `url:"domain_blacklist,omitempty" json:"domain_blacklist,omitempty"` + DomainWhitelist []string `url:"domain_whitelist,omitempty" json:"domain_whitelist,omitempty"` + DSAKeyRestriction *int `url:"dsa_key_restriction,omitempty" json:"dsa_key_restriction,omitempty"` + ECDSAKeyRestriction *int `url:"ecdsa_key_restriction,omitempty" json:"ecdsa_key_restriction,omitempty"` + Ed25519KeyRestriction *int `url:"ed25519_key_restriction,omitempty" json:"ed25519_key_restriction,omitempty"` + EmailAuthorInBody *bool `url:"email_author_in_body,omitempty" json:"email_author_in_body,omitempty"` + EnabledGitAccessProtocol *string `url:"enabled_git_access_protocol,omitempty" json:"enabled_git_access_protocol,omitempty"` + GravatarEnabled *bool `url:"gravatar_enabled,omitempty" json:"gravatar_enabled,omitempty"` + HelpPageHideCommercialContent *bool `url:"help_page_hide_commercial_content,omitempty" json:"help_page_hide_commercial_content,omitempty"` + HelpPageSupportURL *string `url:"help_page_support_url,omitempty" json:"help_page_support_url,omitempty"` + HomePageURL *string `url:"home_page_url,omitempty" json:"home_page_url,omitempty"` + HousekeepingBitmapsEnabled *bool `url:"housekeeping_bitmaps_enabled,omitempty" json:"housekeeping_bitmaps_enabled,omitempty"` + HousekeepingEnabled *bool `url:"housekeeping_enabled,omitempty" json:"housekeeping_enabled,omitempty"` + HousekeepingFullRepackPeriod *int `url:"housekeeping_full_repack_period,omitempty" json:"housekeeping_full_repack_period,omitempty"` + HousekeepingGcPeriod *int `url:"housekeeping_gc_period,omitempty" json:"housekeeping_gc_period,omitempty"` + HousekeepingIncrementalRepackPeriod *int `url:"housekeeping_incremental_repack_period,omitempty" json:"housekeeping_incremental_repack_period,omitempty"` + HTMLEmailsEnabled *bool `url:"html_emails_enabled,omitempty" json:"html_emails_enabled,omitempty"` + ImportSources []string `url:"import_sources,omitempty" json:"import_sources,omitempty"` + KodingEnabled *bool `url:"koding_enabled,omitempty" json:"koding_enabled,omitempty"` + KodingURL *string `url:"koding_url,omitempty" json:"koding_url,omitempty"` + MaxArtifactsSize *int `url:"max_artifacts_size,omitempty" json:"max_artifacts_size,omitempty"` + MaxAttachmentSize *int `url:"max_attachment_size,omitempty" json:"max_attachment_size,omitempty"` + MaxPagesSize *int `url:"max_pages_size,omitempty" json:"max_pages_size,omitempty"` + MetricsEnabled *bool `url:"metrics_enabled,omitempty" json:"metrics_enabled,omitempty"` + MetricsHost *string `url:"metrics_host,omitempty" json:"metrics_host,omitempty"` + MetricsMethodCallThreshold *int `url:"metrics_method_call_threshold,omitempty" json:"metrics_method_call_threshold,omitempty"` + MetricsPacketSize *int `url:"metrics_packet_size,omitempty" json:"metrics_packet_size,omitempty"` + MetricsPoolSize *int `url:"metrics_pool_size,omitempty" json:"metrics_pool_size,omitempty"` + MetricsPort *int `url:"metrics_port,omitempty" json:"metrics_port,omitempty"` + MetricsSampleInterval *int `url:"metrics_sample_interval,omitempty" json:"metrics_sample_interval,omitempty"` + MetricsTimeout *int `url:"metrics_timeout,omitempty" json:"metrics_timeout,omitempty"` + PasswordAuthenticationEnabledForWeb *bool `url:"password_authentication_enabled_for_web,omitempty" json:"password_authentication_enabled_for_web,omitempty"` + PasswordAuthenticationEnabledForGit *bool `url:"password_authentication_enabled_for_git,omitempty" json:"password_authentication_enabled_for_git,omitempty"` + PerformanceBarAllowedGroupID *string `url:"performance_bar_allowed_group_id,omitempty" json:"performance_bar_allowed_group_id,omitempty"` + PerformanceBarEnabled *bool `url:"performance_bar_enabled,omitempty" json:"performance_bar_enabled,omitempty"` + PlantumlEnabled *bool `url:"plantuml_enabled,omitempty" json:"plantuml_enabled,omitempty"` + PlantumlURL *string `url:"plantuml_url,omitempty" json:"plantuml_url,omitempty"` + PollingIntervalMultiplier *float64 `url:"polling_interval_multiplier,omitempty" json:"polling_interval_multiplier,omitempty"` + ProjectExportEnabled *bool `url:"project_export_enabled,omitempty" json:"project_export_enabled,omitempty"` + PrometheusMetricsEnabled *bool `url:"prometheus_metrics_enabled,omitempty" json:"prometheus_metrics_enabled,omitempty"` + RecaptchaEnabled *bool `url:"recaptcha_enabled,omitempty" json:"recaptcha_enabled,omitempty"` + RecaptchaPrivateKey *string `url:"recaptcha_private_key,omitempty" json:"recaptcha_private_key,omitempty"` + RecaptchaSiteKey *string `url:"recaptcha_site_key,omitempty" json:"recaptcha_site_key,omitempty"` + RepositoryChecksEnabled *bool `url:"repository_checks_enabled,omitempty" json:"repository_checks_enabled,omitempty"` + RepositoryStorages []string `url:"repository_storages,omitempty" json:"repository_storages,omitempty"` + RequireTwoFactorAuthentication *bool `url:"require_two_factor_authentication,omitempty" json:"require_two_factor_authentication,omitempty"` + RestrictedVisibilityLevels []VisibilityValue `url:"restricted_visibility_levels,omitempty" json:"restricted_visibility_levels,omitempty"` + RsaKeyRestriction *int `url:"rsa_key_restriction,omitempty" json:"rsa_key_restriction,omitempty"` + SendUserConfirmationEmail *bool `url:"send_user_confirmation_email,omitempty" json:"send_user_confirmation_email,omitempty"` + SentryDSN *string `url:"sentry_dsn,omitempty" json:"sentry_dsn,omitempty"` + SentryEnabled *bool `url:"sentry_enabled,omitempty" json:"sentry_enabled,omitempty"` + SessionExpireDelay *int `url:"session_expire_delay,omitempty" json:"session_expire_delay,omitempty"` + SharedRunnersEnabled *bool `url:"shared_runners_enabled,omitempty" json:"shared_runners_enabled,omitempty"` + SharedRunnersText *string `url:"shared_runners_text,omitempty" json:"shared_runners_text,omitempty"` + SidekiqThrottlingEnabled *bool `url:"sidekiq_throttling_enabled,omitempty" json:"sidekiq_throttling_enabled,omitempty"` + SidekiqThrottlingFactor *float64 `url:"sidekiq_throttling_factor,omitempty" json:"sidekiq_throttling_factor,omitempty"` + SidekiqThrottlingQueues []string `url:"sidekiq_throttling_queues,omitempty" json:"sidekiq_throttling_queues,omitempty"` + SignInText *string `url:"sign_in_text,omitempty" json:"sign_in_text,omitempty"` + SignupEnabled *bool `url:"signup_enabled,omitempty" json:"signup_enabled,omitempty"` + TerminalMaxSessionTime *int `url:"terminal_max_session_time,omitempty" json:"terminal_max_session_time,omitempty"` + TwoFactorGracePeriod *int `url:"two_factor_grace_period,omitempty" json:"two_factor_grace_period,omitempty"` + UniqueIPsLimitEnabled *bool `url:"unique_ips_limit_enabled,omitempty" json:"unique_ips_limit_enabled,omitempty"` + UniqueIPsLimitPerUser *int `url:"unique_ips_limit_per_user,omitempty" json:"unique_ips_limit_per_user,omitempty"` + UniqueIPsLimitTimeWindow *int `url:"unique_ips_limit_time_window,omitempty" json:"unique_ips_limit_time_window,omitempty"` + UsagePingEnabled *bool `url:"usage_ping_enabled,omitempty" json:"usage_ping_enabled,omitempty"` + UserDefaultExternal *bool `url:"user_default_external,omitempty" json:"user_default_external,omitempty"` + UserOauthApplications *bool `url:"user_oauth_applications,omitempty" json:"user_oauth_applications,omitempty"` + VersionCheckEnabled *bool `url:"version_check_enabled,omitempty" json:"version_check_enabled,omitempty"` +} + +// UpdateSettings updates the application settings. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/settings.html#change-application.settings +func (s *SettingsService) UpdateSettings(opt *UpdateSettingsOptions, options ...OptionFunc) (*Settings, *Response, error) { + req, err := s.client.NewRequest("PUT", "application/settings", opt, options) + if err != nil { + return nil, nil, err + } + + as := new(Settings) + resp, err := s.client.Do(req, as) + if err != nil { + return nil, resp, err + } + + return as, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/sidekiq_metrics.go b/vendor/github.com/xanzy/go-gitlab/sidekiq_metrics.go new file mode 100644 index 00000000..83e77024 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/sidekiq_metrics.go @@ -0,0 +1,154 @@ +// +// Copyright 2018, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import "time" + +// SidekiqService handles communication with the sidekiq service +// +// GitLab API docs: https://docs.gitlab.com/ce/api/sidekiq_metrics.html +type SidekiqService struct { + client *Client +} + +// QueueMetrics represents the GitLab sidekiq queue metrics. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/sidekiq_metrics.html#get-the-current-queue-metrics +type QueueMetrics struct { + Queues map[string]struct { + Backlog int `json:"backlog"` + Latency int `json:"latency"` + } `json:"queues"` +} + +// GetQueueMetrics lists information about all the registered queues, +// their backlog and their latency. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/sidekiq_metrics.html#get-the-current-queue-metrics +func (s *SidekiqService) GetQueueMetrics(options ...OptionFunc) (*QueueMetrics, *Response, error) { + req, err := s.client.NewRequest("GET", "/sidekiq/queue_metrics", nil, options) + if err != nil { + return nil, nil, err + } + + q := new(QueueMetrics) + resp, err := s.client.Do(req, q) + if err != nil { + return nil, resp, err + } + + return q, resp, err +} + +// ProcessMetrics represents the GitLab sidekiq process metrics. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/sidekiq_metrics.html#get-the-current-process-metrics +type ProcessMetrics struct { + Processes []struct { + Hostname string `json:"hostname"` + Pid int `json:"pid"` + Tag string `json:"tag"` + StartedAt *time.Time `json:"started_at"` + Queues []string `json:"queues"` + Labels []string `json:"labels"` + Concurrency int `json:"concurrency"` + Busy int `json:"busy"` + } `json:"processes"` +} + +// GetProcessMetrics lists information about all the Sidekiq workers registered +// to process your queues. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/sidekiq_metrics.html#get-the-current-process-metrics +func (s *SidekiqService) GetProcessMetrics(options ...OptionFunc) (*ProcessMetrics, *Response, error) { + req, err := s.client.NewRequest("GET", "/sidekiq/process_metrics", nil, options) + if err != nil { + return nil, nil, err + } + + p := new(ProcessMetrics) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} + +// JobStats represents the GitLab sidekiq job stats. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/sidekiq_metrics.html#get-the-current-job-statistics +type JobStats struct { + Jobs struct { + Processed int `json:"processed"` + Failed int `json:"failed"` + Enqueued int `json:"enqueued"` + } `json:"jobs"` +} + +// GetJobStats list information about the jobs that Sidekiq has performed. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/sidekiq_metrics.html#get-the-current-job-statistics +func (s *SidekiqService) GetJobStats(options ...OptionFunc) (*JobStats, *Response, error) { + req, err := s.client.NewRequest("GET", "/sidekiq/job_stats", nil, options) + if err != nil { + return nil, nil, err + } + + j := new(JobStats) + resp, err := s.client.Do(req, j) + if err != nil { + return nil, resp, err + } + + return j, resp, err +} + +// CompoundMetrics represents the GitLab sidekiq compounded stats. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/sidekiq_metrics.html#get-a-compound-response-of-all-the-previously-mentioned-metrics +type CompoundMetrics struct { + QueueMetrics + ProcessMetrics + JobStats +} + +// GetCompoundMetrics lists all the currently available information about Sidekiq. +// Get a compound response of all the previously mentioned metrics +// +// GitLab API docs: https://docs.gitlab.com/ce/api/sidekiq_metrics.html#get-the-current-job-statistics +func (s *SidekiqService) GetCompoundMetrics(options ...OptionFunc) (*CompoundMetrics, *Response, error) { + req, err := s.client.NewRequest("GET", "/sidekiq/compound_metrics", nil, options) + if err != nil { + return nil, nil, err + } + + c := new(CompoundMetrics) + resp, err := s.client.Do(req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/snippets.go b/vendor/github.com/xanzy/go-gitlab/snippets.go new file mode 100644 index 00000000..be232c8c --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/snippets.go @@ -0,0 +1,230 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "bytes" + "fmt" + "time" +) + +// SnippetsService handles communication with the snippets +// related methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/snippets.html +type SnippetsService struct { + client *Client +} + +// Snippet represents a GitLab snippet. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/snippets.html +type Snippet struct { + ID int `json:"id"` + Title string `json:"title"` + FileName string `json:"file_name"` + Description string `json:"description"` + Author struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + } `json:"author"` + UpdatedAt *time.Time `json:"updated_at"` + CreatedAt *time.Time `json:"created_at"` + WebURL string `json:"web_url"` + RawURL string `json:"raw_url"` +} + +func (s Snippet) String() string { + return Stringify(s) +} + +// ListSnippetsOptions represents the available ListSnippets() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/snippets.html#list-snippets +type ListSnippetsOptions ListOptions + +// ListSnippets gets a list of snippets. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/snippets.html#list-snippets +func (s *SnippetsService) ListSnippets(opt *ListSnippetsOptions, options ...OptionFunc) ([]*Snippet, *Response, error) { + req, err := s.client.NewRequest("GET", "snippets", opt, options) + if err != nil { + return nil, nil, err + } + + var ps []*Snippet + resp, err := s.client.Do(req, &ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// GetSnippet gets a single snippet +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#single-snippet +func (s *SnippetsService) GetSnippet(snippet int, options ...OptionFunc) (*Snippet, *Response, error) { + u := fmt.Sprintf("snippets/%d", snippet) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + ps := new(Snippet) + resp, err := s.client.Do(req, ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// CreateSnippetOptions represents the available CreateSnippet() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#create-new-snippet +type CreateSnippetOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + FileName *string `url:"file_name,omitempty" json:"file_name,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Content *string `url:"content,omitempty" json:"content,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` +} + +// CreateSnippet creates a new snippet. The user must have permission +// to create new snippets. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#create-new-snippet +func (s *SnippetsService) CreateSnippet(opt *CreateSnippetOptions, options ...OptionFunc) (*Snippet, *Response, error) { + req, err := s.client.NewRequest("POST", "snippets", opt, options) + if err != nil { + return nil, nil, err + } + + ps := new(Snippet) + resp, err := s.client.Do(req, ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// UpdateSnippetOptions represents the available UpdateSnippet() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#update-snippet +type UpdateSnippetOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + FileName *string `url:"file_name,omitempty" json:"file_name,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Content *string `url:"content,omitempty" json:"content,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` +} + +// UpdateSnippet updates an existing snippet. The user must have +// permission to change an existing snippet. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#update-snippet +func (s *SnippetsService) UpdateSnippet(snippet int, opt *UpdateSnippetOptions, options ...OptionFunc) (*Snippet, *Response, error) { + u := fmt.Sprintf("snippets/%d", snippet) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + ps := new(Snippet) + resp, err := s.client.Do(req, ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} + +// DeleteSnippet deletes an existing snippet. This is an idempotent +// function and deleting a non-existent snippet still returns a 200 OK status +// code. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#delete-snippet +func (s *SnippetsService) DeleteSnippet(snippet int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("snippets/%d", snippet) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// SnippetContent returns the raw snippet as plain text. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#snippet-content +func (s *SnippetsService) SnippetContent(snippet int, options ...OptionFunc) ([]byte, *Response, error) { + u := fmt.Sprintf("snippets/%d/raw", snippet) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var b bytes.Buffer + resp, err := s.client.Do(req, &b) + if err != nil { + return nil, resp, err + } + + return b.Bytes(), resp, err +} + +// ExploreSnippetsOptions represents the available ExploreSnippets() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#explore-all-public-snippets +type ExploreSnippetsOptions ListOptions + +// ExploreSnippets gets the list of public snippets. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/snippets.html#explore-all-public-snippets +func (s *SnippetsService) ExploreSnippets(opt *ExploreSnippetsOptions, options ...OptionFunc) ([]*Snippet, *Response, error) { + req, err := s.client.NewRequest("GET", "snippets/public", nil, options) + if err != nil { + return nil, nil, err + } + + var ps []*Snippet + resp, err := s.client.Do(req, &ps) + if err != nil { + return nil, resp, err + } + + return ps, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/strings.go b/vendor/github.com/xanzy/go-gitlab/strings.go new file mode 100644 index 00000000..aeefb6b8 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/strings.go @@ -0,0 +1,94 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "bytes" + "fmt" + + "reflect" +) + +// Stringify attempts to create a reasonable string representation of types in +// the GitHub library. It does things like resolve pointers to their values +// and omits struct fields with nil values. +func Stringify(message interface{}) string { + var buf bytes.Buffer + v := reflect.ValueOf(message) + stringifyValue(&buf, v) + return buf.String() +} + +// stringifyValue was heavily inspired by the goprotobuf library. +func stringifyValue(buf *bytes.Buffer, val reflect.Value) { + if val.Kind() == reflect.Ptr && val.IsNil() { + buf.WriteString("") + return + } + + v := reflect.Indirect(val) + + switch v.Kind() { + case reflect.String: + fmt.Fprintf(buf, `"%s"`, v) + case reflect.Slice: + buf.WriteByte('[') + for i := 0; i < v.Len(); i++ { + if i > 0 { + buf.WriteByte(' ') + } + + stringifyValue(buf, v.Index(i)) + } + + buf.WriteByte(']') + return + case reflect.Struct: + if v.Type().Name() != "" { + buf.WriteString(v.Type().String()) + } + + buf.WriteByte('{') + + var sep bool + for i := 0; i < v.NumField(); i++ { + fv := v.Field(i) + if fv.Kind() == reflect.Ptr && fv.IsNil() { + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + continue + } + + if sep { + buf.WriteString(", ") + } else { + sep = true + } + + buf.WriteString(v.Type().Field(i).Name) + buf.WriteByte(':') + stringifyValue(buf, fv) + } + + buf.WriteByte('}') + default: + if v.CanInterface() { + fmt.Fprint(buf, v.Interface()) + } + } +} diff --git a/vendor/github.com/xanzy/go-gitlab/system_hooks.go b/vendor/github.com/xanzy/go-gitlab/system_hooks.go new file mode 100644 index 00000000..d5209d4f --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/system_hooks.go @@ -0,0 +1,143 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "time" +) + +// SystemHooksService handles communication with the system hooks related +// methods of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/system_hooks.html +type SystemHooksService struct { + client *Client +} + +// Hook represents a GitLap system hook. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/system_hooks.html +type Hook struct { + ID int `json:"id"` + URL string `json:"url"` + CreatedAt *time.Time `json:"created_at"` +} + +func (h Hook) String() string { + return Stringify(h) +} + +// ListHooks gets a list of system hooks. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/system_hooks.html#list-system-hooks +func (s *SystemHooksService) ListHooks(options ...OptionFunc) ([]*Hook, *Response, error) { + req, err := s.client.NewRequest("GET", "hooks", nil, options) + if err != nil { + return nil, nil, err + } + + var h []*Hook + resp, err := s.client.Do(req, &h) + if err != nil { + return nil, resp, err + } + + return h, resp, err +} + +// AddHookOptions represents the available AddHook() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/system_hooks.html#add-new-system-hook-hook +type AddHookOptions struct { + URL *string `url:"url,omitempty" json:"url,omitempty"` +} + +// AddHook adds a new system hook hook. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/system_hooks.html#add-new-system-hook-hook +func (s *SystemHooksService) AddHook(opt *AddHookOptions, options ...OptionFunc) (*Hook, *Response, error) { + req, err := s.client.NewRequest("POST", "hooks", opt, options) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, err +} + +// HookEvent represents an event trigger by a GitLab system hook. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/system_hooks.html +type HookEvent struct { + EventName string `json:"event_name"` + Name string `json:"name"` + Path string `json:"path"` + ProjectID int `json:"project_id"` + OwnerName string `json:"owner_name"` + OwnerEmail string `json:"owner_email"` +} + +func (h HookEvent) String() string { + return Stringify(h) +} + +// TestHook tests a system hook. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/system_hooks.html#test-system-hook +func (s *SystemHooksService) TestHook(hook int, options ...OptionFunc) (*HookEvent, *Response, error) { + u := fmt.Sprintf("hooks/%d", hook) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + h := new(HookEvent) + resp, err := s.client.Do(req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, err +} + +// DeleteHook deletes a system hook. This is an idempotent API function and +// returns 200 OK even if the hook is not available. If the hook is deleted it +// is also returned as JSON. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/system_hooks.html#delete-system-hook +func (s *SystemHooksService) DeleteHook(hook int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("hooks/%d", hook) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/tags.go b/vendor/github.com/xanzy/go-gitlab/tags.go new file mode 100644 index 00000000..b726410e --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/tags.go @@ -0,0 +1,232 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "fmt" + "net/url" +) + +// TagsService handles communication with the tags related methods +// of the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/tags.html +type TagsService struct { + client *Client +} + +// Tag represents a GitLab tag. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/tags.html +type Tag struct { + Commit *Commit `json:"commit"` + Release *Release `json:"release"` + Name string `json:"name"` + Message string `json:"message"` +} + +// Release represents a GitLab version release. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/tags.html +type Release struct { + TagName string `json:"tag_name"` + Description string `json:"description"` +} + +func (t Tag) String() string { + return Stringify(t) +} + +// ListTagsOptions represents the available ListTags() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#list-project-repository-tags +type ListTagsOptions ListOptions + +// ListTags gets a list of tags from a project, sorted by name in reverse +// alphabetical order. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#list-project-repository-tags +func (s *TagsService) ListTags(pid interface{}, opt *ListTagsOptions, options ...OptionFunc) ([]*Tag, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/tags", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var t []*Tag + resp, err := s.client.Do(req, &t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// GetTag a specific repository tag determined by its name. It returns 200 together +// with the tag information if the tag exists. It returns 404 if the tag does not exist. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#get-a-single-repository-tag +func (s *TagsService) GetTag(pid interface{}, tag string, options ...OptionFunc) (*Tag, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/tags/%s", url.QueryEscape(project), tag) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var t *Tag + resp, err := s.client.Do(req, &t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// CreateTagOptions represents the available CreateTag() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#create-a-new-tag +type CreateTagOptions struct { + TagName *string `url:"tag_name,omitempty" json:"tag_name,omitempty"` + Ref *string `url:"ref,omitempty" json:"ref,omitempty"` + Message *string `url:"message,omitempty" json:"message,omitempty"` + ReleaseDescription *string `url:"release_description:omitempty" json:"release_description,omitempty"` +} + +// CreateTag creates a new tag in the repository that points to the supplied ref. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#create-a-new-tag +func (s *TagsService) CreateTag(pid interface{}, opt *CreateTagOptions, options ...OptionFunc) (*Tag, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/tags", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + t := new(Tag) + resp, err := s.client.Do(req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// DeleteTag deletes a tag of a repository with given name. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#delete-a-tag +func (s *TagsService) DeleteTag(pid interface{}, tag string, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/repository/tags/%s", url.QueryEscape(project), tag) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// CreateReleaseOptions represents the available CreateRelease() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#create-a-new-release +type CreateReleaseOptions struct { + Description *string `url:"description:omitempty" json:"description,omitempty"` +} + +// CreateRelease Add release notes to the existing git tag. +// If there already exists a release for the given tag, status code 409 is returned. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#create-a-new-release +func (s *TagsService) CreateRelease(pid interface{}, tag string, opt *CreateReleaseOptions, options ...OptionFunc) (*Release, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/tags/%s/release", url.QueryEscape(project), tag) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + r := new(Release) + resp, err := s.client.Do(req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} + +// UpdateReleaseOptions represents the available UpdateRelease() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#update-a-release +type UpdateReleaseOptions struct { + Description *string `url:"description:omitempty" json:"description,omitempty"` +} + +// UpdateRelease Updates the release notes of a given release. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/tags.html#update-a-release +func (s *TagsService) UpdateRelease(pid interface{}, tag string, opt *UpdateReleaseOptions, options ...OptionFunc) (*Release, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/repository/tags/%s/release", url.QueryEscape(project), tag) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + r := new(Release) + resp, err := s.client.Do(req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/time_stats.go b/vendor/github.com/xanzy/go-gitlab/time_stats.go new file mode 100644 index 00000000..5e3bff90 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/time_stats.go @@ -0,0 +1,163 @@ +package gitlab + +import ( + "fmt" + "net/url" +) + +// timeStatsService handles communication with the time tracking related +// methods of the GitLab API. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +type timeStatsService struct { + client *Client +} + +// TimeStats represents the time estimates and time spent for an issue. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +type TimeStats struct { + HumanTimeEstimate string `json:"human_time_estimate"` + HumanTotalTimeSpent string `json:"human_total_time_spent"` + TimeEstimate int `json:"time_estimate"` + TotalTimeSpent int `json:"total_time_spent"` +} + +func (t TimeStats) String() string { + return Stringify(t) +} + +// SetTimeEstimateOptions represents the available SetTimeEstimate() +// options. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +type SetTimeEstimateOptions struct { + Duration *string `url:"duration,omitempty" json:"duration,omitempty"` +} + +// setTimeEstimate sets the time estimate for a single project issue. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +func (s *timeStatsService) setTimeEstimate(pid interface{}, entity string, issue int, opt *SetTimeEstimateOptions, options ...OptionFunc) (*TimeStats, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/time_estimate", url.QueryEscape(project), entity, issue) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + t := new(TimeStats) + resp, err := s.client.Do(req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// resetTimeEstimate resets the time estimate for a single project issue. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +func (s *timeStatsService) resetTimeEstimate(pid interface{}, entity string, issue int, options ...OptionFunc) (*TimeStats, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/reset_time_estimate", url.QueryEscape(project), entity, issue) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + t := new(TimeStats) + resp, err := s.client.Do(req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// AddSpentTimeOptions represents the available AddSpentTime() options. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +type AddSpentTimeOptions struct { + Duration *string `url:"duration,omitempty" json:"duration,omitempty"` +} + +// addSpentTime adds spent time for a single project issue. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +func (s *timeStatsService) addSpentTime(pid interface{}, entity string, issue int, opt *AddSpentTimeOptions, options ...OptionFunc) (*TimeStats, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/add_spent_time", url.QueryEscape(project), entity, issue) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + t := new(TimeStats) + resp, err := s.client.Do(req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// resetSpentTime resets the spent time for a single project issue. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +func (s *timeStatsService) resetSpentTime(pid interface{}, entity string, issue int, options ...OptionFunc) (*TimeStats, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/reset_spent_time", url.QueryEscape(project), entity, issue) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, nil, err + } + + t := new(TimeStats) + resp, err := s.client.Do(req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// getTimeSpent gets the spent time for a single project issue. +// +// GitLab docs: https://docs.gitlab.com/ce/workflow/time_tracking.html +func (s *timeStatsService) getTimeSpent(pid interface{}, entity string, issue int, options ...OptionFunc) (*TimeStats, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/%s/%d/time_stats", url.QueryEscape(project), entity, issue) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + t := new(TimeStats) + resp, err := s.client.Do(req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/todos.go b/vendor/github.com/xanzy/go-gitlab/todos.go new file mode 100644 index 00000000..db58eddb --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/todos.go @@ -0,0 +1,175 @@ +package gitlab + +import "time" +import "fmt" + +// TodosService handles communication with the todos related methods of +// the Gitlab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/todos.html +type TodosService struct { + client *Client +} + +// TodoAction represents the available actions that can be performed on a todo. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/todos.html +type TodoAction string + +// The available todo actions. +const ( + TodoAssigned TodoAction = "assigned" + TodoMentioned TodoAction = "mentioned" + TodoBuildFailed TodoAction = "build_failed" + TodoMarked TodoAction = "marked" + TodoApprovalRequired TodoAction = "approval_required" + TodoDirectlyAddressed TodoAction = "directly_addressed" +) + +// TodoTarget represents a todo target of type Issue or MergeRequest +type TodoTarget struct { + // TODO: replace both Assignee and Author structs with v4 User struct + Assignee struct { + Name string `json:"name"` + Username string `json:"username"` + ID int `json:"id"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"assignee"` + Author struct { + Name string `json:"name"` + Username string `json:"username"` + ID int `json:"id"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"author"` + CreatedAt *time.Time `json:"created_at"` + Description string `json:"description"` + Downvotes int `json:"downvotes"` + ID int `json:"id"` + IID int `json:"iid"` + Labels []string `json:"labels"` + Milestone Milestone `json:"milestone"` + ProjectID int `json:"project_id"` + State string `json:"state"` + Subscribed bool `json:"subscribed"` + Title string `json:"title"` + UpdatedAt *time.Time `json:"updated_at"` + Upvotes int `json:"upvotes"` + UserNotesCount int `json:"user_notes_count"` + WebURL string `json:"web_url"` + + // Only available for type Issue + Confidential bool `json:"confidential"` + DueDate string `json:"due_date"` + Weight int `json:"weight"` + + // Only available for type MergeRequest + ApprovalsBeforeMerge bool `json:"approvals_before_merge"` + ForceRemoveSourceBranch bool `json:"force_remove_source_branch"` + MergeCommitSha string `json:"merge_commit_sha"` + MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` + MergeStatus string `json:"merge_status"` + Sha string `json:"sha"` + ShouldRemoveSourceBranch bool `json:"should_remove_source_branch"` + SourceBranch string `json:"source_branch"` + SourceProjectID int `json:"source_project_id"` + Squash bool `json:"squash"` + TargetBranch string `json:"target_branch"` + TargetProjectID int `json:"target_project_id"` + WorkInProgress bool `json:"work_in_progress"` +} + +// Todo represents a GitLab todo. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/todos.html +type Todo struct { + ID int `json:"id"` + Project struct { + ID int `json:"id"` + HTTPURLToRepo string `json:"http_url_to_repo"` + WebURL string `json:"web_url"` + Name string `json:"name"` + NameWithNamespace string `json:"name_with_namespace"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` + } `json:"project"` + Author struct { + ID int `json:"id"` + Name string `json:"name"` + Username string `json:"username"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + } `json:"author"` + ActionName TodoAction `json:"action_name"` + TargetType string `json:"target_type"` + Target TodoTarget `json:"target"` + TargetURL string `json:"target_url"` + Body string `json:"body"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` +} + +func (t Todo) String() string { + return Stringify(t) +} + +// ListTodosOptions represents the available ListTodos() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/todos.html#get-a-list-of-todos +type ListTodosOptions struct { + Action *TodoAction `url:"action,omitempty" json:"action,omitempty"` + AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + ProjectID *int `url:"project_id,omitempty" json:"project_id,omitempty"` + State *string `url:"state,omitempty" json:"state,omitempty"` + Type *string `url:"type,omitempty" json:"type,omitempty"` +} + +// ListTodos lists all todos created by authenticated user. +// When no filter is applied, it returns all pending todos for the current user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/todos.html#get-a-list-of-todos +func (s *TodosService) ListTodos(opt *ListTodosOptions, options ...OptionFunc) ([]*Todo, *Response, error) { + req, err := s.client.NewRequest("GET", "todos", opt, options) + if err != nil { + return nil, nil, err + } + + var t []*Todo + resp, err := s.client.Do(req, &t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// MarkTodoAsDone marks a single pending todo given by its ID for the current user as done. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/todos.html#mark-a-todo-as-done +func (s *TodosService) MarkTodoAsDone(id int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("todos/%d/mark_as_done", id) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// MarkAllTodosAsDone marks all pending todos for the current user as done. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/todos.html#mark-all-todos-as-done +func (s *TodosService) MarkAllTodosAsDone(options ...OptionFunc) (*Response, error) { + req, err := s.client.NewRequest("POST", "todos/mark_as_done", nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/xanzy/go-gitlab/users.go b/vendor/github.com/xanzy/go-gitlab/users.go new file mode 100644 index 00000000..a619ab03 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/users.go @@ -0,0 +1,767 @@ +// +// Copyright 2017, Sander van Harmelen +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "errors" + "fmt" + "time" +) + +// UsersService handles communication with the user related methods of +// the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html +type UsersService struct { + client *Client +} + +// User represents a GitLab user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html +type User struct { + ID int `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` + Bio string `json:"bio"` + Location string `json:"location"` + Skype string `json:"skype"` + Linkedin string `json:"linkedin"` + Twitter string `json:"twitter"` + WebsiteURL string `json:"website_url"` + Organization string `json:"organization"` + ExternUID string `json:"extern_uid"` + Provider string `json:"provider"` + ThemeID int `json:"theme_id"` + LastActivityOn *ISOTime `json:"last_activity_on"` + ColorSchemeID int `json:"color_scheme_id"` + IsAdmin bool `json:"is_admin"` + AvatarURL string `json:"avatar_url"` + CanCreateGroup bool `json:"can_create_group"` + CanCreateProject bool `json:"can_create_project"` + ProjectsLimit int `json:"projects_limit"` + CurrentSignInAt *time.Time `json:"current_sign_in_at"` + LastSignInAt *time.Time `json:"last_sign_in_at"` + TwoFactorEnabled bool `json:"two_factor_enabled"` + Identities []*UserIdentity `json:"identities"` + External bool `json:"external"` +} + +// UserIdentity represents a user identity. +type UserIdentity struct { + Provider string `json:"provider"` + ExternUID string `json:"extern_uid"` +} + +// ListUsersOptions represents the available ListUsers() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-users +type ListUsersOptions struct { + ListOptions + Active *bool `url:"active,omitempty" json:"active,omitempty"` + Blocked *bool `url:"blocked,omitempty" json:"blocked,omitempty"` + + // The options below are only available for admins. + Search *string `url:"search,omitempty" json:"search,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + ExternalUID *string `url:"extern_uid,omitempty" json:"extern_uid,omitempty"` + Provider *string `url:"provider,omitempty" json:"provider,omitempty"` + CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` + CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` +} + +// ListUsers gets a list of users. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-users +func (s *UsersService) ListUsers(opt *ListUsersOptions, options ...OptionFunc) ([]*User, *Response, error) { + req, err := s.client.NewRequest("GET", "users", opt, options) + if err != nil { + return nil, nil, err + } + + var usr []*User + resp, err := s.client.Do(req, &usr) + if err != nil { + return nil, resp, err + } + + return usr, resp, err +} + +// GetUser gets a single user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#single-user +func (s *UsersService) GetUser(user int, options ...OptionFunc) (*User, *Response, error) { + u := fmt.Sprintf("users/%d", user) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + usr := new(User) + resp, err := s.client.Do(req, usr) + if err != nil { + return nil, resp, err + } + + return usr, resp, err +} + +// CreateUserOptions represents the available CreateUser() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-creation +type CreateUserOptions struct { + Email *string `url:"email,omitempty" json:"email,omitempty"` + Password *string `url:"password,omitempty" json:"password,omitempty"` + ResetPassword *bool `url:"reset_password,omitempty" json:"reset_password,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + Skype *string `url:"skype,omitempty" json:"skype,omitempty"` + Linkedin *string `url:"linkedin,omitempty" json:"linkedin,omitempty"` + Twitter *string `url:"twitter,omitempty" json:"twitter,omitempty"` + WebsiteURL *string `url:"website_url,omitempty" json:"website_url,omitempty"` + Organization *string `url:"organization,omitempty" json:"organization,omitempty"` + ProjectsLimit *int `url:"projects_limit,omitempty" json:"projects_limit,omitempty"` + ExternUID *string `url:"extern_uid,omitempty" json:"extern_uid,omitempty"` + Provider *string `url:"provider,omitempty" json:"provider,omitempty"` + Bio *string `url:"bio,omitempty" json:"bio,omitempty"` + Location *string `url:"location,omitempty" json:"location,omitempty"` + Admin *bool `url:"admin,omitempty" json:"admin,omitempty"` + CanCreateGroup *bool `url:"can_create_group,omitempty" json:"can_create_group,omitempty"` + SkipConfirmation *bool `url:"skip_confirmation,omitempty" json:"skip_confirmation,omitempty"` + External *bool `url:"external,omitempty" json:"external,omitempty"` +} + +// CreateUser creates a new user. Note only administrators can create new users. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-creation +func (s *UsersService) CreateUser(opt *CreateUserOptions, options ...OptionFunc) (*User, *Response, error) { + req, err := s.client.NewRequest("POST", "users", opt, options) + if err != nil { + return nil, nil, err + } + + usr := new(User) + resp, err := s.client.Do(req, usr) + if err != nil { + return nil, resp, err + } + + return usr, resp, err +} + +// ModifyUserOptions represents the available ModifyUser() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-modification +type ModifyUserOptions struct { + Email *string `url:"email,omitempty" json:"email,omitempty"` + Password *string `url:"password,omitempty" json:"password,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + Skype *string `url:"skype,omitempty" json:"skype,omitempty"` + Linkedin *string `url:"linkedin,omitempty" json:"linkedin,omitempty"` + Twitter *string `url:"twitter,omitempty" json:"twitter,omitempty"` + WebsiteURL *string `url:"website_url,omitempty" json:"website_url,omitempty"` + Organization *string `url:"organization,omitempty" json:"organization,omitempty"` + ProjectsLimit *int `url:"projects_limit,omitempty" json:"projects_limit,omitempty"` + ExternUID *string `url:"extern_uid,omitempty" json:"extern_uid,omitempty"` + Provider *string `url:"provider,omitempty" json:"provider,omitempty"` + Bio *string `url:"bio,omitempty" json:"bio,omitempty"` + Location *string `url:"location,omitempty" json:"location,omitempty"` + Admin *bool `url:"admin,omitempty" json:"admin,omitempty"` + CanCreateGroup *bool `url:"can_create_group,omitempty" json:"can_create_group,omitempty"` + SkipReconfirmation *bool `url:"skip_reconfirmation,omitempty" json:"skip_reconfirmation,omitempty"` + External *bool `url:"external,omitempty" json:"external,omitempty"` +} + +// ModifyUser modifies an existing user. Only administrators can change attributes +// of a user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-modification +func (s *UsersService) ModifyUser(user int, opt *ModifyUserOptions, options ...OptionFunc) (*User, *Response, error) { + u := fmt.Sprintf("users/%d", user) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + usr := new(User) + resp, err := s.client.Do(req, usr) + if err != nil { + return nil, resp, err + } + + return usr, resp, err +} + +// DeleteUser deletes a user. Available only for administrators. This is an +// idempotent function, calling this function for a non-existent user id still +// returns a status code 200 OK. The JSON response differs if the user was +// actually deleted or not. In the former the user is returned and in the +// latter not. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-deletion +func (s *UsersService) DeleteUser(user int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("users/%d", user) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// CurrentUser gets currently authenticated user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#current-user +func (s *UsersService) CurrentUser(options ...OptionFunc) (*User, *Response, error) { + req, err := s.client.NewRequest("GET", "user", nil, options) + if err != nil { + return nil, nil, err + } + + usr := new(User) + resp, err := s.client.Do(req, usr) + if err != nil { + return nil, resp, err + } + + return usr, resp, err +} + +// SSHKey represents a SSH key. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-ssh-keys +type SSHKey struct { + ID int `json:"id"` + Title string `json:"title"` + Key string `json:"key"` + CreatedAt *time.Time `json:"created_at"` +} + +// ListSSHKeys gets a list of currently authenticated user's SSH keys. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-ssh-keys +func (s *UsersService) ListSSHKeys(options ...OptionFunc) ([]*SSHKey, *Response, error) { + req, err := s.client.NewRequest("GET", "user/keys", nil, options) + if err != nil { + return nil, nil, err + } + + var k []*SSHKey + resp, err := s.client.Do(req, &k) + if err != nil { + return nil, resp, err + } + + return k, resp, err +} + +// ListSSHKeysForUserOptions represents the available ListSSHKeysForUser() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#list-ssh-keys-for-user +type ListSSHKeysForUserOptions ListOptions + +// ListSSHKeysForUser gets a list of a specified user's SSH keys. Available +// only for admin +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#list-ssh-keys-for-user +func (s *UsersService) ListSSHKeysForUser(user int, opt *ListSSHKeysForUserOptions, options ...OptionFunc) ([]*SSHKey, *Response, error) { + u := fmt.Sprintf("users/%d/keys", user) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var k []*SSHKey + resp, err := s.client.Do(req, &k) + if err != nil { + return nil, resp, err + } + + return k, resp, err +} + +// GetSSHKey gets a single key. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#single-ssh-key +func (s *UsersService) GetSSHKey(key int, options ...OptionFunc) (*SSHKey, *Response, error) { + u := fmt.Sprintf("user/keys/%d", key) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + k := new(SSHKey) + resp, err := s.client.Do(req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, err +} + +// AddSSHKeyOptions represents the available AddSSHKey() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#add-ssh-key +type AddSSHKeyOptions struct { + Title *string `url:"title,omitempty" json:"title,omitempty"` + Key *string `url:"key,omitempty" json:"key,omitempty"` +} + +// AddSSHKey creates a new key owned by the currently authenticated user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#add-ssh-key +func (s *UsersService) AddSSHKey(opt *AddSSHKeyOptions, options ...OptionFunc) (*SSHKey, *Response, error) { + req, err := s.client.NewRequest("POST", "user/keys", opt, options) + if err != nil { + return nil, nil, err + } + + k := new(SSHKey) + resp, err := s.client.Do(req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, err +} + +// AddSSHKeyForUser creates new key owned by specified user. Available only for +// admin. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#add-ssh-key-for-user +func (s *UsersService) AddSSHKeyForUser(user int, opt *AddSSHKeyOptions, options ...OptionFunc) (*SSHKey, *Response, error) { + u := fmt.Sprintf("users/%d/keys", user) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + k := new(SSHKey) + resp, err := s.client.Do(req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, err +} + +// DeleteSSHKey deletes key owned by currently authenticated user. This is an +// idempotent function and calling it on a key that is already deleted or not +// available results in 200 OK. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#delete-ssh-key-for-current-owner +func (s *UsersService) DeleteSSHKey(key int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("user/keys/%d", key) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteSSHKeyForUser deletes key owned by a specified user. Available only +// for admin. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#delete-ssh-key-for-given-user +func (s *UsersService) DeleteSSHKeyForUser(user, key int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("users/%d/keys/%d", user, key) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// BlockUser blocks the specified user. Available only for admin. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#block-user +func (s *UsersService) BlockUser(user int, options ...OptionFunc) error { + u := fmt.Sprintf("users/%d/block", user) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return err + } + + switch resp.StatusCode { + case 201: + return nil + case 403: + return errors.New("Cannot block a user that is already blocked by LDAP synchronization") + case 404: + return errors.New("User does not exist") + default: + return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode) + } +} + +// UnblockUser unblocks the specified user. Available only for admin. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#unblock-user +func (s *UsersService) UnblockUser(user int, options ...OptionFunc) error { + u := fmt.Sprintf("users/%d/unblock", user) + + req, err := s.client.NewRequest("POST", u, nil, options) + if err != nil { + return err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return err + } + + switch resp.StatusCode { + case 201: + return nil + case 403: + return errors.New("Cannot unblock a user that is blocked by LDAP synchronization") + case 404: + return errors.New("User does not exist") + default: + return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode) + } +} + +// Email represents an Email. +// +// GitLab API docs: https://doc.gitlab.com/ce/api/users.html#list-emails +type Email struct { + ID int `json:"id"` + Email string `json:"email"` +} + +// ListEmails gets a list of currently authenticated user's Emails. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-emails +func (s *UsersService) ListEmails(options ...OptionFunc) ([]*Email, *Response, error) { + req, err := s.client.NewRequest("GET", "user/emails", nil, options) + if err != nil { + return nil, nil, err + } + + var e []*Email + resp, err := s.client.Do(req, &e) + if err != nil { + return nil, resp, err + } + + return e, resp, err +} + +// ListEmailsForUserOptions represents the available ListEmailsForUser() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#list-emails-for-user +type ListEmailsForUserOptions ListOptions + +// ListEmailsForUser gets a list of a specified user's Emails. Available +// only for admin +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#list-emails-for-user +func (s *UsersService) ListEmailsForUser(user int, opt *ListEmailsForUserOptions, options ...OptionFunc) ([]*Email, *Response, error) { + u := fmt.Sprintf("users/%d/emails", user) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var e []*Email + resp, err := s.client.Do(req, &e) + if err != nil { + return nil, resp, err + } + + return e, resp, err +} + +// GetEmail gets a single email. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#single-email +func (s *UsersService) GetEmail(email int, options ...OptionFunc) (*Email, *Response, error) { + u := fmt.Sprintf("user/emails/%d", email) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + e := new(Email) + resp, err := s.client.Do(req, e) + if err != nil { + return nil, resp, err + } + + return e, resp, err +} + +// AddEmailOptions represents the available AddEmail() options. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#add-email +type AddEmailOptions struct { + Email *string `url:"email,omitempty" json:"email,omitempty"` +} + +// AddEmail creates a new email owned by the currently authenticated user. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#add-email +func (s *UsersService) AddEmail(opt *AddEmailOptions, options ...OptionFunc) (*Email, *Response, error) { + req, err := s.client.NewRequest("POST", "user/emails", opt, options) + if err != nil { + return nil, nil, err + } + + e := new(Email) + resp, err := s.client.Do(req, e) + if err != nil { + return nil, resp, err + } + + return e, resp, err +} + +// AddEmailForUser creates new email owned by specified user. Available only for +// admin. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#add-email-for-user +func (s *UsersService) AddEmailForUser(user int, opt *AddEmailOptions, options ...OptionFunc) (*Email, *Response, error) { + u := fmt.Sprintf("users/%d/emails", user) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + e := new(Email) + resp, err := s.client.Do(req, e) + if err != nil { + return nil, resp, err + } + + return e, resp, err +} + +// DeleteEmail deletes email owned by currently authenticated user. This is an +// idempotent function and calling it on a key that is already deleted or not +// available results in 200 OK. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#delete-email-for-current-owner +func (s *UsersService) DeleteEmail(email int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("user/emails/%d", email) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// DeleteEmailForUser deletes email owned by a specified user. Available only +// for admin. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#delete-email-for-given-user +func (s *UsersService) DeleteEmailForUser(user, email int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("users/%d/emails/%d", user, email) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// ImpersonationToken represents an impersonation token. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#get-all-impersonation-tokens-of-a-user +type ImpersonationToken struct { + ID int `json:"id"` + Name string `json:"name"` + Active bool `json:"active"` + Token string `json:"token"` + Scopes []string `json:"scopes"` + Revoked bool `json:"revoked"` + CreatedAt *time.Time `json:"created_at"` + ExpiresAt *ISOTime `json:"expires_at"` +} + +// GetAllImpersonationTokensOptions represents the available +// GetAllImpersonationTokens() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#get-all-impersonation-tokens-of-a-user +type GetAllImpersonationTokensOptions struct { + ListOptions + State *string `url:"state,omitempty" json:"state,omitempty"` +} + +// GetAllImpersonationTokens retrieves all impersonation tokens of a user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#get-all-impersonation-tokens-of-a-user +func (s *UsersService) GetAllImpersonationTokens(user int, opt *GetAllImpersonationTokensOptions, options ...OptionFunc) ([]*ImpersonationToken, *Response, error) { + u := fmt.Sprintf("users/%d/impersonation_tokens", user) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var ts []*ImpersonationToken + resp, err := s.client.Do(req, &ts) + if err != nil { + return nil, resp, err + } + + return ts, resp, err +} + +// GetImpersonationToken retrieves an impersonation token of a user. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#get-an-impersonation-token-of-a-user +func (s *UsersService) GetImpersonationToken(user, token int, options ...OptionFunc) (*ImpersonationToken, *Response, error) { + u := fmt.Sprintf("users/%d/impersonation_tokens/%d", user, token) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + t := new(ImpersonationToken) + resp, err := s.client.Do(req, &t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// CreateImpersonationTokenOptions represents the available +// CreateImpersonationToken() options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#create-an-impersonation-token +type CreateImpersonationTokenOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"` + ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"` +} + +// CreateImpersonationToken creates an impersonation token. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#create-an-impersonation-token +func (s *UsersService) CreateImpersonationToken(user int, opt *CreateImpersonationTokenOptions, options ...OptionFunc) (*ImpersonationToken, *Response, error) { + u := fmt.Sprintf("users/%d/impersonation_tokens", user) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + t := new(ImpersonationToken) + resp, err := s.client.Do(req, &t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} + +// RevokeImpersonationToken revokes an impersonation token. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#revoke-an-impersonation-token +func (s *UsersService) RevokeImpersonationToken(user, token int, options ...OptionFunc) (*Response, error) { + u := fmt.Sprintf("users/%d/impersonation_tokens/%d", user, token) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + +// UserActivity represents an entry in the user/activities response +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#get-user-activities-admin-only +type UserActivity struct { + Username string `json:"username"` + LastActivityOn *ISOTime `json:"last_activity_on"` +} + +// GetUserActivitiesOptions represents the options for GetUserActivities +// +// GitLap API docs: +// https://docs.gitlab.com/ce/api/users.html#get-user-activities-admin-only +type GetUserActivitiesOptions struct { + From *ISOTime `url:"from,omitempty" json:"from,omitempty"` +} + +// GetUserActivities retrieves user activities (admin only) +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/users.html#get-user-activities-admin-only +func (s *UsersService) GetUserActivities(opt *GetUserActivitiesOptions, options ...OptionFunc) ([]*UserActivity, *Response, error) { + req, err := s.client.NewRequest("GET", "user/activities", opt, options) + if err != nil { + return nil, nil, err + } + + var t []*UserActivity + resp, err := s.client.Do(req, &t) + if err != nil { + return nil, resp, err + } + + return t, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/validate.go b/vendor/github.com/xanzy/go-gitlab/validate.go new file mode 100644 index 00000000..a88e1884 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/validate.go @@ -0,0 +1,40 @@ +package gitlab + +// ValidateService handles communication with the validation related methods of +// the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/lint.html +type ValidateService struct { + client *Client +} + +// LintResult represents the linting results. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/lint.html +type LintResult struct { + Status string `json:"status"` + Errors []string `json:"errors"` +} + +// Lint validates .gitlab-ci.yml content. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/lint.html +func (s *ValidateService) Lint(content string, options ...OptionFunc) (*LintResult, *Response, error) { + var opts struct { + Content string `url:"content,omitempty" json:"content,omitempty"` + } + opts.Content = content + + req, err := s.client.NewRequest("POST", "ci/lint", &opts, options) + if err != nil { + return nil, nil, err + } + + l := new(LintResult) + resp, err := s.client.Do(req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} diff --git a/vendor/github.com/xanzy/go-gitlab/version.go b/vendor/github.com/xanzy/go-gitlab/version.go new file mode 100644 index 00000000..f1a3a7f5 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/version.go @@ -0,0 +1,56 @@ +// +// Copyright 2017, Andrea Funto' +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +// VersionService handles communication with the GitLab server instance to +// retrieve its version information via the GitLab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/version.md +type VersionService struct { + client *Client +} + +// Version represents a GitLab instance version. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/version.md +type Version struct { + Version string `json:"version"` + Revision string `json:"revision"` +} + +func (s Version) String() string { + return Stringify(s) +} + +// GetVersion gets a GitLab server instance version; it is only available to +// authenticated users. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/version.md +func (s *VersionService) GetVersion() (*Version, *Response, error) { + req, err := s.client.NewRequest("GET", "version", nil, nil) + if err != nil { + return nil, nil, err + } + + v := new(Version) + resp, err := s.client.Do(req, v) + if err != nil { + return nil, resp, err + } + + return v, resp, err +} diff --git a/vendor/github.com/xanzy/go-gitlab/wikis.go b/vendor/github.com/xanzy/go-gitlab/wikis.go new file mode 100644 index 00000000..72889851 --- /dev/null +++ b/vendor/github.com/xanzy/go-gitlab/wikis.go @@ -0,0 +1,204 @@ +// Copyright 2017, Stany MARCEL +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gitlab + +import ( + "fmt" + "net/url" +) + +// WikisService handles communication with the wikis related methods of +// the Gitlab API. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/wikis.html +type WikisService struct { + client *Client +} + +// WikiFormat represents the available wiki formats. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/wikis.html +type WikiFormat string + +// The available wiki formats. +const ( + WikiFormatMarkdown WikiFormat = "markdown" + WikiFormatRFoc WikiFormat = "rdoc" + WikiFormatASCIIDoc WikiFormat = "asciidoc" +) + +// Wiki represents a GitLab wiki. +// +// GitLab API docs: https://docs.gitlab.com/ce/api/wikis.html +type Wiki struct { + Content string `json:"content"` + Format WikiFormat `json:"format"` + Slug string `json:"slug"` + Title string `json:"title"` +} + +func (w Wiki) String() string { + return Stringify(w) +} + +// ListWikisOptions represents the available ListWikis options. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/wikis.html#list-wiki-pages +type ListWikisOptions struct { + WithContent *bool `url:"with_content,omitempty" json:"with_content,omitempty"` +} + +// ListWikis lists all pages of the wiki of the given project id. +// When with_content is set, it also returns the content of the pages. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/wikis.html#list-wiki-pages +func (s *WikisService) ListWikis(pid interface{}, opt *ListWikisOptions, options ...OptionFunc) ([]*Wiki, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/wikis", url.QueryEscape(project)) + + req, err := s.client.NewRequest("GET", u, opt, options) + if err != nil { + return nil, nil, err + } + + var w []*Wiki + resp, err := s.client.Do(req, &w) + if err != nil { + return nil, resp, err + } + + return w, resp, err +} + +// GetWikiPage gets a wiki page for a given project. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/wikis.html#get-a-wiki-page +func (s *WikisService) GetWikiPage(pid interface{}, slug string, options ...OptionFunc) (*Wiki, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/wikis/%s", url.QueryEscape(project), url.QueryEscape(slug)) + + req, err := s.client.NewRequest("GET", u, nil, options) + if err != nil { + return nil, nil, err + } + + var w *Wiki + resp, err := s.client.Do(req, &w) + if err != nil { + return nil, resp, err + } + + return w, resp, err +} + +// CreateWikiPageOptions represents options to CreateWikiPage. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/wikis.html#create-a-new-wiki-page +type CreateWikiPageOptions struct { + Content *string `url:"content" json:"content"` + Title *string `url:"title" json:"title"` + Format *string `url:"format,omitempty" json:"format,omitempty"` +} + +// CreateWikiPage creates a new wiki page for the given repository with +// the given title, slug, and content. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/wikis.html#create-a-new-wiki-page +func (s *WikisService) CreateWikiPage(pid interface{}, opt *CreateWikiPageOptions, options ...OptionFunc) (*Wiki, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/wikis", url.QueryEscape(project)) + + req, err := s.client.NewRequest("POST", u, opt, options) + if err != nil { + return nil, nil, err + } + + w := new(Wiki) + resp, err := s.client.Do(req, w) + if err != nil { + return nil, resp, err + } + + return w, resp, err +} + +// EditWikiPageOptions represents options to EditWikiPage. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/wikis.html#edit-an-existing-wiki-page +type EditWikiPageOptions struct { + Content *string `url:"content" json:"content"` + Title *string `url:"title" json:"title"` + Format *string `url:"format,omitempty" json:"format,omitempty"` +} + +// EditWikiPage Updates an existing wiki page. At least one parameter is +// required to update the wiki page. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/wikis.html#edit-an-existing-wiki-page +func (s *WikisService) EditWikiPage(pid interface{}, slug string, opt *EditWikiPageOptions, options ...OptionFunc) (*Wiki, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s/wikis/%s", url.QueryEscape(project), url.QueryEscape(slug)) + + req, err := s.client.NewRequest("PUT", u, opt, options) + if err != nil { + return nil, nil, err + } + + w := new(Wiki) + resp, err := s.client.Do(req, w) + if err != nil { + return nil, resp, err + } + + return w, resp, err +} + +// DeleteWikiPage deletes a wiki page with a given slug. +// +// GitLab API docs: +// https://docs.gitlab.com/ce/api/wikis.html#delete-a-wiki-page +func (s *WikisService) DeleteWikiPage(pid interface{}, slug string, options ...OptionFunc) (*Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("projects/%s/wikis/%s", url.QueryEscape(project), url.QueryEscape(slug)) + + req, err := s.client.NewRequest("DELETE", u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/vendor/github.com/yfronto/newrelic/.gitignore b/vendor/github.com/yfronto/newrelic/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/yfronto/newrelic/.travis.yml b/vendor/github.com/yfronto/newrelic/.travis.yml new file mode 100644 index 00000000..3c2f32b4 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/.travis.yml @@ -0,0 +1,16 @@ +language: go + +go: + - 1.6 + - 1.7 + - tip + +env: + - "PATH=/home/travis/gopath/bin:$PATH" +script: + - go get -u github.com/golang/lint/golint + - golint ./... + - test `golint ./... | wc -l` = 0 + - gofmt -l . + - test `gofmt -l . | wc -l` = 0 + - go test -v diff --git a/vendor/github.com/yfronto/newrelic/LICENSE b/vendor/github.com/yfronto/newrelic/LICENSE new file mode 100644 index 00000000..0de274ef --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2016 by authors and contributors. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/yfronto/newrelic/README.md b/vendor/github.com/yfronto/newrelic/README.md new file mode 100644 index 00000000..ab4fcac8 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/README.md @@ -0,0 +1,75 @@ +[![GoDoc](http://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/yfronto/newrelic) +[![Build +status](https://travis-ci.org/yfronto/newrelic.svg)](https://travis-ci.org/yfronto/newrelic) + +# New Relic API library for Go + +This is a Go library that wraps the [New Relic][1] REST +API. It provides the needed types to interact with the New Relic REST API. + +It's still in progress and I haven't finished the entirety of the API, yet. I +plan to finish all GET (read) operations before any POST (create) operations, +and then PUT (update) operations, and, finally, the DELETE operations. + +The API documentation can be found from [New Relic][1], +and you'll need an API key (for some operations, an Admin API key is +required). + +## USAGE + +This library will provide a client object and any operations can be performed +through it. Simply import this library and create a client to get started: + +```go +package main + +import ( + "github.com/yfronto/newrelic" +) + +var api_key = "..." // Required + +func main() { + // Create the client object + client := newrelic.NewClient(api_key) + + // Get the applciation with ID 12345 + myApp, err := client.GetApplication(12345) + if err != nil { + // Handle error + } + + // Work with the object + fmt.Println(myApp.Name) + + // Some operations accept options + opts := &newrelic.AlertEventOptions{ + // Only events with "MyProduct" as the product name + Filter: newRelic.AlertEventFilter{ + Product: "MyProduct", + }, + } + // Get a list of recent events for my product + events, err := client.GetAlertEvents(opts) + if err != nil { + // Handle error + } + // Display each event with some information + for _, e := range events { + fmt.Printf("%d -- %d (%s): %s\n", e.Timestamp, e.Id, e.Priority, e.Description) + } +} +``` + +## Contributing + +As I work to populate all actions, bugs are bound to come up. Feel free to +send me a pull request or just file an issue. Staying up to date with an API +is hard work and I'm happy to accept contributors. + +**DISCLAIMER:** *I am in no way affiliated with New Relic and this work is +merely a convenience project for myself with no guarantees. It should be +considered "as-is" with no implication of responsibility. See the included +LICENSE for more details.* + +[1]: http://www.newrelic.com \ No newline at end of file diff --git a/vendor/github.com/yfronto/newrelic/alert_conditions.go b/vendor/github.com/yfronto/newrelic/alert_conditions.go new file mode 100644 index 00000000..ee7d1a2d --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/alert_conditions.go @@ -0,0 +1,59 @@ +package newrelic + +// AlertCondition describes what triggers an alert for a specific policy. +type AlertCondition struct { + ID int `json:"id,omitempty"` + Type string `json:"type,omitempty"` + Name string `json:"name,omitempty"` + Enabled bool `json:"name,omitempty"` + Entities []string `json:"entities,omitempty"` + Metric string `json:"metric,omitempty"` + RunbookURL string `json:"runbook_url,omitempty"` + Terms []AlertConditionTerm `json:"terms,omitempty"` + UserDefined AlertUserDefined `json:"user_defined,omitempty"` +} + +// AlertConditionTerm defines thresholds that trigger an AlertCondition. +type AlertConditionTerm struct { + Duration string `json:"duration,omitempty"` + Operator string `json:"operator,omitempty"` + Priority string `json:"priority,omitempty"` + Threshold string `json:"threshold,omitempty"` + TimeFunction string `json:"time_function,omitempty"` +} + +// AlertUserDefined describes user-defined behavior for an AlertCondition. +type AlertUserDefined struct { + Metric string `json:"metric,omitempty"` + ValueFunction string `json:"value_function,omitempty"` +} + +// AlertConditionOptions define filters for GetAlertConditions. +type AlertConditionOptions struct { + policyID int + Page int +} + +func (o *AlertConditionOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "policy_id": o.policyID, + "page": o.Page, + }) +} + +// GetAlertConditions will return any AlertCondition defined for a given +// policy, optionally filtered by AlertConditionOptions. +func (c *Client) GetAlertConditions(policy int, options *AlertConditionOptions) ([]AlertCondition, error) { + resp := &struct { + Conditions []AlertCondition `json:"conditions,omitempty"` + }{} + options.policyID = policy + err := c.doGet("alerts_conditions.json", options, resp) + if err != nil { + return nil, err + } + return resp.Conditions, nil +} diff --git a/vendor/github.com/yfronto/newrelic/alert_events.go b/vendor/github.com/yfronto/newrelic/alert_events.go new file mode 100644 index 00000000..ce3c298a --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/alert_events.go @@ -0,0 +1,60 @@ +package newrelic + +// AlertEvent describes a triggered event. +type AlertEvent struct { + ID int `json:"id,omitempty"` + EventType string `json:"event_type,omitempty"` + Product string `json:"product,omitempty"` + EntityType string `json:"entity_type,omitempty"` + EntityGroupID int `json:"entity_group_id,omitempty"` + EntityID int `json:"entity_id,omitempty"` + Priority string `json:"priority,omitempty"` + Description string `json:"description,omitempty"` + Timestamp int64 `json:"timestamp,omitempty"` + IncidentID int `json:"incident_id"` +} + +// AlertEventFilter provides filters for AlertEventOptions when calling +// GetAlertEvents. +type AlertEventFilter struct { + // TODO: New relic restricts these options + Product string + EntityType string + EntityGroupID int + EntityID int + EventType string +} + +// AlertEventOptions is an optional means of filtering AlertEvents when +// calling GetAlertEvents. +type AlertEventOptions struct { + Filter AlertEventFilter + Page int +} + +func (o *AlertEventOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[product]": o.Filter.Product, + "filter[entity_type]": o.Filter.EntityType, + "filter[entity_group_id]": o.Filter.EntityGroupID, + "filter[entity_id]": o.Filter.EntityID, + "filter[event_type]": o.Filter.EventType, + "page": o.Page, + }) +} + +// GetAlertEvents will return a slice of recent AlertEvent items triggered, +// optionally filtering by AlertEventOptions. +func (c *Client) GetAlertEvents(options *AlertEventOptions) ([]AlertEvent, error) { + resp := &struct { + RecentEvents []AlertEvent `json:"recent_events,omitempty"` + }{} + err := c.doGet("alerts_events.json", options, resp) + if err != nil { + return nil, err + } + return resp.RecentEvents, nil +} diff --git a/vendor/github.com/yfronto/newrelic/alert_events_test_fixtures.go b/vendor/github.com/yfronto/newrelic/alert_events_test_fixtures.go new file mode 100644 index 00000000..b27c4ef2 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/alert_events_test_fixtures.go @@ -0,0 +1,91 @@ +package newrelic + +type getAlertEventsTestsInput struct { + options *AlertEventOptions + data string +} + +type getAlertEventsTestsOutput struct { + data []AlertEvent + err error +} + +const ( + testAlertEventJSON = ` + { + "id": 123, + "event_type": "VIOLATION_OPEN", + "product": "APM", + "entity_type": "Application", + "entity_group_id": 1234, + "entity_id": 12, + "priority": "Warning", + "description": "Test Alert", + "timestamp": 1472355451353, + "incident_id": 23 + } +` +) + +var ( + testAlertEvent = AlertEvent{ + ID: 123, + EventType: "VIOLATION_OPEN", + Product: "APM", + EntityType: "Application", + EntityGroupID: 1234, + EntityID: 12, + Priority: "Warning", + Description: "Test Alert", + Timestamp: 1472355451353, + IncidentID: 23, + } + getAlertEventsTests = []struct { + in getAlertEventsTestsInput + out getAlertEventsTestsOutput + }{ + { + getAlertEventsTestsInput{ + options: nil, + data: `{"recent_events": [` + testAlertEventJSON + `]}`, + }, + getAlertEventsTestsOutput{ + data: []AlertEvent{ + testAlertEvent, + }, + err: nil, + }, + }, + } + alertEventOptionsStringerTests = []struct { + in *AlertEventOptions + out string + }{ + { + &AlertEventOptions{}, + "", + }, + { + nil, + "", + }, + { + &AlertEventOptions{ + Filter: AlertEventFilter{ + Product: "testProduct", + EntityType: "testEntityType", + EntityGroupID: 123, + EntityID: 1234, + EventType: "testEventType", + }, + Page: 1, + }, + "filter%5Bentity_group_id%5D=123" + + "&filter%5Bentity_id%5D=1234" + + "&filter%5Bentity_type%5D=testEntityType" + + "&filter%5Bevent_type%5D=testEventType" + + "&filter%5Bproduct%5D=testProduct" + + "&page=1", + }, + } +) diff --git a/vendor/github.com/yfronto/newrelic/application_deployments.go b/vendor/github.com/yfronto/newrelic/application_deployments.go new file mode 100644 index 00000000..db8438e6 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/application_deployments.go @@ -0,0 +1,53 @@ +package newrelic + +import ( + "strconv" + "time" +) + +// ApplicationDeploymentLinks represents links that apply to an +// ApplicationDeployment. +type ApplicationDeploymentLinks struct { + Application int `json:"application,omitempty"` +} + +// ApplicationDeploymentOptions provide a means to filter when calling +// GetApplicationDeployments. +type ApplicationDeploymentOptions struct { + Page int +} + +// ApplicationDeployment contains information about a New Relic Application +// Deployment. +type ApplicationDeployment struct { + ID int `json:"id,omitempty"` + Revision string `json:"revision,omitempty"` + Changelog string `json:"changelog,omitempty"` + Description string `json:"description,omitempty"` + User string `json:"user,omitemtpy"` + Timestamp time.Time `json:"timestamp,omitempty"` + Links ApplicationDeploymentLinks `json:"links,omitempty"` +} + +// GetApplicationDeployments returns a slice of New Relic Application +// Deployments. +func (c *Client) GetApplicationDeployments(id int, opt *ApplicationDeploymentOptions) ([]ApplicationDeployment, error) { + resp := &struct { + Deployments []ApplicationDeployment `json:"deployments,omitempty"` + }{} + path := "applications/" + strconv.Itoa(id) + "/deployments.json" + err := c.doGet(path, opt, resp) + if err != nil { + return nil, err + } + return resp.Deployments, nil +} + +func (o *ApplicationDeploymentOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "page": o.Page, + }) +} diff --git a/vendor/github.com/yfronto/newrelic/application_host_metrics.go b/vendor/github.com/yfronto/newrelic/application_host_metrics.go new file mode 100644 index 00000000..ef3dd64c --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/application_host_metrics.go @@ -0,0 +1,38 @@ +package newrelic + +import ( + "fmt" +) + +// GetApplicationHostMetrics will return a slice of Metric items for a +// particular Application ID's Host ID, optionally filtering by +// MetricsOptions. +func (c *Client) GetApplicationHostMetrics(appID, hostID int, options *MetricsOptions) ([]Metric, error) { + mc := NewMetricClient(c) + + return mc.GetMetrics( + fmt.Sprintf( + "applications/%d/hosts/%d/metrics.json", + appID, + hostID, + ), + options, + ) +} + +// GetApplicationHostMetricData will return all metric data for a particular +// application's host and slice of metric names, optionally filtered by +// MetricDataOptions. +func (c *Client) GetApplicationHostMetricData(appID, hostID int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) { + mc := NewMetricClient(c) + + return mc.GetMetricData( + fmt.Sprintf( + "applications/%d/hosts/%d/metrics/data.json", + appID, + hostID, + ), + names, + options, + ) +} diff --git a/vendor/github.com/yfronto/newrelic/application_hosts.go b/vendor/github.com/yfronto/newrelic/application_hosts.go new file mode 100644 index 00000000..ad8cc5d5 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/application_hosts.go @@ -0,0 +1,94 @@ +package newrelic + +import ( + "strconv" +) + +// ApplicationHostSummary describes an Application's host. +type ApplicationHostSummary struct { + ApdexScore float64 `json:"apdex_score,omitempty"` + ErrorRate float64 `json:"error_rate,omitempty"` + InstanceCount int `json:"instance_count,omitempty"` + ResponseTime float64 `json:"response_time,omitempty"` + Throughput float64 `json:"throughput,omitempty"` +} + +// ApplicationHostEndUserSummary describes the end user summary component of +// an ApplicationHost. +type ApplicationHostEndUserSummary struct { + ResponseTime float64 `json:"response_time,omitempty"` + Throughput float64 `json:"throughput,omitempty"` + ApdexScore float64 `json:"apdex_score,omitempty"` +} + +// ApplicationHostLinks list IDs associated with an ApplicationHost. +type ApplicationHostLinks struct { + Application int `json:"application,omitempty"` + ApplicationInstances []int `json:"application_instances,omitempty"` + Server int `json:"server,omitempty"` +} + +// ApplicationHost describes a New Relic Application Host. +type ApplicationHost struct { + ApplicationName string `json:"application_name,omitempty"` + ApplicationSummary ApplicationHostSummary `json:"application_summary,omitempty"` + HealthStatus string `json:"health_status,omitempty"` + Host string `json:"host,omitempty"` + ID int `json:"idomitempty"` + Language string `json:"language,omitempty"` + Links ApplicationHostLinks `json:"links,omitempty"` + EndUserSummary ApplicationHostEndUserSummary `json:"end_user_summary,omitempty"` +} + +// ApplicationHostsFilter provides a means to filter requests through +// ApplicationHostsOptions when calling GetApplicationHosts. +type ApplicationHostsFilter struct { + Hostname string + IDs []int +} + +// ApplicationHostsOptions provide a means to filter results when calling +// GetApplicationHosts. +type ApplicationHostsOptions struct { + Filter ApplicationHostsFilter + Page int +} + +// GetApplicationHosts returns a slice of New Relic Application Hosts, +// optionally filtering by ApplicationHostOptions. +func (c *Client) GetApplicationHosts(id int, options *ApplicationHostsOptions) ([]ApplicationHost, error) { + resp := &struct { + ApplicationHosts []ApplicationHost `json:"application_hosts,omitempty"` + }{} + path := "applications/" + strconv.Itoa(id) + "/hosts.json" + err := c.doGet(path, options, resp) + if err != nil { + return nil, err + } + return resp.ApplicationHosts, nil +} + +// GetApplicationHost returns a single Application Host associated with the +// given application host ID and host ID. +func (c *Client) GetApplicationHost(appID, hostID int) (*ApplicationHost, error) { + resp := &struct { + ApplicationHost ApplicationHost `json:"application_host,omitempty"` + }{} + path := "applications/" + strconv.Itoa(appID) + "/hosts/" + strconv.Itoa(hostID) + ".json" + err := c.doGet(path, nil, resp) + if err != nil { + return nil, err + } + return &resp.ApplicationHost, nil +} + +func (o *ApplicationHostsOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[hostname]": o.Filter.Hostname, + "filter[ids]": o.Filter.IDs, + "page": o.Page, + }) +} diff --git a/vendor/github.com/yfronto/newrelic/application_instance_metrics.go b/vendor/github.com/yfronto/newrelic/application_instance_metrics.go new file mode 100644 index 00000000..9a0c8bf7 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/application_instance_metrics.go @@ -0,0 +1,38 @@ +package newrelic + +import ( + "fmt" +) + +// GetApplicationInstanceMetrics will return a slice of Metric items for a +// particular Application ID's instance ID, optionally filtering by +// MetricsOptions. +func (c *Client) GetApplicationInstanceMetrics(appID, instanceID int, options *MetricsOptions) ([]Metric, error) { + mc := NewMetricClient(c) + + return mc.GetMetrics( + fmt.Sprintf( + "applications/%d/instances/%d/metrics.json", + appID, + instanceID, + ), + options, + ) +} + +// GetApplicationInstanceMetricData will return all metric data for a +// particular application's instance and slice of metric names, optionally +// filtered by MetricDataOptions. +func (c *Client) GetApplicationInstanceMetricData(appID, instanceID int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) { + mc := NewMetricClient(c) + + return mc.GetMetricData( + fmt.Sprintf( + "applications/%d/instances/%d/metrics/data.json", + appID, + instanceID, + ), + names, + options, + ) +} diff --git a/vendor/github.com/yfronto/newrelic/application_instances.go b/vendor/github.com/yfronto/newrelic/application_instances.go new file mode 100644 index 00000000..0a8b2de1 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/application_instances.go @@ -0,0 +1,94 @@ +package newrelic + +import ( + "strconv" +) + +// ApplicationInstanceSummary describes an Application's instance. +type ApplicationInstanceSummary struct { + ResponseTime float64 `json:"response_time,omitempty"` + Throughput float64 `json:"throughput,omitempty"` + ErrorRate float64 `json:"error_rate,omitempty"` + ApdexScore float64 `json:"apdex_score,omitempty"` + InstanceCount int `json:"instance_count,omitempty"` +} + +// ApplicationInstanceEndUserSummary describes the end user summary component +// of an ApplicationInstance. +type ApplicationInstanceEndUserSummary struct { + ResponseTime float64 `json:"response_time,omitempty"` + Throughput float64 `json:"throughput,omitempty"` + ApdexScore float64 `json:"apdex_score,omitempty"` +} + +// ApplicationInstanceLinks lists IDs associated with an ApplicationInstances. +type ApplicationInstanceLinks struct { + Application int `json:"application,omitempty"` + ApplicationHost int `json:"application_host,omitempty"` + Server int `json:"server,omitempty"` +} + +// ApplicationInstance describes a New Relic Application instance. +type ApplicationInstance struct { + ID int `json:"id,omitempty"` + ApplicationName string `json:"application_name,omitempty"` + Host string `json:"host,omitempty"` + Port int `json:"port,omitempty"` + Language string `json:"language,omitempty"` + HealthStatus string `json:"health_status,omitempty"` + ApplicationSummary ApplicationInstanceSummary `json:"application_summary,omitempty"` + EndUserSummary ApplicationInstanceEndUserSummary `json:"end_user_summary,omitempty"` + Links ApplicationInstanceLinks `json:"links,omitempty"` +} + +// ApplicationInstancesFilter provides a means to filter requests through +// ApplicationInstancesOptions when calling GetApplicationInstances. +type ApplicationInstancesFilter struct { + Hostname string + IDs []int +} + +// ApplicationInstancesOptions provides a means to filter results when calling +// GetApplicationInstances. +type ApplicationInstancesOptions struct { + Filter ApplicationInstancesFilter + Page int +} + +// GetApplicationInstances returns a slice of New Relic Application Instances, +// optionall filtering by ApplicationInstancesOptions. +func (c *Client) GetApplicationInstances(appID int, options *ApplicationInstancesOptions) ([]ApplicationInstance, error) { + resp := &struct { + ApplicationInstances []ApplicationInstance `json:"application_instances,omitempty"` + }{} + path := "applications/" + strconv.Itoa(appID) + "/instances.json" + err := c.doGet(path, options, resp) + if err != nil { + return nil, err + } + return resp.ApplicationInstances, nil +} + +// GetApplicationInstance returns a single Application Instance associated +// with the given application ID and instance ID +func (c *Client) GetApplicationInstance(appID, instanceID int) (*ApplicationInstance, error) { + resp := &struct { + ApplicationInstance ApplicationInstance `json:"application_instance,omitempty"` + }{} + path := "applications/" + strconv.Itoa(appID) + "/instances/" + strconv.Itoa(instanceID) + ".json" + err := c.doGet(path, nil, resp) + if err != nil { + return nil, err + } + return &resp.ApplicationInstance, nil +} +func (o *ApplicationInstancesOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[hostname]": o.Filter.Hostname, + "filter[ids]": o.Filter.IDs, + "page": o.Page, + }) +} diff --git a/vendor/github.com/yfronto/newrelic/application_metrics.go b/vendor/github.com/yfronto/newrelic/application_metrics.go new file mode 100644 index 00000000..e0c09b80 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/application_metrics.go @@ -0,0 +1,36 @@ +package newrelic + +import ( + "fmt" +) + +// GetApplicationMetrics will return a slice of Metric items for a +// particular Application ID, optionally filtering by +// MetricsOptions. +func (c *Client) GetApplicationMetrics(id int, options *MetricsOptions) ([]Metric, error) { + mc := NewMetricClient(c) + + return mc.GetMetrics( + fmt.Sprintf( + "applications/%d/metrics.json", + id, + ), + options, + ) +} + +// GetApplicationMetricData will return all metric data for a particular +// application and slice of metric names, optionally filtered by +// MetricDataOptions. +func (c *Client) GetApplicationMetricData(id int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) { + mc := NewMetricClient(c) + + return mc.GetMetricData( + fmt.Sprintf( + "applications/%d/metrics/data.json", + id, + ), + names, + options, + ) +} diff --git a/vendor/github.com/yfronto/newrelic/application_metrics_test_fixtures.go b/vendor/github.com/yfronto/newrelic/application_metrics_test_fixtures.go new file mode 100644 index 00000000..67e4e53d --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/application_metrics_test_fixtures.go @@ -0,0 +1,175 @@ +package newrelic + +type getApplicationMetricsTestsInput struct { + id int + options *MetricsOptions + data string +} + +type getApplicationMetricsTestsOutput struct { + data []Metric + err error +} + +type getApplicationMetricDataTestsInput struct { + id int + Names []string + options *MetricDataOptions + data string +} + +type getApplicationMetricDataTestsOutput struct { + data *MetricDataResponse + err error +} + +const ( + testApplicationMetricJSON = ` + { + "name": "testMetric", + "values": [ + "testValue1", + "testValue2" + ] + } +` +) + +var ( + testApplicationMetric = Metric{ + Name: "testMetric", + Values: []string{"testValue1", "testValue2"}, + } + getApplicaitonMetricsTests = []struct { + in getApplicationMetricsTestsInput + out getApplicationMetricsTestsOutput + }{ + { + getApplicationMetricsTestsInput{ + id: 123, + options: nil, + data: `{"metrics": [` + + testApplicationMetricJSON + `,` + + testApplicationMetricJSON + + `]}`, + }, + getApplicationMetricsTestsOutput{ + data: []Metric{ + testApplicationMetric, + testApplicationMetric, + }, + err: nil, + }, + }, + } + applicationMetricOptionsStringerTests = []struct { + in *MetricsOptions + out string + }{ + { + &MetricsOptions{}, + "", + }, + { + nil, + "", + }, + { + &MetricsOptions{ + Name: "testName", + Page: 5, + }, + "name=testName" + + "&page=5", + }, + } + applicationMetricDataOptionsStringerTests = []struct { + in *MetricDataOptions + out string + }{ + { + &MetricDataOptions{}, + "", + }, + { + nil, + "", + }, + { + &MetricDataOptions{ + Names: Array{[]string{"test1", "test2"}}, + Values: Array{[]string{"value1", "value2"}}, + From: testTime, + To: testTime, + Period: 123, + Summarize: true, + Raw: true, + }, + "from=" + testTimeStringEscaped + + "&names%5B%5D=test1" + + "&names%5B%5D=test2" + + "&period=123" + + "&raw=true" + + "&summarize=true" + + "&to=" + testTimeStringEscaped + + "&values%5B%5D=value1&values%5B%5D=value2", + }, + } + testApplicationMetricDataJSON = ` + { + "metric_data": { + "from": "` + testTimeRawString + `", + "to": "` + testTimeRawString + `", + "metrics_found": ["name1"], + "metrics_not_found": ["name2"], + "metrics": [ + { + "name": "testName", + "timeslices": [ + { + "from": "` + testTimeRawString + `", + "to": "` + testTimeRawString + `", + "values": {"testVal": 1.234} + } + ] + } + ] + } + } +` + testApplicationMetricData = MetricData{ + Name: "testName", + Timeslices: []MetricTimeslice{ + MetricTimeslice{ + From: testTime, + To: testTime, + Values: map[string]float64{ + "testVal": 1.234, + }, + }, + }, + } + getApplicaitonMetricDataTests = []struct { + in getApplicationMetricDataTestsInput + out getApplicationMetricDataTestsOutput + }{ + { + getApplicationMetricDataTestsInput{ + id: 1234, + Names: []string{"name1", "name2"}, + options: &MetricDataOptions{}, + data: testApplicationMetricDataJSON, + }, + getApplicationMetricDataTestsOutput{ + data: &MetricDataResponse{ + From: testTime, + To: testTime, + MetricsFound: []string{"name1"}, + MetricsNotFound: []string{"name2"}, + Metrics: []MetricData{testApplicationMetricData}, + }, + err: nil, + }, + }, + } +) diff --git a/vendor/github.com/yfronto/newrelic/applications.go b/vendor/github.com/yfronto/newrelic/applications.go new file mode 100644 index 00000000..034f7db1 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/applications.go @@ -0,0 +1,111 @@ +package newrelic + +import ( + "strconv" + "time" +) + +// ApplicationSummary describes the brief summary component of an Application. +type ApplicationSummary struct { + ResponseTime float64 `json:"response_time,omitempty"` + Throughput float64 `json:"throughput,omitempty"` + ErrorRate float64 `json:"error_rate,omitempty"` + ApdexTarget float64 `json:"apdex_target,omitempty"` + ApdexScore float64 `json:"apdex_score,omitempty"` + HostCount int `json:"host_count,omitempty"` + InstanceCount int `json:"instance_count,omitempty"` + ConcurrentInstanceCount int `json:"concurrent_instance_count,omitempty"` +} + +// EndUserSummary describes the end user summary component of an Application. +type EndUserSummary struct { + ResponseTime float64 `json:"response_time,omitempty"` + Throughput float64 `json:"throughput,omitempty"` + ApdexTarget float64 `json:"apdex_target,omitempty"` + ApdexScore float64 `json:"apdex_score,omitempty"` +} + +// Settings describe settings for an Application. +type Settings struct { + AppApdexThreshold float64 `json:"app_apdex_threshold,omitempty"` + EndUserApdexThreshold float64 `json:"end_user_apdex_threshold,omitempty"` + EnableRealUserMonitoring bool `json:"enable_real_user_monitoring,omitempty"` + UseServerSideConfig bool `json:"use_server_side_config,omitempty"` +} + +// Links list IDs associated with an Application. +type Links struct { + Servers []int `json:"servers,omitempty"` + ApplicationHosts []int `json:"application_hosts,omitempty"` + ApplicationInstances []int `json:"application_instances,omitempty"` + AlertPolicy int `json:"alert_policy,omitempty"` +} + +// Application describes a New Relic Application. +type Application struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Language string `json:"language,omitempty"` + HealthStatus string `json:"health_status,omitempty"` + Reporting bool `json:"reporting,omitempty"` + LastReportedAt time.Time `json:"last_reported_at,omitempty"` + ApplicationSummary ApplicationSummary `json:"application_summary,omitempty"` + EndUserSummary EndUserSummary `json:"end_user_summary,omitempty"` + Settings Settings `json:"settings,omitempty"` + Links Links `json:"links,omitempty"` +} + +// ApplicationFilter provides a means to filter requests through +// ApplicaitonOptions when calling GetApplications. +type ApplicationFilter struct { + Name string + Host string + IDs []int + Language string +} + +// ApplicationOptions provides a means to filter results when calling +// GetApplicaitons. +type ApplicationOptions struct { + Filter ApplicationFilter + Page int +} + +func (o *ApplicationOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[name]": o.Filter.Name, + "filter[host]": o.Filter.Host, + "filter[ids]": o.Filter.IDs, + "filter[language]": o.Filter.Language, + "page": o.Page, + }) +} + +// GetApplications returns a slice of New Relic Applications, optionally +// filtering by ApplicationOptions. +func (c *Client) GetApplications(options *ApplicationOptions) ([]Application, error) { + resp := &struct { + Applications []Application `json:"applications,omitempty"` + }{} + err := c.doGet("applications.json", options, resp) + if err != nil { + return nil, err + } + return resp.Applications, nil +} + +// GetApplication returns a single Application associated with a given ID. +func (c *Client) GetApplication(id int) (*Application, error) { + resp := &struct { + Application Application `json:"application,omitempty"` + }{} + path := "applications/" + strconv.Itoa(id) + ".json" + err := c.doGet(path, nil, resp) + if err != nil { + return nil, err + } + return &resp.Application, nil +} diff --git a/vendor/github.com/yfronto/newrelic/applications_test_fixtures.go b/vendor/github.com/yfronto/newrelic/applications_test_fixtures.go new file mode 100644 index 00000000..faf4cf5b --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/applications_test_fixtures.go @@ -0,0 +1,165 @@ +package newrelic + +type getApplicationsTestsInput struct { + options *ApplicationOptions + data string +} + +type getApplicationsTestsOutput struct { + data []Application + err error +} + +type getApplicationTestsInput struct { + id int + data string +} + +type getApplicationTestsOutput struct { + data *Application + err error +} + +var ( + testApplicationJSON = ` + { + "application_summary": { + "apdex_score": 1.0, + "apdex_target": 0.5, + "error_rate": 0.0, + "host_count": 1, + "instance_count": 1, + "response_time": 0.263, + "throughput": 12.3 + }, + "end_user_summary": { + "response_time": 0.263, + "throughput": 12.3, + "apdex_target": 0.5, + "apdex_score": 1 + }, + "health_status": "green", + "id": 12345, + "language": "java", + "last_reported_at": "` + testTimeRawString + `", + "links": { + "alert_policy": 123, + "application_hosts": [ + 1234567 + ], + "application_instances": [ + 1234568 + ], + "servers": [ + 54321 + ] + }, + "name": "test.example.com", + "reporting": true, + "settings": { + "app_apdex_threshold": 0.5, + "enable_real_user_monitoring": true, + "end_user_apdex_threshold": 1.0, + "use_server_side_config": false + } + } +` + testApplication = Application{ + ID: 12345, + Name: "test.example.com", + Language: "java", + HealthStatus: "green", + Reporting: true, + LastReportedAt: testTime, + ApplicationSummary: ApplicationSummary{ + ResponseTime: 0.263, + Throughput: 12.3, + ErrorRate: 0, + ApdexTarget: 0.5, + ApdexScore: 1, + HostCount: 1, + InstanceCount: 1, + ConcurrentInstanceCount: 0, + }, + EndUserSummary: EndUserSummary{ + ResponseTime: 0.263, + Throughput: 12.3, + ApdexTarget: 0.5, + ApdexScore: 1, + }, + Settings: Settings{ + AppApdexThreshold: 0.5, + EndUserApdexThreshold: 1, + EnableRealUserMonitoring: true, + UseServerSideConfig: false, + }, + Links: Links{ + Servers: []int{54321}, + ApplicationHosts: []int{1234567}, + ApplicationInstances: []int{1234568}, + AlertPolicy: 123, + }, + } + testApplications = []Application{ + testApplication, + testApplication, + } + getApplicationTests = []struct { + in getApplicationTestsInput + out getApplicationTestsOutput + }{ + { + getApplicationTestsInput{ + id: 12345, + data: `{ "application":` + testApplicationJSON + `}`, + }, + getApplicationTestsOutput{ + data: &testApplication, + }, + }, + } + getApplicationsTests = []struct { + in getApplicationsTestsInput + out getApplicationsTestsOutput + }{ + { + getApplicationsTestsInput{ + options: nil, + data: `{"applications":[` + testApplicationJSON + "," + testApplicationJSON + "]}", + }, + getApplicationsTestsOutput{ + data: testApplications, + err: nil, + }, + }, + } + applicationOptionsStringerTests = []struct { + in *ApplicationOptions + out string + }{ + { + &ApplicationOptions{}, + "", + }, + { + &ApplicationOptions{ + Filter: ApplicationFilter{ + Name: "testName", + Host: "testHost", + IDs: []int{123, 456}, + Language: "java", + }, + Page: 5, + }, + `filter%5Bhost%5D=testHost` + + `&filter%5Bids%5D=123%2C456` + + `&filter%5Blanguage%5D=java` + + `&filter%5Bname%5D=testName` + + `&page=5`, + }, + { + nil, + "", + }, + } +) diff --git a/vendor/github.com/yfronto/newrelic/array.go b/vendor/github.com/yfronto/newrelic/array.go new file mode 100644 index 00000000..59c06baf --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/array.go @@ -0,0 +1,11 @@ +package newrelic + +// An Array is a type expected by the NewRelic API that differs from a comma- +// separated list. When passing GET params that expect an 'Array' type with +// one to many values, the expected format is "key=val1&key=val2" but an +// argument with zero to many values is of the form "key=val1,val2", and +// neither can be used in the other's place, so we have to differentiate +// somehow. +type Array struct { + arr []string +} diff --git a/vendor/github.com/yfronto/newrelic/browser_applications.go b/vendor/github.com/yfronto/newrelic/browser_applications.go new file mode 100644 index 00000000..d64c203c --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/browser_applications.go @@ -0,0 +1,48 @@ +package newrelic + +// BrowserApplicationsFilter is the filtering component of +// BrowserApplicationsOptions +type BrowserApplicationsFilter struct { + Name string + IDs []int +} + +// BrowserApplicationsOptions provides a filtering mechanism for +// GetBrowserApplications. +type BrowserApplicationsOptions struct { + Filter BrowserApplicationsFilter + Page int +} + +// BrowserApplication describes a New Relic Browser Application. +type BrowserApplication struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + BrowserMonitoringKey string `json:"browser_monitoring_key,omitempty"` + LoaderScript string `json:"loader_script,omitempty"` +} + +// GetBrowserApplications will return a slice of New Relic Browser +// Applications, optionally filtered by BrowserApplicationsOptions. +func (c *Client) GetBrowserApplications(opt *BrowserApplicationsOptions) ([]BrowserApplication, error) { + resp := &struct { + BrowserApplications []BrowserApplication `json:"browser_applications,omitempty"` + }{} + path := "browser_applications.json" + err := c.doGet(path, opt, resp) + if err != nil { + return nil, err + } + return resp.BrowserApplications, nil +} + +func (o *BrowserApplicationsOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[name]": o.Filter.Name, + "filter[ids]": o.Filter.IDs, + "page": o.Page, + }) +} diff --git a/vendor/github.com/yfronto/newrelic/common_test_fixtures.go b/vendor/github.com/yfronto/newrelic/common_test_fixtures.go new file mode 100644 index 00000000..f5c8a6d6 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/common_test_fixtures.go @@ -0,0 +1,17 @@ +package newrelic + +import ( + "net/url" + "time" +) + +const ( + testAPIKey = "test_api_key" + testTimeRawString = "2016-01-20T20:29:38Z" +) + +var ( + testTime, _ = time.Parse(time.RFC3339, testTimeRawString) + testTimeString = testTime.String() + testTimeStringEscaped = url.QueryEscape(testTimeString) +) diff --git a/vendor/github.com/yfronto/newrelic/component_metrics.go b/vendor/github.com/yfronto/newrelic/component_metrics.go new file mode 100644 index 00000000..6c5ef599 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/component_metrics.go @@ -0,0 +1,34 @@ +package newrelic + +import ( + "fmt" +) + +// GetComponentMetrics will return a slice of Metric items for a +// particular Component ID, optionally filtered by MetricsOptions. +func (c *Client) GetComponentMetrics(id int, options *MetricsOptions) ([]Metric, error) { + mc := NewMetricClient(c) + + return mc.GetMetrics( + fmt.Sprintf( + "components/%d/metrics.json", + id, + ), + options, + ) +} + +// GetComponentMetricData will return all metric data for a particular +// component, optionally filtered by MetricDataOptions. +func (c *Client) GetComponentMetricData(id int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) { + mc := NewMetricClient(c) + + return mc.GetMetricData( + fmt.Sprintf( + "components/%d/metrics/data.json", + id, + ), + names, + options, + ) +} diff --git a/vendor/github.com/yfronto/newrelic/http_helper.go b/vendor/github.com/yfronto/newrelic/http_helper.go new file mode 100644 index 00000000..e853a5fc --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/http_helper.go @@ -0,0 +1,100 @@ +package newrelic + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strconv" + "strings" + "time" +) + +func (c *Client) doGet(path string, params fmt.Stringer, out interface{}) error { + var s string + if params != nil { + s = params.String() + } + r := strings.NewReader(s) + req, err := http.NewRequest("GET", c.url.String()+path, r) + if err != nil { + return err + } + req.Header.Add("X-Api-Key", c.apiKey) + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + return c.doRequest(req, out) +} + +func (c *Client) doRequest(req *http.Request, out interface{}) error { + resp, err := c.httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + if resp.StatusCode != 200 { + return fmt.Errorf("newrelic http error (%s): %s", resp.Status, b) + } + if len(b) == 0 { + b = []byte{'{', '}'} + } + err = json.Unmarshal(b, &out) + if err != nil { + return err + } + return nil +} + +func encodeGetParams(params map[string]interface{}) string { + s := url.Values{} + for k, v := range params { + switch v.(type) { + case string: + val := v.(string) + if val != "" { + s.Add(k, val) + } + case int: + val := v.(int) + // TODO: Zero values versus not defined + if val != 0 { + s.Add(k, strconv.Itoa(val)) + } + case []string: + val := v.([]string) + if len(val) != 0 { + s.Add(k, strings.Join(val, ",")) + } + case []int: + val := v.([]int) + arr := []string{} + for _, v := range val { + arr = append(arr, strconv.Itoa(v)) + } + if len(arr) != 0 { + s.Add(k, strings.Join(arr, ",")) + } + case time.Time: + val := v.(time.Time) + if !val.IsZero() { + s.Add(k, val.String()) + } + case Array: + val := v.(Array) + for _, v := range val.arr { + s.Add(k, v) + } + case bool: + if v.(bool) { + s.Add(k, "true") + } + default: + s.Add(k, fmt.Sprintf("%v", v)) + } + } + return s.Encode() +} diff --git a/vendor/github.com/yfronto/newrelic/http_helper_test_fixtures.go b/vendor/github.com/yfronto/newrelic/http_helper_test_fixtures.go new file mode 100644 index 00000000..de0f0b3d --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/http_helper_test_fixtures.go @@ -0,0 +1,119 @@ +package newrelic + +import ( + "errors" + "net/http" + "strings" +) + +type testJSONInterface struct { + data string `json:"data"id,omitempty"` +} + +type testParamsInterface struct { + data string +} + +type doGetTestsInput struct { + path string + params *testParamsInterface + out testJSONInterface + status int + data string +} + +type doGetTestsOutput struct { + data testJSONInterface + err error +} + +type doRequestTestsInput struct { + req *http.Request + out testJSONInterface + status int + data string +} + +type doRequestTestOutput struct { + data testJSONInterface + err error +} + +var ( + doGetTests = []struct { + in doGetTestsInput + out doGetTestsOutput + }{ + { + doGetTestsInput{ + path: "somePath", + params: &testParamsInterface{"testData"}, + out: testJSONInterface{"testData"}, + status: 200, + data: `{"data": "testStructData"}`, + }, + doGetTestsOutput{ + data: testJSONInterface{"testData"}, + err: nil, + }, + }, + { + doGetTestsInput{ + status: 404, + data: "Not Found", + }, + doGetTestsOutput{ + err: errors.New("newrelic http error (404 Not Found): Not Found"), + }, + }, + } + testRequest, _ = http.NewRequest("GET", "http://testPath", + strings.NewReader("testBody")) + doRequestTests = []struct { + in doRequestTestsInput + out doRequestTestOutput + }{ + { + doRequestTestsInput{ + req: testRequest, + out: testJSONInterface{"testData"}, + status: 200, + data: `{"data": "testStructData"}`, + }, + doRequestTestOutput{ + data: testJSONInterface{"testData"}, + err: nil, + }, + }, + } + encodeGetParamsTests = []struct { + in map[string]interface{} + out string + }{ + { + map[string]interface{}{ + "testInt": 5, + "testString": "test", + "testStringSlice": []string{"test1", "test2"}, + "testArray": Array{[]string{"test1", "test2"}}, + "testTime": testTime, + }, + "testArray=test1" + + "&testArray=test2" + + "&testInt=5" + + "&testString=test" + + "&testStringSlice=test1%2Ctest2" + + "&testTime=" + testTimeStringEscaped, + }, + { + map[string]interface{}{ + "unexpectedType": map[string]string{"unexpected": "type"}, + }, + "unexpectedType=map%5Bunexpected%3Atype%5D", + }, + } +) + +func (m *testParamsInterface) String() string { + return "data=testData" +} diff --git a/vendor/github.com/yfronto/newrelic/key_transactions.go b/vendor/github.com/yfronto/newrelic/key_transactions.go new file mode 100644 index 00000000..b057909d --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/key_transactions.go @@ -0,0 +1,76 @@ +package newrelic + +import ( + "strconv" + "time" +) + +// KeyTransactionsFilter is the filtering component of KeyTransactionsOptions. +type KeyTransactionsFilter struct { + Name string + IDs []int +} + +// KeyTransactionsOptions provides a filtering mechanism for GetKeyTransactions. +type KeyTransactionsOptions struct { + Filter KeyTransactionsFilter + Page int +} + +// KeyTransactionLinks link KeyTransactions to the objects to which they +// pertain. +type KeyTransactionLinks struct { + Application int `json:"application,omitempty"` +} + +// KeyTransaction represents a New Relic Key Transaction. +type KeyTransaction struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + TransactionName string `json:"transaction_name,omitempty"` + HealthStatus string `json:"health_status,omitempty"` + Reporting bool `json:"reporting,omitempty"` + LastReportedAt time.Time `json:"last_reported_at,omitempty"` + ApplicationSummary ApplicationSummary `json:"application_summary,omitempty"` + EndUserSummary EndUserSummary `json:"end_user_summary,omitempty"` + Links KeyTransactionLinks `json:"links,omitempty"` +} + +// GetKeyTransactions will return a slice of New Relic Key Transactions, +// optionally filtered by KeyTransactionsOptions. +func (c *Client) GetKeyTransactions(opt *KeyTransactionsOptions) ([]KeyTransaction, error) { + resp := &struct { + KeyTransactions []KeyTransaction `json:"key_transactions,omitempty"` + }{} + path := "key_transactions.json" + err := c.doGet(path, opt, resp) + if err != nil { + return nil, err + } + return resp.KeyTransactions, nil +} + +// GetKeyTransaction will return a single New Relic Key Transaction for the +// given id. +func (c *Client) GetKeyTransaction(id int) (*KeyTransaction, error) { + resp := &struct { + KeyTransaction *KeyTransaction `json:"key_transaction,omitempty"` + }{} + path := "key_transactions/" + strconv.Itoa(id) + ".json" + err := c.doGet(path, nil, resp) + if err != nil { + return nil, err + } + return resp.KeyTransaction, nil +} + +func (o *KeyTransactionsOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[name]": o.Filter.Name, + "filter[ids]": o.Filter.IDs, + "page": o.Page, + }) +} diff --git a/vendor/github.com/yfronto/newrelic/legacy_alert_policies.go b/vendor/github.com/yfronto/newrelic/legacy_alert_policies.go new file mode 100644 index 00000000..423192f0 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/legacy_alert_policies.go @@ -0,0 +1,78 @@ +package newrelic + +import ( + "strconv" +) + +// LegacyAlertPolicyLinks describes object links for Alert Policies. +type LegacyAlertPolicyLinks struct { + NotificationChannels []int `json:"notification_channels,omitempty"` + Servers []int `json:"servers,omitempty"` +} + +// LegacyAlertPolicyCondition describes conditions that trigger an LegacyAlertPolicy. +type LegacyAlertPolicyCondition struct { + ID int `json:"id,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Severity string `json:"severity,omitempty"` + Threshold float64 `json:"threshold,omitempty"` + TriggerMinutes int `json:"trigger_minutes,omitempty"` + Type string `json:"type,omitempty"` +} + +// LegacyAlertPolicy describes a New Relic alert policy. +type LegacyAlertPolicy struct { + Conditions []LegacyAlertPolicyCondition `json:"conditions,omitempty"` + Enabled bool `json:"enabled,omitempty"` + ID int `json:"id,omitempty"` + Links LegacyAlertPolicyLinks `json:"links,omitempty"` + IncidentPreference string `json:"incident_preference,omitempty"` + Name string `json:"name,omitempty"` +} + +// LegacyAlertPolicyFilter provides filters for LegacyAlertPolicyOptions. +type LegacyAlertPolicyFilter struct { + Name string +} + +// LegacyAlertPolicyOptions is an optional means of filtering when calling +// GetLegacyAlertPolicies. +type LegacyAlertPolicyOptions struct { + Filter LegacyAlertPolicyFilter + Page int +} + +func (o *LegacyAlertPolicyOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[name]": o.Filter.Name, + "page": o.Page, + }) +} + +// GetLegacyAlertPolicy will return the LegacyAlertPolicy with particular ID. +func (c *Client) GetLegacyAlertPolicy(id int) (*LegacyAlertPolicy, error) { + resp := &struct { + LegacyAlertPolicy *LegacyAlertPolicy `json:"alert_policy,omitempty"` + }{} + err := c.doGet("alert_policies/"+strconv.Itoa(id)+".json", nil, resp) + if err != nil { + return nil, err + } + return resp.LegacyAlertPolicy, nil +} + +// GetLegacyAlertPolicies will return a slice of LegacyAlertPolicy items, +// optionally filtering by LegacyAlertPolicyOptions. +func (c *Client) GetLegacyAlertPolicies(options *LegacyAlertPolicyOptions) ([]LegacyAlertPolicy, error) { + resp := &struct { + LegacyAlertPolicies []LegacyAlertPolicy `json:"alert_policies,omitempty"` + }{} + err := c.doGet("alert_policies.json", options, resp) + if err != nil { + return nil, err + } + return resp.LegacyAlertPolicies, nil +} diff --git a/vendor/github.com/yfronto/newrelic/main.go b/vendor/github.com/yfronto/newrelic/main.go new file mode 100644 index 00000000..874f10c9 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/main.go @@ -0,0 +1,48 @@ +/* + * NewRelic API for Go + * + * Please see the included LICENSE file for licensing information. + * + * Copyright 2016 by authors and contributors. + */ + +package newrelic + +import ( + "net/http" + "net/url" + "time" +) + +const ( + // defaultAPIURL is the default base URL for New Relic's latest API. + defaultAPIURL = "https://api.newrelic.com/v2/" + // defaultTimeout is the default timeout for the http.Client used. + defaultTimeout = 5 * time.Second +) + +// Client provides a set of methods to interact with the New Relic API. +type Client struct { + apiKey string + httpClient *http.Client + url *url.URL +} + +// NewWithHTTPClient returns a new Client object for interfacing with the New +// Relic API, allowing for override of the http.Client object. +func NewWithHTTPClient(apiKey string, client *http.Client) *Client { + u, err := url.Parse(defaultAPIURL) + if err != nil { + panic(err) + } + return &Client{ + apiKey: apiKey, + httpClient: client, + url: u, + } +} + +// NewClient returns a new Client object for interfacing with the New Relic API. +func NewClient(apiKey string) *Client { + return NewWithHTTPClient(apiKey, &http.Client{Timeout: defaultTimeout}) +} diff --git a/vendor/github.com/yfronto/newrelic/metrics.go b/vendor/github.com/yfronto/newrelic/metrics.go new file mode 100644 index 00000000..fb609a81 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/metrics.go @@ -0,0 +1,128 @@ +package newrelic + +import ( + "time" +) + +// Metric describes a New Relic metric. +type Metric struct { + Name string `json:"name,omitempty"` + Values []string `json:"values,omitempty"` +} + +// MetricsOptions options allow filtering when getting lists of metric names +// associated with an entity. +type MetricsOptions struct { + Name string + Page int +} + +// MetricTimeslice describes the period to which a Metric pertains. +type MetricTimeslice struct { + From time.Time `json:"from,omitempty"` + To time.Time `json:"to,omitempty"` + Values map[string]float64 `json:"values,omitempty"` +} + +// MetricData describes the data for a particular metric. +type MetricData struct { + Name string `json:"name,omitempty"` + Timeslices []MetricTimeslice `json:"timeslices,omitempty"` +} + +// MetricDataOptions allow filtering when getting data about a particular set +// of New Relic metrics. +type MetricDataOptions struct { + Names Array + Values Array + From time.Time + To time.Time + Period int + Summarize bool + Raw bool +} + +// MetricDataResponse is the response received from New Relic for any request +// for metric data. +type MetricDataResponse struct { + From time.Time `json:"from,omitempty"` + To time.Time `json:"to,omitempty"` + MetricsNotFound []string `json:"metrics_not_found,omitempty"` + MetricsFound []string `json:"metrics_found,omitempty"` + Metrics []MetricData `json:"metrics,omitempty"` +} + +func (o *MetricsOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "name": o.Name, + "page": o.Page, + }) +} + +func (o *MetricDataOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "names[]": o.Names, + "values[]": o.Values, + "from": o.From, + "to": o.To, + "period": o.Period, + "summarize": o.Summarize, + "raw": o.Raw, + }) +} + +// MetricClient implements a generic New Relic metrics client. +// This is used as a general client for fetching metric names and data. +type MetricClient struct { + newRelicClient *Client +} + +// NewMetricClient creates and returns a new MetricClient. +func NewMetricClient(newRelicClient *Client) *MetricClient { + return &MetricClient{ + newRelicClient: newRelicClient, + } +} + +// GetMetrics is a generic function for fetching a list of available metrics +// from different parts of New Relic. +// Example: Application metrics, Component metrics, etc. +func (mc *MetricClient) GetMetrics(path string, options *MetricsOptions) ([]Metric, error) { + resp := &struct { + Metrics []Metric `json:"metrics,omitempty"` + }{} + + err := mc.newRelicClient.doGet(path, options, resp) + if err != nil { + return nil, err + } + + return resp.Metrics, nil +} + +// GetMetricData is a generic function for fetching data for a specific metric. +// from different parts of New Relic. +// Example: Application metric data, Component metric data, etc. +func (mc *MetricClient) GetMetricData(path string, names []string, options *MetricDataOptions) (*MetricDataResponse, error) { + resp := &struct { + MetricData MetricDataResponse `json:"metric_data,omitempty"` + }{} + + if options == nil { + options = &MetricDataOptions{} + } + + options.Names = Array{names} + err := mc.newRelicClient.doGet(path, options, resp) + if err != nil { + return nil, err + } + + return &resp.MetricData, nil +} diff --git a/vendor/github.com/yfronto/newrelic/mobile_application_metrics.go b/vendor/github.com/yfronto/newrelic/mobile_application_metrics.go new file mode 100644 index 00000000..c1a905aa --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/mobile_application_metrics.go @@ -0,0 +1,36 @@ +package newrelic + +import ( + "fmt" +) + +// GetMobileApplicationMetrics will return a slice of Metric items for a +// particular MobileAplication ID, optionally filtering by +// MetricsOptions. +func (c *Client) GetMobileApplicationMetrics(id int, options *MetricsOptions) ([]Metric, error) { + mc := NewMetricClient(c) + + return mc.GetMetrics( + fmt.Sprintf( + "mobile_applications/%d/metrics.json", + id, + ), + options, + ) +} + +// GetMobileApplicationMetricData will return all metric data for a particular +// MobileAplication and slice of metric names, optionally filtered by +// MetricDataOptions. +func (c *Client) GetMobileApplicationMetricData(id int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) { + mc := NewMetricClient(c) + + return mc.GetMetricData( + fmt.Sprintf( + "mobile_applications/%d/metrics/data.json", + id, + ), + names, + options, + ) +} diff --git a/vendor/github.com/yfronto/newrelic/mobile_applications.go b/vendor/github.com/yfronto/newrelic/mobile_applications.go new file mode 100644 index 00000000..0df108d7 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/mobile_applications.go @@ -0,0 +1,61 @@ +package newrelic + +import ( + "strconv" +) + +// MobileApplicationSummary describes an Application's host. +type MobileApplicationSummary struct { + ActiveUsers int `json:"active_users,omitempty"` + LaunchCount int `json:"launch_count,omitempty"` + Throughput float64 `json:"throughput,omitempty"` + ResponseTime float64 `json:"response_time,omitempty"` + CallsPerSession float64 `json:"calls_per_session,omitempty"` + InteractionTime float64 `json:"interaction_time,omitempty"` + FailedCallRate float64 `json:"failed_call_rate,omitempty"` + RemoteErrorRate float64 `json:"remote_error_rate"` +} + +// MobileApplicationCrashSummary describes a MobileApplication's crash data. +type MobileApplicationCrashSummary struct { + SupportsCrashData bool `json:"supports_crash_data,omitempty"` + UnresolvedCrashCount int `json:"unresolved_crash_count,omitempty"` + CrashCount int `json:"crash_count,omitempty"` + CrashRate float64 `json:"crash_rate,omitempty"` +} + +// MobileApplication describes a New Relic Application Host. +type MobileApplication struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + HealthStatus string `json:"health_status,omitempty"` + Reporting bool `json:"reporting,omitempty"` + MobileSummary MobileApplicationSummary `json:"mobile_summary,omitempty"` + CrashSummary MobileApplicationCrashSummary `json:"crash_summary,omitempty"` +} + +// GetMobileApplications returns a slice of New Relic Mobile Applications. +func (c *Client) GetMobileApplications() ([]MobileApplication, error) { + resp := &struct { + Applications []MobileApplication `json:"applications,omitempty"` + }{} + path := "mobile_applications.json" + err := c.doGet(path, nil, resp) + if err != nil { + return nil, err + } + return resp.Applications, nil +} + +// GetMobileApplication returns a single Mobile Application with the id. +func (c *Client) GetMobileApplication(id int) (*MobileApplication, error) { + resp := &struct { + Application MobileApplication `json:"application,omitempty"` + }{} + path := "mobile_applications/" + strconv.Itoa(id) + ".json" + err := c.doGet(path, nil, resp) + if err != nil { + return nil, err + } + return &resp.Application, nil +} diff --git a/vendor/github.com/yfronto/newrelic/notification_channels.go b/vendor/github.com/yfronto/newrelic/notification_channels.go new file mode 100644 index 00000000..8a64c17d --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/notification_channels.go @@ -0,0 +1,78 @@ +package newrelic + +import ( + "strconv" +) + +// NotificationChannelLinks describes object links for notification channels. +type NotificationChannelLinks struct { + NotificationChannels []int `json:"notification_channels,omitempty"` + User int `json:"user,omitempty"` +} + +// NotificationChannel describes a New Relic notification channel. +type NotificationChannel struct { + ID int `json:"id,omitempty"` + Type string `json:"type,omitempty"` + DowntimeOnly bool `json:"downtime_only,omitempty"` + URL string `json:"url,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Email string `json:"email,omitempty"` + Subdomain string `json:"subdomain,omitempty"` + Service string `json:"service,omitempty"` + MobileAlerts bool `json:"mobile_alerts,omitempty"` + EmailAlerts bool `json:"email_alerts,omitempty"` + Room string `json:"room,omitempty"` + Links NotificationChannelLinks `json:"links,omitempty"` +} + +// NotificationChannelsFilter provides filters for +// NotificationChannelsOptions. +type NotificationChannelsFilter struct { + Type []string + IDs []int +} + +// NotificationChannelsOptions is an optional means of filtering when calling +// GetNotificationChannels. +type NotificationChannelsOptions struct { + Filter NotificationChannelsFilter + Page int +} + +func (o *NotificationChannelsOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[type]": o.Filter.Type, + "filter[ids]": o.Filter.IDs, + "page": o.Page, + }) +} + +// GetNotificationChannel will return the NotificationChannel with particular ID. +func (c *Client) GetNotificationChannel(id int) (*NotificationChannel, error) { + resp := &struct { + NotificationChannel *NotificationChannel `json:"notification_channel,omitempty"` + }{} + err := c.doGet("notification_channels/"+strconv.Itoa(id)+".json", nil, resp) + if err != nil { + return nil, err + } + return resp.NotificationChannel, nil +} + +// GetNotificationChannels will return a slice of NotificationChannel items, +// optionally filtering by NotificationChannelsOptions. +func (c *Client) GetNotificationChannels(options *NotificationChannelsOptions) ([]NotificationChannel, error) { + resp := &struct { + NotificationChannels []NotificationChannel `json:"notification_channels,omitempty"` + }{} + err := c.doGet("notification_channels.json", options, resp) + if err != nil { + return nil, err + } + return resp.NotificationChannels, nil +} diff --git a/vendor/github.com/yfronto/newrelic/server_metrics.go b/vendor/github.com/yfronto/newrelic/server_metrics.go new file mode 100644 index 00000000..0387e696 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/server_metrics.go @@ -0,0 +1,34 @@ +package newrelic + +import ( + "fmt" +) + +// GetServerMetrics will return a slice of Metric items for a particular +// Server ID, optionally filtering by MetricsOptions. +func (c *Client) GetServerMetrics(id int, options *MetricsOptions) ([]Metric, error) { + mc := NewMetricClient(c) + + return mc.GetMetrics( + fmt.Sprintf( + "servers/%d/metrics.json", + id, + ), + options, + ) +} + +// GetServerMetricData will return all metric data for a particular Server and +// slice of metric names, optionally filtered by MetricDataOptions. +func (c *Client) GetServerMetricData(id int, names []string, options *MetricDataOptions) (*MetricDataResponse, error) { + mc := NewMetricClient(c) + + return mc.GetMetricData( + fmt.Sprintf( + "servers/%d/metrics/data.json", + id, + ), + names, + options, + ) +} diff --git a/vendor/github.com/yfronto/newrelic/servers.go b/vendor/github.com/yfronto/newrelic/servers.go new file mode 100644 index 00000000..04cf0ae4 --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/servers.go @@ -0,0 +1,92 @@ +package newrelic + +import ( + "strconv" + "time" +) + +// ServersFilter is the filtering component of ServersOptions. +type ServersFilter struct { + Name string + Host string + IDs []int + Labels []string + Reported bool +} + +// ServersOptions provides a filtering mechanism for GetServers. +type ServersOptions struct { + Filter ServersFilter + Page int +} + +// ServerSummary describes the summary component of a Server. +type ServerSummary struct { + CPU float64 `json:"cpu,omitempty"` + CPUStolen float64 `json:"cpu_stolen,omitempty"` + DiskIO float64 `json:"disk_io,omitempty"` + Memory float64 `json:"memory,omitempty"` + MemoryUsed int64 `json:"memory_used,omitempty"` + MemoryTotal int64 `json:"memory_total,omitempty"` + FullestDisk float64 `json:"fullest_disk,omitempty"` + FullestDiskFree int64 `json:"fullest_disk_free,omitempty"` +} + +// ServerLinks link Servers to the objects to which they pertain. +type ServerLinks struct { + AlertPolicy int `json:"alert_policy,omitempty"` +} + +// Server represents a New Relic Server. +type Server struct { + ID int `json:"id,omitempty"` + AccountID int `json:"account_id,omitempty"` + Name string `json:"name,omitempty"` + Host string `json:"host,omitempty"` + HealthStatus string `json:"health_status,omitempty"` + Reporting bool `json:"reporting,omitempty"` + LastReportedAt time.Time `json:"last_reported_at,omitempty"` + Summary ServerSummary `json:"summary,omitempty"` + Links ServerLinks `json:"links,omitempty"` +} + +// GetServers will return a slice of New Relic Servers, optionally filtered by +// ServerOptions. +func (c *Client) GetServers(opt *ServersOptions) ([]Server, error) { + resp := &struct { + Servers []Server `json:"servers,omitempty"` + }{} + path := "servers.json" + err := c.doGet(path, opt, resp) + if err != nil { + return nil, err + } + return resp.Servers, nil +} + +// GetServer will return a single New Relic Server for the given id. +func (c *Client) GetServer(id int) (*Server, error) { + resp := &struct { + Server *Server `json:"server,omitempty"` + }{} + path := "servers/" + strconv.Itoa(id) + ".json" + err := c.doGet(path, nil, resp) + if err != nil { + return nil, err + } + return resp.Server, nil +} + +func (o *ServersOptions) String() string { + if o == nil { + return "" + } + return encodeGetParams(map[string]interface{}{ + "filter[name]": o.Filter.Name, + "filter[host]": o.Filter.Host, + "filter[ids]": o.Filter.IDs, + "filter[labels]": o.Filter.Labels, + "filter[reported]": o.Filter.Reported, + "page": o.Page, + }) +} diff --git a/vendor/github.com/yfronto/newrelic/usages.go b/vendor/github.com/yfronto/newrelic/usages.go new file mode 100644 index 00000000..97b2f90b --- /dev/null +++ b/vendor/github.com/yfronto/newrelic/usages.go @@ -0,0 +1,49 @@ +package newrelic + +import ( + "time" +) + +// Usage describes usage over a single time period. +type Usage struct { + From time.Time `json"from,omitempty"` + To time.Time `json:"to,omitempty"` + Usage int `json:"usage,omitempty"` +} + +// UsageData represents usage data for a product over a time frame, including +// a slice of Usages. +type UsageData struct { + Product string `json:"product,omitempty"` + From time.Time `json:"from,omitempty"` + To time.Time `json:"to,omitempty"` + Unit string `json:"unit,omitempty"` + Usages []Usage `json:"usages,omitempty"` +} + +type usageParams struct { + Start time.Time + End time.Time + IncludeSubaccount bool +} + +func (o *usageParams) String() string { + return encodeGetParams(map[string]interface{}{ + "start_date": o.Start.Format("2006-01-02"), + "end_date": o.End.Format("2006-01-02"), + "include_subaccounts": o.IncludeSubaccount, + }) +} + +// GetUsages will return usage for a product in a given time frame. +func (c *Client) GetUsages(product string, start, end time.Time, includeSubaccounts bool) (*UsageData, error) { + resp := &struct { + UsageData *UsageData `json:"usage_data,omitempty"` + }{} + options := &usageParams{start, end, includeSubaccounts} + err := c.doGet("usages/"+product+".json", options, resp) + if err != nil { + return nil, err + } + return resp.UsageData, nil +} diff --git a/vendor/golang.org/x/net/AUTHORS b/vendor/golang.org/x/net/AUTHORS new file mode 100644 index 00000000..15167cd7 --- /dev/null +++ b/vendor/golang.org/x/net/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/net/CONTRIBUTORS b/vendor/golang.org/x/net/CONTRIBUTORS new file mode 100644 index 00000000..1c4577e9 --- /dev/null +++ b/vendor/golang.org/x/net/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE new file mode 100644 index 00000000..6a66aea5 --- /dev/null +++ b/vendor/golang.org/x/net/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/golang.org/x/net/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go new file mode 100644 index 00000000..a3c021d3 --- /dev/null +++ b/vendor/golang.org/x/net/context/context.go @@ -0,0 +1,56 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package context defines the Context type, which carries deadlines, +// cancelation signals, and other request-scoped values across API boundaries +// and between processes. +// As of Go 1.7 this package is available in the standard library under the +// name context. https://golang.org/pkg/context. +// +// Incoming requests to a server should create a Context, and outgoing calls to +// servers should accept a Context. The chain of function calls between must +// propagate the Context, optionally replacing it with a modified copy created +// using WithDeadline, WithTimeout, WithCancel, or WithValue. +// +// Programs that use Contexts should follow these rules to keep interfaces +// consistent across packages and enable static analysis tools to check context +// propagation: +// +// Do not store Contexts inside a struct type; instead, pass a Context +// explicitly to each function that needs it. The Context should be the first +// parameter, typically named ctx: +// +// func DoSomething(ctx context.Context, arg Arg) error { +// // ... use ctx ... +// } +// +// Do not pass a nil Context, even if a function permits it. Pass context.TODO +// if you are unsure about which Context to use. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +// +// The same Context may be passed to functions running in different goroutines; +// Contexts are safe for simultaneous use by multiple goroutines. +// +// See http://blog.golang.org/context for example code for a server that uses +// Contexts. +package context // import "golang.org/x/net/context" + +// Background returns a non-nil, empty Context. It is never canceled, has no +// values, and has no deadline. It is typically used by the main function, +// initialization, and tests, and as the top-level Context for incoming +// requests. +func Background() Context { + return background +} + +// TODO returns a non-nil, empty Context. Code should use context.TODO when +// it's unclear which Context to use or it is not yet available (because the +// surrounding function has not yet been extended to accept a Context +// parameter). TODO is recognized by static analysis tools that determine +// whether Contexts are propagated correctly in a program. +func TODO() Context { + return todo +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go new file mode 100644 index 00000000..606cf1f9 --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go @@ -0,0 +1,74 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +// Package ctxhttp provides helper functions for performing context-aware HTTP requests. +package ctxhttp // import "golang.org/x/net/context/ctxhttp" + +import ( + "io" + "net/http" + "net/url" + "strings" + + "golang.org/x/net/context" +) + +// Do sends an HTTP request with the provided http.Client and returns +// an HTTP response. +// +// If the client is nil, http.DefaultClient is used. +// +// The provided ctx must be non-nil. If it is canceled or times out, +// ctx.Err() will be returned. +func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { + if client == nil { + client = http.DefaultClient + } + resp, err := client.Do(req.WithContext(ctx)) + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + if err != nil { + select { + case <-ctx.Done(): + err = ctx.Err() + default: + } + } + return resp, err +} + +// Get issues a GET request via the Do function. +func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Head issues a HEAD request via the Do function. +func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Post issues a POST request via the Do function. +func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest("POST", url, body) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", bodyType) + return Do(ctx, client, req) +} + +// PostForm issues a POST request via the Do function. +func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { + return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) +} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go new file mode 100644 index 00000000..926870cc --- /dev/null +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go @@ -0,0 +1,147 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7 + +package ctxhttp // import "golang.org/x/net/context/ctxhttp" + +import ( + "io" + "net/http" + "net/url" + "strings" + + "golang.org/x/net/context" +) + +func nop() {} + +var ( + testHookContextDoneBeforeHeaders = nop + testHookDoReturned = nop + testHookDidBodyClose = nop +) + +// Do sends an HTTP request with the provided http.Client and returns an HTTP response. +// If the client is nil, http.DefaultClient is used. +// If the context is canceled or times out, ctx.Err() will be returned. +func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { + if client == nil { + client = http.DefaultClient + } + + // TODO(djd): Respect any existing value of req.Cancel. + cancel := make(chan struct{}) + req.Cancel = cancel + + type responseAndError struct { + resp *http.Response + err error + } + result := make(chan responseAndError, 1) + + // Make local copies of test hooks closed over by goroutines below. + // Prevents data races in tests. + testHookDoReturned := testHookDoReturned + testHookDidBodyClose := testHookDidBodyClose + + go func() { + resp, err := client.Do(req) + testHookDoReturned() + result <- responseAndError{resp, err} + }() + + var resp *http.Response + + select { + case <-ctx.Done(): + testHookContextDoneBeforeHeaders() + close(cancel) + // Clean up after the goroutine calling client.Do: + go func() { + if r := <-result; r.resp != nil { + testHookDidBodyClose() + r.resp.Body.Close() + } + }() + return nil, ctx.Err() + case r := <-result: + var err error + resp, err = r.resp, r.err + if err != nil { + return resp, err + } + } + + c := make(chan struct{}) + go func() { + select { + case <-ctx.Done(): + close(cancel) + case <-c: + // The response's Body is closed. + } + }() + resp.Body = ¬ifyingReader{resp.Body, c} + + return resp, nil +} + +// Get issues a GET request via the Do function. +func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Head issues a HEAD request via the Do function. +func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return nil, err + } + return Do(ctx, client, req) +} + +// Post issues a POST request via the Do function. +func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest("POST", url, body) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", bodyType) + return Do(ctx, client, req) +} + +// PostForm issues a POST request via the Do function. +func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { + return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) +} + +// notifyingReader is an io.ReadCloser that closes the notify channel after +// Close is called or a Read fails on the underlying ReadCloser. +type notifyingReader struct { + io.ReadCloser + notify chan<- struct{} +} + +func (r *notifyingReader) Read(p []byte) (int, error) { + n, err := r.ReadCloser.Read(p) + if err != nil && r.notify != nil { + close(r.notify) + r.notify = nil + } + return n, err +} + +func (r *notifyingReader) Close() error { + err := r.ReadCloser.Close() + if r.notify != nil { + close(r.notify) + r.notify = nil + } + return err +} diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go new file mode 100644 index 00000000..d20f52b7 --- /dev/null +++ b/vendor/golang.org/x/net/context/go17.go @@ -0,0 +1,72 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package context + +import ( + "context" // standard library's context, as of Go 1.7 + "time" +) + +var ( + todo = context.TODO() + background = context.Background() +) + +// Canceled is the error returned by Context.Err when the context is canceled. +var Canceled = context.Canceled + +// DeadlineExceeded is the error returned by Context.Err when the context's +// deadline passes. +var DeadlineExceeded = context.DeadlineExceeded + +// WithCancel returns a copy of parent with a new Done channel. The returned +// context's Done channel is closed when the returned cancel function is called +// or when the parent context's Done channel is closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { + ctx, f := context.WithCancel(parent) + return ctx, CancelFunc(f) +} + +// WithDeadline returns a copy of the parent context with the deadline adjusted +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// context's Done channel is closed when the deadline expires, when the returned +// cancel function is called, or when the parent context's Done channel is +// closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { + ctx, f := context.WithDeadline(parent, deadline) + return ctx, CancelFunc(f) +} + +// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete: +// +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } +func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { + return WithDeadline(parent, time.Now().Add(timeout)) +} + +// WithValue returns a copy of parent in which the value associated with key is +// val. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +func WithValue(parent Context, key interface{}, val interface{}) Context { + return context.WithValue(parent, key, val) +} diff --git a/vendor/golang.org/x/net/context/go19.go b/vendor/golang.org/x/net/context/go19.go new file mode 100644 index 00000000..d88bd1db --- /dev/null +++ b/vendor/golang.org/x/net/context/go19.go @@ -0,0 +1,20 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +package context + +import "context" // standard library's context, as of Go 1.7 + +// A Context carries a deadline, a cancelation signal, and other values across +// API boundaries. +// +// Context's methods may be called by multiple goroutines simultaneously. +type Context = context.Context + +// A CancelFunc tells an operation to abandon its work. +// A CancelFunc does not wait for the work to stop. +// After the first call, subsequent calls to a CancelFunc do nothing. +type CancelFunc = context.CancelFunc diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go new file mode 100644 index 00000000..0f35592d --- /dev/null +++ b/vendor/golang.org/x/net/context/pre_go17.go @@ -0,0 +1,300 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7 + +package context + +import ( + "errors" + "fmt" + "sync" + "time" +) + +// An emptyCtx is never canceled, has no values, and has no deadline. It is not +// struct{}, since vars of this type must have distinct addresses. +type emptyCtx int + +func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { + return +} + +func (*emptyCtx) Done() <-chan struct{} { + return nil +} + +func (*emptyCtx) Err() error { + return nil +} + +func (*emptyCtx) Value(key interface{}) interface{} { + return nil +} + +func (e *emptyCtx) String() string { + switch e { + case background: + return "context.Background" + case todo: + return "context.TODO" + } + return "unknown empty Context" +} + +var ( + background = new(emptyCtx) + todo = new(emptyCtx) +) + +// Canceled is the error returned by Context.Err when the context is canceled. +var Canceled = errors.New("context canceled") + +// DeadlineExceeded is the error returned by Context.Err when the context's +// deadline passes. +var DeadlineExceeded = errors.New("context deadline exceeded") + +// WithCancel returns a copy of parent with a new Done channel. The returned +// context's Done channel is closed when the returned cancel function is called +// or when the parent context's Done channel is closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { + c := newCancelCtx(parent) + propagateCancel(parent, c) + return c, func() { c.cancel(true, Canceled) } +} + +// newCancelCtx returns an initialized cancelCtx. +func newCancelCtx(parent Context) *cancelCtx { + return &cancelCtx{ + Context: parent, + done: make(chan struct{}), + } +} + +// propagateCancel arranges for child to be canceled when parent is. +func propagateCancel(parent Context, child canceler) { + if parent.Done() == nil { + return // parent is never canceled + } + if p, ok := parentCancelCtx(parent); ok { + p.mu.Lock() + if p.err != nil { + // parent has already been canceled + child.cancel(false, p.err) + } else { + if p.children == nil { + p.children = make(map[canceler]bool) + } + p.children[child] = true + } + p.mu.Unlock() + } else { + go func() { + select { + case <-parent.Done(): + child.cancel(false, parent.Err()) + case <-child.Done(): + } + }() + } +} + +// parentCancelCtx follows a chain of parent references until it finds a +// *cancelCtx. This function understands how each of the concrete types in this +// package represents its parent. +func parentCancelCtx(parent Context) (*cancelCtx, bool) { + for { + switch c := parent.(type) { + case *cancelCtx: + return c, true + case *timerCtx: + return c.cancelCtx, true + case *valueCtx: + parent = c.Context + default: + return nil, false + } + } +} + +// removeChild removes a context from its parent. +func removeChild(parent Context, child canceler) { + p, ok := parentCancelCtx(parent) + if !ok { + return + } + p.mu.Lock() + if p.children != nil { + delete(p.children, child) + } + p.mu.Unlock() +} + +// A canceler is a context type that can be canceled directly. The +// implementations are *cancelCtx and *timerCtx. +type canceler interface { + cancel(removeFromParent bool, err error) + Done() <-chan struct{} +} + +// A cancelCtx can be canceled. When canceled, it also cancels any children +// that implement canceler. +type cancelCtx struct { + Context + + done chan struct{} // closed by the first cancel call. + + mu sync.Mutex + children map[canceler]bool // set to nil by the first cancel call + err error // set to non-nil by the first cancel call +} + +func (c *cancelCtx) Done() <-chan struct{} { + return c.done +} + +func (c *cancelCtx) Err() error { + c.mu.Lock() + defer c.mu.Unlock() + return c.err +} + +func (c *cancelCtx) String() string { + return fmt.Sprintf("%v.WithCancel", c.Context) +} + +// cancel closes c.done, cancels each of c's children, and, if +// removeFromParent is true, removes c from its parent's children. +func (c *cancelCtx) cancel(removeFromParent bool, err error) { + if err == nil { + panic("context: internal error: missing cancel error") + } + c.mu.Lock() + if c.err != nil { + c.mu.Unlock() + return // already canceled + } + c.err = err + close(c.done) + for child := range c.children { + // NOTE: acquiring the child's lock while holding parent's lock. + child.cancel(false, err) + } + c.children = nil + c.mu.Unlock() + + if removeFromParent { + removeChild(c.Context, c) + } +} + +// WithDeadline returns a copy of the parent context with the deadline adjusted +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// context's Done channel is closed when the deadline expires, when the returned +// cancel function is called, or when the parent context's Done channel is +// closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { + if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { + // The current deadline is already sooner than the new one. + return WithCancel(parent) + } + c := &timerCtx{ + cancelCtx: newCancelCtx(parent), + deadline: deadline, + } + propagateCancel(parent, c) + d := deadline.Sub(time.Now()) + if d <= 0 { + c.cancel(true, DeadlineExceeded) // deadline has already passed + return c, func() { c.cancel(true, Canceled) } + } + c.mu.Lock() + defer c.mu.Unlock() + if c.err == nil { + c.timer = time.AfterFunc(d, func() { + c.cancel(true, DeadlineExceeded) + }) + } + return c, func() { c.cancel(true, Canceled) } +} + +// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to +// implement Done and Err. It implements cancel by stopping its timer then +// delegating to cancelCtx.cancel. +type timerCtx struct { + *cancelCtx + timer *time.Timer // Under cancelCtx.mu. + + deadline time.Time +} + +func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { + return c.deadline, true +} + +func (c *timerCtx) String() string { + return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) +} + +func (c *timerCtx) cancel(removeFromParent bool, err error) { + c.cancelCtx.cancel(false, err) + if removeFromParent { + // Remove this timerCtx from its parent cancelCtx's children. + removeChild(c.cancelCtx.Context, c) + } + c.mu.Lock() + if c.timer != nil { + c.timer.Stop() + c.timer = nil + } + c.mu.Unlock() +} + +// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete: +// +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } +func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { + return WithDeadline(parent, time.Now().Add(timeout)) +} + +// WithValue returns a copy of parent in which the value associated with key is +// val. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +func WithValue(parent Context, key interface{}, val interface{}) Context { + return &valueCtx{parent, key, val} +} + +// A valueCtx carries a key-value pair. It implements Value for that key and +// delegates all other calls to the embedded Context. +type valueCtx struct { + Context + key, val interface{} +} + +func (c *valueCtx) String() string { + return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) +} + +func (c *valueCtx) Value(key interface{}) interface{} { + if c.key == key { + return c.val + } + return c.Context.Value(key) +} diff --git a/vendor/golang.org/x/net/context/pre_go19.go b/vendor/golang.org/x/net/context/pre_go19.go new file mode 100644 index 00000000..b105f80b --- /dev/null +++ b/vendor/golang.org/x/net/context/pre_go19.go @@ -0,0 +1,109 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.9 + +package context + +import "time" + +// A Context carries a deadline, a cancelation signal, and other values across +// API boundaries. +// +// Context's methods may be called by multiple goroutines simultaneously. +type Context interface { + // Deadline returns the time when work done on behalf of this context + // should be canceled. Deadline returns ok==false when no deadline is + // set. Successive calls to Deadline return the same results. + Deadline() (deadline time.Time, ok bool) + + // Done returns a channel that's closed when work done on behalf of this + // context should be canceled. Done may return nil if this context can + // never be canceled. Successive calls to Done return the same value. + // + // WithCancel arranges for Done to be closed when cancel is called; + // WithDeadline arranges for Done to be closed when the deadline + // expires; WithTimeout arranges for Done to be closed when the timeout + // elapses. + // + // Done is provided for use in select statements: + // + // // Stream generates values with DoSomething and sends them to out + // // until DoSomething returns an error or ctx.Done is closed. + // func Stream(ctx context.Context, out chan<- Value) error { + // for { + // v, err := DoSomething(ctx) + // if err != nil { + // return err + // } + // select { + // case <-ctx.Done(): + // return ctx.Err() + // case out <- v: + // } + // } + // } + // + // See http://blog.golang.org/pipelines for more examples of how to use + // a Done channel for cancelation. + Done() <-chan struct{} + + // Err returns a non-nil error value after Done is closed. Err returns + // Canceled if the context was canceled or DeadlineExceeded if the + // context's deadline passed. No other values for Err are defined. + // After Done is closed, successive calls to Err return the same value. + Err() error + + // Value returns the value associated with this context for key, or nil + // if no value is associated with key. Successive calls to Value with + // the same key returns the same result. + // + // Use context values only for request-scoped data that transits + // processes and API boundaries, not for passing optional parameters to + // functions. + // + // A key identifies a specific value in a Context. Functions that wish + // to store values in Context typically allocate a key in a global + // variable then use that key as the argument to context.WithValue and + // Context.Value. A key can be any type that supports equality; + // packages should define keys as an unexported type to avoid + // collisions. + // + // Packages that define a Context key should provide type-safe accessors + // for the values stores using that key: + // + // // Package user defines a User type that's stored in Contexts. + // package user + // + // import "golang.org/x/net/context" + // + // // User is the type of value stored in the Contexts. + // type User struct {...} + // + // // key is an unexported type for keys defined in this package. + // // This prevents collisions with keys defined in other packages. + // type key int + // + // // userKey is the key for user.User values in Contexts. It is + // // unexported; clients use user.NewContext and user.FromContext + // // instead of using this key directly. + // var userKey key = 0 + // + // // NewContext returns a new Context that carries value u. + // func NewContext(ctx context.Context, u *User) context.Context { + // return context.WithValue(ctx, userKey, u) + // } + // + // // FromContext returns the User value stored in ctx, if any. + // func FromContext(ctx context.Context) (*User, bool) { + // u, ok := ctx.Value(userKey).(*User) + // return u, ok + // } + Value(key interface{}) interface{} +} + +// A CancelFunc tells an operation to abandon its work. +// A CancelFunc does not wait for the work to stop. +// After the first call, subsequent calls to a CancelFunc do nothing. +type CancelFunc func() diff --git a/vendor/golang.org/x/oauth2/.travis.yml b/vendor/golang.org/x/oauth2/.travis.yml new file mode 100644 index 00000000..fa139db2 --- /dev/null +++ b/vendor/golang.org/x/oauth2/.travis.yml @@ -0,0 +1,13 @@ +language: go + +go: + - tip + +install: + - export GOPATH="$HOME/gopath" + - mkdir -p "$GOPATH/src/golang.org/x" + - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2" + - go get -v -t -d golang.org/x/oauth2/... + +script: + - go test -v golang.org/x/oauth2/... diff --git a/vendor/golang.org/x/oauth2/AUTHORS b/vendor/golang.org/x/oauth2/AUTHORS new file mode 100644 index 00000000..15167cd7 --- /dev/null +++ b/vendor/golang.org/x/oauth2/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md new file mode 100644 index 00000000..dfbed62c --- /dev/null +++ b/vendor/golang.org/x/oauth2/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +## Filing issues + +When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. +The gophers there will answer or ask you to file an issue if you've tripped over a bug. + +## Contributing code + +Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) +before sending patches. + +Unless otherwise noted, the Go source files are distributed under +the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTORS b/vendor/golang.org/x/oauth2/CONTRIBUTORS new file mode 100644 index 00000000..1c4577e9 --- /dev/null +++ b/vendor/golang.org/x/oauth2/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE new file mode 100644 index 00000000..6a66aea5 --- /dev/null +++ b/vendor/golang.org/x/oauth2/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md new file mode 100644 index 00000000..eb8dcee1 --- /dev/null +++ b/vendor/golang.org/x/oauth2/README.md @@ -0,0 +1,77 @@ +# OAuth2 for Go + +[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2) +[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2) + +oauth2 package contains a client implementation for OAuth 2.0 spec. + +## Installation + +~~~~ +go get golang.org/x/oauth2 +~~~~ + +Or you can manually git clone the repository to +`$(go env GOPATH)/src/golang.org/x/oauth2`. + +See godoc for further documentation and examples. + +* [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2) +* [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google) + + +## App Engine + +In change 96e89be (March 2015), we removed the `oauth2.Context2` type in favor +of the [`context.Context`](https://golang.org/x/net/context#Context) type from +the `golang.org/x/net/context` package + +This means it's no longer possible to use the "Classic App Engine" +`appengine.Context` type with the `oauth2` package. (You're using +Classic App Engine if you import the package `"appengine"`.) + +To work around this, you may use the new `"google.golang.org/appengine"` +package. This package has almost the same API as the `"appengine"` package, +but it can be fetched with `go get` and used on "Managed VMs" and well as +Classic App Engine. + +See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app) +for information on updating your app. + +If you don't want to update your entire app to use the new App Engine packages, +you may use both sets of packages in parallel, using only the new packages +with the `oauth2` package. + +```go +import ( + "golang.org/x/net/context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + newappengine "google.golang.org/appengine" + newurlfetch "google.golang.org/appengine/urlfetch" + + "appengine" +) + +func handler(w http.ResponseWriter, r *http.Request) { + var c appengine.Context = appengine.NewContext(r) + c.Infof("Logging a message with the old package") + + var ctx context.Context = newappengine.NewContext(r) + client := &http.Client{ + Transport: &oauth2.Transport{ + Source: google.AppEngineTokenSource(ctx, "scope"), + Base: &newurlfetch.Transport{Context: ctx}, + }, + } + client.Get("...") +} +``` + +## Report Issues / Send Patches + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://golang.org/doc/contribute.html. + +The main issue tracker for the oauth2 repository is located at +https://github.com/golang/oauth2/issues. diff --git a/vendor/golang.org/x/oauth2/google/appengine.go b/vendor/golang.org/x/oauth2/google/appengine.go new file mode 100644 index 00000000..50d918b8 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/appengine.go @@ -0,0 +1,89 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package google + +import ( + "sort" + "strings" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/oauth2" +) + +// appengineFlex is set at init time by appengineflex_hook.go. If true, we are on App Engine Flex. +var appengineFlex bool + +// Set at init time by appengine_hook.go. If nil, we're not on App Engine. +var appengineTokenFunc func(c context.Context, scopes ...string) (token string, expiry time.Time, err error) + +// Set at init time by appengine_hook.go. If nil, we're not on App Engine. +var appengineAppIDFunc func(c context.Context) string + +// AppEngineTokenSource returns a token source that fetches tokens +// issued to the current App Engine application's service account. +// If you are implementing a 3-legged OAuth 2.0 flow on App Engine +// that involves user accounts, see oauth2.Config instead. +// +// The provided context must have come from appengine.NewContext. +func AppEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource { + if appengineTokenFunc == nil { + panic("google: AppEngineTokenSource can only be used on App Engine.") + } + scopes := append([]string{}, scope...) + sort.Strings(scopes) + return &appEngineTokenSource{ + ctx: ctx, + scopes: scopes, + key: strings.Join(scopes, " "), + } +} + +// aeTokens helps the fetched tokens to be reused until their expiration. +var ( + aeTokensMu sync.Mutex + aeTokens = make(map[string]*tokenLock) // key is space-separated scopes +) + +type tokenLock struct { + mu sync.Mutex // guards t; held while fetching or updating t + t *oauth2.Token +} + +type appEngineTokenSource struct { + ctx context.Context + scopes []string + key string // to aeTokens map; space-separated scopes +} + +func (ts *appEngineTokenSource) Token() (*oauth2.Token, error) { + if appengineTokenFunc == nil { + panic("google: AppEngineTokenSource can only be used on App Engine.") + } + + aeTokensMu.Lock() + tok, ok := aeTokens[ts.key] + if !ok { + tok = &tokenLock{} + aeTokens[ts.key] = tok + } + aeTokensMu.Unlock() + + tok.mu.Lock() + defer tok.mu.Unlock() + if tok.t.Valid() { + return tok.t, nil + } + access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...) + if err != nil { + return nil, err + } + tok.t = &oauth2.Token{ + AccessToken: access, + Expiry: exp, + } + return tok.t, nil +} diff --git a/vendor/golang.org/x/oauth2/google/appengine_hook.go b/vendor/golang.org/x/oauth2/google/appengine_hook.go new file mode 100644 index 00000000..56669eaa --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/appengine_hook.go @@ -0,0 +1,14 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build appengine appenginevm + +package google + +import "google.golang.org/appengine" + +func init() { + appengineTokenFunc = appengine.AccessToken + appengineAppIDFunc = appengine.AppID +} diff --git a/vendor/golang.org/x/oauth2/google/appengineflex_hook.go b/vendor/golang.org/x/oauth2/google/appengineflex_hook.go new file mode 100644 index 00000000..5d0231af --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/appengineflex_hook.go @@ -0,0 +1,11 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build appenginevm + +package google + +func init() { + appengineFlex = true // Flex doesn't support appengine.AccessToken; depend on metadata server. +} diff --git a/vendor/golang.org/x/oauth2/google/default.go b/vendor/golang.org/x/oauth2/google/default.go new file mode 100644 index 00000000..a3160743 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/default.go @@ -0,0 +1,115 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package google + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "runtime" + + "cloud.google.com/go/compute/metadata" + "golang.org/x/net/context" + "golang.org/x/oauth2" +) + +// DefaultClient returns an HTTP Client that uses the +// DefaultTokenSource to obtain authentication credentials. +func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) { + ts, err := DefaultTokenSource(ctx, scope...) + if err != nil { + return nil, err + } + return oauth2.NewClient(ctx, ts), nil +} + +// DefaultTokenSource returns the token source for +// "Application Default Credentials". +// It is a shortcut for FindDefaultCredentials(ctx, scope).TokenSource. +func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) { + creds, err := FindDefaultCredentials(ctx, scope...) + if err != nil { + return nil, err + } + return creds.TokenSource, nil +} + +// Common implementation for FindDefaultCredentials. +func findDefaultCredentials(ctx context.Context, scopes []string) (*DefaultCredentials, error) { + // First, try the environment variable. + const envVar = "GOOGLE_APPLICATION_CREDENTIALS" + if filename := os.Getenv(envVar); filename != "" { + creds, err := readCredentialsFile(ctx, filename, scopes) + if err != nil { + return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err) + } + return creds, nil + } + + // Second, try a well-known file. + filename := wellKnownFile() + if creds, err := readCredentialsFile(ctx, filename, scopes); err == nil { + return creds, nil + } else if !os.IsNotExist(err) { + return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err) + } + + // Third, if we're on Google App Engine use those credentials. + if appengineTokenFunc != nil && !appengineFlex { + return &DefaultCredentials{ + ProjectID: appengineAppIDFunc(ctx), + TokenSource: AppEngineTokenSource(ctx, scopes...), + }, nil + } + + // Fourth, if we're on Google Compute Engine use the metadata server. + if metadata.OnGCE() { + id, _ := metadata.ProjectID() + return &DefaultCredentials{ + ProjectID: id, + TokenSource: ComputeTokenSource(""), + }, nil + } + + // None are found; return helpful error. + const url = "https://developers.google.com/accounts/docs/application-default-credentials" + return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url) +} + +// Common implementation for CredentialsFromJSON. +func credentialsFromJSON(ctx context.Context, jsonData []byte, scopes []string) (*DefaultCredentials, error) { + var f credentialsFile + if err := json.Unmarshal(jsonData, &f); err != nil { + return nil, err + } + ts, err := f.tokenSource(ctx, append([]string(nil), scopes...)) + if err != nil { + return nil, err + } + return &DefaultCredentials{ + ProjectID: f.ProjectID, + TokenSource: ts, + JSON: jsonData, + }, nil +} + +func wellKnownFile() string { + const f = "application_default_credentials.json" + if runtime.GOOS == "windows" { + return filepath.Join(os.Getenv("APPDATA"), "gcloud", f) + } + return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f) +} + +func readCredentialsFile(ctx context.Context, filename string, scopes []string) (*DefaultCredentials, error) { + b, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + return CredentialsFromJSON(ctx, b, scopes...) +} diff --git a/vendor/golang.org/x/oauth2/google/doc_go19.go b/vendor/golang.org/x/oauth2/google/doc_go19.go new file mode 100644 index 00000000..2a86325f --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/doc_go19.go @@ -0,0 +1,42 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +// Package google provides support for making OAuth2 authorized and authenticated +// HTTP requests to Google APIs. It supports the Web server flow, client-side +// credentials, service accounts, Google Compute Engine service accounts, and Google +// App Engine service accounts. +// +// A brief overview of the package follows. For more information, please read +// https://developers.google.com/accounts/docs/OAuth2 +// and +// https://developers.google.com/accounts/docs/application-default-credentials. +// +// OAuth2 Configs +// +// Two functions in this package return golang.org/x/oauth2.Config values from Google credential +// data. Google supports two JSON formats for OAuth2 credentials: one is handled by ConfigFromJSON, +// the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or +// create an http.Client. +// +// +// Credentials +// +// The Credentials type represents Google credentials, including Application Default +// Credentials. +// +// Use FindDefaultCredentials to obtain Application Default Credentials. +// FindDefaultCredentials looks in some well-known places for a credentials file, and +// will call AppEngineTokenSource or ComputeTokenSource as needed. +// +// DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials, +// then use the credentials to construct an http.Client or an oauth2.TokenSource. +// +// Use CredentialsFromJSON to obtain credentials from either of the two JSON formats +// described in OAuth2 Configs, above. The TokenSource in the returned value is the +// same as the one obtained from the oauth2.Config returned from ConfigFromJSON or +// JWTConfigFromJSON, but the Credentials may contain additional information +// that is useful is some circumstances. +package google // import "golang.org/x/oauth2/google" diff --git a/vendor/golang.org/x/oauth2/google/doc_not_go19.go b/vendor/golang.org/x/oauth2/google/doc_not_go19.go new file mode 100644 index 00000000..5c3c6e14 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/doc_not_go19.go @@ -0,0 +1,43 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.9 + +// Package google provides support for making OAuth2 authorized and authenticated +// HTTP requests to Google APIs. It supports the Web server flow, client-side +// credentials, service accounts, Google Compute Engine service accounts, and Google +// App Engine service accounts. +// +// A brief overview of the package follows. For more information, please read +// https://developers.google.com/accounts/docs/OAuth2 +// and +// https://developers.google.com/accounts/docs/application-default-credentials. +// +// OAuth2 Configs +// +// Two functions in this package return golang.org/x/oauth2.Config values from Google credential +// data. Google supports two JSON formats for OAuth2 credentials: one is handled by ConfigFromJSON, +// the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or +// create an http.Client. +// +// +// Credentials +// +// The DefaultCredentials type represents Google Application Default Credentials, as +// well as other forms of credential. +// +// Use FindDefaultCredentials to obtain Application Default Credentials. +// FindDefaultCredentials looks in some well-known places for a credentials file, and +// will call AppEngineTokenSource or ComputeTokenSource as needed. +// +// DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials, +// then use the credentials to construct an http.Client or an oauth2.TokenSource. +// +// Use CredentialsFromJSON to obtain credentials from either of the two JSON +// formats described in OAuth2 Configs, above. (The DefaultCredentials returned may +// not be "Application Default Credentials".) The TokenSource in the returned value +// is the same as the one obtained from the oauth2.Config returned from +// ConfigFromJSON or JWTConfigFromJSON, but the DefaultCredentials may contain +// additional information that is useful is some circumstances. +package google // import "golang.org/x/oauth2/google" diff --git a/vendor/golang.org/x/oauth2/google/go19.go b/vendor/golang.org/x/oauth2/google/go19.go new file mode 100644 index 00000000..4d0318b1 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/go19.go @@ -0,0 +1,57 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +package google + +import ( + "golang.org/x/net/context" + "golang.org/x/oauth2" +) + +// Credentials holds Google credentials, including "Application Default Credentials". +// For more details, see: +// https://developers.google.com/accounts/docs/application-default-credentials +type Credentials struct { + ProjectID string // may be empty + TokenSource oauth2.TokenSource + + // JSON contains the raw bytes from a JSON credentials file. + // This field may be nil if authentication is provided by the + // environment and not with a credentials file, e.g. when code is + // running on Google Cloud Platform. + JSON []byte +} + +// DefaultCredentials is the old name of Credentials. +// +// Deprecated: use Credentials instead. +type DefaultCredentials = Credentials + +// FindDefaultCredentials searches for "Application Default Credentials". +// +// It looks for credentials in the following places, +// preferring the first location found: +// +// 1. A JSON file whose path is specified by the +// GOOGLE_APPLICATION_CREDENTIALS environment variable. +// 2. A JSON file in a location known to the gcloud command-line tool. +// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. +// On other systems, $HOME/.config/gcloud/application_default_credentials.json. +// 3. On Google App Engine it uses the appengine.AccessToken function. +// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches +// credentials from the metadata server. +// (In this final case any provided scopes are ignored.) +func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials, error) { + return findDefaultCredentials(ctx, scopes) +} + +// CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can +// represent either a Google Developers Console client_credentials.json file (as in +// ConfigFromJSON) or a Google Developers service account key file (as in +// JWTConfigFromJSON). +func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*Credentials, error) { + return credentialsFromJSON(ctx, jsonData, scopes) +} diff --git a/vendor/golang.org/x/oauth2/google/google.go b/vendor/golang.org/x/oauth2/google/google.go new file mode 100644 index 00000000..f7481fbc --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/google.go @@ -0,0 +1,192 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package google + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "cloud.google.com/go/compute/metadata" + "golang.org/x/net/context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/jwt" +) + +// Endpoint is Google's OAuth 2.0 endpoint. +var Endpoint = oauth2.Endpoint{ + AuthURL: "https://accounts.google.com/o/oauth2/auth", + TokenURL: "https://accounts.google.com/o/oauth2/token", +} + +// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow. +const JWTTokenURL = "https://accounts.google.com/o/oauth2/token" + +// ConfigFromJSON uses a Google Developers Console client_credentials.json +// file to construct a config. +// client_credentials.json can be downloaded from +// https://console.developers.google.com, under "Credentials". Download the Web +// application credentials in the JSON format and provide the contents of the +// file as jsonKey. +func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) { + type cred struct { + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` + RedirectURIs []string `json:"redirect_uris"` + AuthURI string `json:"auth_uri"` + TokenURI string `json:"token_uri"` + } + var j struct { + Web *cred `json:"web"` + Installed *cred `json:"installed"` + } + if err := json.Unmarshal(jsonKey, &j); err != nil { + return nil, err + } + var c *cred + switch { + case j.Web != nil: + c = j.Web + case j.Installed != nil: + c = j.Installed + default: + return nil, fmt.Errorf("oauth2/google: no credentials found") + } + if len(c.RedirectURIs) < 1 { + return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json") + } + return &oauth2.Config{ + ClientID: c.ClientID, + ClientSecret: c.ClientSecret, + RedirectURL: c.RedirectURIs[0], + Scopes: scope, + Endpoint: oauth2.Endpoint{ + AuthURL: c.AuthURI, + TokenURL: c.TokenURI, + }, + }, nil +} + +// JWTConfigFromJSON uses a Google Developers service account JSON key file to read +// the credentials that authorize and authenticate the requests. +// Create a service account on "Credentials" for your project at +// https://console.developers.google.com to download a JSON key file. +func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) { + var f credentialsFile + if err := json.Unmarshal(jsonKey, &f); err != nil { + return nil, err + } + if f.Type != serviceAccountKey { + return nil, fmt.Errorf("google: read JWT from JSON credentials: 'type' field is %q (expected %q)", f.Type, serviceAccountKey) + } + scope = append([]string(nil), scope...) // copy + return f.jwtConfig(scope), nil +} + +// JSON key file types. +const ( + serviceAccountKey = "service_account" + userCredentialsKey = "authorized_user" +) + +// credentialsFile is the unmarshalled representation of a credentials file. +type credentialsFile struct { + Type string `json:"type"` // serviceAccountKey or userCredentialsKey + + // Service Account fields + ClientEmail string `json:"client_email"` + PrivateKeyID string `json:"private_key_id"` + PrivateKey string `json:"private_key"` + TokenURL string `json:"token_uri"` + ProjectID string `json:"project_id"` + + // User Credential fields + // (These typically come from gcloud auth.) + ClientSecret string `json:"client_secret"` + ClientID string `json:"client_id"` + RefreshToken string `json:"refresh_token"` +} + +func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config { + cfg := &jwt.Config{ + Email: f.ClientEmail, + PrivateKey: []byte(f.PrivateKey), + PrivateKeyID: f.PrivateKeyID, + Scopes: scopes, + TokenURL: f.TokenURL, + } + if cfg.TokenURL == "" { + cfg.TokenURL = JWTTokenURL + } + return cfg +} + +func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oauth2.TokenSource, error) { + switch f.Type { + case serviceAccountKey: + cfg := f.jwtConfig(scopes) + return cfg.TokenSource(ctx), nil + case userCredentialsKey: + cfg := &oauth2.Config{ + ClientID: f.ClientID, + ClientSecret: f.ClientSecret, + Scopes: scopes, + Endpoint: Endpoint, + } + tok := &oauth2.Token{RefreshToken: f.RefreshToken} + return cfg.TokenSource(ctx, tok), nil + case "": + return nil, errors.New("missing 'type' field in credentials") + default: + return nil, fmt.Errorf("unknown credential type: %q", f.Type) + } +} + +// ComputeTokenSource returns a token source that fetches access tokens +// from Google Compute Engine (GCE)'s metadata server. It's only valid to use +// this token source if your program is running on a GCE instance. +// If no account is specified, "default" is used. +// Further information about retrieving access tokens from the GCE metadata +// server can be found at https://cloud.google.com/compute/docs/authentication. +func ComputeTokenSource(account string) oauth2.TokenSource { + return oauth2.ReuseTokenSource(nil, computeSource{account: account}) +} + +type computeSource struct { + account string +} + +func (cs computeSource) Token() (*oauth2.Token, error) { + if !metadata.OnGCE() { + return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE") + } + acct := cs.account + if acct == "" { + acct = "default" + } + tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token") + if err != nil { + return nil, err + } + var res struct { + AccessToken string `json:"access_token"` + ExpiresInSec int `json:"expires_in"` + TokenType string `json:"token_type"` + } + err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res) + if err != nil { + return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err) + } + if res.ExpiresInSec == 0 || res.AccessToken == "" { + return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata") + } + return &oauth2.Token{ + AccessToken: res.AccessToken, + TokenType: res.TokenType, + Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second), + }, nil +} diff --git a/vendor/golang.org/x/oauth2/google/jwt.go b/vendor/golang.org/x/oauth2/google/jwt.go new file mode 100644 index 00000000..b0fdb3a8 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/jwt.go @@ -0,0 +1,74 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package google + +import ( + "crypto/rsa" + "fmt" + "time" + + "golang.org/x/oauth2" + "golang.org/x/oauth2/internal" + "golang.org/x/oauth2/jws" +) + +// JWTAccessTokenSourceFromJSON uses a Google Developers service account JSON +// key file to read the credentials that authorize and authenticate the +// requests, and returns a TokenSource that does not use any OAuth2 flow but +// instead creates a JWT and sends that as the access token. +// The audience is typically a URL that specifies the scope of the credentials. +// +// Note that this is not a standard OAuth flow, but rather an +// optimization supported by a few Google services. +// Unless you know otherwise, you should use JWTConfigFromJSON instead. +func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.TokenSource, error) { + cfg, err := JWTConfigFromJSON(jsonKey) + if err != nil { + return nil, fmt.Errorf("google: could not parse JSON key: %v", err) + } + pk, err := internal.ParseKey(cfg.PrivateKey) + if err != nil { + return nil, fmt.Errorf("google: could not parse key: %v", err) + } + ts := &jwtAccessTokenSource{ + email: cfg.Email, + audience: audience, + pk: pk, + pkID: cfg.PrivateKeyID, + } + tok, err := ts.Token() + if err != nil { + return nil, err + } + return oauth2.ReuseTokenSource(tok, ts), nil +} + +type jwtAccessTokenSource struct { + email, audience string + pk *rsa.PrivateKey + pkID string +} + +func (ts *jwtAccessTokenSource) Token() (*oauth2.Token, error) { + iat := time.Now() + exp := iat.Add(time.Hour) + cs := &jws.ClaimSet{ + Iss: ts.email, + Sub: ts.email, + Aud: ts.audience, + Iat: iat.Unix(), + Exp: exp.Unix(), + } + hdr := &jws.Header{ + Algorithm: "RS256", + Typ: "JWT", + KeyID: string(ts.pkID), + } + msg, err := jws.Encode(hdr, cs, ts.pk) + if err != nil { + return nil, fmt.Errorf("google: could not encode JWT: %v", err) + } + return &oauth2.Token{AccessToken: msg, TokenType: "Bearer", Expiry: exp}, nil +} diff --git a/vendor/golang.org/x/oauth2/google/not_go19.go b/vendor/golang.org/x/oauth2/google/not_go19.go new file mode 100644 index 00000000..544e4062 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/not_go19.go @@ -0,0 +1,54 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.9 + +package google + +import ( + "golang.org/x/net/context" + "golang.org/x/oauth2" +) + +// DefaultCredentials holds Google credentials, including "Application Default Credentials". +// For more details, see: +// https://developers.google.com/accounts/docs/application-default-credentials +type DefaultCredentials struct { + ProjectID string // may be empty + TokenSource oauth2.TokenSource + + // JSON contains the raw bytes from a JSON credentials file. + // This field may be nil if authentication is provided by the + // environment and not with a credentials file, e.g. when code is + // running on Google Cloud Platform. + JSON []byte +} + +// FindDefaultCredentials searches for "Application Default Credentials". +// +// It looks for credentials in the following places, +// preferring the first location found: +// +// 1. A JSON file whose path is specified by the +// GOOGLE_APPLICATION_CREDENTIALS environment variable. +// 2. A JSON file in a location known to the gcloud command-line tool. +// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. +// On other systems, $HOME/.config/gcloud/application_default_credentials.json. +// 3. On Google App Engine it uses the appengine.AccessToken function. +// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches +// credentials from the metadata server. +// (In this final case any provided scopes are ignored.) +func FindDefaultCredentials(ctx context.Context, scopes ...string) (*DefaultCredentials, error) { + return findDefaultCredentials(ctx, scopes) +} + +// CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can +// represent either a Google Developers Console client_credentials.json file (as in +// ConfigFromJSON) or a Google Developers service account key file (as in +// JWTConfigFromJSON). +// +// Note: despite the name, the returned credentials may not be Application Default Credentials. +func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*DefaultCredentials, error) { + return credentialsFromJSON(ctx, jsonData, scopes) +} diff --git a/vendor/golang.org/x/oauth2/google/sdk.go b/vendor/golang.org/x/oauth2/google/sdk.go new file mode 100644 index 00000000..b9660cad --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/sdk.go @@ -0,0 +1,201 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package google + +import ( + "bufio" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "os" + "os/user" + "path/filepath" + "runtime" + "strings" + "time" + + "golang.org/x/net/context" + "golang.org/x/oauth2" +) + +type sdkCredentials struct { + Data []struct { + Credential struct { + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + TokenExpiry *time.Time `json:"token_expiry"` + } `json:"credential"` + Key struct { + Account string `json:"account"` + Scope string `json:"scope"` + } `json:"key"` + } +} + +// An SDKConfig provides access to tokens from an account already +// authorized via the Google Cloud SDK. +type SDKConfig struct { + conf oauth2.Config + initialToken *oauth2.Token +} + +// NewSDKConfig creates an SDKConfig for the given Google Cloud SDK +// account. If account is empty, the account currently active in +// Google Cloud SDK properties is used. +// Google Cloud SDK credentials must be created by running `gcloud auth` +// before using this function. +// The Google Cloud SDK is available at https://cloud.google.com/sdk/. +func NewSDKConfig(account string) (*SDKConfig, error) { + configPath, err := sdkConfigPath() + if err != nil { + return nil, fmt.Errorf("oauth2/google: error getting SDK config path: %v", err) + } + credentialsPath := filepath.Join(configPath, "credentials") + f, err := os.Open(credentialsPath) + if err != nil { + return nil, fmt.Errorf("oauth2/google: failed to load SDK credentials: %v", err) + } + defer f.Close() + + var c sdkCredentials + if err := json.NewDecoder(f).Decode(&c); err != nil { + return nil, fmt.Errorf("oauth2/google: failed to decode SDK credentials from %q: %v", credentialsPath, err) + } + if len(c.Data) == 0 { + return nil, fmt.Errorf("oauth2/google: no credentials found in %q, run `gcloud auth login` to create one", credentialsPath) + } + if account == "" { + propertiesPath := filepath.Join(configPath, "properties") + f, err := os.Open(propertiesPath) + if err != nil { + return nil, fmt.Errorf("oauth2/google: failed to load SDK properties: %v", err) + } + defer f.Close() + ini, err := parseINI(f) + if err != nil { + return nil, fmt.Errorf("oauth2/google: failed to parse SDK properties %q: %v", propertiesPath, err) + } + core, ok := ini["core"] + if !ok { + return nil, fmt.Errorf("oauth2/google: failed to find [core] section in %v", ini) + } + active, ok := core["account"] + if !ok { + return nil, fmt.Errorf("oauth2/google: failed to find %q attribute in %v", "account", core) + } + account = active + } + + for _, d := range c.Data { + if account == "" || d.Key.Account == account { + if d.Credential.AccessToken == "" && d.Credential.RefreshToken == "" { + return nil, fmt.Errorf("oauth2/google: no token available for account %q", account) + } + var expiry time.Time + if d.Credential.TokenExpiry != nil { + expiry = *d.Credential.TokenExpiry + } + return &SDKConfig{ + conf: oauth2.Config{ + ClientID: d.Credential.ClientID, + ClientSecret: d.Credential.ClientSecret, + Scopes: strings.Split(d.Key.Scope, " "), + Endpoint: Endpoint, + RedirectURL: "oob", + }, + initialToken: &oauth2.Token{ + AccessToken: d.Credential.AccessToken, + RefreshToken: d.Credential.RefreshToken, + Expiry: expiry, + }, + }, nil + } + } + return nil, fmt.Errorf("oauth2/google: no such credentials for account %q", account) +} + +// Client returns an HTTP client using Google Cloud SDK credentials to +// authorize requests. The token will auto-refresh as necessary. The +// underlying http.RoundTripper will be obtained using the provided +// context. The returned client and its Transport should not be +// modified. +func (c *SDKConfig) Client(ctx context.Context) *http.Client { + return &http.Client{ + Transport: &oauth2.Transport{ + Source: c.TokenSource(ctx), + }, + } +} + +// TokenSource returns an oauth2.TokenSource that retrieve tokens from +// Google Cloud SDK credentials using the provided context. +// It will returns the current access token stored in the credentials, +// and refresh it when it expires, but it won't update the credentials +// with the new access token. +func (c *SDKConfig) TokenSource(ctx context.Context) oauth2.TokenSource { + return c.conf.TokenSource(ctx, c.initialToken) +} + +// Scopes are the OAuth 2.0 scopes the current account is authorized for. +func (c *SDKConfig) Scopes() []string { + return c.conf.Scopes +} + +func parseINI(ini io.Reader) (map[string]map[string]string, error) { + result := map[string]map[string]string{ + "": {}, // root section + } + scanner := bufio.NewScanner(ini) + currentSection := "" + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(line, ";") { + // comment. + continue + } + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + currentSection = strings.TrimSpace(line[1 : len(line)-1]) + result[currentSection] = map[string]string{} + continue + } + parts := strings.SplitN(line, "=", 2) + if len(parts) == 2 && parts[0] != "" { + result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) + } + } + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error scanning ini: %v", err) + } + return result, nil +} + +// sdkConfigPath tries to guess where the gcloud config is located. +// It can be overridden during tests. +var sdkConfigPath = func() (string, error) { + if runtime.GOOS == "windows" { + return filepath.Join(os.Getenv("APPDATA"), "gcloud"), nil + } + homeDir := guessUnixHomeDir() + if homeDir == "" { + return "", errors.New("unable to get current user home directory: os/user lookup failed; $HOME is empty") + } + return filepath.Join(homeDir, ".config", "gcloud"), nil +} + +func guessUnixHomeDir() string { + // Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470 + if v := os.Getenv("HOME"); v != "" { + return v + } + // Else, fall back to user.Current: + if u, err := user.Current(); err == nil { + return u.HomeDir + } + return "" +} diff --git a/vendor/golang.org/x/oauth2/internal/client_appengine.go b/vendor/golang.org/x/oauth2/internal/client_appengine.go new file mode 100644 index 00000000..74348718 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/client_appengine.go @@ -0,0 +1,13 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build appengine + +package internal + +import "google.golang.org/appengine/urlfetch" + +func init() { + appengineClientHook = urlfetch.Client +} diff --git a/vendor/golang.org/x/oauth2/internal/doc.go b/vendor/golang.org/x/oauth2/internal/doc.go new file mode 100644 index 00000000..03265e88 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/doc.go @@ -0,0 +1,6 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package internal contains support packages for oauth2 package. +package internal diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go new file mode 100644 index 00000000..fc63fcab --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/oauth2.go @@ -0,0 +1,37 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" +) + +// ParseKey converts the binary contents of a private key file +// to an *rsa.PrivateKey. It detects whether the private key is in a +// PEM container or not. If so, it extracts the the private key +// from PEM container before conversion. It only supports PEM +// containers with no passphrase. +func ParseKey(key []byte) (*rsa.PrivateKey, error) { + block, _ := pem.Decode(key) + if block != nil { + key = block.Bytes + } + parsedKey, err := x509.ParsePKCS8PrivateKey(key) + if err != nil { + parsedKey, err = x509.ParsePKCS1PrivateKey(key) + if err != nil { + return nil, fmt.Errorf("private key should be a PEM or plain PKSC1 or PKCS8; parse error: %v", err) + } + } + parsed, ok := parsedKey.(*rsa.PrivateKey) + if !ok { + return nil, errors.New("private key is invalid") + } + return parsed, nil +} diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go new file mode 100644 index 00000000..3954c9b5 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/token.go @@ -0,0 +1,269 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "mime" + "net/http" + "net/url" + "strconv" + "strings" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/context/ctxhttp" +) + +// Token represents the credentials used to authorize +// the requests to access protected resources on the OAuth 2.0 +// provider's backend. +// +// This type is a mirror of oauth2.Token and exists to break +// an otherwise-circular dependency. Other internal packages +// should convert this Token into an oauth2.Token before use. +type Token struct { + // AccessToken is the token that authorizes and authenticates + // the requests. + AccessToken string + + // TokenType is the type of token. + // The Type method returns either this or "Bearer", the default. + TokenType string + + // RefreshToken is a token that's used by the application + // (as opposed to the user) to refresh the access token + // if it expires. + RefreshToken string + + // Expiry is the optional expiration time of the access token. + // + // If zero, TokenSource implementations will reuse the same + // token forever and RefreshToken or equivalent + // mechanisms for that TokenSource will not be used. + Expiry time.Time + + // Raw optionally contains extra metadata from the server + // when updating a token. + Raw interface{} +} + +// tokenJSON is the struct representing the HTTP response from OAuth2 +// providers returning a token in JSON form. +type tokenJSON struct { + AccessToken string `json:"access_token"` + TokenType string `json:"token_type"` + RefreshToken string `json:"refresh_token"` + ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number + Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in +} + +func (e *tokenJSON) expiry() (t time.Time) { + if v := e.ExpiresIn; v != 0 { + return time.Now().Add(time.Duration(v) * time.Second) + } + if v := e.Expires; v != 0 { + return time.Now().Add(time.Duration(v) * time.Second) + } + return +} + +type expirationTime int32 + +func (e *expirationTime) UnmarshalJSON(b []byte) error { + var n json.Number + err := json.Unmarshal(b, &n) + if err != nil { + return err + } + i, err := n.Int64() + if err != nil { + return err + } + *e = expirationTime(i) + return nil +} + +var brokenAuthHeaderProviders = []string{ + "https://accounts.google.com/", + "https://api.codeswholesale.com/oauth/token", + "https://api.dropbox.com/", + "https://api.dropboxapi.com/", + "https://api.instagram.com/", + "https://api.netatmo.net/", + "https://api.odnoklassniki.ru/", + "https://api.pushbullet.com/", + "https://api.soundcloud.com/", + "https://api.twitch.tv/", + "https://id.twitch.tv/", + "https://app.box.com/", + "https://connect.stripe.com/", + "https://login.mailchimp.com/", + "https://login.microsoftonline.com/", + "https://login.salesforce.com/", + "https://login.windows.net", + "https://login.live.com/", + "https://oauth.sandbox.trainingpeaks.com/", + "https://oauth.trainingpeaks.com/", + "https://oauth.vk.com/", + "https://openapi.baidu.com/", + "https://slack.com/", + "https://test-sandbox.auth.corp.google.com", + "https://test.salesforce.com/", + "https://user.gini.net/", + "https://www.douban.com/", + "https://www.googleapis.com/", + "https://www.linkedin.com/", + "https://www.strava.com/oauth/", + "https://www.wunderlist.com/oauth/", + "https://api.patreon.com/", + "https://sandbox.codeswholesale.com/oauth/token", + "https://api.sipgate.com/v1/authorization/oauth", + "https://api.medium.com/v1/tokens", + "https://log.finalsurge.com/oauth/token", + "https://multisport.todaysplan.com.au/rest/oauth/access_token", + "https://whats.todaysplan.com.au/rest/oauth/access_token", +} + +// brokenAuthHeaderDomains lists broken providers that issue dynamic endpoints. +var brokenAuthHeaderDomains = []string{ + ".auth0.com", + ".force.com", + ".myshopify.com", + ".okta.com", + ".oktapreview.com", +} + +func RegisterBrokenAuthHeaderProvider(tokenURL string) { + brokenAuthHeaderProviders = append(brokenAuthHeaderProviders, tokenURL) +} + +// providerAuthHeaderWorks reports whether the OAuth2 server identified by the tokenURL +// implements the OAuth2 spec correctly +// See https://code.google.com/p/goauth2/issues/detail?id=31 for background. +// In summary: +// - Reddit only accepts client secret in the Authorization header +// - Dropbox accepts either it in URL param or Auth header, but not both. +// - Google only accepts URL param (not spec compliant?), not Auth header +// - Stripe only accepts client secret in Auth header with Bearer method, not Basic +func providerAuthHeaderWorks(tokenURL string) bool { + for _, s := range brokenAuthHeaderProviders { + if strings.HasPrefix(tokenURL, s) { + // Some sites fail to implement the OAuth2 spec fully. + return false + } + } + + if u, err := url.Parse(tokenURL); err == nil { + for _, s := range brokenAuthHeaderDomains { + if strings.HasSuffix(u.Host, s) { + return false + } + } + } + + // Assume the provider implements the spec properly + // otherwise. We can add more exceptions as they're + // discovered. We will _not_ be adding configurable hooks + // to this package to let users select server bugs. + return true +} + +func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values) (*Token, error) { + bustedAuth := !providerAuthHeaderWorks(tokenURL) + if bustedAuth { + if clientID != "" { + v.Set("client_id", clientID) + } + if clientSecret != "" { + v.Set("client_secret", clientSecret) + } + } + req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode())) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + if !bustedAuth { + req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret)) + } + r, err := ctxhttp.Do(ctx, ContextClient(ctx), req) + if err != nil { + return nil, err + } + defer r.Body.Close() + body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20)) + if err != nil { + return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) + } + if code := r.StatusCode; code < 200 || code > 299 { + return nil, &RetrieveError{ + Response: r, + Body: body, + } + } + + var token *Token + content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) + switch content { + case "application/x-www-form-urlencoded", "text/plain": + vals, err := url.ParseQuery(string(body)) + if err != nil { + return nil, err + } + token = &Token{ + AccessToken: vals.Get("access_token"), + TokenType: vals.Get("token_type"), + RefreshToken: vals.Get("refresh_token"), + Raw: vals, + } + e := vals.Get("expires_in") + if e == "" { + // TODO(jbd): Facebook's OAuth2 implementation is broken and + // returns expires_in field in expires. Remove the fallback to expires, + // when Facebook fixes their implementation. + e = vals.Get("expires") + } + expires, _ := strconv.Atoi(e) + if expires != 0 { + token.Expiry = time.Now().Add(time.Duration(expires) * time.Second) + } + default: + var tj tokenJSON + if err = json.Unmarshal(body, &tj); err != nil { + return nil, err + } + token = &Token{ + AccessToken: tj.AccessToken, + TokenType: tj.TokenType, + RefreshToken: tj.RefreshToken, + Expiry: tj.expiry(), + Raw: make(map[string]interface{}), + } + json.Unmarshal(body, &token.Raw) // no error checks for optional fields + } + // Don't overwrite `RefreshToken` with an empty value + // if this was a token refreshing request. + if token.RefreshToken == "" { + token.RefreshToken = v.Get("refresh_token") + } + if token.AccessToken == "" { + return token, errors.New("oauth2: server response missing access_token") + } + return token, nil +} + +type RetrieveError struct { + Response *http.Response + Body []byte +} + +func (r *RetrieveError) Error() string { + return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) +} diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go new file mode 100644 index 00000000..d16f9ae1 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/transport.go @@ -0,0 +1,34 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "net/http" + + "golang.org/x/net/context" +) + +// HTTPClient is the context key to use with golang.org/x/net/context's +// WithValue function to associate an *http.Client value with a context. +var HTTPClient ContextKey + +// ContextKey is just an empty struct. It exists so HTTPClient can be +// an immutable public variable with a unique type. It's immutable +// because nobody else can create a ContextKey, being unexported. +type ContextKey struct{} + +var appengineClientHook func(context.Context) *http.Client + +func ContextClient(ctx context.Context) *http.Client { + if ctx != nil { + if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { + return hc + } + } + if appengineClientHook != nil { + return appengineClientHook(ctx) + } + return http.DefaultClient +} diff --git a/vendor/golang.org/x/oauth2/jws/jws.go b/vendor/golang.org/x/oauth2/jws/jws.go new file mode 100644 index 00000000..683d2d27 --- /dev/null +++ b/vendor/golang.org/x/oauth2/jws/jws.go @@ -0,0 +1,182 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package jws provides a partial implementation +// of JSON Web Signature encoding and decoding. +// It exists to support the golang.org/x/oauth2 package. +// +// See RFC 7515. +// +// Deprecated: this package is not intended for public use and might be +// removed in the future. It exists for internal use only. +// Please switch to another JWS package or copy this package into your own +// source tree. +package jws // import "golang.org/x/oauth2/jws" + +import ( + "bytes" + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "strings" + "time" +) + +// ClaimSet contains information about the JWT signature including the +// permissions being requested (scopes), the target of the token, the issuer, +// the time the token was issued, and the lifetime of the token. +type ClaimSet struct { + Iss string `json:"iss"` // email address of the client_id of the application making the access token request + Scope string `json:"scope,omitempty"` // space-delimited list of the permissions the application requests + Aud string `json:"aud"` // descriptor of the intended target of the assertion (Optional). + Exp int64 `json:"exp"` // the expiration time of the assertion (seconds since Unix epoch) + Iat int64 `json:"iat"` // the time the assertion was issued (seconds since Unix epoch) + Typ string `json:"typ,omitempty"` // token type (Optional). + + // Email for which the application is requesting delegated access (Optional). + Sub string `json:"sub,omitempty"` + + // The old name of Sub. Client keeps setting Prn to be + // complaint with legacy OAuth 2.0 providers. (Optional) + Prn string `json:"prn,omitempty"` + + // See http://tools.ietf.org/html/draft-jones-json-web-token-10#section-4.3 + // This array is marshalled using custom code (see (c *ClaimSet) encode()). + PrivateClaims map[string]interface{} `json:"-"` +} + +func (c *ClaimSet) encode() (string, error) { + // Reverting time back for machines whose time is not perfectly in sync. + // If client machine's time is in the future according + // to Google servers, an access token will not be issued. + now := time.Now().Add(-10 * time.Second) + if c.Iat == 0 { + c.Iat = now.Unix() + } + if c.Exp == 0 { + c.Exp = now.Add(time.Hour).Unix() + } + if c.Exp < c.Iat { + return "", fmt.Errorf("jws: invalid Exp = %v; must be later than Iat = %v", c.Exp, c.Iat) + } + + b, err := json.Marshal(c) + if err != nil { + return "", err + } + + if len(c.PrivateClaims) == 0 { + return base64.RawURLEncoding.EncodeToString(b), nil + } + + // Marshal private claim set and then append it to b. + prv, err := json.Marshal(c.PrivateClaims) + if err != nil { + return "", fmt.Errorf("jws: invalid map of private claims %v", c.PrivateClaims) + } + + // Concatenate public and private claim JSON objects. + if !bytes.HasSuffix(b, []byte{'}'}) { + return "", fmt.Errorf("jws: invalid JSON %s", b) + } + if !bytes.HasPrefix(prv, []byte{'{'}) { + return "", fmt.Errorf("jws: invalid JSON %s", prv) + } + b[len(b)-1] = ',' // Replace closing curly brace with a comma. + b = append(b, prv[1:]...) // Append private claims. + return base64.RawURLEncoding.EncodeToString(b), nil +} + +// Header represents the header for the signed JWS payloads. +type Header struct { + // The algorithm used for signature. + Algorithm string `json:"alg"` + + // Represents the token type. + Typ string `json:"typ"` + + // The optional hint of which key is being used. + KeyID string `json:"kid,omitempty"` +} + +func (h *Header) encode() (string, error) { + b, err := json.Marshal(h) + if err != nil { + return "", err + } + return base64.RawURLEncoding.EncodeToString(b), nil +} + +// Decode decodes a claim set from a JWS payload. +func Decode(payload string) (*ClaimSet, error) { + // decode returned id token to get expiry + s := strings.Split(payload, ".") + if len(s) < 2 { + // TODO(jbd): Provide more context about the error. + return nil, errors.New("jws: invalid token received") + } + decoded, err := base64.RawURLEncoding.DecodeString(s[1]) + if err != nil { + return nil, err + } + c := &ClaimSet{} + err = json.NewDecoder(bytes.NewBuffer(decoded)).Decode(c) + return c, err +} + +// Signer returns a signature for the given data. +type Signer func(data []byte) (sig []byte, err error) + +// EncodeWithSigner encodes a header and claim set with the provided signer. +func EncodeWithSigner(header *Header, c *ClaimSet, sg Signer) (string, error) { + head, err := header.encode() + if err != nil { + return "", err + } + cs, err := c.encode() + if err != nil { + return "", err + } + ss := fmt.Sprintf("%s.%s", head, cs) + sig, err := sg([]byte(ss)) + if err != nil { + return "", err + } + return fmt.Sprintf("%s.%s", ss, base64.RawURLEncoding.EncodeToString(sig)), nil +} + +// Encode encodes a signed JWS with provided header and claim set. +// This invokes EncodeWithSigner using crypto/rsa.SignPKCS1v15 with the given RSA private key. +func Encode(header *Header, c *ClaimSet, key *rsa.PrivateKey) (string, error) { + sg := func(data []byte) (sig []byte, err error) { + h := sha256.New() + h.Write(data) + return rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, h.Sum(nil)) + } + return EncodeWithSigner(header, c, sg) +} + +// Verify tests whether the provided JWT token's signature was produced by the private key +// associated with the supplied public key. +func Verify(token string, key *rsa.PublicKey) error { + parts := strings.Split(token, ".") + if len(parts) != 3 { + return errors.New("jws: invalid token received, token must have 3 parts") + } + + signedContent := parts[0] + "." + parts[1] + signatureString, err := base64.RawURLEncoding.DecodeString(parts[2]) + if err != nil { + return err + } + + h := sha256.New() + h.Write([]byte(signedContent)) + return rsa.VerifyPKCS1v15(key, crypto.SHA256, h.Sum(nil), []byte(signatureString)) +} diff --git a/vendor/golang.org/x/oauth2/jwt/jwt.go b/vendor/golang.org/x/oauth2/jwt/jwt.go new file mode 100644 index 00000000..e08f3159 --- /dev/null +++ b/vendor/golang.org/x/oauth2/jwt/jwt.go @@ -0,0 +1,162 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package jwt implements the OAuth 2.0 JSON Web Token flow, commonly +// known as "two-legged OAuth 2.0". +// +// See: https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12 +package jwt + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "strings" + "time" + + "golang.org/x/net/context" + "golang.org/x/oauth2" + "golang.org/x/oauth2/internal" + "golang.org/x/oauth2/jws" +) + +var ( + defaultGrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer" + defaultHeader = &jws.Header{Algorithm: "RS256", Typ: "JWT"} +) + +// Config is the configuration for using JWT to fetch tokens, +// commonly known as "two-legged OAuth 2.0". +type Config struct { + // Email is the OAuth client identifier used when communicating with + // the configured OAuth provider. + Email string + + // PrivateKey contains the contents of an RSA private key or the + // contents of a PEM file that contains a private key. The provided + // private key is used to sign JWT payloads. + // PEM containers with a passphrase are not supported. + // Use the following command to convert a PKCS 12 file into a PEM. + // + // $ openssl pkcs12 -in key.p12 -out key.pem -nodes + // + PrivateKey []byte + + // PrivateKeyID contains an optional hint indicating which key is being + // used. + PrivateKeyID string + + // Subject is the optional user to impersonate. + Subject string + + // Scopes optionally specifies a list of requested permission scopes. + Scopes []string + + // TokenURL is the endpoint required to complete the 2-legged JWT flow. + TokenURL string + + // Expires optionally specifies how long the token is valid for. + Expires time.Duration +} + +// TokenSource returns a JWT TokenSource using the configuration +// in c and the HTTP client from the provided context. +func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource { + return oauth2.ReuseTokenSource(nil, jwtSource{ctx, c}) +} + +// Client returns an HTTP client wrapping the context's +// HTTP transport and adding Authorization headers with tokens +// obtained from c. +// +// The returned client and its Transport should not be modified. +func (c *Config) Client(ctx context.Context) *http.Client { + return oauth2.NewClient(ctx, c.TokenSource(ctx)) +} + +// jwtSource is a source that always does a signed JWT request for a token. +// It should typically be wrapped with a reuseTokenSource. +type jwtSource struct { + ctx context.Context + conf *Config +} + +func (js jwtSource) Token() (*oauth2.Token, error) { + pk, err := internal.ParseKey(js.conf.PrivateKey) + if err != nil { + return nil, err + } + hc := oauth2.NewClient(js.ctx, nil) + claimSet := &jws.ClaimSet{ + Iss: js.conf.Email, + Scope: strings.Join(js.conf.Scopes, " "), + Aud: js.conf.TokenURL, + } + if subject := js.conf.Subject; subject != "" { + claimSet.Sub = subject + // prn is the old name of sub. Keep setting it + // to be compatible with legacy OAuth 2.0 providers. + claimSet.Prn = subject + } + if t := js.conf.Expires; t > 0 { + claimSet.Exp = time.Now().Add(t).Unix() + } + h := *defaultHeader + h.KeyID = js.conf.PrivateKeyID + payload, err := jws.Encode(&h, claimSet, pk) + if err != nil { + return nil, err + } + v := url.Values{} + v.Set("grant_type", defaultGrantType) + v.Set("assertion", payload) + resp, err := hc.PostForm(js.conf.TokenURL, v) + if err != nil { + return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20)) + if err != nil { + return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) + } + if c := resp.StatusCode; c < 200 || c > 299 { + return nil, &oauth2.RetrieveError{ + Response: resp, + Body: body, + } + } + // tokenRes is the JSON response body. + var tokenRes struct { + AccessToken string `json:"access_token"` + TokenType string `json:"token_type"` + IDToken string `json:"id_token"` + ExpiresIn int64 `json:"expires_in"` // relative seconds from now + } + if err := json.Unmarshal(body, &tokenRes); err != nil { + return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) + } + token := &oauth2.Token{ + AccessToken: tokenRes.AccessToken, + TokenType: tokenRes.TokenType, + } + raw := make(map[string]interface{}) + json.Unmarshal(body, &raw) // no error checks for optional fields + token = token.WithExtra(raw) + + if secs := tokenRes.ExpiresIn; secs > 0 { + token.Expiry = time.Now().Add(time.Duration(secs) * time.Second) + } + if v := tokenRes.IDToken; v != "" { + // decode returned id token to get expiry + claimSet, err := jws.Decode(v) + if err != nil { + return nil, fmt.Errorf("oauth2: error decoding JWT token: %v", err) + } + token.Expiry = time.Unix(claimSet.Exp, 0) + } + return token, nil +} diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go new file mode 100644 index 00000000..10299d2e --- /dev/null +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -0,0 +1,354 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package oauth2 provides support for making +// OAuth2 authorized and authenticated HTTP requests, +// as specified in RFC 6749. +// It can additionally grant authorization with Bearer JWT. +package oauth2 // import "golang.org/x/oauth2" + +import ( + "bytes" + "errors" + "net/http" + "net/url" + "strings" + "sync" + + "golang.org/x/net/context" + "golang.org/x/oauth2/internal" +) + +// NoContext is the default context you should supply if not using +// your own context.Context (see https://golang.org/x/net/context). +// +// Deprecated: Use context.Background() or context.TODO() instead. +var NoContext = context.TODO() + +// RegisterBrokenAuthHeaderProvider registers an OAuth2 server +// identified by the tokenURL prefix as an OAuth2 implementation +// which doesn't support the HTTP Basic authentication +// scheme to authenticate with the authorization server. +// Once a server is registered, credentials (client_id and client_secret) +// will be passed as query parameters rather than being present +// in the Authorization header. +// See https://code.google.com/p/goauth2/issues/detail?id=31 for background. +func RegisterBrokenAuthHeaderProvider(tokenURL string) { + internal.RegisterBrokenAuthHeaderProvider(tokenURL) +} + +// Config describes a typical 3-legged OAuth2 flow, with both the +// client application information and the server's endpoint URLs. +// For the client credentials 2-legged OAuth2 flow, see the clientcredentials +// package (https://golang.org/x/oauth2/clientcredentials). +type Config struct { + // ClientID is the application's ID. + ClientID string + + // ClientSecret is the application's secret. + ClientSecret string + + // Endpoint contains the resource server's token endpoint + // URLs. These are constants specific to each server and are + // often available via site-specific packages, such as + // google.Endpoint or github.Endpoint. + Endpoint Endpoint + + // RedirectURL is the URL to redirect users going through + // the OAuth flow, after the resource owner's URLs. + RedirectURL string + + // Scope specifies optional requested permissions. + Scopes []string +} + +// A TokenSource is anything that can return a token. +type TokenSource interface { + // Token returns a token or an error. + // Token must be safe for concurrent use by multiple goroutines. + // The returned Token must not be modified. + Token() (*Token, error) +} + +// Endpoint contains the OAuth 2.0 provider's authorization and token +// endpoint URLs. +type Endpoint struct { + AuthURL string + TokenURL string +} + +var ( + // AccessTypeOnline and AccessTypeOffline are options passed + // to the Options.AuthCodeURL method. They modify the + // "access_type" field that gets sent in the URL returned by + // AuthCodeURL. + // + // Online is the default if neither is specified. If your + // application needs to refresh access tokens when the user + // is not present at the browser, then use offline. This will + // result in your application obtaining a refresh token the + // first time your application exchanges an authorization + // code for a user. + AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online") + AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline") + + // ApprovalForce forces the users to view the consent dialog + // and confirm the permissions request at the URL returned + // from AuthCodeURL, even if they've already done so. + ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force") +) + +// An AuthCodeOption is passed to Config.AuthCodeURL. +type AuthCodeOption interface { + setValue(url.Values) +} + +type setParam struct{ k, v string } + +func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) } + +// SetAuthURLParam builds an AuthCodeOption which passes key/value parameters +// to a provider's authorization endpoint. +func SetAuthURLParam(key, value string) AuthCodeOption { + return setParam{key, value} +} + +// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page +// that asks for permissions for the required scopes explicitly. +// +// State is a token to protect the user from CSRF attacks. You must +// always provide a non-empty string and validate that it matches the +// the state query parameter on your redirect callback. +// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info. +// +// Opts may include AccessTypeOnline or AccessTypeOffline, as well +// as ApprovalForce. +func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { + var buf bytes.Buffer + buf.WriteString(c.Endpoint.AuthURL) + v := url.Values{ + "response_type": {"code"}, + "client_id": {c.ClientID}, + } + if c.RedirectURL != "" { + v.Set("redirect_uri", c.RedirectURL) + } + if len(c.Scopes) > 0 { + v.Set("scope", strings.Join(c.Scopes, " ")) + } + if state != "" { + // TODO(light): Docs say never to omit state; don't allow empty. + v.Set("state", state) + } + for _, opt := range opts { + opt.setValue(v) + } + if strings.Contains(c.Endpoint.AuthURL, "?") { + buf.WriteByte('&') + } else { + buf.WriteByte('?') + } + buf.WriteString(v.Encode()) + return buf.String() +} + +// PasswordCredentialsToken converts a resource owner username and password +// pair into a token. +// +// Per the RFC, this grant type should only be used "when there is a high +// degree of trust between the resource owner and the client (e.g., the client +// is part of the device operating system or a highly privileged application), +// and when other authorization grant types are not available." +// See https://tools.ietf.org/html/rfc6749#section-4.3 for more info. +// +// The HTTP client to use is derived from the context. +// If nil, http.DefaultClient is used. +func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { + v := url.Values{ + "grant_type": {"password"}, + "username": {username}, + "password": {password}, + } + if len(c.Scopes) > 0 { + v.Set("scope", strings.Join(c.Scopes, " ")) + } + return retrieveToken(ctx, c, v) +} + +// Exchange converts an authorization code into a token. +// +// It is used after a resource provider redirects the user back +// to the Redirect URI (the URL obtained from AuthCodeURL). +// +// The HTTP client to use is derived from the context. +// If a client is not provided via the context, http.DefaultClient is used. +// +// The code will be in the *http.Request.FormValue("code"). Before +// calling Exchange, be sure to validate FormValue("state"). +func (c *Config) Exchange(ctx context.Context, code string) (*Token, error) { + v := url.Values{ + "grant_type": {"authorization_code"}, + "code": {code}, + } + if c.RedirectURL != "" { + v.Set("redirect_uri", c.RedirectURL) + } + return retrieveToken(ctx, c, v) +} + +// Client returns an HTTP client using the provided token. +// The token will auto-refresh as necessary. The underlying +// HTTP transport will be obtained using the provided context. +// The returned client and its Transport should not be modified. +func (c *Config) Client(ctx context.Context, t *Token) *http.Client { + return NewClient(ctx, c.TokenSource(ctx, t)) +} + +// TokenSource returns a TokenSource that returns t until t expires, +// automatically refreshing it as necessary using the provided context. +// +// Most users will use Config.Client instead. +func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource { + tkr := &tokenRefresher{ + ctx: ctx, + conf: c, + } + if t != nil { + tkr.refreshToken = t.RefreshToken + } + return &reuseTokenSource{ + t: t, + new: tkr, + } +} + +// tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token" +// HTTP requests to renew a token using a RefreshToken. +type tokenRefresher struct { + ctx context.Context // used to get HTTP requests + conf *Config + refreshToken string +} + +// WARNING: Token is not safe for concurrent access, as it +// updates the tokenRefresher's refreshToken field. +// Within this package, it is used by reuseTokenSource which +// synchronizes calls to this method with its own mutex. +func (tf *tokenRefresher) Token() (*Token, error) { + if tf.refreshToken == "" { + return nil, errors.New("oauth2: token expired and refresh token is not set") + } + + tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{ + "grant_type": {"refresh_token"}, + "refresh_token": {tf.refreshToken}, + }) + + if err != nil { + return nil, err + } + if tf.refreshToken != tk.RefreshToken { + tf.refreshToken = tk.RefreshToken + } + return tk, err +} + +// reuseTokenSource is a TokenSource that holds a single token in memory +// and validates its expiry before each call to retrieve it with +// Token. If it's expired, it will be auto-refreshed using the +// new TokenSource. +type reuseTokenSource struct { + new TokenSource // called when t is expired. + + mu sync.Mutex // guards t + t *Token +} + +// Token returns the current token if it's still valid, else will +// refresh the current token (using r.Context for HTTP client +// information) and return the new one. +func (s *reuseTokenSource) Token() (*Token, error) { + s.mu.Lock() + defer s.mu.Unlock() + if s.t.Valid() { + return s.t, nil + } + t, err := s.new.Token() + if err != nil { + return nil, err + } + s.t = t + return t, nil +} + +// StaticTokenSource returns a TokenSource that always returns the same token. +// Because the provided token t is never refreshed, StaticTokenSource is only +// useful for tokens that never expire. +func StaticTokenSource(t *Token) TokenSource { + return staticTokenSource{t} +} + +// staticTokenSource is a TokenSource that always returns the same Token. +type staticTokenSource struct { + t *Token +} + +func (s staticTokenSource) Token() (*Token, error) { + return s.t, nil +} + +// HTTPClient is the context key to use with golang.org/x/net/context's +// WithValue function to associate an *http.Client value with a context. +var HTTPClient internal.ContextKey + +// NewClient creates an *http.Client from a Context and TokenSource. +// The returned client is not valid beyond the lifetime of the context. +// +// Note that if a custom *http.Client is provided via the Context it +// is used only for token acquisition and is not used to configure the +// *http.Client returned from NewClient. +// +// As a special case, if src is nil, a non-OAuth2 client is returned +// using the provided context. This exists to support related OAuth2 +// packages. +func NewClient(ctx context.Context, src TokenSource) *http.Client { + if src == nil { + return internal.ContextClient(ctx) + } + return &http.Client{ + Transport: &Transport{ + Base: internal.ContextClient(ctx).Transport, + Source: ReuseTokenSource(nil, src), + }, + } +} + +// ReuseTokenSource returns a TokenSource which repeatedly returns the +// same token as long as it's valid, starting with t. +// When its cached token is invalid, a new token is obtained from src. +// +// ReuseTokenSource is typically used to reuse tokens from a cache +// (such as a file on disk) between runs of a program, rather than +// obtaining new tokens unnecessarily. +// +// The initial token t may be nil, in which case the TokenSource is +// wrapped in a caching version if it isn't one already. This also +// means it's always safe to wrap ReuseTokenSource around any other +// TokenSource without adverse effects. +func ReuseTokenSource(t *Token, src TokenSource) TokenSource { + // Don't wrap a reuseTokenSource in itself. That would work, + // but cause an unnecessary number of mutex operations. + // Just build the equivalent one. + if rt, ok := src.(*reuseTokenSource); ok { + if t == nil { + // Just use it directly. + return rt + } + src = rt.new + } + return &reuseTokenSource{ + t: t, + new: src, + } +} diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go new file mode 100644 index 00000000..34db8cdc --- /dev/null +++ b/vendor/golang.org/x/oauth2/token.go @@ -0,0 +1,175 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package oauth2 + +import ( + "fmt" + "net/http" + "net/url" + "strconv" + "strings" + "time" + + "golang.org/x/net/context" + "golang.org/x/oauth2/internal" +) + +// expiryDelta determines how earlier a token should be considered +// expired than its actual expiration time. It is used to avoid late +// expirations due to client-server time mismatches. +const expiryDelta = 10 * time.Second + +// Token represents the credentials used to authorize +// the requests to access protected resources on the OAuth 2.0 +// provider's backend. +// +// Most users of this package should not access fields of Token +// directly. They're exported mostly for use by related packages +// implementing derivative OAuth2 flows. +type Token struct { + // AccessToken is the token that authorizes and authenticates + // the requests. + AccessToken string `json:"access_token"` + + // TokenType is the type of token. + // The Type method returns either this or "Bearer", the default. + TokenType string `json:"token_type,omitempty"` + + // RefreshToken is a token that's used by the application + // (as opposed to the user) to refresh the access token + // if it expires. + RefreshToken string `json:"refresh_token,omitempty"` + + // Expiry is the optional expiration time of the access token. + // + // If zero, TokenSource implementations will reuse the same + // token forever and RefreshToken or equivalent + // mechanisms for that TokenSource will not be used. + Expiry time.Time `json:"expiry,omitempty"` + + // raw optionally contains extra metadata from the server + // when updating a token. + raw interface{} +} + +// Type returns t.TokenType if non-empty, else "Bearer". +func (t *Token) Type() string { + if strings.EqualFold(t.TokenType, "bearer") { + return "Bearer" + } + if strings.EqualFold(t.TokenType, "mac") { + return "MAC" + } + if strings.EqualFold(t.TokenType, "basic") { + return "Basic" + } + if t.TokenType != "" { + return t.TokenType + } + return "Bearer" +} + +// SetAuthHeader sets the Authorization header to r using the access +// token in t. +// +// This method is unnecessary when using Transport or an HTTP Client +// returned by this package. +func (t *Token) SetAuthHeader(r *http.Request) { + r.Header.Set("Authorization", t.Type()+" "+t.AccessToken) +} + +// WithExtra returns a new Token that's a clone of t, but using the +// provided raw extra map. This is only intended for use by packages +// implementing derivative OAuth2 flows. +func (t *Token) WithExtra(extra interface{}) *Token { + t2 := new(Token) + *t2 = *t + t2.raw = extra + return t2 +} + +// Extra returns an extra field. +// Extra fields are key-value pairs returned by the server as a +// part of the token retrieval response. +func (t *Token) Extra(key string) interface{} { + if raw, ok := t.raw.(map[string]interface{}); ok { + return raw[key] + } + + vals, ok := t.raw.(url.Values) + if !ok { + return nil + } + + v := vals.Get(key) + switch s := strings.TrimSpace(v); strings.Count(s, ".") { + case 0: // Contains no "."; try to parse as int + if i, err := strconv.ParseInt(s, 10, 64); err == nil { + return i + } + case 1: // Contains a single "."; try to parse as float + if f, err := strconv.ParseFloat(s, 64); err == nil { + return f + } + } + + return v +} + +// expired reports whether the token is expired. +// t must be non-nil. +func (t *Token) expired() bool { + if t.Expiry.IsZero() { + return false + } + return t.Expiry.Round(0).Add(-expiryDelta).Before(time.Now()) +} + +// Valid reports whether t is non-nil, has an AccessToken, and is not expired. +func (t *Token) Valid() bool { + return t != nil && t.AccessToken != "" && !t.expired() +} + +// tokenFromInternal maps an *internal.Token struct into +// a *Token struct. +func tokenFromInternal(t *internal.Token) *Token { + if t == nil { + return nil + } + return &Token{ + AccessToken: t.AccessToken, + TokenType: t.TokenType, + RefreshToken: t.RefreshToken, + Expiry: t.Expiry, + raw: t.Raw, + } +} + +// retrieveToken takes a *Config and uses that to retrieve an *internal.Token. +// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along +// with an error.. +func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { + tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v) + if err != nil { + if rErr, ok := err.(*internal.RetrieveError); ok { + return nil, (*RetrieveError)(rErr) + } + return nil, err + } + return tokenFromInternal(tk), nil +} + +// RetrieveError is the error returned when the token endpoint returns a +// non-2XX HTTP status code. +type RetrieveError struct { + Response *http.Response + // Body is the body that was consumed by reading Response.Body. + // It may be truncated. + Body []byte +} + +func (r *RetrieveError) Error() string { + return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) +} diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go new file mode 100644 index 00000000..aa0d34f1 --- /dev/null +++ b/vendor/golang.org/x/oauth2/transport.go @@ -0,0 +1,144 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package oauth2 + +import ( + "errors" + "io" + "net/http" + "sync" +) + +// Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests, +// wrapping a base RoundTripper and adding an Authorization header +// with a token from the supplied Sources. +// +// Transport is a low-level mechanism. Most code will use the +// higher-level Config.Client method instead. +type Transport struct { + // Source supplies the token to add to outgoing requests' + // Authorization headers. + Source TokenSource + + // Base is the base RoundTripper used to make HTTP requests. + // If nil, http.DefaultTransport is used. + Base http.RoundTripper + + mu sync.Mutex // guards modReq + modReq map[*http.Request]*http.Request // original -> modified +} + +// RoundTrip authorizes and authenticates the request with an +// access token from Transport's Source. +func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + reqBodyClosed := false + if req.Body != nil { + defer func() { + if !reqBodyClosed { + req.Body.Close() + } + }() + } + + if t.Source == nil { + return nil, errors.New("oauth2: Transport's Source is nil") + } + token, err := t.Source.Token() + if err != nil { + return nil, err + } + + req2 := cloneRequest(req) // per RoundTripper contract + token.SetAuthHeader(req2) + t.setModReq(req, req2) + res, err := t.base().RoundTrip(req2) + + // req.Body is assumed to have been closed by the base RoundTripper. + reqBodyClosed = true + + if err != nil { + t.setModReq(req, nil) + return nil, err + } + res.Body = &onEOFReader{ + rc: res.Body, + fn: func() { t.setModReq(req, nil) }, + } + return res, nil +} + +// CancelRequest cancels an in-flight request by closing its connection. +func (t *Transport) CancelRequest(req *http.Request) { + type canceler interface { + CancelRequest(*http.Request) + } + if cr, ok := t.base().(canceler); ok { + t.mu.Lock() + modReq := t.modReq[req] + delete(t.modReq, req) + t.mu.Unlock() + cr.CancelRequest(modReq) + } +} + +func (t *Transport) base() http.RoundTripper { + if t.Base != nil { + return t.Base + } + return http.DefaultTransport +} + +func (t *Transport) setModReq(orig, mod *http.Request) { + t.mu.Lock() + defer t.mu.Unlock() + if t.modReq == nil { + t.modReq = make(map[*http.Request]*http.Request) + } + if mod == nil { + delete(t.modReq, orig) + } else { + t.modReq[orig] = mod + } +} + +// cloneRequest returns a clone of the provided *http.Request. +// The clone is a shallow copy of the struct and its Header map. +func cloneRequest(r *http.Request) *http.Request { + // shallow copy of the struct + r2 := new(http.Request) + *r2 = *r + // deep copy of the Header + r2.Header = make(http.Header, len(r.Header)) + for k, s := range r.Header { + r2.Header[k] = append([]string(nil), s...) + } + return r2 +} + +type onEOFReader struct { + rc io.ReadCloser + fn func() +} + +func (r *onEOFReader) Read(p []byte) (n int, err error) { + n, err = r.rc.Read(p) + if err == io.EOF { + r.runFunc() + } + return +} + +func (r *onEOFReader) Close() error { + err := r.rc.Close() + r.runFunc() + return err +} + +func (r *onEOFReader) runFunc() { + if fn := r.fn; fn != nil { + fn() + r.fn = nil + } +} diff --git a/vendor/golang.org/x/text/AUTHORS b/vendor/golang.org/x/text/AUTHORS new file mode 100644 index 00000000..15167cd7 --- /dev/null +++ b/vendor/golang.org/x/text/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/text/CONTRIBUTORS b/vendor/golang.org/x/text/CONTRIBUTORS new file mode 100644 index 00000000..1c4577e9 --- /dev/null +++ b/vendor/golang.org/x/text/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/text/LICENSE b/vendor/golang.org/x/text/LICENSE new file mode 100644 index 00000000..6a66aea5 --- /dev/null +++ b/vendor/golang.org/x/text/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/text/PATENTS b/vendor/golang.org/x/text/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/golang.org/x/text/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/text/encoding/encoding.go b/vendor/golang.org/x/text/encoding/encoding.go new file mode 100644 index 00000000..221f175c --- /dev/null +++ b/vendor/golang.org/x/text/encoding/encoding.go @@ -0,0 +1,335 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package encoding defines an interface for character encodings, such as Shift +// JIS and Windows 1252, that can convert to and from UTF-8. +// +// Encoding implementations are provided in other packages, such as +// golang.org/x/text/encoding/charmap and +// golang.org/x/text/encoding/japanese. +package encoding // import "golang.org/x/text/encoding" + +import ( + "errors" + "io" + "strconv" + "unicode/utf8" + + "golang.org/x/text/encoding/internal/identifier" + "golang.org/x/text/transform" +) + +// TODO: +// - There seems to be some inconsistency in when decoders return errors +// and when not. Also documentation seems to suggest they shouldn't return +// errors at all (except for UTF-16). +// - Encoders seem to rely on or at least benefit from the input being in NFC +// normal form. Perhaps add an example how users could prepare their output. + +// Encoding is a character set encoding that can be transformed to and from +// UTF-8. +type Encoding interface { + // NewDecoder returns a Decoder. + NewDecoder() *Decoder + + // NewEncoder returns an Encoder. + NewEncoder() *Encoder +} + +// A Decoder converts bytes to UTF-8. It implements transform.Transformer. +// +// Transforming source bytes that are not of that encoding will not result in an +// error per se. Each byte that cannot be transcoded will be represented in the +// output by the UTF-8 encoding of '\uFFFD', the replacement rune. +type Decoder struct { + transform.Transformer + + // This forces external creators of Decoders to use names in struct + // initializers, allowing for future extendibility without having to break + // code. + _ struct{} +} + +// Bytes converts the given encoded bytes to UTF-8. It returns the converted +// bytes or nil, err if any error occurred. +func (d *Decoder) Bytes(b []byte) ([]byte, error) { + b, _, err := transform.Bytes(d, b) + if err != nil { + return nil, err + } + return b, nil +} + +// String converts the given encoded string to UTF-8. It returns the converted +// string or "", err if any error occurred. +func (d *Decoder) String(s string) (string, error) { + s, _, err := transform.String(d, s) + if err != nil { + return "", err + } + return s, nil +} + +// Reader wraps another Reader to decode its bytes. +// +// The Decoder may not be used for any other operation as long as the returned +// Reader is in use. +func (d *Decoder) Reader(r io.Reader) io.Reader { + return transform.NewReader(r, d) +} + +// An Encoder converts bytes from UTF-8. It implements transform.Transformer. +// +// Each rune that cannot be transcoded will result in an error. In this case, +// the transform will consume all source byte up to, not including the offending +// rune. Transforming source bytes that are not valid UTF-8 will be replaced by +// `\uFFFD`. To return early with an error instead, use transform.Chain to +// preprocess the data with a UTF8Validator. +type Encoder struct { + transform.Transformer + + // This forces external creators of Encoders to use names in struct + // initializers, allowing for future extendibility without having to break + // code. + _ struct{} +} + +// Bytes converts bytes from UTF-8. It returns the converted bytes or nil, err if +// any error occurred. +func (e *Encoder) Bytes(b []byte) ([]byte, error) { + b, _, err := transform.Bytes(e, b) + if err != nil { + return nil, err + } + return b, nil +} + +// String converts a string from UTF-8. It returns the converted string or +// "", err if any error occurred. +func (e *Encoder) String(s string) (string, error) { + s, _, err := transform.String(e, s) + if err != nil { + return "", err + } + return s, nil +} + +// Writer wraps another Writer to encode its UTF-8 output. +// +// The Encoder may not be used for any other operation as long as the returned +// Writer is in use. +func (e *Encoder) Writer(w io.Writer) io.Writer { + return transform.NewWriter(w, e) +} + +// ASCIISub is the ASCII substitute character, as recommended by +// http://unicode.org/reports/tr36/#Text_Comparison +const ASCIISub = '\x1a' + +// Nop is the nop encoding. Its transformed bytes are the same as the source +// bytes; it does not replace invalid UTF-8 sequences. +var Nop Encoding = nop{} + +type nop struct{} + +func (nop) NewDecoder() *Decoder { + return &Decoder{Transformer: transform.Nop} +} +func (nop) NewEncoder() *Encoder { + return &Encoder{Transformer: transform.Nop} +} + +// Replacement is the replacement encoding. Decoding from the replacement +// encoding yields a single '\uFFFD' replacement rune. Encoding from UTF-8 to +// the replacement encoding yields the same as the source bytes except that +// invalid UTF-8 is converted to '\uFFFD'. +// +// It is defined at http://encoding.spec.whatwg.org/#replacement +var Replacement Encoding = replacement{} + +type replacement struct{} + +func (replacement) NewDecoder() *Decoder { + return &Decoder{Transformer: replacementDecoder{}} +} + +func (replacement) NewEncoder() *Encoder { + return &Encoder{Transformer: replacementEncoder{}} +} + +func (replacement) ID() (mib identifier.MIB, other string) { + return identifier.Replacement, "" +} + +type replacementDecoder struct{ transform.NopResetter } + +func (replacementDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + if len(dst) < 3 { + return 0, 0, transform.ErrShortDst + } + if atEOF { + const fffd = "\ufffd" + dst[0] = fffd[0] + dst[1] = fffd[1] + dst[2] = fffd[2] + nDst = 3 + } + return nDst, len(src), nil +} + +type replacementEncoder struct{ transform.NopResetter } + +func (replacementEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + r, size := rune(0), 0 + + for ; nSrc < len(src); nSrc += size { + r = rune(src[nSrc]) + + // Decode a 1-byte rune. + if r < utf8.RuneSelf { + size = 1 + + } else { + // Decode a multi-byte rune. + r, size = utf8.DecodeRune(src[nSrc:]) + if size == 1 { + // All valid runes of size 1 (those below utf8.RuneSelf) were + // handled above. We have invalid UTF-8 or we haven't seen the + // full character yet. + if !atEOF && !utf8.FullRune(src[nSrc:]) { + err = transform.ErrShortSrc + break + } + r = '\ufffd' + } + } + + if nDst+utf8.RuneLen(r) > len(dst) { + err = transform.ErrShortDst + break + } + nDst += utf8.EncodeRune(dst[nDst:], r) + } + return nDst, nSrc, err +} + +// HTMLEscapeUnsupported wraps encoders to replace source runes outside the +// repertoire of the destination encoding with HTML escape sequences. +// +// This wrapper exists to comply to URL and HTML forms requiring a +// non-terminating legacy encoder. The produced sequences may lead to data +// loss as they are indistinguishable from legitimate input. To avoid this +// issue, use UTF-8 encodings whenever possible. +func HTMLEscapeUnsupported(e *Encoder) *Encoder { + return &Encoder{Transformer: &errorHandler{e, errorToHTML}} +} + +// ReplaceUnsupported wraps encoders to replace source runes outside the +// repertoire of the destination encoding with an encoding-specific +// replacement. +// +// This wrapper is only provided for backwards compatibility and legacy +// handling. Its use is strongly discouraged. Use UTF-8 whenever possible. +func ReplaceUnsupported(e *Encoder) *Encoder { + return &Encoder{Transformer: &errorHandler{e, errorToReplacement}} +} + +type errorHandler struct { + *Encoder + handler func(dst []byte, r rune, err repertoireError) (n int, ok bool) +} + +// TODO: consider making this error public in some form. +type repertoireError interface { + Replacement() byte +} + +func (h errorHandler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + nDst, nSrc, err = h.Transformer.Transform(dst, src, atEOF) + for err != nil { + rerr, ok := err.(repertoireError) + if !ok { + return nDst, nSrc, err + } + r, sz := utf8.DecodeRune(src[nSrc:]) + n, ok := h.handler(dst[nDst:], r, rerr) + if !ok { + return nDst, nSrc, transform.ErrShortDst + } + err = nil + nDst += n + if nSrc += sz; nSrc < len(src) { + var dn, sn int + dn, sn, err = h.Transformer.Transform(dst[nDst:], src[nSrc:], atEOF) + nDst += dn + nSrc += sn + } + } + return nDst, nSrc, err +} + +func errorToHTML(dst []byte, r rune, err repertoireError) (n int, ok bool) { + buf := [8]byte{} + b := strconv.AppendUint(buf[:0], uint64(r), 10) + if n = len(b) + len("&#;"); n >= len(dst) { + return 0, false + } + dst[0] = '&' + dst[1] = '#' + dst[copy(dst[2:], b)+2] = ';' + return n, true +} + +func errorToReplacement(dst []byte, r rune, err repertoireError) (n int, ok bool) { + if len(dst) == 0 { + return 0, false + } + dst[0] = err.Replacement() + return 1, true +} + +// ErrInvalidUTF8 means that a transformer encountered invalid UTF-8. +var ErrInvalidUTF8 = errors.New("encoding: invalid UTF-8") + +// UTF8Validator is a transformer that returns ErrInvalidUTF8 on the first +// input byte that is not valid UTF-8. +var UTF8Validator transform.Transformer = utf8Validator{} + +type utf8Validator struct{ transform.NopResetter } + +func (utf8Validator) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + n := len(src) + if n > len(dst) { + n = len(dst) + } + for i := 0; i < n; { + if c := src[i]; c < utf8.RuneSelf { + dst[i] = c + i++ + continue + } + _, size := utf8.DecodeRune(src[i:]) + if size == 1 { + // All valid runes of size 1 (those below utf8.RuneSelf) were + // handled above. We have invalid UTF-8 or we haven't seen the + // full character yet. + err = ErrInvalidUTF8 + if !atEOF && !utf8.FullRune(src[i:]) { + err = transform.ErrShortSrc + } + return i, i, err + } + if i+size > len(dst) { + return i, i, transform.ErrShortDst + } + for ; size > 0; size-- { + dst[i] = src[i] + i++ + } + } + if len(src) > len(dst) { + err = transform.ErrShortDst + } + return n, n, err +} diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/gen.go b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go new file mode 100644 index 00000000..0c8eba7e --- /dev/null +++ b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go @@ -0,0 +1,137 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bytes" + "encoding/xml" + "fmt" + "io" + "log" + "strings" + + "golang.org/x/text/internal/gen" +) + +type registry struct { + XMLName xml.Name `xml:"registry"` + Updated string `xml:"updated"` + Registry []struct { + ID string `xml:"id,attr"` + Record []struct { + Name string `xml:"name"` + Xref []struct { + Type string `xml:"type,attr"` + Data string `xml:"data,attr"` + } `xml:"xref"` + Desc struct { + Data string `xml:",innerxml"` + // Any []struct { + // Data string `xml:",chardata"` + // } `xml:",any"` + // Data string `xml:",chardata"` + } `xml:"description,"` + MIB string `xml:"value"` + Alias []string `xml:"alias"` + MIME string `xml:"preferred_alias"` + } `xml:"record"` + } `xml:"registry"` +} + +func main() { + r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml") + reg := ®istry{} + if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF { + log.Fatalf("Error decoding charset registry: %v", err) + } + if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" { + log.Fatalf("Unexpected ID %s", reg.Registry[0].ID) + } + + w := &bytes.Buffer{} + fmt.Fprintf(w, "const (\n") + for _, rec := range reg.Registry[0].Record { + constName := "" + for _, a := range rec.Alias { + if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 { + // Some of the constant definitions have comments in them. Strip those. + constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0]) + } + } + if constName == "" { + switch rec.MIB { + case "2085": + constName = "HZGB2312" // Not listed as alias for some reason. + default: + log.Fatalf("No cs alias defined for %s.", rec.MIB) + } + } + if rec.MIME != "" { + rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME) + } + fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME) + if len(rec.Desc.Data) > 0 { + fmt.Fprint(w, "// ") + d := xml.NewDecoder(strings.NewReader(rec.Desc.Data)) + inElem := true + attr := "" + for { + t, err := d.Token() + if err != nil { + if err != io.EOF { + log.Fatal(err) + } + break + } + switch x := t.(type) { + case xml.CharData: + attr = "" // Don't need attribute info. + a := bytes.Split([]byte(x), []byte("\n")) + for i, b := range a { + if b = bytes.TrimSpace(b); len(b) != 0 { + if !inElem && i > 0 { + fmt.Fprint(w, "\n// ") + } + inElem = false + fmt.Fprintf(w, "%s ", string(b)) + } + } + case xml.StartElement: + if x.Name.Local == "xref" { + inElem = true + use := false + for _, a := range x.Attr { + if a.Name.Local == "type" { + use = use || a.Value != "person" + } + if a.Name.Local == "data" && use { + attr = a.Value + " " + } + } + } + case xml.EndElement: + inElem = false + fmt.Fprint(w, attr) + } + } + fmt.Fprint(w, "\n") + } + for _, x := range rec.Xref { + switch x.Type { + case "rfc": + fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data)) + case "uri": + fmt.Fprintf(w, "// Reference: %s\n", x.Data) + } + } + fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB) + fmt.Fprintln(w) + } + fmt.Fprintln(w, ")") + + gen.WriteGoFile("mib.go", "identifier", w.Bytes()) +} diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/identifier.go b/vendor/golang.org/x/text/encoding/internal/identifier/identifier.go new file mode 100644 index 00000000..7351b4ef --- /dev/null +++ b/vendor/golang.org/x/text/encoding/internal/identifier/identifier.go @@ -0,0 +1,81 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go + +// Package identifier defines the contract between implementations of Encoding +// and Index by defining identifiers that uniquely identify standardized coded +// character sets (CCS) and character encoding schemes (CES), which we will +// together refer to as encodings, for which Encoding implementations provide +// converters to and from UTF-8. This package is typically only of concern to +// implementers of Indexes and Encodings. +// +// One part of the identifier is the MIB code, which is defined by IANA and +// uniquely identifies a CCS or CES. Each code is associated with data that +// references authorities, official documentation as well as aliases and MIME +// names. +// +// Not all CESs are covered by the IANA registry. The "other" string that is +// returned by ID can be used to identify other character sets or versions of +// existing ones. +// +// It is recommended that each package that provides a set of Encodings provide +// the All and Common variables to reference all supported encodings and +// commonly used subset. This allows Index implementations to include all +// available encodings without explicitly referencing or knowing about them. +package identifier + +// Note: this package is internal, but could be made public if there is a need +// for writing third-party Indexes and Encodings. + +// References: +// - http://source.icu-project.org/repos/icu/icu/trunk/source/data/mappings/convrtrs.txt +// - http://www.iana.org/assignments/character-sets/character-sets.xhtml +// - http://www.iana.org/assignments/ianacharset-mib/ianacharset-mib +// - http://www.ietf.org/rfc/rfc2978.txt +// - http://www.unicode.org/reports/tr22/ +// - http://www.w3.org/TR/encoding/ +// - https://encoding.spec.whatwg.org/ +// - https://encoding.spec.whatwg.org/encodings.json +// - https://tools.ietf.org/html/rfc6657#section-5 + +// Interface can be implemented by Encodings to define the CCS or CES for which +// it implements conversions. +type Interface interface { + // ID returns an encoding identifier. Exactly one of the mib and other + // values should be non-zero. + // + // In the usual case it is only necessary to indicate the MIB code. The + // other string can be used to specify encodings for which there is no MIB, + // such as "x-mac-dingbat". + // + // The other string may only contain the characters a-z, A-Z, 0-9, - and _. + ID() (mib MIB, other string) + + // NOTE: the restrictions on the encoding are to allow extending the syntax + // with additional information such as versions, vendors and other variants. +} + +// A MIB identifies an encoding. It is derived from the IANA MIB codes and adds +// some identifiers for some encodings that are not covered by the IANA +// standard. +// +// See http://www.iana.org/assignments/ianacharset-mib. +type MIB uint16 + +// These additional MIB types are not defined in IANA. They are added because +// they are common and defined within the text repo. +const ( + // Unofficial marks the start of encodings not registered by IANA. + Unofficial MIB = 10000 + iota + + // Replacement is the WhatWG replacement encoding. + Replacement + + // XUserDefined is the code for x-user-defined. + XUserDefined + + // MacintoshCyrillic is the code for x-mac-cyrillic. + MacintoshCyrillic +) diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/mib.go b/vendor/golang.org/x/text/encoding/internal/identifier/mib.go new file mode 100644 index 00000000..768842b0 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/internal/identifier/mib.go @@ -0,0 +1,1621 @@ +// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. + +package identifier + +const ( + // ASCII is the MIB identifier with IANA name US-ASCII (MIME: US-ASCII). + // + // ANSI X3.4-1986 + // Reference: RFC2046 + ASCII MIB = 3 + + // ISOLatin1 is the MIB identifier with IANA name ISO_8859-1:1987 (MIME: ISO-8859-1). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatin1 MIB = 4 + + // ISOLatin2 is the MIB identifier with IANA name ISO_8859-2:1987 (MIME: ISO-8859-2). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatin2 MIB = 5 + + // ISOLatin3 is the MIB identifier with IANA name ISO_8859-3:1988 (MIME: ISO-8859-3). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatin3 MIB = 6 + + // ISOLatin4 is the MIB identifier with IANA name ISO_8859-4:1988 (MIME: ISO-8859-4). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatin4 MIB = 7 + + // ISOLatinCyrillic is the MIB identifier with IANA name ISO_8859-5:1988 (MIME: ISO-8859-5). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatinCyrillic MIB = 8 + + // ISOLatinArabic is the MIB identifier with IANA name ISO_8859-6:1987 (MIME: ISO-8859-6). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatinArabic MIB = 9 + + // ISOLatinGreek is the MIB identifier with IANA name ISO_8859-7:1987 (MIME: ISO-8859-7). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1947 + // Reference: RFC1345 + ISOLatinGreek MIB = 10 + + // ISOLatinHebrew is the MIB identifier with IANA name ISO_8859-8:1988 (MIME: ISO-8859-8). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatinHebrew MIB = 11 + + // ISOLatin5 is the MIB identifier with IANA name ISO_8859-9:1989 (MIME: ISO-8859-9). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatin5 MIB = 12 + + // ISOLatin6 is the MIB identifier with IANA name ISO-8859-10 (MIME: ISO-8859-10). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOLatin6 MIB = 13 + + // ISOTextComm is the MIB identifier with IANA name ISO_6937-2-add. + // + // ISO-IR: International Register of Escape Sequences and ISO 6937-2:1983 + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISOTextComm MIB = 14 + + // HalfWidthKatakana is the MIB identifier with IANA name JIS_X0201. + // + // JIS X 0201-1976. One byte only, this is equivalent to + // JIS/Roman (similar to ASCII) plus eight-bit half-width + // Katakana + // Reference: RFC1345 + HalfWidthKatakana MIB = 15 + + // JISEncoding is the MIB identifier with IANA name JIS_Encoding. + // + // JIS X 0202-1991. Uses ISO 2022 escape sequences to + // shift code sets as documented in JIS X 0202-1991. + JISEncoding MIB = 16 + + // ShiftJIS is the MIB identifier with IANA name Shift_JIS (MIME: Shift_JIS). + // + // This charset is an extension of csHalfWidthKatakana by + // adding graphic characters in JIS X 0208. The CCS's are + // JIS X0201:1997 and JIS X0208:1997. The + // complete definition is shown in Appendix 1 of JIS + // X0208:1997. + // This charset can be used for the top-level media type "text". + ShiftJIS MIB = 17 + + // EUCPkdFmtJapanese is the MIB identifier with IANA name Extended_UNIX_Code_Packed_Format_for_Japanese (MIME: EUC-JP). + // + // Standardized by OSF, UNIX International, and UNIX Systems + // Laboratories Pacific. Uses ISO 2022 rules to select + // code set 0: US-ASCII (a single 7-bit byte set) + // code set 1: JIS X0208-1990 (a double 8-bit byte set) + // restricted to A0-FF in both bytes + // code set 2: Half Width Katakana (a single 7-bit byte set) + // requiring SS2 as the character prefix + // code set 3: JIS X0212-1990 (a double 7-bit byte set) + // restricted to A0-FF in both bytes + // requiring SS3 as the character prefix + EUCPkdFmtJapanese MIB = 18 + + // EUCFixWidJapanese is the MIB identifier with IANA name Extended_UNIX_Code_Fixed_Width_for_Japanese. + // + // Used in Japan. Each character is 2 octets. + // code set 0: US-ASCII (a single 7-bit byte set) + // 1st byte = 00 + // 2nd byte = 20-7E + // code set 1: JIS X0208-1990 (a double 7-bit byte set) + // restricted to A0-FF in both bytes + // code set 2: Half Width Katakana (a single 7-bit byte set) + // 1st byte = 00 + // 2nd byte = A0-FF + // code set 3: JIS X0212-1990 (a double 7-bit byte set) + // restricted to A0-FF in + // the first byte + // and 21-7E in the second byte + EUCFixWidJapanese MIB = 19 + + // ISO4UnitedKingdom is the MIB identifier with IANA name BS_4730. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO4UnitedKingdom MIB = 20 + + // ISO11SwedishForNames is the MIB identifier with IANA name SEN_850200_C. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO11SwedishForNames MIB = 21 + + // ISO15Italian is the MIB identifier with IANA name IT. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO15Italian MIB = 22 + + // ISO17Spanish is the MIB identifier with IANA name ES. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO17Spanish MIB = 23 + + // ISO21German is the MIB identifier with IANA name DIN_66003. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO21German MIB = 24 + + // ISO60Norwegian1 is the MIB identifier with IANA name NS_4551-1. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO60Norwegian1 MIB = 25 + + // ISO69French is the MIB identifier with IANA name NF_Z_62-010. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO69French MIB = 26 + + // ISO10646UTF1 is the MIB identifier with IANA name ISO-10646-UTF-1. + // + // Universal Transfer Format (1), this is the multibyte + // encoding, that subsets ASCII-7. It does not have byte + // ordering issues. + ISO10646UTF1 MIB = 27 + + // ISO646basic1983 is the MIB identifier with IANA name ISO_646.basic:1983. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO646basic1983 MIB = 28 + + // INVARIANT is the MIB identifier with IANA name INVARIANT. + // + // Reference: RFC1345 + INVARIANT MIB = 29 + + // ISO2IntlRefVersion is the MIB identifier with IANA name ISO_646.irv:1983. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO2IntlRefVersion MIB = 30 + + // NATSSEFI is the MIB identifier with IANA name NATS-SEFI. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + NATSSEFI MIB = 31 + + // NATSSEFIADD is the MIB identifier with IANA name NATS-SEFI-ADD. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + NATSSEFIADD MIB = 32 + + // NATSDANO is the MIB identifier with IANA name NATS-DANO. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + NATSDANO MIB = 33 + + // NATSDANOADD is the MIB identifier with IANA name NATS-DANO-ADD. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + NATSDANOADD MIB = 34 + + // ISO10Swedish is the MIB identifier with IANA name SEN_850200_B. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO10Swedish MIB = 35 + + // KSC56011987 is the MIB identifier with IANA name KS_C_5601-1987. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + KSC56011987 MIB = 36 + + // ISO2022KR is the MIB identifier with IANA name ISO-2022-KR (MIME: ISO-2022-KR). + // + // rfc1557 (see also KS_C_5601-1987) + // Reference: RFC1557 + ISO2022KR MIB = 37 + + // EUCKR is the MIB identifier with IANA name EUC-KR (MIME: EUC-KR). + // + // rfc1557 (see also KS_C_5861-1992) + // Reference: RFC1557 + EUCKR MIB = 38 + + // ISO2022JP is the MIB identifier with IANA name ISO-2022-JP (MIME: ISO-2022-JP). + // + // rfc1468 (see also rfc2237 ) + // Reference: RFC1468 + ISO2022JP MIB = 39 + + // ISO2022JP2 is the MIB identifier with IANA name ISO-2022-JP-2 (MIME: ISO-2022-JP-2). + // + // rfc1554 + // Reference: RFC1554 + ISO2022JP2 MIB = 40 + + // ISO13JISC6220jp is the MIB identifier with IANA name JIS_C6220-1969-jp. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO13JISC6220jp MIB = 41 + + // ISO14JISC6220ro is the MIB identifier with IANA name JIS_C6220-1969-ro. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO14JISC6220ro MIB = 42 + + // ISO16Portuguese is the MIB identifier with IANA name PT. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO16Portuguese MIB = 43 + + // ISO18Greek7Old is the MIB identifier with IANA name greek7-old. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO18Greek7Old MIB = 44 + + // ISO19LatinGreek is the MIB identifier with IANA name latin-greek. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO19LatinGreek MIB = 45 + + // ISO25French is the MIB identifier with IANA name NF_Z_62-010_(1973). + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO25French MIB = 46 + + // ISO27LatinGreek1 is the MIB identifier with IANA name Latin-greek-1. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO27LatinGreek1 MIB = 47 + + // ISO5427Cyrillic is the MIB identifier with IANA name ISO_5427. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO5427Cyrillic MIB = 48 + + // ISO42JISC62261978 is the MIB identifier with IANA name JIS_C6226-1978. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO42JISC62261978 MIB = 49 + + // ISO47BSViewdata is the MIB identifier with IANA name BS_viewdata. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO47BSViewdata MIB = 50 + + // ISO49INIS is the MIB identifier with IANA name INIS. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO49INIS MIB = 51 + + // ISO50INIS8 is the MIB identifier with IANA name INIS-8. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO50INIS8 MIB = 52 + + // ISO51INISCyrillic is the MIB identifier with IANA name INIS-cyrillic. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO51INISCyrillic MIB = 53 + + // ISO54271981 is the MIB identifier with IANA name ISO_5427:1981. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO54271981 MIB = 54 + + // ISO5428Greek is the MIB identifier with IANA name ISO_5428:1980. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO5428Greek MIB = 55 + + // ISO57GB1988 is the MIB identifier with IANA name GB_1988-80. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO57GB1988 MIB = 56 + + // ISO58GB231280 is the MIB identifier with IANA name GB_2312-80. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO58GB231280 MIB = 57 + + // ISO61Norwegian2 is the MIB identifier with IANA name NS_4551-2. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO61Norwegian2 MIB = 58 + + // ISO70VideotexSupp1 is the MIB identifier with IANA name videotex-suppl. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO70VideotexSupp1 MIB = 59 + + // ISO84Portuguese2 is the MIB identifier with IANA name PT2. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO84Portuguese2 MIB = 60 + + // ISO85Spanish2 is the MIB identifier with IANA name ES2. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO85Spanish2 MIB = 61 + + // ISO86Hungarian is the MIB identifier with IANA name MSZ_7795.3. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO86Hungarian MIB = 62 + + // ISO87JISX0208 is the MIB identifier with IANA name JIS_C6226-1983. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO87JISX0208 MIB = 63 + + // ISO88Greek7 is the MIB identifier with IANA name greek7. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO88Greek7 MIB = 64 + + // ISO89ASMO449 is the MIB identifier with IANA name ASMO_449. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO89ASMO449 MIB = 65 + + // ISO90 is the MIB identifier with IANA name iso-ir-90. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO90 MIB = 66 + + // ISO91JISC62291984a is the MIB identifier with IANA name JIS_C6229-1984-a. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO91JISC62291984a MIB = 67 + + // ISO92JISC62991984b is the MIB identifier with IANA name JIS_C6229-1984-b. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO92JISC62991984b MIB = 68 + + // ISO93JIS62291984badd is the MIB identifier with IANA name JIS_C6229-1984-b-add. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO93JIS62291984badd MIB = 69 + + // ISO94JIS62291984hand is the MIB identifier with IANA name JIS_C6229-1984-hand. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO94JIS62291984hand MIB = 70 + + // ISO95JIS62291984handadd is the MIB identifier with IANA name JIS_C6229-1984-hand-add. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO95JIS62291984handadd MIB = 71 + + // ISO96JISC62291984kana is the MIB identifier with IANA name JIS_C6229-1984-kana. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO96JISC62291984kana MIB = 72 + + // ISO2033 is the MIB identifier with IANA name ISO_2033-1983. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO2033 MIB = 73 + + // ISO99NAPLPS is the MIB identifier with IANA name ANSI_X3.110-1983. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO99NAPLPS MIB = 74 + + // ISO102T617bit is the MIB identifier with IANA name T.61-7bit. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO102T617bit MIB = 75 + + // ISO103T618bit is the MIB identifier with IANA name T.61-8bit. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO103T618bit MIB = 76 + + // ISO111ECMACyrillic is the MIB identifier with IANA name ECMA-cyrillic. + // + // ISO registry + // (formerly ECMA + // registry ) + ISO111ECMACyrillic MIB = 77 + + // ISO121Canadian1 is the MIB identifier with IANA name CSA_Z243.4-1985-1. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO121Canadian1 MIB = 78 + + // ISO122Canadian2 is the MIB identifier with IANA name CSA_Z243.4-1985-2. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO122Canadian2 MIB = 79 + + // ISO123CSAZ24341985gr is the MIB identifier with IANA name CSA_Z243.4-1985-gr. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO123CSAZ24341985gr MIB = 80 + + // ISO88596E is the MIB identifier with IANA name ISO_8859-6-E (MIME: ISO-8859-6-E). + // + // rfc1556 + // Reference: RFC1556 + ISO88596E MIB = 81 + + // ISO88596I is the MIB identifier with IANA name ISO_8859-6-I (MIME: ISO-8859-6-I). + // + // rfc1556 + // Reference: RFC1556 + ISO88596I MIB = 82 + + // ISO128T101G2 is the MIB identifier with IANA name T.101-G2. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO128T101G2 MIB = 83 + + // ISO88598E is the MIB identifier with IANA name ISO_8859-8-E (MIME: ISO-8859-8-E). + // + // rfc1556 + // Reference: RFC1556 + ISO88598E MIB = 84 + + // ISO88598I is the MIB identifier with IANA name ISO_8859-8-I (MIME: ISO-8859-8-I). + // + // rfc1556 + // Reference: RFC1556 + ISO88598I MIB = 85 + + // ISO139CSN369103 is the MIB identifier with IANA name CSN_369103. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO139CSN369103 MIB = 86 + + // ISO141JUSIB1002 is the MIB identifier with IANA name JUS_I.B1.002. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO141JUSIB1002 MIB = 87 + + // ISO143IECP271 is the MIB identifier with IANA name IEC_P27-1. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO143IECP271 MIB = 88 + + // ISO146Serbian is the MIB identifier with IANA name JUS_I.B1.003-serb. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO146Serbian MIB = 89 + + // ISO147Macedonian is the MIB identifier with IANA name JUS_I.B1.003-mac. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO147Macedonian MIB = 90 + + // ISO150GreekCCITT is the MIB identifier with IANA name greek-ccitt. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO150GreekCCITT MIB = 91 + + // ISO151Cuba is the MIB identifier with IANA name NC_NC00-10:81. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO151Cuba MIB = 92 + + // ISO6937Add is the MIB identifier with IANA name ISO_6937-2-25. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO6937Add MIB = 93 + + // ISO153GOST1976874 is the MIB identifier with IANA name GOST_19768-74. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO153GOST1976874 MIB = 94 + + // ISO8859Supp is the MIB identifier with IANA name ISO_8859-supp. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO8859Supp MIB = 95 + + // ISO10367Box is the MIB identifier with IANA name ISO_10367-box. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO10367Box MIB = 96 + + // ISO158Lap is the MIB identifier with IANA name latin-lap. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO158Lap MIB = 97 + + // ISO159JISX02121990 is the MIB identifier with IANA name JIS_X0212-1990. + // + // ISO-IR: International Register of Escape Sequences + // Note: The current registration authority is IPSJ/ITSCJ, Japan. + // Reference: RFC1345 + ISO159JISX02121990 MIB = 98 + + // ISO646Danish is the MIB identifier with IANA name DS_2089. + // + // Danish Standard, DS 2089, February 1974 + // Reference: RFC1345 + ISO646Danish MIB = 99 + + // USDK is the MIB identifier with IANA name us-dk. + // + // Reference: RFC1345 + USDK MIB = 100 + + // DKUS is the MIB identifier with IANA name dk-us. + // + // Reference: RFC1345 + DKUS MIB = 101 + + // KSC5636 is the MIB identifier with IANA name KSC5636. + // + // Reference: RFC1345 + KSC5636 MIB = 102 + + // Unicode11UTF7 is the MIB identifier with IANA name UNICODE-1-1-UTF-7. + // + // rfc1642 + // Reference: RFC1642 + Unicode11UTF7 MIB = 103 + + // ISO2022CN is the MIB identifier with IANA name ISO-2022-CN. + // + // rfc1922 + // Reference: RFC1922 + ISO2022CN MIB = 104 + + // ISO2022CNEXT is the MIB identifier with IANA name ISO-2022-CN-EXT. + // + // rfc1922 + // Reference: RFC1922 + ISO2022CNEXT MIB = 105 + + // UTF8 is the MIB identifier with IANA name UTF-8. + // + // rfc3629 + // Reference: RFC3629 + UTF8 MIB = 106 + + // ISO885913 is the MIB identifier with IANA name ISO-8859-13. + // + // ISO See http://www.iana.org/assignments/charset-reg/ISO-8859-13 http://www.iana.org/assignments/charset-reg/ISO-8859-13 + ISO885913 MIB = 109 + + // ISO885914 is the MIB identifier with IANA name ISO-8859-14. + // + // ISO See http://www.iana.org/assignments/charset-reg/ISO-8859-14 + ISO885914 MIB = 110 + + // ISO885915 is the MIB identifier with IANA name ISO-8859-15. + // + // ISO + // Please see: http://www.iana.org/assignments/charset-reg/ISO-8859-15 + ISO885915 MIB = 111 + + // ISO885916 is the MIB identifier with IANA name ISO-8859-16. + // + // ISO + ISO885916 MIB = 112 + + // GBK is the MIB identifier with IANA name GBK. + // + // Chinese IT Standardization Technical Committee + // Please see: http://www.iana.org/assignments/charset-reg/GBK + GBK MIB = 113 + + // GB18030 is the MIB identifier with IANA name GB18030. + // + // Chinese IT Standardization Technical Committee + // Please see: http://www.iana.org/assignments/charset-reg/GB18030 + GB18030 MIB = 114 + + // OSDEBCDICDF0415 is the MIB identifier with IANA name OSD_EBCDIC_DF04_15. + // + // Fujitsu-Siemens standard mainframe EBCDIC encoding + // Please see: http://www.iana.org/assignments/charset-reg/OSD-EBCDIC-DF04-15 + OSDEBCDICDF0415 MIB = 115 + + // OSDEBCDICDF03IRV is the MIB identifier with IANA name OSD_EBCDIC_DF03_IRV. + // + // Fujitsu-Siemens standard mainframe EBCDIC encoding + // Please see: http://www.iana.org/assignments/charset-reg/OSD-EBCDIC-DF03-IRV + OSDEBCDICDF03IRV MIB = 116 + + // OSDEBCDICDF041 is the MIB identifier with IANA name OSD_EBCDIC_DF04_1. + // + // Fujitsu-Siemens standard mainframe EBCDIC encoding + // Please see: http://www.iana.org/assignments/charset-reg/OSD-EBCDIC-DF04-1 + OSDEBCDICDF041 MIB = 117 + + // ISO115481 is the MIB identifier with IANA name ISO-11548-1. + // + // See http://www.iana.org/assignments/charset-reg/ISO-11548-1 + ISO115481 MIB = 118 + + // KZ1048 is the MIB identifier with IANA name KZ-1048. + // + // See http://www.iana.org/assignments/charset-reg/KZ-1048 + KZ1048 MIB = 119 + + // Unicode is the MIB identifier with IANA name ISO-10646-UCS-2. + // + // the 2-octet Basic Multilingual Plane, aka Unicode + // this needs to specify network byte order: the standard + // does not specify (it is a 16-bit integer space) + Unicode MIB = 1000 + + // UCS4 is the MIB identifier with IANA name ISO-10646-UCS-4. + // + // the full code space. (same comment about byte order, + // these are 31-bit numbers. + UCS4 MIB = 1001 + + // UnicodeASCII is the MIB identifier with IANA name ISO-10646-UCS-Basic. + // + // ASCII subset of Unicode. Basic Latin = collection 1 + // See ISO 10646, Appendix A + UnicodeASCII MIB = 1002 + + // UnicodeLatin1 is the MIB identifier with IANA name ISO-10646-Unicode-Latin1. + // + // ISO Latin-1 subset of Unicode. Basic Latin and Latin-1 + // Supplement = collections 1 and 2. See ISO 10646, + // Appendix A. See rfc1815 . + UnicodeLatin1 MIB = 1003 + + // UnicodeJapanese is the MIB identifier with IANA name ISO-10646-J-1. + // + // ISO 10646 Japanese, see rfc1815 . + UnicodeJapanese MIB = 1004 + + // UnicodeIBM1261 is the MIB identifier with IANA name ISO-Unicode-IBM-1261. + // + // IBM Latin-2, -3, -5, Extended Presentation Set, GCSGID: 1261 + UnicodeIBM1261 MIB = 1005 + + // UnicodeIBM1268 is the MIB identifier with IANA name ISO-Unicode-IBM-1268. + // + // IBM Latin-4 Extended Presentation Set, GCSGID: 1268 + UnicodeIBM1268 MIB = 1006 + + // UnicodeIBM1276 is the MIB identifier with IANA name ISO-Unicode-IBM-1276. + // + // IBM Cyrillic Greek Extended Presentation Set, GCSGID: 1276 + UnicodeIBM1276 MIB = 1007 + + // UnicodeIBM1264 is the MIB identifier with IANA name ISO-Unicode-IBM-1264. + // + // IBM Arabic Presentation Set, GCSGID: 1264 + UnicodeIBM1264 MIB = 1008 + + // UnicodeIBM1265 is the MIB identifier with IANA name ISO-Unicode-IBM-1265. + // + // IBM Hebrew Presentation Set, GCSGID: 1265 + UnicodeIBM1265 MIB = 1009 + + // Unicode11 is the MIB identifier with IANA name UNICODE-1-1. + // + // rfc1641 + // Reference: RFC1641 + Unicode11 MIB = 1010 + + // SCSU is the MIB identifier with IANA name SCSU. + // + // SCSU See http://www.iana.org/assignments/charset-reg/SCSU + SCSU MIB = 1011 + + // UTF7 is the MIB identifier with IANA name UTF-7. + // + // rfc2152 + // Reference: RFC2152 + UTF7 MIB = 1012 + + // UTF16BE is the MIB identifier with IANA name UTF-16BE. + // + // rfc2781 + // Reference: RFC2781 + UTF16BE MIB = 1013 + + // UTF16LE is the MIB identifier with IANA name UTF-16LE. + // + // rfc2781 + // Reference: RFC2781 + UTF16LE MIB = 1014 + + // UTF16 is the MIB identifier with IANA name UTF-16. + // + // rfc2781 + // Reference: RFC2781 + UTF16 MIB = 1015 + + // CESU8 is the MIB identifier with IANA name CESU-8. + // + // http://www.unicode.org/unicode/reports/tr26 + CESU8 MIB = 1016 + + // UTF32 is the MIB identifier with IANA name UTF-32. + // + // http://www.unicode.org/unicode/reports/tr19/ + UTF32 MIB = 1017 + + // UTF32BE is the MIB identifier with IANA name UTF-32BE. + // + // http://www.unicode.org/unicode/reports/tr19/ + UTF32BE MIB = 1018 + + // UTF32LE is the MIB identifier with IANA name UTF-32LE. + // + // http://www.unicode.org/unicode/reports/tr19/ + UTF32LE MIB = 1019 + + // BOCU1 is the MIB identifier with IANA name BOCU-1. + // + // http://www.unicode.org/notes/tn6/ + BOCU1 MIB = 1020 + + // Windows30Latin1 is the MIB identifier with IANA name ISO-8859-1-Windows-3.0-Latin-1. + // + // Extended ISO 8859-1 Latin-1 for Windows 3.0. + // PCL Symbol Set id: 9U + Windows30Latin1 MIB = 2000 + + // Windows31Latin1 is the MIB identifier with IANA name ISO-8859-1-Windows-3.1-Latin-1. + // + // Extended ISO 8859-1 Latin-1 for Windows 3.1. + // PCL Symbol Set id: 19U + Windows31Latin1 MIB = 2001 + + // Windows31Latin2 is the MIB identifier with IANA name ISO-8859-2-Windows-Latin-2. + // + // Extended ISO 8859-2. Latin-2 for Windows 3.1. + // PCL Symbol Set id: 9E + Windows31Latin2 MIB = 2002 + + // Windows31Latin5 is the MIB identifier with IANA name ISO-8859-9-Windows-Latin-5. + // + // Extended ISO 8859-9. Latin-5 for Windows 3.1 + // PCL Symbol Set id: 5T + Windows31Latin5 MIB = 2003 + + // HPRoman8 is the MIB identifier with IANA name hp-roman8. + // + // LaserJet IIP Printer User's Manual, + // HP part no 33471-90901, Hewlet-Packard, June 1989. + // Reference: RFC1345 + HPRoman8 MIB = 2004 + + // AdobeStandardEncoding is the MIB identifier with IANA name Adobe-Standard-Encoding. + // + // PostScript Language Reference Manual + // PCL Symbol Set id: 10J + AdobeStandardEncoding MIB = 2005 + + // VenturaUS is the MIB identifier with IANA name Ventura-US. + // + // Ventura US. ASCII plus characters typically used in + // publishing, like pilcrow, copyright, registered, trade mark, + // section, dagger, and double dagger in the range A0 (hex) + // to FF (hex). + // PCL Symbol Set id: 14J + VenturaUS MIB = 2006 + + // VenturaInternational is the MIB identifier with IANA name Ventura-International. + // + // Ventura International. ASCII plus coded characters similar + // to Roman8. + // PCL Symbol Set id: 13J + VenturaInternational MIB = 2007 + + // DECMCS is the MIB identifier with IANA name DEC-MCS. + // + // VAX/VMS User's Manual, + // Order Number: AI-Y517A-TE, April 1986. + // Reference: RFC1345 + DECMCS MIB = 2008 + + // PC850Multilingual is the MIB identifier with IANA name IBM850. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + PC850Multilingual MIB = 2009 + + // PC8DanishNorwegian is the MIB identifier with IANA name PC8-Danish-Norwegian. + // + // PC Danish Norwegian + // 8-bit PC set for Danish Norwegian + // PCL Symbol Set id: 11U + PC8DanishNorwegian MIB = 2012 + + // PC862LatinHebrew is the MIB identifier with IANA name IBM862. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + PC862LatinHebrew MIB = 2013 + + // PC8Turkish is the MIB identifier with IANA name PC8-Turkish. + // + // PC Latin Turkish. PCL Symbol Set id: 9T + PC8Turkish MIB = 2014 + + // IBMSymbols is the MIB identifier with IANA name IBM-Symbols. + // + // Presentation Set, CPGID: 259 + IBMSymbols MIB = 2015 + + // IBMThai is the MIB identifier with IANA name IBM-Thai. + // + // Presentation Set, CPGID: 838 + IBMThai MIB = 2016 + + // HPLegal is the MIB identifier with IANA name HP-Legal. + // + // PCL 5 Comparison Guide, Hewlett-Packard, + // HP part number 5961-0510, October 1992 + // PCL Symbol Set id: 1U + HPLegal MIB = 2017 + + // HPPiFont is the MIB identifier with IANA name HP-Pi-font. + // + // PCL 5 Comparison Guide, Hewlett-Packard, + // HP part number 5961-0510, October 1992 + // PCL Symbol Set id: 15U + HPPiFont MIB = 2018 + + // HPMath8 is the MIB identifier with IANA name HP-Math8. + // + // PCL 5 Comparison Guide, Hewlett-Packard, + // HP part number 5961-0510, October 1992 + // PCL Symbol Set id: 8M + HPMath8 MIB = 2019 + + // HPPSMath is the MIB identifier with IANA name Adobe-Symbol-Encoding. + // + // PostScript Language Reference Manual + // PCL Symbol Set id: 5M + HPPSMath MIB = 2020 + + // HPDesktop is the MIB identifier with IANA name HP-DeskTop. + // + // PCL 5 Comparison Guide, Hewlett-Packard, + // HP part number 5961-0510, October 1992 + // PCL Symbol Set id: 7J + HPDesktop MIB = 2021 + + // VenturaMath is the MIB identifier with IANA name Ventura-Math. + // + // PCL 5 Comparison Guide, Hewlett-Packard, + // HP part number 5961-0510, October 1992 + // PCL Symbol Set id: 6M + VenturaMath MIB = 2022 + + // MicrosoftPublishing is the MIB identifier with IANA name Microsoft-Publishing. + // + // PCL 5 Comparison Guide, Hewlett-Packard, + // HP part number 5961-0510, October 1992 + // PCL Symbol Set id: 6J + MicrosoftPublishing MIB = 2023 + + // Windows31J is the MIB identifier with IANA name Windows-31J. + // + // Windows Japanese. A further extension of Shift_JIS + // to include NEC special characters (Row 13), NEC + // selection of IBM extensions (Rows 89 to 92), and IBM + // extensions (Rows 115 to 119). The CCS's are + // JIS X0201:1997, JIS X0208:1997, and these extensions. + // This charset can be used for the top-level media type "text", + // but it is of limited or specialized use (see rfc2278 ). + // PCL Symbol Set id: 19K + Windows31J MIB = 2024 + + // GB2312 is the MIB identifier with IANA name GB2312 (MIME: GB2312). + // + // Chinese for People's Republic of China (PRC) mixed one byte, + // two byte set: + // 20-7E = one byte ASCII + // A1-FE = two byte PRC Kanji + // See GB 2312-80 + // PCL Symbol Set Id: 18C + GB2312 MIB = 2025 + + // Big5 is the MIB identifier with IANA name Big5 (MIME: Big5). + // + // Chinese for Taiwan Multi-byte set. + // PCL Symbol Set Id: 18T + Big5 MIB = 2026 + + // Macintosh is the MIB identifier with IANA name macintosh. + // + // The Unicode Standard ver1.0, ISBN 0-201-56788-1, Oct 1991 + // Reference: RFC1345 + Macintosh MIB = 2027 + + // IBM037 is the MIB identifier with IANA name IBM037. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM037 MIB = 2028 + + // IBM038 is the MIB identifier with IANA name IBM038. + // + // IBM 3174 Character Set Ref, GA27-3831-02, March 1990 + // Reference: RFC1345 + IBM038 MIB = 2029 + + // IBM273 is the MIB identifier with IANA name IBM273. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM273 MIB = 2030 + + // IBM274 is the MIB identifier with IANA name IBM274. + // + // IBM 3174 Character Set Ref, GA27-3831-02, March 1990 + // Reference: RFC1345 + IBM274 MIB = 2031 + + // IBM275 is the MIB identifier with IANA name IBM275. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM275 MIB = 2032 + + // IBM277 is the MIB identifier with IANA name IBM277. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM277 MIB = 2033 + + // IBM278 is the MIB identifier with IANA name IBM278. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM278 MIB = 2034 + + // IBM280 is the MIB identifier with IANA name IBM280. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM280 MIB = 2035 + + // IBM281 is the MIB identifier with IANA name IBM281. + // + // IBM 3174 Character Set Ref, GA27-3831-02, March 1990 + // Reference: RFC1345 + IBM281 MIB = 2036 + + // IBM284 is the MIB identifier with IANA name IBM284. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM284 MIB = 2037 + + // IBM285 is the MIB identifier with IANA name IBM285. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM285 MIB = 2038 + + // IBM290 is the MIB identifier with IANA name IBM290. + // + // IBM 3174 Character Set Ref, GA27-3831-02, March 1990 + // Reference: RFC1345 + IBM290 MIB = 2039 + + // IBM297 is the MIB identifier with IANA name IBM297. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM297 MIB = 2040 + + // IBM420 is the MIB identifier with IANA name IBM420. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990, + // IBM NLS RM p 11-11 + // Reference: RFC1345 + IBM420 MIB = 2041 + + // IBM423 is the MIB identifier with IANA name IBM423. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM423 MIB = 2042 + + // IBM424 is the MIB identifier with IANA name IBM424. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM424 MIB = 2043 + + // PC8CodePage437 is the MIB identifier with IANA name IBM437. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + PC8CodePage437 MIB = 2011 + + // IBM500 is the MIB identifier with IANA name IBM500. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM500 MIB = 2044 + + // IBM851 is the MIB identifier with IANA name IBM851. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM851 MIB = 2045 + + // PCp852 is the MIB identifier with IANA name IBM852. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + PCp852 MIB = 2010 + + // IBM855 is the MIB identifier with IANA name IBM855. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM855 MIB = 2046 + + // IBM857 is the MIB identifier with IANA name IBM857. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM857 MIB = 2047 + + // IBM860 is the MIB identifier with IANA name IBM860. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM860 MIB = 2048 + + // IBM861 is the MIB identifier with IANA name IBM861. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM861 MIB = 2049 + + // IBM863 is the MIB identifier with IANA name IBM863. + // + // IBM Keyboard layouts and code pages, PN 07G4586 June 1991 + // Reference: RFC1345 + IBM863 MIB = 2050 + + // IBM864 is the MIB identifier with IANA name IBM864. + // + // IBM Keyboard layouts and code pages, PN 07G4586 June 1991 + // Reference: RFC1345 + IBM864 MIB = 2051 + + // IBM865 is the MIB identifier with IANA name IBM865. + // + // IBM DOS 3.3 Ref (Abridged), 94X9575 (Feb 1987) + // Reference: RFC1345 + IBM865 MIB = 2052 + + // IBM868 is the MIB identifier with IANA name IBM868. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM868 MIB = 2053 + + // IBM869 is the MIB identifier with IANA name IBM869. + // + // IBM Keyboard layouts and code pages, PN 07G4586 June 1991 + // Reference: RFC1345 + IBM869 MIB = 2054 + + // IBM870 is the MIB identifier with IANA name IBM870. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM870 MIB = 2055 + + // IBM871 is the MIB identifier with IANA name IBM871. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM871 MIB = 2056 + + // IBM880 is the MIB identifier with IANA name IBM880. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM880 MIB = 2057 + + // IBM891 is the MIB identifier with IANA name IBM891. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM891 MIB = 2058 + + // IBM903 is the MIB identifier with IANA name IBM903. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM903 MIB = 2059 + + // IBBM904 is the MIB identifier with IANA name IBM904. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBBM904 MIB = 2060 + + // IBM905 is the MIB identifier with IANA name IBM905. + // + // IBM 3174 Character Set Ref, GA27-3831-02, March 1990 + // Reference: RFC1345 + IBM905 MIB = 2061 + + // IBM918 is the MIB identifier with IANA name IBM918. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM918 MIB = 2062 + + // IBM1026 is the MIB identifier with IANA name IBM1026. + // + // IBM NLS RM Vol2 SE09-8002-01, March 1990 + // Reference: RFC1345 + IBM1026 MIB = 2063 + + // IBMEBCDICATDE is the MIB identifier with IANA name EBCDIC-AT-DE. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + IBMEBCDICATDE MIB = 2064 + + // EBCDICATDEA is the MIB identifier with IANA name EBCDIC-AT-DE-A. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICATDEA MIB = 2065 + + // EBCDICCAFR is the MIB identifier with IANA name EBCDIC-CA-FR. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICCAFR MIB = 2066 + + // EBCDICDKNO is the MIB identifier with IANA name EBCDIC-DK-NO. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICDKNO MIB = 2067 + + // EBCDICDKNOA is the MIB identifier with IANA name EBCDIC-DK-NO-A. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICDKNOA MIB = 2068 + + // EBCDICFISE is the MIB identifier with IANA name EBCDIC-FI-SE. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICFISE MIB = 2069 + + // EBCDICFISEA is the MIB identifier with IANA name EBCDIC-FI-SE-A. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICFISEA MIB = 2070 + + // EBCDICFR is the MIB identifier with IANA name EBCDIC-FR. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICFR MIB = 2071 + + // EBCDICIT is the MIB identifier with IANA name EBCDIC-IT. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICIT MIB = 2072 + + // EBCDICPT is the MIB identifier with IANA name EBCDIC-PT. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICPT MIB = 2073 + + // EBCDICES is the MIB identifier with IANA name EBCDIC-ES. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICES MIB = 2074 + + // EBCDICESA is the MIB identifier with IANA name EBCDIC-ES-A. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICESA MIB = 2075 + + // EBCDICESS is the MIB identifier with IANA name EBCDIC-ES-S. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICESS MIB = 2076 + + // EBCDICUK is the MIB identifier with IANA name EBCDIC-UK. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICUK MIB = 2077 + + // EBCDICUS is the MIB identifier with IANA name EBCDIC-US. + // + // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987 + // Reference: RFC1345 + EBCDICUS MIB = 2078 + + // Unknown8BiT is the MIB identifier with IANA name UNKNOWN-8BIT. + // + // Reference: RFC1428 + Unknown8BiT MIB = 2079 + + // Mnemonic is the MIB identifier with IANA name MNEMONIC. + // + // rfc1345 , also known as "mnemonic+ascii+38" + // Reference: RFC1345 + Mnemonic MIB = 2080 + + // Mnem is the MIB identifier with IANA name MNEM. + // + // rfc1345 , also known as "mnemonic+ascii+8200" + // Reference: RFC1345 + Mnem MIB = 2081 + + // VISCII is the MIB identifier with IANA name VISCII. + // + // rfc1456 + // Reference: RFC1456 + VISCII MIB = 2082 + + // VIQR is the MIB identifier with IANA name VIQR. + // + // rfc1456 + // Reference: RFC1456 + VIQR MIB = 2083 + + // KOI8R is the MIB identifier with IANA name KOI8-R (MIME: KOI8-R). + // + // rfc1489 , based on GOST-19768-74, ISO-6937/8, + // INIS-Cyrillic, ISO-5427. + // Reference: RFC1489 + KOI8R MIB = 2084 + + // HZGB2312 is the MIB identifier with IANA name HZ-GB-2312. + // + // rfc1842 , rfc1843 rfc1843 rfc1842 + HZGB2312 MIB = 2085 + + // IBM866 is the MIB identifier with IANA name IBM866. + // + // IBM NLDG Volume 2 (SE09-8002-03) August 1994 + IBM866 MIB = 2086 + + // PC775Baltic is the MIB identifier with IANA name IBM775. + // + // HP PCL 5 Comparison Guide (P/N 5021-0329) pp B-13, 1996 + PC775Baltic MIB = 2087 + + // KOI8U is the MIB identifier with IANA name KOI8-U. + // + // rfc2319 + // Reference: RFC2319 + KOI8U MIB = 2088 + + // IBM00858 is the MIB identifier with IANA name IBM00858. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM00858 + IBM00858 MIB = 2089 + + // IBM00924 is the MIB identifier with IANA name IBM00924. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM00924 + IBM00924 MIB = 2090 + + // IBM01140 is the MIB identifier with IANA name IBM01140. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01140 + IBM01140 MIB = 2091 + + // IBM01141 is the MIB identifier with IANA name IBM01141. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01141 + IBM01141 MIB = 2092 + + // IBM01142 is the MIB identifier with IANA name IBM01142. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01142 + IBM01142 MIB = 2093 + + // IBM01143 is the MIB identifier with IANA name IBM01143. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01143 + IBM01143 MIB = 2094 + + // IBM01144 is the MIB identifier with IANA name IBM01144. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01144 + IBM01144 MIB = 2095 + + // IBM01145 is the MIB identifier with IANA name IBM01145. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01145 + IBM01145 MIB = 2096 + + // IBM01146 is the MIB identifier with IANA name IBM01146. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01146 + IBM01146 MIB = 2097 + + // IBM01147 is the MIB identifier with IANA name IBM01147. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01147 + IBM01147 MIB = 2098 + + // IBM01148 is the MIB identifier with IANA name IBM01148. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01148 + IBM01148 MIB = 2099 + + // IBM01149 is the MIB identifier with IANA name IBM01149. + // + // IBM See http://www.iana.org/assignments/charset-reg/IBM01149 + IBM01149 MIB = 2100 + + // Big5HKSCS is the MIB identifier with IANA name Big5-HKSCS. + // + // See http://www.iana.org/assignments/charset-reg/Big5-HKSCS + Big5HKSCS MIB = 2101 + + // IBM1047 is the MIB identifier with IANA name IBM1047. + // + // IBM1047 (EBCDIC Latin 1/Open Systems) http://www-1.ibm.com/servers/eserver/iseries/software/globalization/pdf/cp01047z.pdf + IBM1047 MIB = 2102 + + // PTCP154 is the MIB identifier with IANA name PTCP154. + // + // See http://www.iana.org/assignments/charset-reg/PTCP154 + PTCP154 MIB = 2103 + + // Amiga1251 is the MIB identifier with IANA name Amiga-1251. + // + // See http://www.amiga.ultranet.ru/Amiga-1251.html + Amiga1251 MIB = 2104 + + // KOI7switched is the MIB identifier with IANA name KOI7-switched. + // + // See http://www.iana.org/assignments/charset-reg/KOI7-switched + KOI7switched MIB = 2105 + + // BRF is the MIB identifier with IANA name BRF. + // + // See http://www.iana.org/assignments/charset-reg/BRF + BRF MIB = 2106 + + // TSCII is the MIB identifier with IANA name TSCII. + // + // See http://www.iana.org/assignments/charset-reg/TSCII + TSCII MIB = 2107 + + // CP51932 is the MIB identifier with IANA name CP51932. + // + // See http://www.iana.org/assignments/charset-reg/CP51932 + CP51932 MIB = 2108 + + // Windows874 is the MIB identifier with IANA name windows-874. + // + // See http://www.iana.org/assignments/charset-reg/windows-874 + Windows874 MIB = 2109 + + // Windows1250 is the MIB identifier with IANA name windows-1250. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1250 + Windows1250 MIB = 2250 + + // Windows1251 is the MIB identifier with IANA name windows-1251. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1251 + Windows1251 MIB = 2251 + + // Windows1252 is the MIB identifier with IANA name windows-1252. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1252 + Windows1252 MIB = 2252 + + // Windows1253 is the MIB identifier with IANA name windows-1253. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1253 + Windows1253 MIB = 2253 + + // Windows1254 is the MIB identifier with IANA name windows-1254. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1254 + Windows1254 MIB = 2254 + + // Windows1255 is the MIB identifier with IANA name windows-1255. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1255 + Windows1255 MIB = 2255 + + // Windows1256 is the MIB identifier with IANA name windows-1256. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1256 + Windows1256 MIB = 2256 + + // Windows1257 is the MIB identifier with IANA name windows-1257. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1257 + Windows1257 MIB = 2257 + + // Windows1258 is the MIB identifier with IANA name windows-1258. + // + // Microsoft http://www.iana.org/assignments/charset-reg/windows-1258 + Windows1258 MIB = 2258 + + // TIS620 is the MIB identifier with IANA name TIS-620. + // + // Thai Industrial Standards Institute (TISI) + TIS620 MIB = 2259 + + // CP50220 is the MIB identifier with IANA name CP50220. + // + // See http://www.iana.org/assignments/charset-reg/CP50220 + CP50220 MIB = 2260 +) diff --git a/vendor/golang.org/x/text/internal/gen/code.go b/vendor/golang.org/x/text/internal/gen/code.go new file mode 100644 index 00000000..0389509f --- /dev/null +++ b/vendor/golang.org/x/text/internal/gen/code.go @@ -0,0 +1,369 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gen + +import ( + "bytes" + "encoding/gob" + "fmt" + "hash" + "hash/fnv" + "io" + "log" + "os" + "reflect" + "strings" + "unicode" + "unicode/utf8" +) + +// This file contains utilities for generating code. + +// TODO: other write methods like: +// - slices, maps, types, etc. + +// CodeWriter is a utility for writing structured code. It computes the content +// hash and size of written content. It ensures there are newlines between +// written code blocks. +type CodeWriter struct { + buf bytes.Buffer + Size int + Hash hash.Hash32 // content hash + gob *gob.Encoder + // For comments we skip the usual one-line separator if they are followed by + // a code block. + skipSep bool +} + +func (w *CodeWriter) Write(p []byte) (n int, err error) { + return w.buf.Write(p) +} + +// NewCodeWriter returns a new CodeWriter. +func NewCodeWriter() *CodeWriter { + h := fnv.New32() + return &CodeWriter{Hash: h, gob: gob.NewEncoder(h)} +} + +// WriteGoFile appends the buffer with the total size of all created structures +// and writes it as a Go file to the the given file with the given package name. +func (w *CodeWriter) WriteGoFile(filename, pkg string) { + f, err := os.Create(filename) + if err != nil { + log.Fatalf("Could not create file %s: %v", filename, err) + } + defer f.Close() + if _, err = w.WriteGo(f, pkg, ""); err != nil { + log.Fatalf("Error writing file %s: %v", filename, err) + } +} + +// WriteVersionedGoFile appends the buffer with the total size of all created +// structures and writes it as a Go file to the the given file with the given +// package name and build tags for the current Unicode version, +func (w *CodeWriter) WriteVersionedGoFile(filename, pkg string) { + tags := buildTags() + if tags != "" { + filename = insertVersion(filename, UnicodeVersion()) + } + f, err := os.Create(filename) + if err != nil { + log.Fatalf("Could not create file %s: %v", filename, err) + } + defer f.Close() + if _, err = w.WriteGo(f, pkg, tags); err != nil { + log.Fatalf("Error writing file %s: %v", filename, err) + } +} + +// WriteGo appends the buffer with the total size of all created structures and +// writes it as a Go file to the the given writer with the given package name. +func (w *CodeWriter) WriteGo(out io.Writer, pkg, tags string) (n int, err error) { + sz := w.Size + w.WriteComment("Total table size %d bytes (%dKiB); checksum: %X\n", sz, sz/1024, w.Hash.Sum32()) + defer w.buf.Reset() + return WriteGo(out, pkg, tags, w.buf.Bytes()) +} + +func (w *CodeWriter) printf(f string, x ...interface{}) { + fmt.Fprintf(w, f, x...) +} + +func (w *CodeWriter) insertSep() { + if w.skipSep { + w.skipSep = false + return + } + // Use at least two newlines to ensure a blank space between the previous + // block. WriteGoFile will remove extraneous newlines. + w.printf("\n\n") +} + +// WriteComment writes a comment block. All line starts are prefixed with "//". +// Initial empty lines are gobbled. The indentation for the first line is +// stripped from consecutive lines. +func (w *CodeWriter) WriteComment(comment string, args ...interface{}) { + s := fmt.Sprintf(comment, args...) + s = strings.Trim(s, "\n") + + // Use at least two newlines to ensure a blank space between the previous + // block. WriteGoFile will remove extraneous newlines. + w.printf("\n\n// ") + w.skipSep = true + + // strip first indent level. + sep := "\n" + for ; len(s) > 0 && (s[0] == '\t' || s[0] == ' '); s = s[1:] { + sep += s[:1] + } + + strings.NewReplacer(sep, "\n// ", "\n", "\n// ").WriteString(w, s) + + w.printf("\n") +} + +func (w *CodeWriter) writeSizeInfo(size int) { + w.printf("// Size: %d bytes\n", size) +} + +// WriteConst writes a constant of the given name and value. +func (w *CodeWriter) WriteConst(name string, x interface{}) { + w.insertSep() + v := reflect.ValueOf(x) + + switch v.Type().Kind() { + case reflect.String: + w.printf("const %s %s = ", name, typeName(x)) + w.WriteString(v.String()) + w.printf("\n") + default: + w.printf("const %s = %#v\n", name, x) + } +} + +// WriteVar writes a variable of the given name and value. +func (w *CodeWriter) WriteVar(name string, x interface{}) { + w.insertSep() + v := reflect.ValueOf(x) + oldSize := w.Size + sz := int(v.Type().Size()) + w.Size += sz + + switch v.Type().Kind() { + case reflect.String: + w.printf("var %s %s = ", name, typeName(x)) + w.WriteString(v.String()) + case reflect.Struct: + w.gob.Encode(x) + fallthrough + case reflect.Slice, reflect.Array: + w.printf("var %s = ", name) + w.writeValue(v) + w.writeSizeInfo(w.Size - oldSize) + default: + w.printf("var %s %s = ", name, typeName(x)) + w.gob.Encode(x) + w.writeValue(v) + w.writeSizeInfo(w.Size - oldSize) + } + w.printf("\n") +} + +func (w *CodeWriter) writeValue(v reflect.Value) { + x := v.Interface() + switch v.Kind() { + case reflect.String: + w.WriteString(v.String()) + case reflect.Array: + // Don't double count: callers of WriteArray count on the size being + // added, so we need to discount it here. + w.Size -= int(v.Type().Size()) + w.writeSlice(x, true) + case reflect.Slice: + w.writeSlice(x, false) + case reflect.Struct: + w.printf("%s{\n", typeName(v.Interface())) + t := v.Type() + for i := 0; i < v.NumField(); i++ { + w.printf("%s: ", t.Field(i).Name) + w.writeValue(v.Field(i)) + w.printf(",\n") + } + w.printf("}") + default: + w.printf("%#v", x) + } +} + +// WriteString writes a string literal. +func (w *CodeWriter) WriteString(s string) { + s = strings.Replace(s, `\`, `\\`, -1) + io.WriteString(w.Hash, s) // content hash + w.Size += len(s) + + const maxInline = 40 + if len(s) <= maxInline { + w.printf("%q", s) + return + } + + // We will render the string as a multi-line string. + const maxWidth = 80 - 4 - len(`"`) - len(`" +`) + + // When starting on its own line, go fmt indents line 2+ an extra level. + n, max := maxWidth, maxWidth-4 + + // As per https://golang.org/issue/18078, the compiler has trouble + // compiling the concatenation of many strings, s0 + s1 + s2 + ... + sN, + // for large N. We insert redundant, explicit parentheses to work around + // that, lowering the N at any given step: (s0 + s1 + ... + s63) + (s64 + + // ... + s127) + etc + (etc + ... + sN). + explicitParens, extraComment := len(s) > 128*1024, "" + if explicitParens { + w.printf(`(`) + extraComment = "; the redundant, explicit parens are for https://golang.org/issue/18078" + } + + // Print "" +\n, if a string does not start on its own line. + b := w.buf.Bytes() + if p := len(bytes.TrimRight(b, " \t")); p > 0 && b[p-1] != '\n' { + w.printf("\"\" + // Size: %d bytes%s\n", len(s), extraComment) + n, max = maxWidth, maxWidth + } + + w.printf(`"`) + + for sz, p, nLines := 0, 0, 0; p < len(s); { + var r rune + r, sz = utf8.DecodeRuneInString(s[p:]) + out := s[p : p+sz] + chars := 1 + if !unicode.IsPrint(r) || r == utf8.RuneError || r == '"' { + switch sz { + case 1: + out = fmt.Sprintf("\\x%02x", s[p]) + case 2, 3: + out = fmt.Sprintf("\\u%04x", r) + case 4: + out = fmt.Sprintf("\\U%08x", r) + } + chars = len(out) + } + if n -= chars; n < 0 { + nLines++ + if explicitParens && nLines&63 == 63 { + w.printf("\") + (\"") + } + w.printf("\" +\n\"") + n = max - len(out) + } + w.printf("%s", out) + p += sz + } + w.printf(`"`) + if explicitParens { + w.printf(`)`) + } +} + +// WriteSlice writes a slice value. +func (w *CodeWriter) WriteSlice(x interface{}) { + w.writeSlice(x, false) +} + +// WriteArray writes an array value. +func (w *CodeWriter) WriteArray(x interface{}) { + w.writeSlice(x, true) +} + +func (w *CodeWriter) writeSlice(x interface{}, isArray bool) { + v := reflect.ValueOf(x) + w.gob.Encode(v.Len()) + w.Size += v.Len() * int(v.Type().Elem().Size()) + name := typeName(x) + if isArray { + name = fmt.Sprintf("[%d]%s", v.Len(), name[strings.Index(name, "]")+1:]) + } + if isArray { + w.printf("%s{\n", name) + } else { + w.printf("%s{ // %d elements\n", name, v.Len()) + } + + switch kind := v.Type().Elem().Kind(); kind { + case reflect.String: + for _, s := range x.([]string) { + w.WriteString(s) + w.printf(",\n") + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + // nLine and nBlock are the number of elements per line and block. + nLine, nBlock, format := 8, 64, "%d," + switch kind { + case reflect.Uint8: + format = "%#02x," + case reflect.Uint16: + format = "%#04x," + case reflect.Uint32: + nLine, nBlock, format = 4, 32, "%#08x," + case reflect.Uint, reflect.Uint64: + nLine, nBlock, format = 4, 32, "%#016x," + case reflect.Int8: + nLine = 16 + } + n := nLine + for i := 0; i < v.Len(); i++ { + if i%nBlock == 0 && v.Len() > nBlock { + w.printf("// Entry %X - %X\n", i, i+nBlock-1) + } + x := v.Index(i).Interface() + w.gob.Encode(x) + w.printf(format, x) + if n--; n == 0 { + n = nLine + w.printf("\n") + } + } + w.printf("\n") + case reflect.Struct: + zero := reflect.Zero(v.Type().Elem()).Interface() + for i := 0; i < v.Len(); i++ { + x := v.Index(i).Interface() + w.gob.EncodeValue(v) + if !reflect.DeepEqual(zero, x) { + line := fmt.Sprintf("%#v,\n", x) + line = line[strings.IndexByte(line, '{'):] + w.printf("%d: ", i) + w.printf(line) + } + } + case reflect.Array: + for i := 0; i < v.Len(); i++ { + w.printf("%d: %#v,\n", i, v.Index(i).Interface()) + } + default: + panic("gen: slice elem type not supported") + } + w.printf("}") +} + +// WriteType writes a definition of the type of the given value and returns the +// type name. +func (w *CodeWriter) WriteType(x interface{}) string { + t := reflect.TypeOf(x) + w.printf("type %s struct {\n", t.Name()) + for i := 0; i < t.NumField(); i++ { + w.printf("\t%s %s\n", t.Field(i).Name, t.Field(i).Type) + } + w.printf("}\n") + return t.Name() +} + +// typeName returns the name of the go type of x. +func typeName(x interface{}) string { + t := reflect.ValueOf(x).Type() + return strings.Replace(fmt.Sprint(t), "main.", "", 1) +} diff --git a/vendor/golang.org/x/text/internal/gen/gen.go b/vendor/golang.org/x/text/internal/gen/gen.go new file mode 100644 index 00000000..4c3f7606 --- /dev/null +++ b/vendor/golang.org/x/text/internal/gen/gen.go @@ -0,0 +1,333 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package gen contains common code for the various code generation tools in the +// text repository. Its usage ensures consistency between tools. +// +// This package defines command line flags that are common to most generation +// tools. The flags allow for specifying specific Unicode and CLDR versions +// in the public Unicode data repository (http://www.unicode.org/Public). +// +// A local Unicode data mirror can be set through the flag -local or the +// environment variable UNICODE_DIR. The former takes precedence. The local +// directory should follow the same structure as the public repository. +// +// IANA data can also optionally be mirrored by putting it in the iana directory +// rooted at the top of the local mirror. Beware, though, that IANA data is not +// versioned. So it is up to the developer to use the right version. +package gen // import "golang.org/x/text/internal/gen" + +import ( + "bytes" + "flag" + "fmt" + "go/build" + "go/format" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "path" + "path/filepath" + "strings" + "sync" + "unicode" + + "golang.org/x/text/unicode/cldr" +) + +var ( + url = flag.String("url", + "http://www.unicode.org/Public", + "URL of Unicode database directory") + iana = flag.String("iana", + "http://www.iana.org", + "URL of the IANA repository") + unicodeVersion = flag.String("unicode", + getEnv("UNICODE_VERSION", unicode.Version), + "unicode version to use") + cldrVersion = flag.String("cldr", + getEnv("CLDR_VERSION", cldr.Version), + "cldr version to use") +) + +func getEnv(name, def string) string { + if v := os.Getenv(name); v != "" { + return v + } + return def +} + +// Init performs common initialization for a gen command. It parses the flags +// and sets up the standard logging parameters. +func Init() { + log.SetPrefix("") + log.SetFlags(log.Lshortfile) + flag.Parse() +} + +const header = `// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. + +` + +// UnicodeVersion reports the requested Unicode version. +func UnicodeVersion() string { + return *unicodeVersion +} + +// CLDRVersion reports the requested CLDR version. +func CLDRVersion() string { + return *cldrVersion +} + +var tags = []struct{ version, buildTags string }{ + {"10.0.0", "go1.10"}, + {"", "!go1.10"}, +} + +// buildTags reports the build tags used for the current Unicode version. +func buildTags() string { + v := UnicodeVersion() + for _, x := range tags { + // We should do a numeric comparison, but including the collate package + // would create an import cycle. We approximate it by assuming that + // longer version strings are later. + if len(x.version) <= len(v) { + return x.buildTags + } + if len(x.version) == len(v) && x.version <= v { + return x.buildTags + } + } + return tags[0].buildTags +} + +// IsLocal reports whether data files are available locally. +func IsLocal() bool { + dir, err := localReadmeFile() + if err != nil { + return false + } + if _, err = os.Stat(dir); err != nil { + return false + } + return true +} + +// OpenUCDFile opens the requested UCD file. The file is specified relative to +// the public Unicode root directory. It will call log.Fatal if there are any +// errors. +func OpenUCDFile(file string) io.ReadCloser { + return openUnicode(path.Join(*unicodeVersion, "ucd", file)) +} + +// OpenCLDRCoreZip opens the CLDR core zip file. It will call log.Fatal if there +// are any errors. +func OpenCLDRCoreZip() io.ReadCloser { + return OpenUnicodeFile("cldr", *cldrVersion, "core.zip") +} + +// OpenUnicodeFile opens the requested file of the requested category from the +// root of the Unicode data archive. The file is specified relative to the +// public Unicode root directory. If version is "", it will use the default +// Unicode version. It will call log.Fatal if there are any errors. +func OpenUnicodeFile(category, version, file string) io.ReadCloser { + if version == "" { + version = UnicodeVersion() + } + return openUnicode(path.Join(category, version, file)) +} + +// OpenIANAFile opens the requested IANA file. The file is specified relative +// to the IANA root, which is typically either http://www.iana.org or the +// iana directory in the local mirror. It will call log.Fatal if there are any +// errors. +func OpenIANAFile(path string) io.ReadCloser { + return Open(*iana, "iana", path) +} + +var ( + dirMutex sync.Mutex + localDir string +) + +const permissions = 0755 + +func localReadmeFile() (string, error) { + p, err := build.Import("golang.org/x/text", "", build.FindOnly) + if err != nil { + return "", fmt.Errorf("Could not locate package: %v", err) + } + return filepath.Join(p.Dir, "DATA", "README"), nil +} + +func getLocalDir() string { + dirMutex.Lock() + defer dirMutex.Unlock() + + readme, err := localReadmeFile() + if err != nil { + log.Fatal(err) + } + dir := filepath.Dir(readme) + if _, err := os.Stat(readme); err != nil { + if err := os.MkdirAll(dir, permissions); err != nil { + log.Fatalf("Could not create directory: %v", err) + } + ioutil.WriteFile(readme, []byte(readmeTxt), permissions) + } + return dir +} + +const readmeTxt = `Generated by golang.org/x/text/internal/gen. DO NOT EDIT. + +This directory contains downloaded files used to generate the various tables +in the golang.org/x/text subrepo. + +Note that the language subtag repo (iana/assignments/language-subtag-registry) +and all other times in the iana subdirectory are not versioned and will need +to be periodically manually updated. The easiest way to do this is to remove +the entire iana directory. This is mostly of concern when updating the language +package. +` + +// Open opens subdir/path if a local directory is specified and the file exists, +// where subdir is a directory relative to the local root, or fetches it from +// urlRoot/path otherwise. It will call log.Fatal if there are any errors. +func Open(urlRoot, subdir, path string) io.ReadCloser { + file := filepath.Join(getLocalDir(), subdir, filepath.FromSlash(path)) + return open(file, urlRoot, path) +} + +func openUnicode(path string) io.ReadCloser { + file := filepath.Join(getLocalDir(), filepath.FromSlash(path)) + return open(file, *url, path) +} + +// TODO: automatically periodically update non-versioned files. + +func open(file, urlRoot, path string) io.ReadCloser { + if f, err := os.Open(file); err == nil { + return f + } + r := get(urlRoot, path) + defer r.Close() + b, err := ioutil.ReadAll(r) + if err != nil { + log.Fatalf("Could not download file: %v", err) + } + os.MkdirAll(filepath.Dir(file), permissions) + if err := ioutil.WriteFile(file, b, permissions); err != nil { + log.Fatalf("Could not create file: %v", err) + } + return ioutil.NopCloser(bytes.NewReader(b)) +} + +func get(root, path string) io.ReadCloser { + url := root + "/" + path + fmt.Printf("Fetching %s...", url) + defer fmt.Println(" done.") + resp, err := http.Get(url) + if err != nil { + log.Fatalf("HTTP GET: %v", err) + } + if resp.StatusCode != 200 { + log.Fatalf("Bad GET status for %q: %q", url, resp.Status) + } + return resp.Body +} + +// TODO: use Write*Version in all applicable packages. + +// WriteUnicodeVersion writes a constant for the Unicode version from which the +// tables are generated. +func WriteUnicodeVersion(w io.Writer) { + fmt.Fprintf(w, "// UnicodeVersion is the Unicode version from which the tables in this package are derived.\n") + fmt.Fprintf(w, "const UnicodeVersion = %q\n\n", UnicodeVersion()) +} + +// WriteCLDRVersion writes a constant for the CLDR version from which the +// tables are generated. +func WriteCLDRVersion(w io.Writer) { + fmt.Fprintf(w, "// CLDRVersion is the CLDR version from which the tables in this package are derived.\n") + fmt.Fprintf(w, "const CLDRVersion = %q\n\n", CLDRVersion()) +} + +// WriteGoFile prepends a standard file comment and package statement to the +// given bytes, applies gofmt, and writes them to a file with the given name. +// It will call log.Fatal if there are any errors. +func WriteGoFile(filename, pkg string, b []byte) { + w, err := os.Create(filename) + if err != nil { + log.Fatalf("Could not create file %s: %v", filename, err) + } + defer w.Close() + if _, err = WriteGo(w, pkg, "", b); err != nil { + log.Fatalf("Error writing file %s: %v", filename, err) + } +} + +func insertVersion(filename, version string) string { + suffix := ".go" + if strings.HasSuffix(filename, "_test.go") { + suffix = "_test.go" + } + return fmt.Sprint(filename[:len(filename)-len(suffix)], version, suffix) +} + +// WriteVersionedGoFile prepends a standard file comment, adds build tags to +// version the file for the current Unicode version, and package statement to +// the given bytes, applies gofmt, and writes them to a file with the given +// name. It will call log.Fatal if there are any errors. +func WriteVersionedGoFile(filename, pkg string, b []byte) { + tags := buildTags() + if tags != "" { + filename = insertVersion(filename, UnicodeVersion()) + } + w, err := os.Create(filename) + if err != nil { + log.Fatalf("Could not create file %s: %v", filename, err) + } + defer w.Close() + if _, err = WriteGo(w, pkg, tags, b); err != nil { + log.Fatalf("Error writing file %s: %v", filename, err) + } +} + +// WriteGo prepends a standard file comment and package statement to the given +// bytes, applies gofmt, and writes them to w. +func WriteGo(w io.Writer, pkg, tags string, b []byte) (n int, err error) { + src := []byte(header) + if tags != "" { + src = append(src, fmt.Sprintf("// +build %s\n\n", tags)...) + } + src = append(src, fmt.Sprintf("package %s\n\n", pkg)...) + src = append(src, b...) + formatted, err := format.Source(src) + if err != nil { + // Print the generated code even in case of an error so that the + // returned error can be meaningfully interpreted. + n, _ = w.Write(src) + return n, err + } + return w.Write(formatted) +} + +// Repackage rewrites a Go file from belonging to package main to belonging to +// the given package. +func Repackage(inFile, outFile, pkg string) { + src, err := ioutil.ReadFile(inFile) + if err != nil { + log.Fatalf("reading %s: %v", inFile, err) + } + const toDelete = "package main\n\n" + i := bytes.Index(src, []byte(toDelete)) + if i < 0 { + log.Fatalf("Could not find %q in %s.", toDelete, inFile) + } + w := &bytes.Buffer{} + w.Write(src[i+len(toDelete):]) + WriteGoFile(outFile, pkg, w.Bytes()) +} diff --git a/vendor/golang.org/x/text/transform/transform.go b/vendor/golang.org/x/text/transform/transform.go new file mode 100644 index 00000000..fe47b9b3 --- /dev/null +++ b/vendor/golang.org/x/text/transform/transform.go @@ -0,0 +1,705 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package transform provides reader and writer wrappers that transform the +// bytes passing through as well as various transformations. Example +// transformations provided by other packages include normalization and +// conversion between character sets. +package transform // import "golang.org/x/text/transform" + +import ( + "bytes" + "errors" + "io" + "unicode/utf8" +) + +var ( + // ErrShortDst means that the destination buffer was too short to + // receive all of the transformed bytes. + ErrShortDst = errors.New("transform: short destination buffer") + + // ErrShortSrc means that the source buffer has insufficient data to + // complete the transformation. + ErrShortSrc = errors.New("transform: short source buffer") + + // ErrEndOfSpan means that the input and output (the transformed input) + // are not identical. + ErrEndOfSpan = errors.New("transform: input and output are not identical") + + // errInconsistentByteCount means that Transform returned success (nil + // error) but also returned nSrc inconsistent with the src argument. + errInconsistentByteCount = errors.New("transform: inconsistent byte count returned") + + // errShortInternal means that an internal buffer is not large enough + // to make progress and the Transform operation must be aborted. + errShortInternal = errors.New("transform: short internal buffer") +) + +// Transformer transforms bytes. +type Transformer interface { + // Transform writes to dst the transformed bytes read from src, and + // returns the number of dst bytes written and src bytes read. The + // atEOF argument tells whether src represents the last bytes of the + // input. + // + // Callers should always process the nDst bytes produced and account + // for the nSrc bytes consumed before considering the error err. + // + // A nil error means that all of the transformed bytes (whether freshly + // transformed from src or left over from previous Transform calls) + // were written to dst. A nil error can be returned regardless of + // whether atEOF is true. If err is nil then nSrc must equal len(src); + // the converse is not necessarily true. + // + // ErrShortDst means that dst was too short to receive all of the + // transformed bytes. ErrShortSrc means that src had insufficient data + // to complete the transformation. If both conditions apply, then + // either error may be returned. Other than the error conditions listed + // here, implementations are free to report other errors that arise. + Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) + + // Reset resets the state and allows a Transformer to be reused. + Reset() +} + +// SpanningTransformer extends the Transformer interface with a Span method +// that determines how much of the input already conforms to the Transformer. +type SpanningTransformer interface { + Transformer + + // Span returns a position in src such that transforming src[:n] results in + // identical output src[:n] for these bytes. It does not necessarily return + // the largest such n. The atEOF argument tells whether src represents the + // last bytes of the input. + // + // Callers should always account for the n bytes consumed before + // considering the error err. + // + // A nil error means that all input bytes are known to be identical to the + // output produced by the Transformer. A nil error can be be returned + // regardless of whether atEOF is true. If err is nil, then then n must + // equal len(src); the converse is not necessarily true. + // + // ErrEndOfSpan means that the Transformer output may differ from the + // input after n bytes. Note that n may be len(src), meaning that the output + // would contain additional bytes after otherwise identical output. + // ErrShortSrc means that src had insufficient data to determine whether the + // remaining bytes would change. Other than the error conditions listed + // here, implementations are free to report other errors that arise. + // + // Calling Span can modify the Transformer state as a side effect. In + // effect, it does the transformation just as calling Transform would, only + // without copying to a destination buffer and only up to a point it can + // determine the input and output bytes are the same. This is obviously more + // limited than calling Transform, but can be more efficient in terms of + // copying and allocating buffers. Calls to Span and Transform may be + // interleaved. + Span(src []byte, atEOF bool) (n int, err error) +} + +// NopResetter can be embedded by implementations of Transformer to add a nop +// Reset method. +type NopResetter struct{} + +// Reset implements the Reset method of the Transformer interface. +func (NopResetter) Reset() {} + +// Reader wraps another io.Reader by transforming the bytes read. +type Reader struct { + r io.Reader + t Transformer + err error + + // dst[dst0:dst1] contains bytes that have been transformed by t but + // not yet copied out via Read. + dst []byte + dst0, dst1 int + + // src[src0:src1] contains bytes that have been read from r but not + // yet transformed through t. + src []byte + src0, src1 int + + // transformComplete is whether the transformation is complete, + // regardless of whether or not it was successful. + transformComplete bool +} + +const defaultBufSize = 4096 + +// NewReader returns a new Reader that wraps r by transforming the bytes read +// via t. It calls Reset on t. +func NewReader(r io.Reader, t Transformer) *Reader { + t.Reset() + return &Reader{ + r: r, + t: t, + dst: make([]byte, defaultBufSize), + src: make([]byte, defaultBufSize), + } +} + +// Read implements the io.Reader interface. +func (r *Reader) Read(p []byte) (int, error) { + n, err := 0, error(nil) + for { + // Copy out any transformed bytes and return the final error if we are done. + if r.dst0 != r.dst1 { + n = copy(p, r.dst[r.dst0:r.dst1]) + r.dst0 += n + if r.dst0 == r.dst1 && r.transformComplete { + return n, r.err + } + return n, nil + } else if r.transformComplete { + return 0, r.err + } + + // Try to transform some source bytes, or to flush the transformer if we + // are out of source bytes. We do this even if r.r.Read returned an error. + // As the io.Reader documentation says, "process the n > 0 bytes returned + // before considering the error". + if r.src0 != r.src1 || r.err != nil { + r.dst0 = 0 + r.dst1, n, err = r.t.Transform(r.dst, r.src[r.src0:r.src1], r.err == io.EOF) + r.src0 += n + + switch { + case err == nil: + if r.src0 != r.src1 { + r.err = errInconsistentByteCount + } + // The Transform call was successful; we are complete if we + // cannot read more bytes into src. + r.transformComplete = r.err != nil + continue + case err == ErrShortDst && (r.dst1 != 0 || n != 0): + // Make room in dst by copying out, and try again. + continue + case err == ErrShortSrc && r.src1-r.src0 != len(r.src) && r.err == nil: + // Read more bytes into src via the code below, and try again. + default: + r.transformComplete = true + // The reader error (r.err) takes precedence over the + // transformer error (err) unless r.err is nil or io.EOF. + if r.err == nil || r.err == io.EOF { + r.err = err + } + continue + } + } + + // Move any untransformed source bytes to the start of the buffer + // and read more bytes. + if r.src0 != 0 { + r.src0, r.src1 = 0, copy(r.src, r.src[r.src0:r.src1]) + } + n, r.err = r.r.Read(r.src[r.src1:]) + r.src1 += n + } +} + +// TODO: implement ReadByte (and ReadRune??). + +// Writer wraps another io.Writer by transforming the bytes read. +// The user needs to call Close to flush unwritten bytes that may +// be buffered. +type Writer struct { + w io.Writer + t Transformer + dst []byte + + // src[:n] contains bytes that have not yet passed through t. + src []byte + n int +} + +// NewWriter returns a new Writer that wraps w by transforming the bytes written +// via t. It calls Reset on t. +func NewWriter(w io.Writer, t Transformer) *Writer { + t.Reset() + return &Writer{ + w: w, + t: t, + dst: make([]byte, defaultBufSize), + src: make([]byte, defaultBufSize), + } +} + +// Write implements the io.Writer interface. If there are not enough +// bytes available to complete a Transform, the bytes will be buffered +// for the next write. Call Close to convert the remaining bytes. +func (w *Writer) Write(data []byte) (n int, err error) { + src := data + if w.n > 0 { + // Append bytes from data to the last remainder. + // TODO: limit the amount copied on first try. + n = copy(w.src[w.n:], data) + w.n += n + src = w.src[:w.n] + } + for { + nDst, nSrc, err := w.t.Transform(w.dst, src, false) + if _, werr := w.w.Write(w.dst[:nDst]); werr != nil { + return n, werr + } + src = src[nSrc:] + if w.n == 0 { + n += nSrc + } else if len(src) <= n { + // Enough bytes from w.src have been consumed. We make src point + // to data instead to reduce the copying. + w.n = 0 + n -= len(src) + src = data[n:] + if n < len(data) && (err == nil || err == ErrShortSrc) { + continue + } + } + switch err { + case ErrShortDst: + // This error is okay as long as we are making progress. + if nDst > 0 || nSrc > 0 { + continue + } + case ErrShortSrc: + if len(src) < len(w.src) { + m := copy(w.src, src) + // If w.n > 0, bytes from data were already copied to w.src and n + // was already set to the number of bytes consumed. + if w.n == 0 { + n += m + } + w.n = m + err = nil + } else if nDst > 0 || nSrc > 0 { + // Not enough buffer to store the remainder. Keep processing as + // long as there is progress. Without this case, transforms that + // require a lookahead larger than the buffer may result in an + // error. This is not something one may expect to be common in + // practice, but it may occur when buffers are set to small + // sizes during testing. + continue + } + case nil: + if w.n > 0 { + err = errInconsistentByteCount + } + } + return n, err + } +} + +// Close implements the io.Closer interface. +func (w *Writer) Close() error { + src := w.src[:w.n] + for { + nDst, nSrc, err := w.t.Transform(w.dst, src, true) + if _, werr := w.w.Write(w.dst[:nDst]); werr != nil { + return werr + } + if err != ErrShortDst { + return err + } + src = src[nSrc:] + } +} + +type nop struct{ NopResetter } + +func (nop) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + n := copy(dst, src) + if n < len(src) { + err = ErrShortDst + } + return n, n, err +} + +func (nop) Span(src []byte, atEOF bool) (n int, err error) { + return len(src), nil +} + +type discard struct{ NopResetter } + +func (discard) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + return 0, len(src), nil +} + +var ( + // Discard is a Transformer for which all Transform calls succeed + // by consuming all bytes and writing nothing. + Discard Transformer = discard{} + + // Nop is a SpanningTransformer that copies src to dst. + Nop SpanningTransformer = nop{} +) + +// chain is a sequence of links. A chain with N Transformers has N+1 links and +// N+1 buffers. Of those N+1 buffers, the first and last are the src and dst +// buffers given to chain.Transform and the middle N-1 buffers are intermediate +// buffers owned by the chain. The i'th link transforms bytes from the i'th +// buffer chain.link[i].b at read offset chain.link[i].p to the i+1'th buffer +// chain.link[i+1].b at write offset chain.link[i+1].n, for i in [0, N). +type chain struct { + link []link + err error + // errStart is the index at which the error occurred plus 1. Processing + // errStart at this level at the next call to Transform. As long as + // errStart > 0, chain will not consume any more source bytes. + errStart int +} + +func (c *chain) fatalError(errIndex int, err error) { + if i := errIndex + 1; i > c.errStart { + c.errStart = i + c.err = err + } +} + +type link struct { + t Transformer + // b[p:n] holds the bytes to be transformed by t. + b []byte + p int + n int +} + +func (l *link) src() []byte { + return l.b[l.p:l.n] +} + +func (l *link) dst() []byte { + return l.b[l.n:] +} + +// Chain returns a Transformer that applies t in sequence. +func Chain(t ...Transformer) Transformer { + if len(t) == 0 { + return nop{} + } + c := &chain{link: make([]link, len(t)+1)} + for i, tt := range t { + c.link[i].t = tt + } + // Allocate intermediate buffers. + b := make([][defaultBufSize]byte, len(t)-1) + for i := range b { + c.link[i+1].b = b[i][:] + } + return c +} + +// Reset resets the state of Chain. It calls Reset on all the Transformers. +func (c *chain) Reset() { + for i, l := range c.link { + if l.t != nil { + l.t.Reset() + } + c.link[i].p, c.link[i].n = 0, 0 + } +} + +// TODO: make chain use Span (is going to be fun to implement!) + +// Transform applies the transformers of c in sequence. +func (c *chain) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + // Set up src and dst in the chain. + srcL := &c.link[0] + dstL := &c.link[len(c.link)-1] + srcL.b, srcL.p, srcL.n = src, 0, len(src) + dstL.b, dstL.n = dst, 0 + var lastFull, needProgress bool // for detecting progress + + // i is the index of the next Transformer to apply, for i in [low, high]. + // low is the lowest index for which c.link[low] may still produce bytes. + // high is the highest index for which c.link[high] has a Transformer. + // The error returned by Transform determines whether to increase or + // decrease i. We try to completely fill a buffer before converting it. + for low, i, high := c.errStart, c.errStart, len(c.link)-2; low <= i && i <= high; { + in, out := &c.link[i], &c.link[i+1] + nDst, nSrc, err0 := in.t.Transform(out.dst(), in.src(), atEOF && low == i) + out.n += nDst + in.p += nSrc + if i > 0 && in.p == in.n { + in.p, in.n = 0, 0 + } + needProgress, lastFull = lastFull, false + switch err0 { + case ErrShortDst: + // Process the destination buffer next. Return if we are already + // at the high index. + if i == high { + return dstL.n, srcL.p, ErrShortDst + } + if out.n != 0 { + i++ + // If the Transformer at the next index is not able to process any + // source bytes there is nothing that can be done to make progress + // and the bytes will remain unprocessed. lastFull is used to + // detect this and break out of the loop with a fatal error. + lastFull = true + continue + } + // The destination buffer was too small, but is completely empty. + // Return a fatal error as this transformation can never complete. + c.fatalError(i, errShortInternal) + case ErrShortSrc: + if i == 0 { + // Save ErrShortSrc in err. All other errors take precedence. + err = ErrShortSrc + break + } + // Source bytes were depleted before filling up the destination buffer. + // Verify we made some progress, move the remaining bytes to the errStart + // and try to get more source bytes. + if needProgress && nSrc == 0 || in.n-in.p == len(in.b) { + // There were not enough source bytes to proceed while the source + // buffer cannot hold any more bytes. Return a fatal error as this + // transformation can never complete. + c.fatalError(i, errShortInternal) + break + } + // in.b is an internal buffer and we can make progress. + in.p, in.n = 0, copy(in.b, in.src()) + fallthrough + case nil: + // if i == low, we have depleted the bytes at index i or any lower levels. + // In that case we increase low and i. In all other cases we decrease i to + // fetch more bytes before proceeding to the next index. + if i > low { + i-- + continue + } + default: + c.fatalError(i, err0) + } + // Exhausted level low or fatal error: increase low and continue + // to process the bytes accepted so far. + i++ + low = i + } + + // If c.errStart > 0, this means we found a fatal error. We will clear + // all upstream buffers. At this point, no more progress can be made + // downstream, as Transform would have bailed while handling ErrShortDst. + if c.errStart > 0 { + for i := 1; i < c.errStart; i++ { + c.link[i].p, c.link[i].n = 0, 0 + } + err, c.errStart, c.err = c.err, 0, nil + } + return dstL.n, srcL.p, err +} + +// Deprecated: use runes.Remove instead. +func RemoveFunc(f func(r rune) bool) Transformer { + return removeF(f) +} + +type removeF func(r rune) bool + +func (removeF) Reset() {} + +// Transform implements the Transformer interface. +func (t removeF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + for r, sz := rune(0), 0; len(src) > 0; src = src[sz:] { + + if r = rune(src[0]); r < utf8.RuneSelf { + sz = 1 + } else { + r, sz = utf8.DecodeRune(src) + + if sz == 1 { + // Invalid rune. + if !atEOF && !utf8.FullRune(src) { + err = ErrShortSrc + break + } + // We replace illegal bytes with RuneError. Not doing so might + // otherwise turn a sequence of invalid UTF-8 into valid UTF-8. + // The resulting byte sequence may subsequently contain runes + // for which t(r) is true that were passed unnoticed. + if !t(r) { + if nDst+3 > len(dst) { + err = ErrShortDst + break + } + nDst += copy(dst[nDst:], "\uFFFD") + } + nSrc++ + continue + } + } + + if !t(r) { + if nDst+sz > len(dst) { + err = ErrShortDst + break + } + nDst += copy(dst[nDst:], src[:sz]) + } + nSrc += sz + } + return +} + +// grow returns a new []byte that is longer than b, and copies the first n bytes +// of b to the start of the new slice. +func grow(b []byte, n int) []byte { + m := len(b) + if m <= 32 { + m = 64 + } else if m <= 256 { + m *= 2 + } else { + m += m >> 1 + } + buf := make([]byte, m) + copy(buf, b[:n]) + return buf +} + +const initialBufSize = 128 + +// String returns a string with the result of converting s[:n] using t, where +// n <= len(s). If err == nil, n will be len(s). It calls Reset on t. +func String(t Transformer, s string) (result string, n int, err error) { + t.Reset() + if s == "" { + // Fast path for the common case for empty input. Results in about a + // 86% reduction of running time for BenchmarkStringLowerEmpty. + if _, _, err := t.Transform(nil, nil, true); err == nil { + return "", 0, nil + } + } + + // Allocate only once. Note that both dst and src escape when passed to + // Transform. + buf := [2 * initialBufSize]byte{} + dst := buf[:initialBufSize:initialBufSize] + src := buf[initialBufSize : 2*initialBufSize] + + // The input string s is transformed in multiple chunks (starting with a + // chunk size of initialBufSize). nDst and nSrc are per-chunk (or + // per-Transform-call) indexes, pDst and pSrc are overall indexes. + nDst, nSrc := 0, 0 + pDst, pSrc := 0, 0 + + // pPrefix is the length of a common prefix: the first pPrefix bytes of the + // result will equal the first pPrefix bytes of s. It is not guaranteed to + // be the largest such value, but if pPrefix, len(result) and len(s) are + // all equal after the final transform (i.e. calling Transform with atEOF + // being true returned nil error) then we don't need to allocate a new + // result string. + pPrefix := 0 + for { + // Invariant: pDst == pPrefix && pSrc == pPrefix. + + n := copy(src, s[pSrc:]) + nDst, nSrc, err = t.Transform(dst, src[:n], pSrc+n == len(s)) + pDst += nDst + pSrc += nSrc + + // TODO: let transformers implement an optional Spanner interface, akin + // to norm's QuickSpan. This would even allow us to avoid any allocation. + if !bytes.Equal(dst[:nDst], src[:nSrc]) { + break + } + pPrefix = pSrc + if err == ErrShortDst { + // A buffer can only be short if a transformer modifies its input. + break + } else if err == ErrShortSrc { + if nSrc == 0 { + // No progress was made. + break + } + // Equal so far and !atEOF, so continue checking. + } else if err != nil || pPrefix == len(s) { + return string(s[:pPrefix]), pPrefix, err + } + } + // Post-condition: pDst == pPrefix + nDst && pSrc == pPrefix + nSrc. + + // We have transformed the first pSrc bytes of the input s to become pDst + // transformed bytes. Those transformed bytes are discontiguous: the first + // pPrefix of them equal s[:pPrefix] and the last nDst of them equal + // dst[:nDst]. We copy them around, into a new dst buffer if necessary, so + // that they become one contiguous slice: dst[:pDst]. + if pPrefix != 0 { + newDst := dst + if pDst > len(newDst) { + newDst = make([]byte, len(s)+nDst-nSrc) + } + copy(newDst[pPrefix:pDst], dst[:nDst]) + copy(newDst[:pPrefix], s[:pPrefix]) + dst = newDst + } + + // Prevent duplicate Transform calls with atEOF being true at the end of + // the input. Also return if we have an unrecoverable error. + if (err == nil && pSrc == len(s)) || + (err != nil && err != ErrShortDst && err != ErrShortSrc) { + return string(dst[:pDst]), pSrc, err + } + + // Transform the remaining input, growing dst and src buffers as necessary. + for { + n := copy(src, s[pSrc:]) + nDst, nSrc, err := t.Transform(dst[pDst:], src[:n], pSrc+n == len(s)) + pDst += nDst + pSrc += nSrc + + // If we got ErrShortDst or ErrShortSrc, do not grow as long as we can + // make progress. This may avoid excessive allocations. + if err == ErrShortDst { + if nDst == 0 { + dst = grow(dst, pDst) + } + } else if err == ErrShortSrc { + if nSrc == 0 { + src = grow(src, 0) + } + } else if err != nil || pSrc == len(s) { + return string(dst[:pDst]), pSrc, err + } + } +} + +// Bytes returns a new byte slice with the result of converting b[:n] using t, +// where n <= len(b). If err == nil, n will be len(b). It calls Reset on t. +func Bytes(t Transformer, b []byte) (result []byte, n int, err error) { + return doAppend(t, 0, make([]byte, len(b)), b) +} + +// Append appends the result of converting src[:n] using t to dst, where +// n <= len(src), If err == nil, n will be len(src). It calls Reset on t. +func Append(t Transformer, dst, src []byte) (result []byte, n int, err error) { + if len(dst) == cap(dst) { + n := len(src) + len(dst) // It is okay for this to be 0. + b := make([]byte, n) + dst = b[:copy(b, dst)] + } + return doAppend(t, len(dst), dst[:cap(dst)], src) +} + +func doAppend(t Transformer, pDst int, dst, src []byte) (result []byte, n int, err error) { + t.Reset() + pSrc := 0 + for { + nDst, nSrc, err := t.Transform(dst[pDst:], src[pSrc:], true) + pDst += nDst + pSrc += nSrc + if err != ErrShortDst { + return dst[:pDst], pSrc, err + } + + // Grow the destination buffer, but do not grow as long as we can make + // progress. This may avoid excessive allocations. + if nDst == 0 { + dst = grow(dst, pDst) + } + } +} diff --git a/vendor/golang.org/x/text/unicode/cldr/base.go b/vendor/golang.org/x/text/unicode/cldr/base.go new file mode 100644 index 00000000..63cdc16c --- /dev/null +++ b/vendor/golang.org/x/text/unicode/cldr/base.go @@ -0,0 +1,105 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cldr + +import ( + "encoding/xml" + "regexp" + "strconv" +) + +// Elem is implemented by every XML element. +type Elem interface { + setEnclosing(Elem) + setName(string) + enclosing() Elem + + GetCommon() *Common +} + +type hidden struct { + CharData string `xml:",chardata"` + Alias *struct { + Common + Source string `xml:"source,attr"` + Path string `xml:"path,attr"` + } `xml:"alias"` + Def *struct { + Common + Choice string `xml:"choice,attr,omitempty"` + Type string `xml:"type,attr,omitempty"` + } `xml:"default"` +} + +// Common holds several of the most common attributes and sub elements +// of an XML element. +type Common struct { + XMLName xml.Name + name string + enclElem Elem + Type string `xml:"type,attr,omitempty"` + Reference string `xml:"reference,attr,omitempty"` + Alt string `xml:"alt,attr,omitempty"` + ValidSubLocales string `xml:"validSubLocales,attr,omitempty"` + Draft string `xml:"draft,attr,omitempty"` + hidden +} + +// Default returns the default type to select from the enclosed list +// or "" if no default value is specified. +func (e *Common) Default() string { + if e.Def == nil { + return "" + } + if e.Def.Choice != "" { + return e.Def.Choice + } else if e.Def.Type != "" { + // Type is still used by the default element in collation. + return e.Def.Type + } + return "" +} + +// Element returns the XML element name. +func (e *Common) Element() string { + return e.name +} + +// GetCommon returns e. It is provided such that Common implements Elem. +func (e *Common) GetCommon() *Common { + return e +} + +// Data returns the character data accumulated for this element. +func (e *Common) Data() string { + e.CharData = charRe.ReplaceAllStringFunc(e.CharData, replaceUnicode) + return e.CharData +} + +func (e *Common) setName(s string) { + e.name = s +} + +func (e *Common) enclosing() Elem { + return e.enclElem +} + +func (e *Common) setEnclosing(en Elem) { + e.enclElem = en +} + +// Escape characters that can be escaped without further escaping the string. +var charRe = regexp.MustCompile(`&#x[0-9a-fA-F]*;|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|\\x[0-9a-fA-F]{2}|\\[0-7]{3}|\\[abtnvfr]`) + +// replaceUnicode converts hexadecimal Unicode codepoint notations to a one-rune string. +// It assumes the input string is correctly formatted. +func replaceUnicode(s string) string { + if s[1] == '#' { + r, _ := strconv.ParseInt(s[3:len(s)-1], 16, 32) + return string(r) + } + r, _, _, _ := strconv.UnquoteChar(s, 0) + return string(r) +} diff --git a/vendor/golang.org/x/text/unicode/cldr/cldr.go b/vendor/golang.org/x/text/unicode/cldr/cldr.go new file mode 100644 index 00000000..2197f8ac --- /dev/null +++ b/vendor/golang.org/x/text/unicode/cldr/cldr.go @@ -0,0 +1,130 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run makexml.go -output xml.go + +// Package cldr provides a parser for LDML and related XML formats. +// This package is intended to be used by the table generation tools +// for the various internationalization-related packages. +// As the XML types are generated from the CLDR DTD, and as the CLDR standard +// is periodically amended, this package may change considerably over time. +// This mostly means that data may appear and disappear between versions. +// That is, old code should keep compiling for newer versions, but data +// may have moved or changed. +// CLDR version 22 is the first version supported by this package. +// Older versions may not work. +package cldr // import "golang.org/x/text/unicode/cldr" + +import ( + "fmt" + "sort" +) + +// CLDR provides access to parsed data of the Unicode Common Locale Data Repository. +type CLDR struct { + parent map[string][]string + locale map[string]*LDML + resolved map[string]*LDML + bcp47 *LDMLBCP47 + supp *SupplementalData +} + +func makeCLDR() *CLDR { + return &CLDR{ + parent: make(map[string][]string), + locale: make(map[string]*LDML), + resolved: make(map[string]*LDML), + bcp47: &LDMLBCP47{}, + supp: &SupplementalData{}, + } +} + +// BCP47 returns the parsed BCP47 LDML data. If no such data was parsed, nil is returned. +func (cldr *CLDR) BCP47() *LDMLBCP47 { + return nil +} + +// Draft indicates the draft level of an element. +type Draft int + +const ( + Approved Draft = iota + Contributed + Provisional + Unconfirmed +) + +var drafts = []string{"unconfirmed", "provisional", "contributed", "approved", ""} + +// ParseDraft returns the Draft value corresponding to the given string. The +// empty string corresponds to Approved. +func ParseDraft(level string) (Draft, error) { + if level == "" { + return Approved, nil + } + for i, s := range drafts { + if level == s { + return Unconfirmed - Draft(i), nil + } + } + return Approved, fmt.Errorf("cldr: unknown draft level %q", level) +} + +func (d Draft) String() string { + return drafts[len(drafts)-1-int(d)] +} + +// SetDraftLevel sets which draft levels to include in the evaluated LDML. +// Any draft element for which the draft level is higher than lev will be excluded. +// If multiple draft levels are available for a single element, the one with the +// lowest draft level will be selected, unless preferDraft is true, in which case +// the highest draft will be chosen. +// It is assumed that the underlying LDML is canonicalized. +func (cldr *CLDR) SetDraftLevel(lev Draft, preferDraft bool) { + // TODO: implement + cldr.resolved = make(map[string]*LDML) +} + +// RawLDML returns the LDML XML for id in unresolved form. +// id must be one of the strings returned by Locales. +func (cldr *CLDR) RawLDML(loc string) *LDML { + return cldr.locale[loc] +} + +// LDML returns the fully resolved LDML XML for loc, which must be one of +// the strings returned by Locales. +func (cldr *CLDR) LDML(loc string) (*LDML, error) { + return cldr.resolve(loc) +} + +// Supplemental returns the parsed supplemental data. If no such data was parsed, +// nil is returned. +func (cldr *CLDR) Supplemental() *SupplementalData { + return cldr.supp +} + +// Locales returns the locales for which there exist files. +// Valid sublocales for which there is no file are not included. +// The root locale is always sorted first. +func (cldr *CLDR) Locales() []string { + loc := []string{"root"} + hasRoot := false + for l, _ := range cldr.locale { + if l == "root" { + hasRoot = true + continue + } + loc = append(loc, l) + } + sort.Strings(loc[1:]) + if !hasRoot { + return loc[1:] + } + return loc +} + +// Get fills in the fields of x based on the XPath path. +func Get(e Elem, path string) (res Elem, err error) { + return walkXPath(e, path) +} diff --git a/vendor/golang.org/x/text/unicode/cldr/collate.go b/vendor/golang.org/x/text/unicode/cldr/collate.go new file mode 100644 index 00000000..80ee28d7 --- /dev/null +++ b/vendor/golang.org/x/text/unicode/cldr/collate.go @@ -0,0 +1,359 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cldr + +import ( + "bufio" + "encoding/xml" + "errors" + "fmt" + "strconv" + "strings" + "unicode" + "unicode/utf8" +) + +// RuleProcessor can be passed to Collator's Process method, which +// parses the rules and calls the respective method for each rule found. +type RuleProcessor interface { + Reset(anchor string, before int) error + Insert(level int, str, context, extend string) error + Index(id string) +} + +const ( + // cldrIndex is a Unicode-reserved sentinel value used to mark the start + // of a grouping within an index. + // We ignore any rule that starts with this rune. + // See http://unicode.org/reports/tr35/#Collation_Elements for details. + cldrIndex = "\uFDD0" + + // specialAnchor is the format in which to represent logical reset positions, + // such as "first tertiary ignorable". + specialAnchor = "<%s/>" +) + +// Process parses the rules for the tailorings of this collation +// and calls the respective methods of p for each rule found. +func (c Collation) Process(p RuleProcessor) (err error) { + if len(c.Cr) > 0 { + if len(c.Cr) > 1 { + return fmt.Errorf("multiple cr elements, want 0 or 1") + } + return processRules(p, c.Cr[0].Data()) + } + if c.Rules.Any != nil { + return c.processXML(p) + } + return errors.New("no tailoring data") +} + +// processRules parses rules in the Collation Rule Syntax defined in +// http://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Tailorings. +func processRules(p RuleProcessor, s string) (err error) { + chk := func(s string, e error) string { + if err == nil { + err = e + } + return s + } + i := 0 // Save the line number for use after the loop. + scanner := bufio.NewScanner(strings.NewReader(s)) + for ; scanner.Scan() && err == nil; i++ { + for s := skipSpace(scanner.Text()); s != "" && s[0] != '#'; s = skipSpace(s) { + level := 5 + var ch byte + switch ch, s = s[0], s[1:]; ch { + case '&': // followed by or '[' ']' + if s = skipSpace(s); consume(&s, '[') { + s = chk(parseSpecialAnchor(p, s)) + } else { + s = chk(parseAnchor(p, 0, s)) + } + case '<': // sort relation '<'{1,4}, optionally followed by '*'. + for level = 1; consume(&s, '<'); level++ { + } + if level > 4 { + err = fmt.Errorf("level %d > 4", level) + } + fallthrough + case '=': // identity relation, optionally followed by *. + if consume(&s, '*') { + s = chk(parseSequence(p, level, s)) + } else { + s = chk(parseOrder(p, level, s)) + } + default: + chk("", fmt.Errorf("illegal operator %q", ch)) + break + } + } + } + if chk("", scanner.Err()); err != nil { + return fmt.Errorf("%d: %v", i, err) + } + return nil +} + +// parseSpecialAnchor parses the anchor syntax which is either of the form +// ['before' ] +// or +// [