Add spinner to ghorg ls command (#451)

This commit is contained in:
gabrie30 2024-09-17 22:45:01 -07:00 committed by GitHub
parent 08add68314
commit e6143784f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
47 changed files with 5085 additions and 9 deletions

View File

@ -5,7 +5,9 @@ import (
"os"
"path/filepath"
"strings"
"time"
"github.com/briandowns/spinner"
"github.com/gabrie30/ghorg/colorlog"
"github.com/gabrie30/ghorg/utils"
"github.com/spf13/cobra"
@ -58,6 +60,9 @@ func listGhorgHome() {
return
}
spinningSpinner := spinner.New(spinner.CharSets[14], 100*time.Millisecond)
spinningSpinner.Start()
var totalDirs int
var totalSizeMB float64
var totalRepos int
@ -86,14 +91,14 @@ func listGhorgHome() {
}
}
totalRepos += subDirCount
if !totalFormat || longFormat {
spinningSpinner.Stop()
if longFormat {
if dirSizeMB > 1000 {
dirSizeGB := dirSizeMB / 1000
colorlog.PrintInfo(fmt.Sprintf("%-50s %10.2f GB %10d repos", dirPath, dirSizeGB, subDirCount))
colorlog.PrintInfo(fmt.Sprintf("%-90s %10.2f GB %10d repos", dirPath, dirSizeGB, subDirCount))
} else {
colorlog.PrintInfo(fmt.Sprintf("%-50s %10.2f MB %10d repos", dirPath, dirSizeMB, subDirCount))
colorlog.PrintInfo(fmt.Sprintf("%-90s %10.2f MB %10d repos", dirPath, dirSizeMB, subDirCount))
}
} else {
colorlog.PrintInfo(path + f.Name())
@ -102,12 +107,13 @@ func listGhorgHome() {
}
}
spinningSpinner.Stop()
if totalFormat {
if totalSizeMB > 1000 {
totalSizeGB := totalSizeMB / 1000
colorlog.PrintInfo(fmt.Sprintf("Total: %d directories, %.2f GB, %d repos", totalDirs, totalSizeGB, totalRepos))
colorlog.PrintSuccess(fmt.Sprintf("Total: %d directories, %.2f GB, %d repos", totalDirs, totalSizeGB, totalRepos))
} else {
colorlog.PrintInfo(fmt.Sprintf("Total: %d directories, %.2f MB, %d repos", totalDirs, totalSizeMB, totalRepos))
colorlog.PrintSuccess(fmt.Sprintf("Total: %d directories, %.2f MB, %d repos", totalDirs, totalSizeMB, totalRepos))
}
}
}
@ -116,7 +122,7 @@ func listGhorgDir(arg string) {
path := os.Getenv("GHORG_ABSOLUTE_PATH_TO_CLONE_TO") + arg
files, err := os.ReadDir(path)
_, err := os.ReadDir(path)
if err != nil {
// ghorg natively uses underscores in folder names, but a user can specify an output dir with underscores
// so first try what the user types if not then try replace
@ -124,15 +130,84 @@ func listGhorgDir(arg string) {
path = os.Getenv("GHORG_ABSOLUTE_PATH_TO_CLONE_TO") + arg
}
files, err = os.ReadDir(path)
files, err := os.ReadDir(path)
if err != nil {
colorlog.PrintError("No clones found. Please clone some and try again.")
}
longFormat := false
totalFormat := false
for _, arg := range os.Args {
if arg == "-l" || arg == "--long" {
longFormat = true
}
if arg == "-t" || arg == "--total" {
totalFormat = true
}
}
if !longFormat && !totalFormat {
for _, f := range files {
if f.IsDir() {
str := filepath.Join(path, f.Name())
colorlog.PrintInfo(str)
}
}
return
}
spinningSpinner := spinner.New(spinner.CharSets[14], 100*time.Millisecond)
spinningSpinner.Start()
var totalDirs int
var totalSizeMB float64
for _, f := range files {
if f.IsDir() {
str := filepath.Join(path, f.Name())
colorlog.PrintSubtleInfo(str)
totalDirs++
dirPath := filepath.Join(path, f.Name())
dirSizeMB, err := utils.CalculateDirSizeInMb(dirPath)
if err != nil {
colorlog.PrintError(fmt.Sprintf("Error calculating directory size for %s: %v", dirPath, err))
continue
}
totalSizeMB += dirSizeMB
// Count the number of directories with a depth of 1 inside
subDirCount := 0
subFiles, err := os.ReadDir(dirPath)
if err != nil {
colorlog.PrintError(fmt.Sprintf("Error reading directory contents for %s: %v", dirPath, err))
continue
}
for _, subFile := range subFiles {
if subFile.IsDir() {
subDirCount++
}
}
if !totalFormat || longFormat {
spinningSpinner.Stop()
if longFormat {
if dirSizeMB > 1000 {
dirSizeGB := dirSizeMB / 1000
colorlog.PrintInfo(fmt.Sprintf("%-90s %10.2f GB ", dirPath, dirSizeGB))
} else {
colorlog.PrintInfo(fmt.Sprintf("%-90s %10.2f MB", dirPath, dirSizeMB))
}
} else {
colorlog.PrintInfo(path + f.Name())
}
}
}
}
spinningSpinner.Stop()
if totalFormat {
if totalSizeMB > 1000 {
totalSizeGB := totalSizeMB / 1000
colorlog.PrintSuccess(fmt.Sprintf("Total: %d repos, %.2f GB", totalDirs, totalSizeGB))
} else {
colorlog.PrintSuccess(fmt.Sprintf("Total: %d repos, %.2f MB", totalDirs, totalSizeMB))
}
}
}

2
go.mod
View File

@ -6,6 +6,7 @@ require (
code.gitea.io/sdk/gitea v0.19.0
github.com/MichaelMure/go-term-markdown v0.1.4
github.com/bradleyfalzon/ghinstallation/v2 v2.11.0
github.com/briandowns/spinner v1.23.1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/fatih/color v1.17.0
github.com/google/go-github/v62 v62.0.0
@ -60,6 +61,7 @@ require (
golang.org/x/image v0.18.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect

2
go.sum
View File

@ -16,6 +16,8 @@ github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkx
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/bradleyfalzon/ghinstallation/v2 v2.11.0 h1:R9d0v+iobRHSaE4wKUnXFiZp53AL4ED5MzgEMwGTZag=
github.com/bradleyfalzon/ghinstallation/v2 v2.11.0/go.mod h1:0LWKQwOHewXO/1acI6TtyE0Xc4ObDb2rFN7eHBAG71M=
github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650=
github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=

29
vendor/github.com/briandowns/spinner/.gitignore generated vendored Normal file
View File

@ -0,0 +1,29 @@
# 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

18
vendor/github.com/briandowns/spinner/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,18 @@
arch:
- amd64
- ppc64le
language: go
go:
- 1.16
- 1.17.5
env:
- GOARCH: amd64
- GOARCH: 386
script:
- go test -v
notifications:
email:
recipients:
- brian.downs@gmail.com
on_success: change
on_failure: always

174
vendor/github.com/briandowns/spinner/LICENSE generated vendored Normal file
View File

@ -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.

20
vendor/github.com/briandowns/spinner/Makefile generated vendored Normal file
View File

@ -0,0 +1,20 @@
GO = go
.PHONY: deps
deps: go.mod
go.mod:
go mod init
go mod tidy
.PHONY: test
test:
$(GO) test -v -cover ./...
.PHONY: check
check:
if [ -d vendor ]; then cp -r vendor/* ${GOPATH}/src/; fi
.PHONY: clean
clean:
$(GO) clean

4
vendor/github.com/briandowns/spinner/NOTICE.txt generated vendored Normal file
View File

@ -0,0 +1,4 @@
Spinner
Copyright (c) 2022 Brian J. Downs
This product is licensed to you under the Apache 2.0 license (the "License"). You may not use this product except in compliance with the Apache 2.0 License.
This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file.

285
vendor/github.com/briandowns/spinner/README.md generated vendored Normal file
View File

@ -0,0 +1,285 @@
# Spinner
[![GoDoc](https://godoc.org/github.com/briandowns/spinner?status.svg)](https://godoc.org/github.com/briandowns/spinner) [![CircleCI](https://circleci.com/gh/briandowns/spinner.svg?style=svg)](https://circleci.com/gh/briandowns/spinner)
spinner is a simple package to add a spinner / progress indicator to any terminal application. Examples can be found below as well as full examples in the examples directory.
For more detail about the library and its features, reference your local godoc once installed.
Contributions welcome!
## Installation
```bash
go get github.com/briandowns/spinner
```
## Available Character Sets
90 Character Sets. Some examples below:
(Numbered by their slice index)
| index | character set | sample gif |
| ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
| 0 | ```←↖↑↗→↘↓↙``` | ![Sample Gif](gifs/0.gif) |
| 1 | ```▁▃▄▅▆▇█▇▆▅▄▃▁``` | ![Sample Gif](gifs/1.gif) |
| 2 | ```▖▘▝▗``` | ![Sample Gif](gifs/2.gif) |
| 3 | ```┤┘┴└├┌┬┐``` | ![Sample Gif](gifs/3.gif) |
| 4 | ```◢◣◤◥``` | ![Sample Gif](gifs/4.gif) |
| 5 | ```◰◳◲◱``` | ![Sample Gif](gifs/5.gif) |
| 6 | ```◴◷◶◵``` | ![Sample Gif](gifs/6.gif) |
| 7 | ```◐◓◑◒``` | ![Sample Gif](gifs/7.gif) |
| 8 | ```.oO@*``` | ![Sample Gif](gifs/8.gif) |
| 9 | ```\|/-\``` | ![Sample Gif](gifs/9.gif) |
| 10 | ```◡◡⊙⊙◠◠``` | ![Sample Gif](gifs/10.gif) |
| 11 | ```⣾⣽⣻⢿⡿⣟⣯⣷``` | ![Sample Gif](gifs/11.gif) |
| 12 | ```>))'> >))'> >))'> >))'> >))'> <'((< <'((< <'((<``` | ![Sample Gif](gifs/12.gif) |
| 13 | ```⠁⠂⠄⡀⢀⠠⠐⠈``` | ![Sample Gif](gifs/13.gif) |
| 14 | ```⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏``` | ![Sample Gif](gifs/14.gif) |
| 15 | ```abcdefghijklmnopqrstuvwxyz``` | ![Sample Gif](gifs/15.gif) |
| 16 | ```▉▊▋▌▍▎▏▎▍▌▋▊▉``` | ![Sample Gif](gifs/16.gif) |
| 17 | ```■□▪▫``` | ![Sample Gif](gifs/17.gif) |
| 18 | ```←↑→↓``` | ![Sample Gif](gifs/18.gif) |
| 19 | ```╫╪``` | ![Sample Gif](gifs/19.gif) |
| 20 | ```⇐⇖⇑⇗⇒⇘⇓⇙``` | ![Sample Gif](gifs/20.gif) |
| 21 | ```⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈``` | ![Sample Gif](gifs/21.gif) |
| 22 | ```⠈⠉⠋⠓⠒⠐⠐⠒⠖⠦⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈``` | ![Sample Gif](gifs/22.gif) |
| 23 | ```⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠴⠲⠒⠂⠂⠒⠚⠙⠉⠁``` | ![Sample Gif](gifs/23.gif) |
| 24 | ```⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒⠐⠐⠒⠓⠋``` | ![Sample Gif](gifs/24.gif) |
| 25 | ```ヲァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン``` | ![Sample Gif](gifs/25.gif) |
| 26 | ```. .. ...``` | ![Sample Gif](gifs/26.gif) |
| 27 | ```▁▂▃▄▅▆▇█▉▊▋▌▍▎▏▏▎▍▌▋▊▉█▇▆▅▄▃▂▁``` | ![Sample Gif](gifs/27.gif) |
| 28 | ```.oO°Oo.``` | ![Sample Gif](gifs/28.gif) |
| 29 | ```+x``` | ![Sample Gif](gifs/29.gif) |
| 30 | ```v<^>``` | ![Sample Gif](gifs/30.gif) |
| 31 | ```>>---> >>---> >>---> >>---> >>---> <---<< <---<< <---<< <---<< <---<<``` | ![Sample Gif](gifs/31.gif) |
| 32 | ```\| \|\| \|\|\| \|\|\|\| \|\|\|\|\| \|\|\|\|\|\| \|\|\|\|\| \|\|\|\| \|\|\| \|\| \|``` | ![Sample Gif](gifs/32.gif) |
| 33 | ```[] [=] [==] [===] [====] [=====] [======] [=======] [========] [=========] [==========]``` | ![Sample Gif](gifs/33.gif) |
| 34 | ```(*---------) (-*--------) (--*-------) (---*------) (----*-----) (-----*----) (------*---) (-------*--) (--------*-) (---------*)``` | ![Sample Gif](gifs/34.gif) |
| 35 | ```█▒▒▒▒▒▒▒▒▒ ███▒▒▒▒▒▒▒ █████▒▒▒▒▒ ███████▒▒▒ ██████████``` | ![Sample Gif](gifs/35.gif) |
| 36 | ```[ ] [=> ] [===> ] [=====> ] [======> ] [========> ] [==========> ] [============> ] [==============> ] [================> ] [==================> ] [===================>]``` | ![Sample Gif](gifs/36.gif) |
| 37 | ```🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙 🕚 🕛``` | ![Sample Gif](gifs/37.gif) |
| 38 | ```🕐 🕜 🕑 🕝 🕒 🕞 🕓 🕟 🕔 🕠 🕕 🕡 🕖 🕢 🕗 🕣 🕘 🕤 🕙 🕥 🕚 🕦 🕛 🕧``` | ![Sample Gif](gifs/38.gif) |
| 39 | ```🌍 🌎 🌏``` | ![Sample Gif](gifs/39.gif) |
| 40 | ```◜ ◝ ◞ ◟``` | ![Sample Gif](gifs/40.gif) |
| 41 | ```⬒ ⬔ ⬓ ⬕``` | ![Sample Gif](gifs/41.gif) |
| 42 | ```⬖ ⬘ ⬗ ⬙``` | ![Sample Gif](gifs/42.gif) |
| 43 | ```[>>> >] []>>>> [] [] >>>> [] [] >>>> [] [] >>>> [] [] >>>>[] [>> >>]``` | ![Sample Gif](gifs/43.gif) |
## Features
* Start
* Stop
* Restart
* Reverse direction
* Update the spinner character set
* Update the spinner speed
* Prefix or append text
* Change spinner color, background, and text attributes such as bold / italics
* Get spinner status
* Chain, pipe, redirect output
* Output final string on spinner/indicator completion
## Examples
```Go
package main
import (
"github.com/briandowns/spinner"
"time"
)
func main() {
s := spinner.New(spinner.CharSets[9], 100*time.Millisecond) // Build our new spinner
s.Start() // Start the spinner
time.Sleep(4 * time.Second) // Run for some time to simulate work
s.Stop()
}
```
## Update the character set and restart the spinner
```Go
s.UpdateCharSet(spinner.CharSets[1]) // Update spinner to use a different character set
s.Restart() // Restart the spinner
time.Sleep(4 * time.Second)
s.Stop()
```
## Update spin speed and restart the spinner
```Go
s.UpdateSpeed(200 * time.Millisecond) // Update the speed the spinner spins at
s.Restart()
time.Sleep(4 * time.Second)
s.Stop()
```
## Reverse the direction of the spinner
```Go
s.Reverse() // Reverse the direction the spinner is spinning
s.Restart()
time.Sleep(4 * time.Second)
s.Stop()
```
## Provide your own spinner
(or send me an issue or pull request to add to the project)
```Go
someSet := []string{"+", "-"}
s := spinner.New(someSet, 100*time.Millisecond)
```
## Prefix or append text to the spinner
```Go
s.Prefix = "prefixed text: " // Prefix text before the spinner
s.Suffix = " :appended text" // Append text after the spinner
```
## Set or change the color of the spinner. Default color is white. The spinner will need to be restarted to pick up the change.
```Go
s.Color("red") // Set the spinner color to red
```
You can specify both the background and foreground color, as well as additional attributes such as `bold` or `underline`.
```Go
s.Color("red", "bold") // Set the spinner color to a bold red
```
To set the background to black, the foreground to a bold red:
```Go
s.Color("bgBlack", "bold", "fgRed")
```
Below is the full color and attribute list:
```Go
// default colors
red
black
green
yellow
blue
magenta
cyan
white
// attributes
reset
bold
faint
italic
underline
blinkslow
blinkrapid
reversevideo
concealed
crossedout
// foreground text
fgBlack
fgRed
fgGreen
fgYellow
fgBlue
fgMagenta
fgCyan
fgWhite
// foreground Hi-Intensity text
fgHiBlack
fgHiRed
fgHiGreen
fgHiYellow
fgHiBlue
fgHiMagenta
fgHiCyan
fgHiWhite
// background text
bgBlack
bgRed
bgGreen
bgYellow
bgBlue
bgMagenta
bgCyan
bgWhite
// background Hi-Intensity text
bgHiBlack
bgHiRed
bgHiGreen
bgHiYellow
bgHiBlue
bgHiMagenta
bgHiCyan
bgHiWhite
```
## Generate a sequence of numbers
```Go
setOfDigits := spinner.GenerateNumberSequence(25) // Generate a 25 digit string of numbers
s := spinner.New(setOfDigits, 100*time.Millisecond)
```
## Get spinner status
```Go
fmt.Println(s.Active())
```
## Unix pipe and redirect
Feature suggested and write up by [dekz](https://github.com/dekz)
Setting the Spinner Writer to Stderr helps show progress to the user, with the enhancement to chain, pipe or redirect the output.
This is the preferred method of setting a Writer at this time.
```go
s := spinner.New(spinner.CharSets[11], 100*time.Millisecond, spinner.WithWriter(os.Stderr))
s.Suffix = " Encrypting data..."
s.Start()
// Encrypt the data into ciphertext
fmt.Println(os.Stdout, ciphertext)
```
```sh
> myprog encrypt "Secret text" > encrypted.txt
⣯ Encrypting data...
```
```sh
> cat encrypted.txt
1243hjkbas23i9ah27sj39jghv237n2oa93hg83
```
## Final String Output
Add additional output when the spinner/indicator has completed. The "final" output string can be multi-lined and will be written to wherever the `io.Writer` has been configured for.
```Go
s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
s.FinalMSG = "Complete!\nNew line!\nAnother one!\n"
s.Start()
time.Sleep(4 * time.Second)
s.Stop()
```
Output
```sh
Complete!
New line!
Another one!
```

121
vendor/github.com/briandowns/spinner/character_sets.go generated vendored Normal file
View File

@ -0,0 +1,121 @@
// Copyright (c) 2022 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 spinner
const (
clockOneOClock = '\U0001F550'
clockOneThirty = '\U0001F55C'
)
// CharSets contains the available character sets
var CharSets = map[int][]string{
0: {"←", "↖", "↑", "↗", "→", "↘", "↓", "↙"},
1: {"▁", "▃", "▄", "▅", "▆", "▇", "█", "▇", "▆", "▅", "▄", "▃", "▁"},
2: {"▖", "▘", "▝", "▗"},
3: {"┤", "┘", "┴", "└", "├", "┌", "┬", "┐"},
4: {"◢", "◣", "◤", "◥"},
5: {"◰", "◳", "◲", "◱"},
6: {"◴", "◷", "◶", "◵"},
7: {"◐", "◓", "◑", "◒"},
8: {".", "o", "O", "@", "*"},
9: {"|", "/", "-", "\\"},
10: {"◡◡", "⊙⊙", "◠◠"},
11: {"⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"},
12: {">))'>", " >))'>", " >))'>", " >))'>", " >))'>", " <'((<", " <'((<", " <'((<"},
13: {"⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"},
14: {"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
15: {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"},
16: {"▉", "▊", "▋", "▌", "▍", "▎", "▏", "▎", "▍", "▌", "▋", "▊", "▉"},
17: {"■", "□", "▪", "▫"},
18: {"←", "↑", "→", "↓"},
19: {"╫", "╪"},
20: {"⇐", "⇖", "⇑", "⇗", "⇒", "⇘", "⇓", "⇙"},
21: {"⠁", "⠁", "⠉", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠤", "⠄", "⠄", "⠤", "⠠", "⠠", "⠤", "⠦", "⠖", "⠒", "⠐", "⠐", "⠒", "⠓", "⠋", "⠉", "⠈", "⠈"},
22: {"⠈", "⠉", "⠋", "⠓", "⠒", "⠐", "⠐", "⠒", "⠖", "⠦", "⠤", "⠠", "⠠", "⠤", "⠦", "⠖", "⠒", "⠐", "⠐", "⠒", "⠓", "⠋", "⠉", "⠈"},
23: {"⠁", "⠉", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠤", "⠄", "⠄", "⠤", "⠴", "⠲", "⠒", "⠂", "⠂", "⠒", "⠚", "⠙", "⠉", "⠁"},
24: {"⠋", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠦", "⠖", "⠒", "⠐", "⠐", "⠒", "⠓", "⠋"},
25: {"ヲ", "ァ", "ィ", "ゥ", "ェ", "ォ", "ャ", "ュ", "ョ", "ッ", "ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ヤ", "ユ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ン"},
26: {".", "..", "..."},
27: {"▁", "▂", "▃", "▄", "▅", "▆", "▇", "█", "▉", "▊", "▋", "▌", "▍", "▎", "▏", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█", "▇", "▆", "▅", "▄", "▃", "▂", "▁"},
28: {".", "o", "O", "°", "O", "o", "."},
29: {"+", "x"},
30: {"v", "<", "^", ">"},
31: {">>--->", " >>--->", " >>--->", " >>--->", " >>--->", " <---<<", " <---<<", " <---<<", " <---<<", "<---<<"},
32: {"|", "||", "|||", "||||", "|||||", "|||||||", "||||||||", "|||||||", "||||||", "|||||", "||||", "|||", "||", "|"},
33: {"[ ]", "[= ]", "[== ]", "[=== ]", "[==== ]", "[===== ]", "[====== ]", "[======= ]", "[======== ]", "[========= ]", "[==========]"},
34: {"(*---------)", "(-*--------)", "(--*-------)", "(---*------)", "(----*-----)", "(-----*----)", "(------*---)", "(-------*--)", "(--------*-)", "(---------*)"},
35: {"█▒▒▒▒▒▒▒▒▒", "███▒▒▒▒▒▒▒", "█████▒▒▒▒▒", "███████▒▒▒", "██████████"},
36: {"[ ]", "[=> ]", "[===> ]", "[=====> ]", "[======> ]", "[========> ]", "[==========> ]", "[============> ]", "[==============> ]", "[================> ]", "[==================> ]", "[===================>]"},
39: {"🌍", "🌎", "🌏"},
40: {"◜", "◝", "◞", "◟"},
41: {"⬒", "⬔", "⬓", "⬕"},
42: {"⬖", "⬘", "⬗", "⬙"},
43: {"[>>> >]", "[]>>>> []", "[] >>>> []", "[] >>>> []", "[] >>>> []", "[] >>>>[]", "[>> >>]"},
44: {"♠", "♣", "♥", "♦"},
45: {"➞", "➟", "➠", "➡", "➠", "➟"},
46: {" | ", ` \ `, "_ ", ` \ `, " | ", " / ", " _", " / "},
47: {" . . . .", ". . . .", ". . . .", ". . . .", ". . . . ", ". . . . ."},
48: {" | ", " / ", " _ ", ` \ `, " | ", ` \ `, " _ ", " / "},
49: {"⎺", "⎻", "⎼", "⎽", "⎼", "⎻"},
50: {"▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸"},
51: {"[ ]", "[ =]", "[ ==]", "[ ===]", "[====]", "[=== ]", "[== ]", "[= ]"},
52: {"( ● )", "( ● )", "( ● )", "( ● )", "( ●)", "( ● )", "( ● )", "( ● )", "( ● )"},
53: {"✶", "✸", "✹", "✺", "✹", "✷"},
54: {"▐|\\____________▌", "▐_|\\___________▌", "▐__|\\__________▌", "▐___|\\_________▌", "▐____|\\________▌", "▐_____|\\_______▌", "▐______|\\______▌", "▐_______|\\_____▌", "▐________|\\____▌", "▐_________|\\___▌", "▐__________|\\__▌", "▐___________|\\_▌", "▐____________|\\▌", "▐____________/|▌", "▐___________/|_▌", "▐__________/|__▌", "▐_________/|___▌", "▐________/|____▌", "▐_______/|_____▌", "▐______/|______▌", "▐_____/|_______▌", "▐____/|________▌", "▐___/|_________▌", "▐__/|__________▌", "▐_/|___________▌", "▐/|____________▌"},
55: {"▐⠂ ▌", "▐⠈ ▌", "▐ ⠂ ▌", "▐ ⠠ ▌", "▐ ⡀ ▌", "▐ ⠠ ▌", "▐ ⠂ ▌", "▐ ⠈ ▌", "▐ ⠂ ▌", "▐ ⠠ ▌", "▐ ⡀ ▌", "▐ ⠠ ▌", "▐ ⠂ ▌", "▐ ⠈ ▌", "▐ ⠂▌", "▐ ⠠▌", "▐ ⡀▌", "▐ ⠠ ▌", "▐ ⠂ ▌", "▐ ⠈ ▌", "▐ ⠂ ▌", "▐ ⠠ ▌", "▐ ⡀ ▌", "▐ ⠠ ▌", "▐ ⠂ ▌", "▐ ⠈ ▌", "▐ ⠂ ▌", "▐ ⠠ ▌", "▐ ⡀ ▌", "▐⠠ ▌"},
56: {"¿", "?"},
57: {"⢹", "⢺", "⢼", "⣸", "⣇", "⡧", "⡗", "⡏"},
58: {"⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠"},
59: {". ", ".. ", "...", " ..", " .", " "},
60: {".", "o", "O", "°", "O", "o", "."},
61: {"▓", "▒", "░"},
62: {"▌", "▀", "▐", "▄"},
63: {"⊶", "⊷"},
64: {"▪", "▫"},
65: {"□", "■"},
66: {"▮", "▯"},
67: {"-", "=", "≡"},
68: {"d", "q", "p", "b"},
69: {"∙∙∙", "●∙∙", "∙●∙", "∙∙●", "∙∙∙"},
70: {"🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "},
71: {"☗", "☖"},
72: {"⧇", "⧆"},
73: {"◉", "◎"},
74: {"㊂", "㊀", "㊁"},
75: {"⦾", "⦿"},
76: {"", ""},
77: {"▌", "▀", "▐▄"},
78: {"⠈⠁", "⠈⠑", "⠈⠱", "⠈⡱", "⢀⡱", "⢄⡱", "⢄⡱", "⢆⡱", "⢎⡱", "⢎⡰", "⢎⡠", "⢎⡀", "⢎⠁", "⠎⠁", "⠊⠁"},
79: {"________", "-_______", "_-______", "__-_____", "___-____", "____-___", "_____-__", "______-_", "_______-", "________", "_______-", "______-_", "_____-__", "____-___", "___-____", "__-_____", "_-______", "-_______", "________"},
80: {"|_______", "_/______", "__-_____", "___\\____", "____|___", "_____/__", "______-_", "_______\\", "_______|", "______\\_", "_____-__", "____/___", "___|____", "__\\_____", "_-______"},
81: {"□", "◱", "◧", "▣", "■"},
82: {"□", "◱", "▨", "▩", "■"},
83: {"░", "▒", "▓", "█"},
84: {"░", "█"},
85: {"⚪", "⚫"},
86: {"◯", "⬤"},
87: {"▱", "▰"},
88: {"➊", "➋", "➌", "➍", "➎", "➏", "➐", "➑", "➒", "➓"},
89: {"½", "⅓", "⅔", "¼", "¾", "⅛", "⅜", "⅝", "⅞"},
90: {"↞", "↟", "↠", "↡"},
}
func init() {
for i := rune(0); i < 12; i++ {
CharSets[37] = append(CharSets[37], string([]rune{clockOneOClock + i}))
CharSets[38] = append(CharSets[38], string([]rune{clockOneOClock + i}), string([]rune{clockOneThirty + i}))
}
}

557
vendor/github.com/briandowns/spinner/spinner.go generated vendored Normal file
View File

@ -0,0 +1,557 @@
// Copyright (c) 2021 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 spinner is a simple package to add a spinner / progress indicator to any terminal application.
package spinner
import (
"errors"
"fmt"
"io"
"math"
"os"
"runtime"
"strconv"
"strings"
"sync"
"time"
"unicode/utf8"
"github.com/fatih/color"
"golang.org/x/term"
)
// errInvalidColor is returned when attempting to set an invalid color
var errInvalidColor = errors.New("invalid color")
// validColors holds an array of the only colors allowed
var validColors = map[string]bool{
// default colors for backwards compatibility
"black": true,
"red": true,
"green": true,
"yellow": true,
"blue": true,
"magenta": true,
"cyan": true,
"white": true,
// attributes
"reset": true,
"bold": true,
"faint": true,
"italic": true,
"underline": true,
"blinkslow": true,
"blinkrapid": true,
"reversevideo": true,
"concealed": true,
"crossedout": true,
// foreground text
"fgBlack": true,
"fgRed": true,
"fgGreen": true,
"fgYellow": true,
"fgBlue": true,
"fgMagenta": true,
"fgCyan": true,
"fgWhite": true,
// foreground Hi-Intensity text
"fgHiBlack": true,
"fgHiRed": true,
"fgHiGreen": true,
"fgHiYellow": true,
"fgHiBlue": true,
"fgHiMagenta": true,
"fgHiCyan": true,
"fgHiWhite": true,
// background text
"bgBlack": true,
"bgRed": true,
"bgGreen": true,
"bgYellow": true,
"bgBlue": true,
"bgMagenta": true,
"bgCyan": true,
"bgWhite": true,
// background Hi-Intensity text
"bgHiBlack": true,
"bgHiRed": true,
"bgHiGreen": true,
"bgHiYellow": true,
"bgHiBlue": true,
"bgHiMagenta": true,
"bgHiCyan": true,
"bgHiWhite": true,
}
// returns true if the OS is windows and the WT_SESSION env variable is set.
var isWindows = runtime.GOOS == "windows"
var isWindowsTerminalOnWindows = len(os.Getenv("WT_SESSION")) > 0 && isWindows
// returns a valid color's foreground text color attribute
var colorAttributeMap = map[string]color.Attribute{
// default colors for backwards compatibility
"black": color.FgBlack,
"red": color.FgRed,
"green": color.FgGreen,
"yellow": color.FgYellow,
"blue": color.FgBlue,
"magenta": color.FgMagenta,
"cyan": color.FgCyan,
"white": color.FgWhite,
// attributes
"reset": color.Reset,
"bold": color.Bold,
"faint": color.Faint,
"italic": color.Italic,
"underline": color.Underline,
"blinkslow": color.BlinkSlow,
"blinkrapid": color.BlinkRapid,
"reversevideo": color.ReverseVideo,
"concealed": color.Concealed,
"crossedout": color.CrossedOut,
// foreground text colors
"fgBlack": color.FgBlack,
"fgRed": color.FgRed,
"fgGreen": color.FgGreen,
"fgYellow": color.FgYellow,
"fgBlue": color.FgBlue,
"fgMagenta": color.FgMagenta,
"fgCyan": color.FgCyan,
"fgWhite": color.FgWhite,
// foreground Hi-Intensity text colors
"fgHiBlack": color.FgHiBlack,
"fgHiRed": color.FgHiRed,
"fgHiGreen": color.FgHiGreen,
"fgHiYellow": color.FgHiYellow,
"fgHiBlue": color.FgHiBlue,
"fgHiMagenta": color.FgHiMagenta,
"fgHiCyan": color.FgHiCyan,
"fgHiWhite": color.FgHiWhite,
// background text colors
"bgBlack": color.BgBlack,
"bgRed": color.BgRed,
"bgGreen": color.BgGreen,
"bgYellow": color.BgYellow,
"bgBlue": color.BgBlue,
"bgMagenta": color.BgMagenta,
"bgCyan": color.BgCyan,
"bgWhite": color.BgWhite,
// background Hi-Intensity text colors
"bgHiBlack": color.BgHiBlack,
"bgHiRed": color.BgHiRed,
"bgHiGreen": color.BgHiGreen,
"bgHiYellow": color.BgHiYellow,
"bgHiBlue": color.BgHiBlue,
"bgHiMagenta": color.BgHiMagenta,
"bgHiCyan": color.BgHiCyan,
"bgHiWhite": color.BgHiWhite,
}
// validColor will make sure the given color is actually allowed.
func validColor(c string) bool {
return validColors[c]
}
// Spinner struct to hold the provided options.
type Spinner struct {
mu *sync.RWMutex
Delay time.Duration // Delay is the speed of the indicator
chars []string // chars holds the chosen character set
Prefix string // Prefix is the text preppended to the indicator
Suffix string // Suffix is the text appended to the indicator
FinalMSG string // string displayed after Stop() is called
lastOutputPlain string // last character(set) written
LastOutput string // last character(set) written with colors
color func(a ...interface{}) string // default color is white
Writer io.Writer // to make testing better, exported so users have access. Use `WithWriter` to update after initialization.
WriterFile *os.File // writer as file to allow terminal check
active bool // active holds the state of the spinner
enabled bool // indicates whether the spinner is enabled or not
stopChan chan struct{} // stopChan is a channel used to stop the indicator
HideCursor bool // hideCursor determines if the cursor is visible
PreUpdate func(s *Spinner) // will be triggered before every spinner update
PostUpdate func(s *Spinner) // will be triggered after every spinner update
}
// New provides a pointer to an instance of Spinner with the supplied options.
func New(cs []string, d time.Duration, options ...Option) *Spinner {
s := &Spinner{
Delay: d,
chars: cs,
color: color.New(color.FgWhite).SprintFunc(),
mu: &sync.RWMutex{},
Writer: color.Output,
WriterFile: os.Stdout, // matches color.Output
stopChan: make(chan struct{}, 1),
active: false,
enabled: true,
HideCursor: true,
}
for _, option := range options {
option(s)
}
return s
}
// Option is a function that takes a spinner and applies
// a given configuration.
type Option func(*Spinner)
// Options contains fields to configure the spinner.
type Options struct {
Color string
Suffix string
FinalMSG string
HideCursor bool
}
// WithColor adds the given color to the spinner.
func WithColor(color string) Option {
return func(s *Spinner) {
s.Color(color)
}
}
// WithSuffix adds the given string to the spinner
// as the suffix.
func WithSuffix(suffix string) Option {
return func(s *Spinner) {
s.Suffix = suffix
}
}
// WithFinalMSG adds the given string ot the spinner
// as the final message to be written.
func WithFinalMSG(finalMsg string) Option {
return func(s *Spinner) {
s.FinalMSG = finalMsg
}
}
// WithHiddenCursor hides the cursor
// if hideCursor = true given.
func WithHiddenCursor(hideCursor bool) Option {
return func(s *Spinner) {
s.HideCursor = hideCursor
}
}
// WithWriter adds the given writer to the spinner. This
// function should be favored over directly assigning to
// the struct value. Assumes it is not working on a terminal
// since it cannot determine from io.Writer. Use WithWriterFile
// to support terminal checks.
func WithWriter(w io.Writer) Option {
return func(s *Spinner) {
s.mu.Lock()
s.Writer = w
s.WriterFile = os.Stdout // emulate previous behavior for terminal check
s.mu.Unlock()
}
}
// WithWriterFile adds the given writer to the spinner. This
// function should be favored over directly assigning to
// the struct value. Unlike WithWriter, this function allows
// us to check if displaying to a terminal (enable spinning) or
// not (disable spinning). Supersedes WithWriter()
func WithWriterFile(f *os.File) Option {
return func(s *Spinner) {
s.mu.Lock()
s.Writer = f // io.Writer for actual writing
s.WriterFile = f // file used only for terminal check
s.mu.Unlock()
}
}
// Active will return whether or not the spinner is currently active.
func (s *Spinner) Active() bool {
return s.active
}
// Enabled returns whether or not the spinner is enabled.
func (s *Spinner) Enabled() bool {
return s.enabled
}
// Enable enables and restarts the spinner
func (s *Spinner) Enable() {
s.enabled = true
s.Restart()
}
// Disable stops and disables the spinner
func (s *Spinner) Disable() {
s.enabled = false
s.Stop()
}
// Start will start the indicator.
func (s *Spinner) Start() {
s.mu.Lock()
if s.active || !s.enabled || !isRunningInTerminal(s) {
s.mu.Unlock()
return
}
if s.HideCursor && !isWindowsTerminalOnWindows {
// hides the cursor
fmt.Fprint(s.Writer, "\033[?25l")
}
// Disable colors for simple Windows CMD or Powershell
// as they can not recognize them
if isWindows && !isWindowsTerminalOnWindows {
color.NoColor = true
}
s.active = true
s.mu.Unlock()
go func() {
for {
for i := 0; i < len(s.chars); i++ {
select {
case <-s.stopChan:
return
default:
s.mu.Lock()
if !s.active {
s.mu.Unlock()
return
}
if !isWindowsTerminalOnWindows {
s.erase()
}
if s.PreUpdate != nil {
s.PreUpdate(s)
}
var outColor string
if isWindows {
if s.Writer == os.Stderr {
outColor = fmt.Sprintf("\r%s%s%s", s.Prefix, s.chars[i], s.Suffix)
} else {
outColor = fmt.Sprintf("\r%s%s%s", s.Prefix, s.color(s.chars[i]), s.Suffix)
}
} else {
outColor = fmt.Sprintf("\r%s%s%s", s.Prefix, s.color(s.chars[i]), s.Suffix)
}
outPlain := fmt.Sprintf("\r%s%s%s", s.Prefix, s.chars[i], s.Suffix)
fmt.Fprint(s.Writer, outColor)
s.lastOutputPlain = outPlain
s.LastOutput = outColor
delay := s.Delay
if s.PostUpdate != nil {
s.PostUpdate(s)
}
s.mu.Unlock()
time.Sleep(delay)
}
}
}
}()
}
// Stop stops the indicator.
func (s *Spinner) Stop() {
s.mu.Lock()
defer s.mu.Unlock()
if s.active {
s.active = false
if s.HideCursor && !isWindowsTerminalOnWindows {
// makes the cursor visible
fmt.Fprint(s.Writer, "\033[?25h")
}
s.erase()
if s.FinalMSG != "" {
if isWindowsTerminalOnWindows {
fmt.Fprint(s.Writer, "\r", s.FinalMSG)
} else {
fmt.Fprint(s.Writer, s.FinalMSG)
}
}
s.stopChan <- struct{}{}
}
}
// Restart will stop and start the indicator.
func (s *Spinner) Restart() {
s.Stop()
s.Start()
}
// Reverse will reverse the order of the slice assigned to the indicator.
func (s *Spinner) Reverse() {
s.mu.Lock()
for i, j := 0, len(s.chars)-1; i < j; i, j = i+1, j-1 {
s.chars[i], s.chars[j] = s.chars[j], s.chars[i]
}
s.mu.Unlock()
}
// Color will set the struct field for the given color to be used. The spinner
// will need to be explicitly restarted.
func (s *Spinner) Color(colors ...string) error {
colorAttributes := make([]color.Attribute, len(colors))
// Verify colours are valid and place the appropriate attribute in the array
for index, c := range colors {
if !validColor(c) {
return errInvalidColor
}
colorAttributes[index] = colorAttributeMap[c]
}
s.mu.Lock()
s.color = color.New(colorAttributes...).SprintFunc()
s.mu.Unlock()
return nil
}
// UpdateSpeed will set the indicator delay to the given value.
func (s *Spinner) UpdateSpeed(d time.Duration) {
s.mu.Lock()
s.Delay = d
s.mu.Unlock()
}
// UpdateCharSet will change the current character set to the given one.
func (s *Spinner) UpdateCharSet(cs []string) {
s.mu.Lock()
s.chars = cs
s.mu.Unlock()
}
// erase deletes written characters on the current line.
// Caller must already hold s.lock.
func (s *Spinner) erase() {
n := utf8.RuneCountInString(s.lastOutputPlain)
if runtime.GOOS == "windows" && !isWindowsTerminalOnWindows {
clearString := "\r" + strings.Repeat(" ", n) + "\r"
fmt.Fprint(s.Writer, clearString)
s.lastOutputPlain = ""
return
}
numberOfLinesToErase := computeNumberOfLinesNeededToPrintString(s.lastOutputPlain)
// Taken from https://en.wikipedia.org/wiki/ANSI_escape_code:
// \r - Carriage return - Moves the cursor to column zero
// \033[K - Erases part of the line. If n is 0 (or missing), clear from
// cursor to the end of the line. If n is 1, clear from cursor to beginning
// of the line. If n is 2, clear entire line. Cursor position does not
// change.
// \033[F - Go to the beginning of previous line
eraseCodeString := strings.Builder{}
// current position is at the end of the last printed line. Start by erasing current line
eraseCodeString.WriteString("\r\033[K") // start by erasing current line
for i := 1; i < numberOfLinesToErase; i++ {
// For each additional lines, go up one line and erase it.
eraseCodeString.WriteString("\033[F\033[K")
}
fmt.Fprintf(s.Writer, eraseCodeString.String())
s.lastOutputPlain = ""
}
// Lock allows for manual control to lock the spinner.
func (s *Spinner) Lock() {
s.mu.Lock()
}
// Unlock allows for manual control to unlock the spinner.
func (s *Spinner) Unlock() {
s.mu.Unlock()
}
// GenerateNumberSequence will generate a slice of integers at the
// provided length and convert them each to a string.
func GenerateNumberSequence(length int) []string {
numSeq := make([]string, length)
for i := 0; i < length; i++ {
numSeq[i] = strconv.Itoa(i)
}
return numSeq
}
// isRunningInTerminal check if the writer file descriptor is a terminal
func isRunningInTerminal(s *Spinner) bool {
fd := s.WriterFile.Fd()
return term.IsTerminal(int(fd))
}
func computeNumberOfLinesNeededToPrintString(linePrinted string) int {
terminalWidth := math.MaxInt // assume infinity by default to keep behaviour consistent with what we had before
if term.IsTerminal(0) {
if width, _, err := term.GetSize(0); err == nil {
terminalWidth = width
}
}
return computeNumberOfLinesNeededToPrintStringInternal(linePrinted, terminalWidth)
}
// isAnsiMarker returns if a rune denotes the start of an ANSI sequence
func isAnsiMarker(r rune) bool {
return r == '\x1b'
}
// isAnsiTerminator returns if a rune denotes the end of an ANSI sequence
func isAnsiTerminator(r rune) bool {
return (r >= 0x40 && r <= 0x5a) || (r == 0x5e) || (r >= 0x60 && r <= 0x7e)
}
// computeLineWidth returns the displayed width of a line
func computeLineWidth(line string) int {
width := 0
ansi := false
for _, r := range []rune(line) {
// increase width only when outside of ANSI escape sequences
if ansi || isAnsiMarker(r) {
ansi = !isAnsiTerminator(r)
} else {
width += utf8.RuneLen(r)
}
}
return width
}
func computeNumberOfLinesNeededToPrintStringInternal(linePrinted string, maxLineWidth int) int {
lineCount := 0
for _, line := range strings.Split(linePrinted, "\n") {
lineCount += 1
lineWidth := computeLineWidth(line)
if lineWidth > maxLineWidth {
lineCount += int(float64(lineWidth) / float64(maxLineWidth))
}
}
return lineCount
}

8
vendor/golang.org/x/sys/plan9/asm.s generated vendored Normal file
View File

@ -0,0 +1,8 @@
// 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.
#include "textflag.h"
TEXT ·use(SB),NOSPLIT,$0
RET

30
vendor/golang.org/x/sys/plan9/asm_plan9_386.s generated vendored Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2009 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.
#include "textflag.h"
//
// System call support for 386, Plan 9
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-32
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-44
JMP syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
JMP syscall·RawSyscall6(SB)
TEXT ·seek(SB),NOSPLIT,$0-36
JMP syscall·seek(SB)
TEXT ·exit(SB),NOSPLIT,$4-4
JMP syscall·exit(SB)

30
vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s generated vendored Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2009 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.
#include "textflag.h"
//
// System call support for amd64, Plan 9
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-64
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-88
JMP syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)
TEXT ·seek(SB),NOSPLIT,$0-56
JMP syscall·seek(SB)
TEXT ·exit(SB),NOSPLIT,$8-8
JMP syscall·exit(SB)

25
vendor/golang.org/x/sys/plan9/asm_plan9_arm.s generated vendored Normal file
View File

@ -0,0 +1,25 @@
// Copyright 2009 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.
#include "textflag.h"
// System call support for plan9 on arm
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-32
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-44
JMP syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
JMP syscall·RawSyscall6(SB)
TEXT ·seek(SB),NOSPLIT,$0-36
JMP syscall·exit(SB)

70
vendor/golang.org/x/sys/plan9/const_plan9.go generated vendored Normal file
View File

@ -0,0 +1,70 @@
package plan9
// Plan 9 Constants
// Open modes
const (
O_RDONLY = 0
O_WRONLY = 1
O_RDWR = 2
O_TRUNC = 16
O_CLOEXEC = 32
O_EXCL = 0x1000
)
// Rfork flags
const (
RFNAMEG = 1 << 0
RFENVG = 1 << 1
RFFDG = 1 << 2
RFNOTEG = 1 << 3
RFPROC = 1 << 4
RFMEM = 1 << 5
RFNOWAIT = 1 << 6
RFCNAMEG = 1 << 10
RFCENVG = 1 << 11
RFCFDG = 1 << 12
RFREND = 1 << 13
RFNOMNT = 1 << 14
)
// Qid.Type bits
const (
QTDIR = 0x80
QTAPPEND = 0x40
QTEXCL = 0x20
QTMOUNT = 0x10
QTAUTH = 0x08
QTTMP = 0x04
QTFILE = 0x00
)
// Dir.Mode bits
const (
DMDIR = 0x80000000
DMAPPEND = 0x40000000
DMEXCL = 0x20000000
DMMOUNT = 0x10000000
DMAUTH = 0x08000000
DMTMP = 0x04000000
DMREAD = 0x4
DMWRITE = 0x2
DMEXEC = 0x1
)
const (
STATMAX = 65535
ERRMAX = 128
STATFIXLEN = 49
)
// Mount and bind flags
const (
MREPL = 0x0000
MBEFORE = 0x0001
MAFTER = 0x0002
MORDER = 0x0003
MCREATE = 0x0004
MCACHE = 0x0010
MMASK = 0x0017
)

212
vendor/golang.org/x/sys/plan9/dir_plan9.go generated vendored Normal file
View File

@ -0,0 +1,212 @@
// Copyright 2012 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.
// Plan 9 directory marshalling. See intro(5).
package plan9
import "errors"
var (
ErrShortStat = errors.New("stat buffer too short")
ErrBadStat = errors.New("malformed stat buffer")
ErrBadName = errors.New("bad character in file name")
)
// A Qid represents a 9P server's unique identification for a file.
type Qid struct {
Path uint64 // the file server's unique identification for the file
Vers uint32 // version number for given Path
Type uint8 // the type of the file (plan9.QTDIR for example)
}
// A Dir contains the metadata for a file.
type Dir struct {
// system-modified data
Type uint16 // server type
Dev uint32 // server subtype
// file data
Qid Qid // unique id from server
Mode uint32 // permissions
Atime uint32 // last read time
Mtime uint32 // last write time
Length int64 // file length
Name string // last element of path
Uid string // owner name
Gid string // group name
Muid string // last modifier name
}
var nullDir = Dir{
Type: ^uint16(0),
Dev: ^uint32(0),
Qid: Qid{
Path: ^uint64(0),
Vers: ^uint32(0),
Type: ^uint8(0),
},
Mode: ^uint32(0),
Atime: ^uint32(0),
Mtime: ^uint32(0),
Length: ^int64(0),
}
// Null assigns special "don't touch" values to members of d to
// avoid modifying them during plan9.Wstat.
func (d *Dir) Null() { *d = nullDir }
// Marshal encodes a 9P stat message corresponding to d into b
//
// If there isn't enough space in b for a stat message, ErrShortStat is returned.
func (d *Dir) Marshal(b []byte) (n int, err error) {
n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
if n > len(b) {
return n, ErrShortStat
}
for _, c := range d.Name {
if c == '/' {
return n, ErrBadName
}
}
b = pbit16(b, uint16(n)-2)
b = pbit16(b, d.Type)
b = pbit32(b, d.Dev)
b = pbit8(b, d.Qid.Type)
b = pbit32(b, d.Qid.Vers)
b = pbit64(b, d.Qid.Path)
b = pbit32(b, d.Mode)
b = pbit32(b, d.Atime)
b = pbit32(b, d.Mtime)
b = pbit64(b, uint64(d.Length))
b = pstring(b, d.Name)
b = pstring(b, d.Uid)
b = pstring(b, d.Gid)
b = pstring(b, d.Muid)
return n, nil
}
// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
//
// If b is too small to hold a valid stat message, ErrShortStat is returned.
//
// If the stat message itself is invalid, ErrBadStat is returned.
func UnmarshalDir(b []byte) (*Dir, error) {
if len(b) < STATFIXLEN {
return nil, ErrShortStat
}
size, buf := gbit16(b)
if len(b) != int(size)+2 {
return nil, ErrBadStat
}
b = buf
var d Dir
d.Type, b = gbit16(b)
d.Dev, b = gbit32(b)
d.Qid.Type, b = gbit8(b)
d.Qid.Vers, b = gbit32(b)
d.Qid.Path, b = gbit64(b)
d.Mode, b = gbit32(b)
d.Atime, b = gbit32(b)
d.Mtime, b = gbit32(b)
n, b := gbit64(b)
d.Length = int64(n)
var ok bool
if d.Name, b, ok = gstring(b); !ok {
return nil, ErrBadStat
}
if d.Uid, b, ok = gstring(b); !ok {
return nil, ErrBadStat
}
if d.Gid, b, ok = gstring(b); !ok {
return nil, ErrBadStat
}
if d.Muid, b, ok = gstring(b); !ok {
return nil, ErrBadStat
}
return &d, nil
}
// pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
func pbit8(b []byte, v uint8) []byte {
b[0] = byte(v)
return b[1:]
}
// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit16(b []byte, v uint16) []byte {
b[0] = byte(v)
b[1] = byte(v >> 8)
return b[2:]
}
// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit32(b []byte, v uint32) []byte {
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
return b[4:]
}
// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit64(b []byte, v uint64) []byte {
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
return b[8:]
}
// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
// returning the remaining slice of b..
func pstring(b []byte, s string) []byte {
b = pbit16(b, uint16(len(s)))
n := copy(b, s)
return b[n:]
}
// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
func gbit8(b []byte) (uint8, []byte) {
return uint8(b[0]), b[1:]
}
// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit16(b []byte) (uint16, []byte) {
return uint16(b[0]) | uint16(b[1])<<8, b[2:]
}
// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit32(b []byte) (uint32, []byte) {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
}
// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit64(b []byte) (uint64, []byte) {
lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
return uint64(lo) | uint64(hi)<<32, b[8:]
}
// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
// It returns the string with the remaining slice of b and a boolean. If the length is
// greater than the number of bytes in b, the boolean will be false.
func gstring(b []byte) (string, []byte, bool) {
n, b := gbit16(b)
if int(n) > len(b) {
return "", b, false
}
return string(b[:n]), b[n:], true
}

31
vendor/golang.org/x/sys/plan9/env_plan9.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
// Copyright 2011 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.
// Plan 9 environment variables.
package plan9
import (
"syscall"
)
func Getenv(key string) (value string, found bool) {
return syscall.Getenv(key)
}
func Setenv(key, value string) error {
return syscall.Setenv(key, value)
}
func Clearenv() {
syscall.Clearenv()
}
func Environ() []string {
return syscall.Environ()
}
func Unsetenv(key string) error {
return syscall.Unsetenv(key)
}

50
vendor/golang.org/x/sys/plan9/errors_plan9.go generated vendored Normal file
View File

@ -0,0 +1,50 @@
// Copyright 2011 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 plan9
import "syscall"
// Constants
const (
// Invented values to support what package os expects.
O_CREAT = 0x02000
O_APPEND = 0x00400
O_NOCTTY = 0x00000
O_NONBLOCK = 0x00000
O_SYNC = 0x00000
O_ASYNC = 0x00000
S_IFMT = 0x1f000
S_IFIFO = 0x1000
S_IFCHR = 0x2000
S_IFDIR = 0x4000
S_IFBLK = 0x6000
S_IFREG = 0x8000
S_IFLNK = 0xa000
S_IFSOCK = 0xc000
)
// Errors
var (
EINVAL = syscall.NewError("bad arg in system call")
ENOTDIR = syscall.NewError("not a directory")
EISDIR = syscall.NewError("file is a directory")
ENOENT = syscall.NewError("file does not exist")
EEXIST = syscall.NewError("file already exists")
EMFILE = syscall.NewError("no free file descriptors")
EIO = syscall.NewError("i/o error")
ENAMETOOLONG = syscall.NewError("file name too long")
EINTR = syscall.NewError("interrupted")
EPERM = syscall.NewError("permission denied")
EBUSY = syscall.NewError("no free devices")
ETIMEDOUT = syscall.NewError("connection timed out")
EPLAN9 = syscall.NewError("not supported by plan 9")
// The following errors do not correspond to any
// Plan 9 system messages. Invented to support
// what package os and others expect.
EACCES = syscall.NewError("access permission denied")
EAFNOSUPPORT = syscall.NewError("address family not supported by protocol")
)

150
vendor/golang.org/x/sys/plan9/mkall.sh generated vendored Normal file
View File

@ -0,0 +1,150 @@
#!/usr/bin/env bash
# Copyright 2009 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.
# The plan9 package provides access to the raw system call
# interface of the underlying operating system. Porting Go to
# a new architecture/operating system combination requires
# some manual effort, though there are tools that automate
# much of the process. The auto-generated files have names
# beginning with z.
#
# This script runs or (given -n) prints suggested commands to generate z files
# for the current system. Running those commands is not automatic.
# This script is documentation more than anything else.
#
# * asm_${GOOS}_${GOARCH}.s
#
# This hand-written assembly file implements system call dispatch.
# There are three entry points:
#
# func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
# func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
# func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
#
# The first and second are the standard ones; they differ only in
# how many arguments can be passed to the kernel.
# The third is for low-level use by the ForkExec wrapper;
# unlike the first two, it does not call into the scheduler to
# let it know that a system call is running.
#
# * syscall_${GOOS}.go
#
# This hand-written Go file implements system calls that need
# special handling and lists "//sys" comments giving prototypes
# for ones that can be auto-generated. Mksyscall reads those
# comments to generate the stubs.
#
# * syscall_${GOOS}_${GOARCH}.go
#
# Same as syscall_${GOOS}.go except that it contains code specific
# to ${GOOS} on one particular architecture.
#
# * types_${GOOS}.c
#
# This hand-written C file includes standard C headers and then
# creates typedef or enum names beginning with a dollar sign
# (use of $ in variable names is a gcc extension). The hardest
# part about preparing this file is figuring out which headers to
# include and which symbols need to be #defined to get the
# actual data structures that pass through to the kernel system calls.
# Some C libraries present alternate versions for binary compatibility
# and translate them on the way in and out of system calls, but
# there is almost always a #define that can get the real ones.
# See types_darwin.c and types_linux.c for examples.
#
# * zerror_${GOOS}_${GOARCH}.go
#
# This machine-generated file defines the system's error numbers,
# error strings, and signal numbers. The generator is "mkerrors.sh".
# Usually no arguments are needed, but mkerrors.sh will pass its
# arguments on to godefs.
#
# * zsyscall_${GOOS}_${GOARCH}.go
#
# Generated by mksyscall.pl; see syscall_${GOOS}.go above.
#
# * zsysnum_${GOOS}_${GOARCH}.go
#
# Generated by mksysnum_${GOOS}.
#
# * ztypes_${GOOS}_${GOARCH}.go
#
# Generated by godefs; see types_${GOOS}.c above.
GOOSARCH="${GOOS}_${GOARCH}"
# defaults
mksyscall="go run mksyscall.go"
mkerrors="./mkerrors.sh"
zerrors="zerrors_$GOOSARCH.go"
mksysctl=""
zsysctl="zsysctl_$GOOSARCH.go"
mksysnum=
mktypes=
run="sh"
case "$1" in
-syscalls)
for i in zsyscall*go
do
sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
rm _$i
done
exit 0
;;
-n)
run="cat"
shift
esac
case "$#" in
0)
;;
*)
echo 'usage: mkall.sh [-n]' 1>&2
exit 2
esac
case "$GOOSARCH" in
_* | *_ | _)
echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
exit 1
;;
plan9_386)
mkerrors=
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,386"
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
mktypes="XXX"
;;
plan9_amd64)
mkerrors=
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,amd64"
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
mktypes="XXX"
;;
plan9_arm)
mkerrors=
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,arm"
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
mktypes="XXX"
;;
*)
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
exit 1
;;
esac
(
if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
case "$GOOS" in
plan9)
syscall_goos="syscall_$GOOS.go"
if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos |gofmt >zsyscall_$GOOSARCH.go"; fi
;;
esac
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi
) | $run

246
vendor/golang.org/x/sys/plan9/mkerrors.sh generated vendored Normal file
View File

@ -0,0 +1,246 @@
#!/usr/bin/env bash
# Copyright 2009 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.
# Generate Go code listing errors and other #defined constant
# values (ENAMETOOLONG etc.), by asking the preprocessor
# about the definitions.
unset LANG
export LC_ALL=C
export LC_CTYPE=C
CC=${CC:-gcc}
uname=$(uname)
includes='
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <sys/signal.h>
#include <signal.h>
#include <sys/resource.h>
'
ccflags="$@"
# Write go tool cgo -godefs input.
(
echo package plan9
echo
echo '/*'
indirect="includes_$(uname)"
echo "${!indirect} $includes"
echo '*/'
echo 'import "C"'
echo
echo 'const ('
# The gcc command line prints all the #defines
# it encounters while processing the input
echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
awk '
$1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
$2 ~ /^(SCM_SRCRT)$/ {next}
$2 ~ /^(MAP_FAILED)$/ {next}
$2 !~ /^ETH_/ &&
$2 !~ /^EPROC_/ &&
$2 !~ /^EQUIV_/ &&
$2 !~ /^EXPR_/ &&
$2 ~ /^E[A-Z0-9_]+$/ ||
$2 ~ /^B[0-9_]+$/ ||
$2 ~ /^V[A-Z0-9]+$/ ||
$2 ~ /^CS[A-Z0-9]/ ||
$2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
$2 ~ /^IGN/ ||
$2 ~ /^IX(ON|ANY|OFF)$/ ||
$2 ~ /^IN(LCR|PCK)$/ ||
$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
$2 ~ /^C(LOCAL|READ)$/ ||
$2 == "BRKINT" ||
$2 == "HUPCL" ||
$2 == "PENDIN" ||
$2 == "TOSTOP" ||
$2 ~ /^PAR/ ||
$2 ~ /^SIG[^_]/ ||
$2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ ||
$2 ~ /^IN_/ ||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
$2 == "ICMPV6_FILTER" ||
$2 == "SOMAXCONN" ||
$2 == "NAME_MAX" ||
$2 == "IFNAMSIZ" ||
$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
$2 ~ /^SYSCTL_VERS/ ||
$2 ~ /^(MS|MNT)_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ ||
$2 ~ /^LINUX_REBOOT_CMD_/ ||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
$2 !~ "NLA_TYPE_MASK" &&
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
$2 ~ /^SIOC/ ||
$2 ~ /^TIOC/ ||
$2 !~ "RTF_BITS" &&
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^BIOC/ ||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ ||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
$2 ~ /^CLONE_[A-Z_]+/ ||
$2 !~ /^(BPF_TIMEVAL)$/ &&
$2 ~ /^(BPF|DLT)_/ ||
$2 !~ "WMESGLEN" &&
$2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)}
$2 ~ /^__WCOREFLAG$/ {next}
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
{next}
' | sort
echo ')'
) >_const.go
# Pull out the error names for later.
errors=$(
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
sort
)
# Pull out the signal names for later.
signals=$(
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' |
sort
)
# Again, writing regexps to a file.
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
sort >_error.grep
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' |
sort >_signal.grep
echo '// mkerrors.sh' "$@"
echo '// Code generated by the command above; DO NOT EDIT.'
echo
go tool cgo -godefs -- "$@" _const.go >_error.out
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
echo
echo '// Errors'
echo 'const ('
cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/'
echo ')'
echo
echo '// Signals'
echo 'const ('
cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= Signal(\1)/'
echo ')'
# Run C program to print error and syscall strings.
(
echo -E "
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
int errors[] = {
"
for i in $errors
do
echo -E ' '$i,
done
echo -E "
};
int signals[] = {
"
for i in $signals
do
echo -E ' '$i,
done
# Use -E because on some systems bash builtin interprets \n itself.
echo -E '
};
static int
intcmp(const void *a, const void *b)
{
return *(int*)a - *(int*)b;
}
int
main(void)
{
int i, j, e;
char buf[1024], *p;
printf("\n\n// Error table\n");
printf("var errors = [...]string {\n");
qsort(errors, nelem(errors), sizeof errors[0], intcmp);
for(i=0; i<nelem(errors); i++) {
e = errors[i];
if(i > 0 && errors[i-1] == e)
continue;
strcpy(buf, strerror(e));
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
buf[0] += a - A;
printf("\t%d: \"%s\",\n", e, buf);
}
printf("}\n\n");
printf("\n\n// Signal table\n");
printf("var signals = [...]string {\n");
qsort(signals, nelem(signals), sizeof signals[0], intcmp);
for(i=0; i<nelem(signals); i++) {
e = signals[i];
if(i > 0 && signals[i-1] == e)
continue;
strcpy(buf, strsignal(e));
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
buf[0] += a - A;
// cut trailing : number.
p = strrchr(buf, ":"[0]);
if(p)
*p = '\0';
printf("\t%d: \"%s\",\n", e, buf);
}
printf("}\n\n");
return 0;
}
'
) >_errors.c
$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out

23
vendor/golang.org/x/sys/plan9/mksysnum_plan9.sh generated vendored Normal file
View File

@ -0,0 +1,23 @@
#!/bin/sh
# Copyright 2009 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.
COMMAND="mksysnum_plan9.sh $@"
cat <<EOF
// $COMMAND
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
package plan9
const(
EOF
SP='[ ]' # space or tab
sed "s/^#define${SP}\\([A-Z0-9_][A-Z0-9_]*\\)${SP}${SP}*\\([0-9][0-9]*\\)/SYS_\\1=\\2/g" \
< $1 | grep -v SYS__
cat <<EOF
)
EOF

21
vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
// 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:build go1.5
package plan9
import "syscall"
func fixwd() {
syscall.Fixwd()
}
func Getwd() (wd string, err error) {
return syscall.Getwd()
}
func Chdir(path string) error {
return syscall.Chdir(path)
}

23
vendor/golang.org/x/sys/plan9/pwd_plan9.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
// 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:build !go1.5
package plan9
func fixwd() {
}
func Getwd() (wd string, err error) {
fd, err := open(".", O_RDONLY)
if err != nil {
return "", err
}
defer Close(fd)
return Fd2path(fd)
}
func Chdir(path string) error {
return chdir(path)
}

30
vendor/golang.org/x/sys/plan9/race.go generated vendored Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2012 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:build plan9 && race
package plan9
import (
"runtime"
"unsafe"
)
const raceenabled = true
func raceAcquire(addr unsafe.Pointer) {
runtime.RaceAcquire(addr)
}
func raceReleaseMerge(addr unsafe.Pointer) {
runtime.RaceReleaseMerge(addr)
}
func raceReadRange(addr unsafe.Pointer, len int) {
runtime.RaceReadRange(addr, len)
}
func raceWriteRange(addr unsafe.Pointer, len int) {
runtime.RaceWriteRange(addr, len)
}

25
vendor/golang.org/x/sys/plan9/race0.go generated vendored Normal file
View File

@ -0,0 +1,25 @@
// Copyright 2012 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:build plan9 && !race
package plan9
import (
"unsafe"
)
const raceenabled = false
func raceAcquire(addr unsafe.Pointer) {
}
func raceReleaseMerge(addr unsafe.Pointer) {
}
func raceReadRange(addr unsafe.Pointer, len int) {
}
func raceWriteRange(addr unsafe.Pointer, len int) {
}

22
vendor/golang.org/x/sys/plan9/str.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// Copyright 2009 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:build plan9
package plan9
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
if val < 0 {
return "-" + itoa(-val)
}
var buf [32]byte // big enough for int64
i := len(buf) - 1
for val >= 10 {
buf[i] = byte(val%10 + '0')
i--
val /= 10
}
buf[i] = byte(val + '0')
return string(buf[i:])
}

109
vendor/golang.org/x/sys/plan9/syscall.go generated vendored Normal file
View File

@ -0,0 +1,109 @@
// Copyright 2009 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:build plan9
// Package plan9 contains an interface to the low-level operating system
// primitives. OS details vary depending on the underlying system, and
// by default, godoc will display the OS-specific documentation for the current
// system. If you want godoc to display documentation for another
// system, set $GOOS and $GOARCH to the desired system. For example, if
// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
// to freebsd and $GOARCH to arm.
//
// The primary use of this package is inside other packages that provide a more
// portable interface to the system, such as "os", "time" and "net". Use
// those packages rather than this one if you can.
//
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
//
// These calls return err == nil to indicate success; otherwise
// err represents an operating system error describing the failure and
// holds a value of type syscall.ErrorString.
package plan9 // import "golang.org/x/sys/plan9"
import (
"bytes"
"strings"
"unsafe"
)
// ByteSliceFromString returns a NUL-terminated slice of bytes
// containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
func ByteSliceFromString(s string) ([]byte, error) {
if strings.IndexByte(s, 0) != -1 {
return nil, EINVAL
}
a := make([]byte, len(s)+1)
copy(a, s)
return a, nil
}
// BytePtrFromString returns a pointer to a NUL-terminated array of
// bytes containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
func BytePtrFromString(s string) (*byte, error) {
a, err := ByteSliceFromString(s)
if err != nil {
return nil, err
}
return &a[0], nil
}
// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any
// bytes after the NUL removed.
func ByteSliceToString(s []byte) string {
if i := bytes.IndexByte(s, 0); i != -1 {
s = s[:i]
}
return string(s)
}
// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string.
// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated
// at a zero byte; if the zero byte is not present, the program may crash.
func BytePtrToString(p *byte) string {
if p == nil {
return ""
}
if *p == 0 {
return ""
}
// Find NUL terminator.
n := 0
for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ {
ptr = unsafe.Pointer(uintptr(ptr) + 1)
}
return string(unsafe.Slice(p, n))
}
// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr
func (ts *Timespec) Unix() (sec int64, nsec int64) {
return int64(ts.Sec), int64(ts.Nsec)
}
func (tv *Timeval) Unix() (sec int64, nsec int64) {
return int64(tv.Sec), int64(tv.Usec) * 1000
}
func (ts *Timespec) Nano() int64 {
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
}
func (tv *Timeval) Nano() int64 {
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
}
// use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point.
//
//go:noescape
func use(p unsafe.Pointer)

361
vendor/golang.org/x/sys/plan9/syscall_plan9.go generated vendored Normal file
View File

@ -0,0 +1,361 @@
// Copyright 2011 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.
// Plan 9 system calls.
// This file is compiled as ordinary Go code,
// but it is also input to mksyscall,
// which parses the //sys lines and generates system call stubs.
// Note that sometimes we use a lowercase //sys name and
// wrap it in our own nicer implementation.
package plan9
import (
"bytes"
"syscall"
"unsafe"
)
// A Note is a string describing a process note.
// It implements the os.Signal interface.
type Note string
func (n Note) Signal() {}
func (n Note) String() string {
return string(n)
}
var (
Stdin = 0
Stdout = 1
Stderr = 2
)
// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
var SocketDisableIPv6 bool
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
func atoi(b []byte) (n uint) {
n = 0
for i := 0; i < len(b); i++ {
n = n*10 + uint(b[i]-'0')
}
return
}
func cstring(s []byte) string {
i := bytes.IndexByte(s, 0)
if i == -1 {
i = len(s)
}
return string(s[:i])
}
func errstr() string {
var buf [ERRMAX]byte
RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
buf[len(buf)-1] = 0
return cstring(buf[:])
}
// Implemented in assembly to import from runtime.
func exit(code int)
func Exit(code int) { exit(code) }
func readnum(path string) (uint, error) {
var b [12]byte
fd, e := Open(path, O_RDONLY)
if e != nil {
return 0, e
}
defer Close(fd)
n, e := Pread(fd, b[:], 0)
if e != nil {
return 0, e
}
m := 0
for ; m < n && b[m] == ' '; m++ {
}
return atoi(b[m : n-1]), nil
}
func Getpid() (pid int) {
n, _ := readnum("#c/pid")
return int(n)
}
func Getppid() (ppid int) {
n, _ := readnum("#c/ppid")
return int(n)
}
func Read(fd int, p []byte) (n int, err error) {
return Pread(fd, p, -1)
}
func Write(fd int, p []byte) (n int, err error) {
return Pwrite(fd, p, -1)
}
var ioSync int64
//sys fd2path(fd int, buf []byte) (err error)
func Fd2path(fd int) (path string, err error) {
var buf [512]byte
e := fd2path(fd, buf[:])
if e != nil {
return "", e
}
return cstring(buf[:]), nil
}
//sys pipe(p *[2]int32) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return syscall.ErrorString("bad arg in system call")
}
var pp [2]int32
err = pipe(&pp)
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return
}
// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
newoffset, e := seek(0, fd, offset, whence)
if newoffset == -1 {
err = syscall.ErrorString(e)
}
return
}
func Mkdir(path string, mode uint32) (err error) {
fd, err := Create(path, O_RDONLY, DMDIR|mode)
if fd != -1 {
Close(fd)
}
return
}
type Waitmsg struct {
Pid int
Time [3]uint32
Msg string
}
func (w Waitmsg) Exited() bool { return true }
func (w Waitmsg) Signaled() bool { return false }
func (w Waitmsg) ExitStatus() int {
if len(w.Msg) == 0 {
// a normal exit returns no message
return 0
}
return 1
}
//sys await(s []byte) (n int, err error)
func Await(w *Waitmsg) (err error) {
var buf [512]byte
var f [5][]byte
n, err := await(buf[:])
if err != nil || w == nil {
return
}
nf := 0
p := 0
for i := 0; i < n && nf < len(f)-1; i++ {
if buf[i] == ' ' {
f[nf] = buf[p:i]
p = i + 1
nf++
}
}
f[nf] = buf[p:]
nf++
if nf != len(f) {
return syscall.ErrorString("invalid wait message")
}
w.Pid = int(atoi(f[0]))
w.Time[0] = uint32(atoi(f[1]))
w.Time[1] = uint32(atoi(f[2]))
w.Time[2] = uint32(atoi(f[3]))
w.Msg = cstring(f[4])
if w.Msg == "''" {
// await() returns '' for no error
w.Msg = ""
}
return
}
func Unmount(name, old string) (err error) {
fixwd()
oldp, err := BytePtrFromString(old)
if err != nil {
return err
}
oldptr := uintptr(unsafe.Pointer(oldp))
var r0 uintptr
var e syscall.ErrorString
// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
if name == "" {
r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
} else {
namep, err := BytePtrFromString(name)
if err != nil {
return err
}
r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
}
if int32(r0) == -1 {
err = e
}
return
}
func Fchdir(fd int) (err error) {
path, err := Fd2path(fd)
if err != nil {
return
}
return Chdir(path)
}
type Timespec struct {
Sec int32
Nsec int32
}
type Timeval struct {
Sec int32
Usec int32
}
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3)
tv.Sec = int32(nsec / 1e9)
return
}
func nsec() int64 {
var scratch int64
r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
if r0 == 0 {
return scratch
}
return int64(r0)
}
func Gettimeofday(tv *Timeval) error {
nsec := nsec()
*tv = NsecToTimeval(nsec)
return nil
}
func Getpagesize() int { return 0x1000 }
func Getegid() (egid int) { return -1 }
func Geteuid() (euid int) { return -1 }
func Getgid() (gid int) { return -1 }
func Getuid() (uid int) { return -1 }
func Getgroups() (gids []int, err error) {
return make([]int, 0), nil
}
//sys open(path string, mode int) (fd int, err error)
func Open(path string, mode int) (fd int, err error) {
fixwd()
return open(path, mode)
}
//sys create(path string, mode int, perm uint32) (fd int, err error)
func Create(path string, mode int, perm uint32) (fd int, err error) {
fixwd()
return create(path, mode, perm)
}
//sys remove(path string) (err error)
func Remove(path string) error {
fixwd()
return remove(path)
}
//sys stat(path string, edir []byte) (n int, err error)
func Stat(path string, edir []byte) (n int, err error) {
fixwd()
return stat(path, edir)
}
//sys bind(name string, old string, flag int) (err error)
func Bind(name string, old string, flag int) (err error) {
fixwd()
return bind(name, old, flag)
}
//sys mount(fd int, afd int, old string, flag int, aname string) (err error)
func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
fixwd()
return mount(fd, afd, old, flag, aname)
}
//sys wstat(path string, edir []byte) (err error)
func Wstat(path string, edir []byte) (err error) {
fixwd()
return wstat(path, edir)
}
//sys chdir(path string) (err error)
//sys Dup(oldfd int, newfd int) (fd int, err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error)
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys Close(fd int) (err error)
//sys Fstat(fd int, edir []byte) (n int, err error)
//sys Fwstat(fd int, edir []byte) (err error)

284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go generated vendored Normal file
View File

@ -0,0 +1,284 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,386 syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT.
//go:build plan9 && 386
package plan9
import "unsafe"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fd2path(fd int, buf []byte) (err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {
_p0 = unsafe.Pointer(&buf[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]int32) (err error) {
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func await(s []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(s) > 0 {
_p0 = unsafe.Pointer(&s[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func open(path string, mode int) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func create(path string, mode int, perm uint32) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func remove(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func stat(path string, edir []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func bind(name string, old string, flag int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(old)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(old)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(aname)
if err != nil {
return
}
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func wstat(path string, edir []byte) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func chdir(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup(oldfd int, newfd int) (fd int, err error) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Close(fd int) (err error) {
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, edir []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fwstat(fd int, edir []byte) (err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}

284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go generated vendored Normal file
View File

@ -0,0 +1,284 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,amd64 syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT.
//go:build plan9 && amd64
package plan9
import "unsafe"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fd2path(fd int, buf []byte) (err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {
_p0 = unsafe.Pointer(&buf[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]int32) (err error) {
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func await(s []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(s) > 0 {
_p0 = unsafe.Pointer(&s[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func open(path string, mode int) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func create(path string, mode int, perm uint32) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func remove(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func stat(path string, edir []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func bind(name string, old string, flag int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(old)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(old)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(aname)
if err != nil {
return
}
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func wstat(path string, edir []byte) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func chdir(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup(oldfd int, newfd int) (fd int, err error) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Close(fd int) (err error) {
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, edir []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fwstat(fd int, edir []byte) (err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}

284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go generated vendored Normal file
View File

@ -0,0 +1,284 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,arm syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT.
//go:build plan9 && arm
package plan9
import "unsafe"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fd2path(fd int, buf []byte) (err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {
_p0 = unsafe.Pointer(&buf[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]int32) (err error) {
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func await(s []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(s) > 0 {
_p0 = unsafe.Pointer(&s[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func open(path string, mode int) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func create(path string, mode int, perm uint32) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func remove(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func stat(path string, edir []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func bind(name string, old string, flag int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(old)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(old)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(aname)
if err != nil {
return
}
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func wstat(path string, edir []byte) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func chdir(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup(oldfd int, newfd int) (fd int, err error) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Close(fd int) (err error) {
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, edir []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fwstat(fd int, edir []byte) (err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}

49
vendor/golang.org/x/sys/plan9/zsysnum_plan9.go generated vendored Normal file
View File

@ -0,0 +1,49 @@
// mksysnum_plan9.sh /opt/plan9/sys/src/libc/9syscall/sys.h
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
package plan9
const (
SYS_SYSR1 = 0
SYS_BIND = 2
SYS_CHDIR = 3
SYS_CLOSE = 4
SYS_DUP = 5
SYS_ALARM = 6
SYS_EXEC = 7
SYS_EXITS = 8
SYS_FAUTH = 10
SYS_SEGBRK = 12
SYS_OPEN = 14
SYS_OSEEK = 16
SYS_SLEEP = 17
SYS_RFORK = 19
SYS_PIPE = 21
SYS_CREATE = 22
SYS_FD2PATH = 23
SYS_BRK_ = 24
SYS_REMOVE = 25
SYS_NOTIFY = 28
SYS_NOTED = 29
SYS_SEGATTACH = 30
SYS_SEGDETACH = 31
SYS_SEGFREE = 32
SYS_SEGFLUSH = 33
SYS_RENDEZVOUS = 34
SYS_UNMOUNT = 35
SYS_SEMACQUIRE = 37
SYS_SEMRELEASE = 38
SYS_SEEK = 39
SYS_FVERSION = 40
SYS_ERRSTR = 41
SYS_STAT = 42
SYS_FSTAT = 43
SYS_WSTAT = 44
SYS_FWSTAT = 45
SYS_MOUNT = 46
SYS_AWAIT = 47
SYS_PREAD = 50
SYS_PWRITE = 51
SYS_TSEMACQUIRE = 52
SYS_NSEC = 53
)

26
vendor/golang.org/x/term/CONTRIBUTING.md generated vendored Normal file
View File

@ -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://golang.org/issue/new), 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.

27
vendor/golang.org/x/term/LICENSE generated vendored Normal file
View File

@ -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.

22
vendor/golang.org/x/term/PATENTS generated vendored Normal file
View File

@ -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.

19
vendor/golang.org/x/term/README.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# Go terminal/console support
[![Go Reference](https://pkg.go.dev/badge/golang.org/x/term.svg)](https://pkg.go.dev/golang.org/x/term)
This repository provides Go terminal and console support packages.
## Download/Install
The easiest way to install is to run `go get -u golang.org/x/term`. You can
also manually git clone the repository to `$GOPATH/src/golang.org/x/term`.
## 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 term repository is located at
https://github.com/golang/go/issues. Prefix your issue with "x/term:" in the
subject line, so it is easy to find.

1
vendor/golang.org/x/term/codereview.cfg generated vendored Normal file
View File

@ -0,0 +1 @@
issuerepo: golang/go

60
vendor/golang.org/x/term/term.go generated vendored Normal file
View File

@ -0,0 +1,60 @@
// Copyright 2019 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 term provides support functions for dealing with terminals, as
// commonly found on UNIX systems.
//
// Putting a terminal into raw mode is the most common requirement:
//
// oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
// if err != nil {
// panic(err)
// }
// defer term.Restore(int(os.Stdin.Fd()), oldState)
//
// Note that on non-Unix systems os.Stdin.Fd() may not be 0.
package term
// State contains the state of a terminal.
type State struct {
state
}
// IsTerminal returns whether the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
return isTerminal(fd)
}
// MakeRaw puts the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd int) (*State, error) {
return makeRaw(fd)
}
// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
return getState(fd)
}
// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, oldState *State) error {
return restore(fd, oldState)
}
// GetSize returns the visible dimensions of the given terminal.
//
// These dimensions don't include any scrollback buffer height.
func GetSize(fd int) (width, height int, err error) {
return getSize(fd)
}
// ReadPassword reads a line of input from a terminal without local echo. This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
return readPassword(fd)
}

42
vendor/golang.org/x/term/term_plan9.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2019 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 term
import (
"fmt"
"runtime"
"golang.org/x/sys/plan9"
)
type state struct{}
func isTerminal(fd int) bool {
path, err := plan9.Fd2path(fd)
if err != nil {
return false
}
return path == "/dev/cons" || path == "/mnt/term/dev/cons"
}
func makeRaw(fd int) (*State, error) {
return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
func getState(fd int) (*State, error) {
return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
func restore(fd int, state *State) error {
return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
func getSize(fd int) (width, height int, err error) {
return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
func readPassword(fd int) ([]byte, error) {
return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}

91
vendor/golang.org/x/term/term_unix.go generated vendored Normal file
View File

@ -0,0 +1,91 @@
// Copyright 2019 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:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
package term
import (
"golang.org/x/sys/unix"
)
type state struct {
termios unix.Termios
}
func isTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil
}
func makeRaw(fd int) (*State, error) {
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if err != nil {
return nil, err
}
oldState := State{state{termios: *termios}}
// This attempts to replicate the behaviour documented for cfmakeraw in
// the termios(3) manpage.
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
termios.Oflag &^= unix.OPOST
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
termios.Cflag &^= unix.CSIZE | unix.PARENB
termios.Cflag |= unix.CS8
termios.Cc[unix.VMIN] = 1
termios.Cc[unix.VTIME] = 0
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
return nil, err
}
return &oldState, nil
}
func getState(fd int) (*State, error) {
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if err != nil {
return nil, err
}
return &State{state{termios: *termios}}, nil
}
func restore(fd int, state *State) error {
return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
}
func getSize(fd int) (width, height int, err error) {
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
if err != nil {
return 0, 0, err
}
return int(ws.Col), int(ws.Row), nil
}
// passwordReader is an io.Reader that reads from a specific file descriptor.
type passwordReader int
func (r passwordReader) Read(buf []byte) (int, error) {
return unix.Read(int(r), buf)
}
func readPassword(fd int) ([]byte, error) {
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if err != nil {
return nil, err
}
newState := *termios
newState.Lflag &^= unix.ECHO
newState.Lflag |= unix.ICANON | unix.ISIG
newState.Iflag |= unix.ICRNL
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
return nil, err
}
defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
return readPasswordLine(passwordReader(fd))
}

12
vendor/golang.org/x/term/term_unix_bsd.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// 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:build darwin || dragonfly || freebsd || netbsd || openbsd
package term
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TIOCGETA
const ioctlWriteTermios = unix.TIOCSETA

12
vendor/golang.org/x/term/term_unix_other.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2021 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:build aix || linux || solaris || zos
package term
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TCGETS
const ioctlWriteTermios = unix.TCSETS

38
vendor/golang.org/x/term/term_unsupported.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// Copyright 2019 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:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !zos && !windows && !solaris && !plan9
package term
import (
"fmt"
"runtime"
)
type state struct{}
func isTerminal(fd int) bool {
return false
}
func makeRaw(fd int) (*State, error) {
return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
func getState(fd int) (*State, error) {
return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
func restore(fd int, state *State) error {
return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
func getSize(fd int) (width, height int, err error) {
return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
func readPassword(fd int) ([]byte, error) {
return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}

79
vendor/golang.org/x/term/term_windows.go generated vendored Normal file
View File

@ -0,0 +1,79 @@
// Copyright 2019 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 term
import (
"os"
"golang.org/x/sys/windows"
)
type state struct {
mode uint32
}
func isTerminal(fd int) bool {
var st uint32
err := windows.GetConsoleMode(windows.Handle(fd), &st)
return err == nil
}
func makeRaw(fd int) (*State, error) {
var st uint32
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
return nil, err
}
raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
return nil, err
}
return &State{state{st}}, nil
}
func getState(fd int) (*State, error) {
var st uint32
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
return nil, err
}
return &State{state{st}}, nil
}
func restore(fd int, state *State) error {
return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}
func getSize(fd int) (width, height int, err error) {
var info windows.ConsoleScreenBufferInfo
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
return 0, 0, err
}
return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil
}
func readPassword(fd int) ([]byte, error) {
var st uint32
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
return nil, err
}
old := st
st &^= (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT)
st |= (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_PROCESSED_INPUT)
if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
return nil, err
}
defer windows.SetConsoleMode(windows.Handle(fd), old)
var h windows.Handle
p, _ := windows.GetCurrentProcess()
if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
return nil, err
}
f := os.NewFile(uintptr(h), "stdin")
defer f.Close()
return readPasswordLine(f)
}

986
vendor/golang.org/x/term/terminal.go generated vendored Normal file
View File

@ -0,0 +1,986 @@
// Copyright 2011 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 term
import (
"bytes"
"io"
"runtime"
"strconv"
"sync"
"unicode/utf8"
)
// EscapeCodes contains escape sequences that can be written to the terminal in
// order to achieve different styles of text.
type EscapeCodes struct {
// Foreground colors
Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
// Reset all attributes
Reset []byte
}
var vt100EscapeCodes = EscapeCodes{
Black: []byte{keyEscape, '[', '3', '0', 'm'},
Red: []byte{keyEscape, '[', '3', '1', 'm'},
Green: []byte{keyEscape, '[', '3', '2', 'm'},
Yellow: []byte{keyEscape, '[', '3', '3', 'm'},
Blue: []byte{keyEscape, '[', '3', '4', 'm'},
Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
Cyan: []byte{keyEscape, '[', '3', '6', 'm'},
White: []byte{keyEscape, '[', '3', '7', 'm'},
Reset: []byte{keyEscape, '[', '0', 'm'},
}
// Terminal contains the state for running a VT100 terminal that is capable of
// reading lines of input.
type Terminal struct {
// AutoCompleteCallback, if non-null, is called for each keypress with
// the full input line and the current position of the cursor (in
// bytes, as an index into |line|). If it returns ok=false, the key
// press is processed normally. Otherwise it returns a replacement line
// and the new cursor position.
AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool)
// Escape contains a pointer to the escape codes for this terminal.
// It's always a valid pointer, although the escape codes themselves
// may be empty if the terminal doesn't support them.
Escape *EscapeCodes
// lock protects the terminal and the state in this object from
// concurrent processing of a key press and a Write() call.
lock sync.Mutex
c io.ReadWriter
prompt []rune
// line is the current line being entered.
line []rune
// pos is the logical position of the cursor in line
pos int
// echo is true if local echo is enabled
echo bool
// pasteActive is true iff there is a bracketed paste operation in
// progress.
pasteActive bool
// cursorX contains the current X value of the cursor where the left
// edge is 0. cursorY contains the row number where the first row of
// the current line is 0.
cursorX, cursorY int
// maxLine is the greatest value of cursorY so far.
maxLine int
termWidth, termHeight int
// outBuf contains the terminal data to be sent.
outBuf []byte
// remainder contains the remainder of any partial key sequences after
// a read. It aliases into inBuf.
remainder []byte
inBuf [256]byte
// history contains previously entered commands so that they can be
// accessed with the up and down keys.
history stRingBuffer
// historyIndex stores the currently accessed history entry, where zero
// means the immediately previous entry.
historyIndex int
// When navigating up and down the history it's possible to return to
// the incomplete, initial line. That value is stored in
// historyPending.
historyPending string
}
// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
// a local terminal, that terminal must first have been put into raw mode.
// prompt is a string that is written at the start of each input line (i.e.
// "> ").
func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
return &Terminal{
Escape: &vt100EscapeCodes,
c: c,
prompt: []rune(prompt),
termWidth: 80,
termHeight: 24,
echo: true,
historyIndex: -1,
}
}
const (
keyCtrlC = 3
keyCtrlD = 4
keyCtrlU = 21
keyEnter = '\r'
keyEscape = 27
keyBackspace = 127
keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota
keyUp
keyDown
keyLeft
keyRight
keyAltLeft
keyAltRight
keyHome
keyEnd
keyDeleteWord
keyDeleteLine
keyClearScreen
keyPasteStart
keyPasteEnd
)
var (
crlf = []byte{'\r', '\n'}
pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
)
// bytesToKey tries to parse a key sequence from b. If successful, it returns
// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
if len(b) == 0 {
return utf8.RuneError, nil
}
if !pasteActive {
switch b[0] {
case 1: // ^A
return keyHome, b[1:]
case 2: // ^B
return keyLeft, b[1:]
case 5: // ^E
return keyEnd, b[1:]
case 6: // ^F
return keyRight, b[1:]
case 8: // ^H
return keyBackspace, b[1:]
case 11: // ^K
return keyDeleteLine, b[1:]
case 12: // ^L
return keyClearScreen, b[1:]
case 23: // ^W
return keyDeleteWord, b[1:]
case 14: // ^N
return keyDown, b[1:]
case 16: // ^P
return keyUp, b[1:]
}
}
if b[0] != keyEscape {
if !utf8.FullRune(b) {
return utf8.RuneError, b
}
r, l := utf8.DecodeRune(b)
return r, b[l:]
}
if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
switch b[2] {
case 'A':
return keyUp, b[3:]
case 'B':
return keyDown, b[3:]
case 'C':
return keyRight, b[3:]
case 'D':
return keyLeft, b[3:]
case 'H':
return keyHome, b[3:]
case 'F':
return keyEnd, b[3:]
}
}
if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
switch b[5] {
case 'C':
return keyAltRight, b[6:]
case 'D':
return keyAltLeft, b[6:]
}
}
if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) {
return keyPasteStart, b[6:]
}
if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) {
return keyPasteEnd, b[6:]
}
// If we get here then we have a key that we don't recognise, or a
// partial sequence. It's not clear how one should find the end of a
// sequence without knowing them all, but it seems that [a-zA-Z~] only
// appears at the end of a sequence.
for i, c := range b[0:] {
if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' {
return keyUnknown, b[i+1:]
}
}
return utf8.RuneError, b
}
// queue appends data to the end of t.outBuf
func (t *Terminal) queue(data []rune) {
t.outBuf = append(t.outBuf, []byte(string(data))...)
}
var space = []rune{' '}
func isPrintable(key rune) bool {
isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
return key >= 32 && !isInSurrogateArea
}
// moveCursorToPos appends data to t.outBuf which will move the cursor to the
// given, logical position in the text.
func (t *Terminal) moveCursorToPos(pos int) {
if !t.echo {
return
}
x := visualLength(t.prompt) + pos
y := x / t.termWidth
x = x % t.termWidth
up := 0
if y < t.cursorY {
up = t.cursorY - y
}
down := 0
if y > t.cursorY {
down = y - t.cursorY
}
left := 0
if x < t.cursorX {
left = t.cursorX - x
}
right := 0
if x > t.cursorX {
right = x - t.cursorX
}
t.cursorX = x
t.cursorY = y
t.move(up, down, left, right)
}
func (t *Terminal) move(up, down, left, right int) {
m := []rune{}
// 1 unit up can be expressed as ^[[A or ^[A
// 5 units up can be expressed as ^[[5A
if up == 1 {
m = append(m, keyEscape, '[', 'A')
} else if up > 1 {
m = append(m, keyEscape, '[')
m = append(m, []rune(strconv.Itoa(up))...)
m = append(m, 'A')
}
if down == 1 {
m = append(m, keyEscape, '[', 'B')
} else if down > 1 {
m = append(m, keyEscape, '[')
m = append(m, []rune(strconv.Itoa(down))...)
m = append(m, 'B')
}
if right == 1 {
m = append(m, keyEscape, '[', 'C')
} else if right > 1 {
m = append(m, keyEscape, '[')
m = append(m, []rune(strconv.Itoa(right))...)
m = append(m, 'C')
}
if left == 1 {
m = append(m, keyEscape, '[', 'D')
} else if left > 1 {
m = append(m, keyEscape, '[')
m = append(m, []rune(strconv.Itoa(left))...)
m = append(m, 'D')
}
t.queue(m)
}
func (t *Terminal) clearLineToRight() {
op := []rune{keyEscape, '[', 'K'}
t.queue(op)
}
const maxLineLength = 4096
func (t *Terminal) setLine(newLine []rune, newPos int) {
if t.echo {
t.moveCursorToPos(0)
t.writeLine(newLine)
for i := len(newLine); i < len(t.line); i++ {
t.writeLine(space)
}
t.moveCursorToPos(newPos)
}
t.line = newLine
t.pos = newPos
}
func (t *Terminal) advanceCursor(places int) {
t.cursorX += places
t.cursorY += t.cursorX / t.termWidth
if t.cursorY > t.maxLine {
t.maxLine = t.cursorY
}
t.cursorX = t.cursorX % t.termWidth
if places > 0 && t.cursorX == 0 {
// Normally terminals will advance the current position
// when writing a character. But that doesn't happen
// for the last character in a line. However, when
// writing a character (except a new line) that causes
// a line wrap, the position will be advanced two
// places.
//
// So, if we are stopping at the end of a line, we
// need to write a newline so that our cursor can be
// advanced to the next line.
t.outBuf = append(t.outBuf, '\r', '\n')
}
}
func (t *Terminal) eraseNPreviousChars(n int) {
if n == 0 {
return
}
if t.pos < n {
n = t.pos
}
t.pos -= n
t.moveCursorToPos(t.pos)
copy(t.line[t.pos:], t.line[n+t.pos:])
t.line = t.line[:len(t.line)-n]
if t.echo {
t.writeLine(t.line[t.pos:])
for i := 0; i < n; i++ {
t.queue(space)
}
t.advanceCursor(n)
t.moveCursorToPos(t.pos)
}
}
// countToLeftWord returns then number of characters from the cursor to the
// start of the previous word.
func (t *Terminal) countToLeftWord() int {
if t.pos == 0 {
return 0
}
pos := t.pos - 1
for pos > 0 {
if t.line[pos] != ' ' {
break
}
pos--
}
for pos > 0 {
if t.line[pos] == ' ' {
pos++
break
}
pos--
}
return t.pos - pos
}
// countToRightWord returns then number of characters from the cursor to the
// start of the next word.
func (t *Terminal) countToRightWord() int {
pos := t.pos
for pos < len(t.line) {
if t.line[pos] == ' ' {
break
}
pos++
}
for pos < len(t.line) {
if t.line[pos] != ' ' {
break
}
pos++
}
return pos - t.pos
}
// visualLength returns the number of visible glyphs in s.
func visualLength(runes []rune) int {
inEscapeSeq := false
length := 0
for _, r := range runes {
switch {
case inEscapeSeq:
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
inEscapeSeq = false
}
case r == '\x1b':
inEscapeSeq = true
default:
length++
}
}
return length
}
// handleKey processes the given key and, optionally, returns a line of text
// that the user has entered.
func (t *Terminal) handleKey(key rune) (line string, ok bool) {
if t.pasteActive && key != keyEnter {
t.addKeyToLine(key)
return
}
switch key {
case keyBackspace:
if t.pos == 0 {
return
}
t.eraseNPreviousChars(1)
case keyAltLeft:
// move left by a word.
t.pos -= t.countToLeftWord()
t.moveCursorToPos(t.pos)
case keyAltRight:
// move right by a word.
t.pos += t.countToRightWord()
t.moveCursorToPos(t.pos)
case keyLeft:
if t.pos == 0 {
return
}
t.pos--
t.moveCursorToPos(t.pos)
case keyRight:
if t.pos == len(t.line) {
return
}
t.pos++
t.moveCursorToPos(t.pos)
case keyHome:
if t.pos == 0 {
return
}
t.pos = 0
t.moveCursorToPos(t.pos)
case keyEnd:
if t.pos == len(t.line) {
return
}
t.pos = len(t.line)
t.moveCursorToPos(t.pos)
case keyUp:
entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1)
if !ok {
return "", false
}
if t.historyIndex == -1 {
t.historyPending = string(t.line)
}
t.historyIndex++
runes := []rune(entry)
t.setLine(runes, len(runes))
case keyDown:
switch t.historyIndex {
case -1:
return
case 0:
runes := []rune(t.historyPending)
t.setLine(runes, len(runes))
t.historyIndex--
default:
entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1)
if ok {
t.historyIndex--
runes := []rune(entry)
t.setLine(runes, len(runes))
}
}
case keyEnter:
t.moveCursorToPos(len(t.line))
t.queue([]rune("\r\n"))
line = string(t.line)
ok = true
t.line = t.line[:0]
t.pos = 0
t.cursorX = 0
t.cursorY = 0
t.maxLine = 0
case keyDeleteWord:
// Delete zero or more spaces and then one or more characters.
t.eraseNPreviousChars(t.countToLeftWord())
case keyDeleteLine:
// Delete everything from the current cursor position to the
// end of line.
for i := t.pos; i < len(t.line); i++ {
t.queue(space)
t.advanceCursor(1)
}
t.line = t.line[:t.pos]
t.moveCursorToPos(t.pos)
case keyCtrlD:
// Erase the character under the current position.
// The EOF case when the line is empty is handled in
// readLine().
if t.pos < len(t.line) {
t.pos++
t.eraseNPreviousChars(1)
}
case keyCtrlU:
t.eraseNPreviousChars(t.pos)
case keyClearScreen:
// Erases the screen and moves the cursor to the home position.
t.queue([]rune("\x1b[2J\x1b[H"))
t.queue(t.prompt)
t.cursorX, t.cursorY = 0, 0
t.advanceCursor(visualLength(t.prompt))
t.setLine(t.line, t.pos)
default:
if t.AutoCompleteCallback != nil {
prefix := string(t.line[:t.pos])
suffix := string(t.line[t.pos:])
t.lock.Unlock()
newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key)
t.lock.Lock()
if completeOk {
t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos]))
return
}
}
if !isPrintable(key) {
return
}
if len(t.line) == maxLineLength {
return
}
t.addKeyToLine(key)
}
return
}
// addKeyToLine inserts the given key at the current position in the current
// line.
func (t *Terminal) addKeyToLine(key rune) {
if len(t.line) == cap(t.line) {
newLine := make([]rune, len(t.line), 2*(1+len(t.line)))
copy(newLine, t.line)
t.line = newLine
}
t.line = t.line[:len(t.line)+1]
copy(t.line[t.pos+1:], t.line[t.pos:])
t.line[t.pos] = key
if t.echo {
t.writeLine(t.line[t.pos:])
}
t.pos++
t.moveCursorToPos(t.pos)
}
func (t *Terminal) writeLine(line []rune) {
for len(line) != 0 {
remainingOnLine := t.termWidth - t.cursorX
todo := len(line)
if todo > remainingOnLine {
todo = remainingOnLine
}
t.queue(line[:todo])
t.advanceCursor(visualLength(line[:todo]))
line = line[todo:]
}
}
// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
for len(buf) > 0 {
i := bytes.IndexByte(buf, '\n')
todo := len(buf)
if i >= 0 {
todo = i
}
var nn int
nn, err = w.Write(buf[:todo])
n += nn
if err != nil {
return n, err
}
buf = buf[todo:]
if i >= 0 {
if _, err = w.Write(crlf); err != nil {
return n, err
}
n++
buf = buf[1:]
}
}
return n, nil
}
func (t *Terminal) Write(buf []byte) (n int, err error) {
t.lock.Lock()
defer t.lock.Unlock()
if t.cursorX == 0 && t.cursorY == 0 {
// This is the easy case: there's nothing on the screen that we
// have to move out of the way.
return writeWithCRLF(t.c, buf)
}
// We have a prompt and possibly user input on the screen. We
// have to clear it first.
t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */)
t.cursorX = 0
t.clearLineToRight()
for t.cursorY > 0 {
t.move(1 /* up */, 0, 0, 0)
t.cursorY--
t.clearLineToRight()
}
if _, err = t.c.Write(t.outBuf); err != nil {
return
}
t.outBuf = t.outBuf[:0]
if n, err = writeWithCRLF(t.c, buf); err != nil {
return
}
t.writeLine(t.prompt)
if t.echo {
t.writeLine(t.line)
}
t.moveCursorToPos(t.pos)
if _, err = t.c.Write(t.outBuf); err != nil {
return
}
t.outBuf = t.outBuf[:0]
return
}
// ReadPassword temporarily changes the prompt and reads a password, without
// echo, from the terminal.
func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
t.lock.Lock()
defer t.lock.Unlock()
oldPrompt := t.prompt
t.prompt = []rune(prompt)
t.echo = false
line, err = t.readLine()
t.prompt = oldPrompt
t.echo = true
return
}
// ReadLine returns a line of input from the terminal.
func (t *Terminal) ReadLine() (line string, err error) {
t.lock.Lock()
defer t.lock.Unlock()
return t.readLine()
}
func (t *Terminal) readLine() (line string, err error) {
// t.lock must be held at this point
if t.cursorX == 0 && t.cursorY == 0 {
t.writeLine(t.prompt)
t.c.Write(t.outBuf)
t.outBuf = t.outBuf[:0]
}
lineIsPasted := t.pasteActive
for {
rest := t.remainder
lineOk := false
for !lineOk {
var key rune
key, rest = bytesToKey(rest, t.pasteActive)
if key == utf8.RuneError {
break
}
if !t.pasteActive {
if key == keyCtrlD {
if len(t.line) == 0 {
return "", io.EOF
}
}
if key == keyCtrlC {
return "", io.EOF
}
if key == keyPasteStart {
t.pasteActive = true
if len(t.line) == 0 {
lineIsPasted = true
}
continue
}
} else if key == keyPasteEnd {
t.pasteActive = false
continue
}
if !t.pasteActive {
lineIsPasted = false
}
line, lineOk = t.handleKey(key)
}
if len(rest) > 0 {
n := copy(t.inBuf[:], rest)
t.remainder = t.inBuf[:n]
} else {
t.remainder = nil
}
t.c.Write(t.outBuf)
t.outBuf = t.outBuf[:0]
if lineOk {
if t.echo {
t.historyIndex = -1
t.history.Add(line)
}
if lineIsPasted {
err = ErrPasteIndicator
}
return
}
// t.remainder is a slice at the beginning of t.inBuf
// containing a partial key sequence
readBuf := t.inBuf[len(t.remainder):]
var n int
t.lock.Unlock()
n, err = t.c.Read(readBuf)
t.lock.Lock()
if err != nil {
return
}
t.remainder = t.inBuf[:n+len(t.remainder)]
}
}
// SetPrompt sets the prompt to be used when reading subsequent lines.
func (t *Terminal) SetPrompt(prompt string) {
t.lock.Lock()
defer t.lock.Unlock()
t.prompt = []rune(prompt)
}
func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
// Move cursor to column zero at the start of the line.
t.move(t.cursorY, 0, t.cursorX, 0)
t.cursorX, t.cursorY = 0, 0
t.clearLineToRight()
for t.cursorY < numPrevLines {
// Move down a line
t.move(0, 1, 0, 0)
t.cursorY++
t.clearLineToRight()
}
// Move back to beginning.
t.move(t.cursorY, 0, 0, 0)
t.cursorX, t.cursorY = 0, 0
t.queue(t.prompt)
t.advanceCursor(visualLength(t.prompt))
t.writeLine(t.line)
t.moveCursorToPos(t.pos)
}
func (t *Terminal) SetSize(width, height int) error {
t.lock.Lock()
defer t.lock.Unlock()
if width == 0 {
width = 1
}
oldWidth := t.termWidth
t.termWidth, t.termHeight = width, height
switch {
case width == oldWidth:
// If the width didn't change then nothing else needs to be
// done.
return nil
case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0:
// If there is nothing on current line and no prompt printed,
// just do nothing
return nil
case width < oldWidth:
// Some terminals (e.g. xterm) will truncate lines that were
// too long when shinking. Others, (e.g. gnome-terminal) will
// attempt to wrap them. For the former, repainting t.maxLine
// works great, but that behaviour goes badly wrong in the case
// of the latter because they have doubled every full line.
// We assume that we are working on a terminal that wraps lines
// and adjust the cursor position based on every previous line
// wrapping and turning into two. This causes the prompt on
// xterms to move upwards, which isn't great, but it avoids a
// huge mess with gnome-terminal.
if t.cursorX >= t.termWidth {
t.cursorX = t.termWidth - 1
}
t.cursorY *= 2
t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2)
case width > oldWidth:
// If the terminal expands then our position calculations will
// be wrong in the future because we think the cursor is
// |t.pos| chars into the string, but there will be a gap at
// the end of any wrapped line.
//
// But the position will actually be correct until we move, so
// we can move back to the beginning and repaint everything.
t.clearAndRepaintLinePlusNPrevious(t.maxLine)
}
_, err := t.c.Write(t.outBuf)
t.outBuf = t.outBuf[:0]
return err
}
type pasteIndicatorError struct{}
func (pasteIndicatorError) Error() string {
return "terminal: ErrPasteIndicator not correctly handled"
}
// ErrPasteIndicator may be returned from ReadLine as the error, in addition
// to valid line data. It indicates that bracketed paste mode is enabled and
// that the returned line consists only of pasted data. Programs may wish to
// interpret pasted data more literally than typed data.
var ErrPasteIndicator = pasteIndicatorError{}
// SetBracketedPasteMode requests that the terminal bracket paste operations
// with markers. Not all terminals support this but, if it is supported, then
// enabling this mode will stop any autocomplete callback from running due to
// pastes. Additionally, any lines that are completely pasted will be returned
// from ReadLine with the error set to ErrPasteIndicator.
func (t *Terminal) SetBracketedPasteMode(on bool) {
if on {
io.WriteString(t.c, "\x1b[?2004h")
} else {
io.WriteString(t.c, "\x1b[?2004l")
}
}
// stRingBuffer is a ring buffer of strings.
type stRingBuffer struct {
// entries contains max elements.
entries []string
max int
// head contains the index of the element most recently added to the ring.
head int
// size contains the number of elements in the ring.
size int
}
func (s *stRingBuffer) Add(a string) {
if s.entries == nil {
const defaultNumEntries = 100
s.entries = make([]string, defaultNumEntries)
s.max = defaultNumEntries
}
s.head = (s.head + 1) % s.max
s.entries[s.head] = a
if s.size < s.max {
s.size++
}
}
// NthPreviousEntry returns the value passed to the nth previous call to Add.
// If n is zero then the immediately prior value is returned, if one, then the
// next most recent, and so on. If such an element doesn't exist then ok is
// false.
func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
if n < 0 || n >= s.size {
return "", false
}
index := s.head - n
if index < 0 {
index += s.max
}
return s.entries[index], true
}
// readPasswordLine reads from reader until it finds \n or io.EOF.
// The slice returned does not include the \n.
// readPasswordLine also ignores any \r it finds.
// Windows uses \r as end of line. So, on Windows, readPasswordLine
// reads until it finds \r and ignores any \n it finds during processing.
func readPasswordLine(reader io.Reader) ([]byte, error) {
var buf [1]byte
var ret []byte
for {
n, err := reader.Read(buf[:])
if n > 0 {
switch buf[0] {
case '\b':
if len(ret) > 0 {
ret = ret[:len(ret)-1]
}
case '\n':
if runtime.GOOS != "windows" {
return ret, nil
}
// otherwise ignore \n
case '\r':
if runtime.GOOS == "windows" {
return ret, nil
}
// otherwise ignore \r
default:
ret = append(ret, buf[0])
}
continue
}
if err != nil {
if err == io.EOF && len(ret) > 0 {
return ret, nil
}
return ret, err
}
}
}

7
vendor/modules.txt vendored
View File

@ -45,6 +45,9 @@ github.com/alecthomas/chroma/styles
# github.com/bradleyfalzon/ghinstallation/v2 v2.11.0
## explicit; go 1.16
github.com/bradleyfalzon/ghinstallation/v2
# github.com/briandowns/spinner v1.23.1
## explicit; go 1.17
github.com/briandowns/spinner
# github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
## explicit
github.com/danwakefield/fnmatch
@ -249,8 +252,12 @@ golang.org/x/oauth2/internal
# golang.org/x/sys v0.20.0
## explicit; go 1.18
golang.org/x/sys/cpu
golang.org/x/sys/plan9
golang.org/x/sys/unix
golang.org/x/sys/windows
# golang.org/x/term v0.19.0
## explicit; go 1.18
golang.org/x/term
# golang.org/x/text v0.16.0
## explicit; go 1.18
golang.org/x/text/encoding