pax_global_header00006660000000000000000000000064146501227200014511gustar00rootroot0000000000000052 comment=77b6635b2ae7664a00c043d0d7ce955f3188e4f6 golang-github-atomicgo-keyboard-0.2.9/000077500000000000000000000000001465012272000176465ustar00rootroot00000000000000golang-github-atomicgo-keyboard-0.2.9/.github/000077500000000000000000000000001465012272000212065ustar00rootroot00000000000000golang-github-atomicgo-keyboard-0.2.9/.github/custom_readme000066400000000000000000000000011465012272000237470ustar00rootroot00000000000000 golang-github-atomicgo-keyboard-0.2.9/.github/settings.yml000066400000000000000000000016241465012272000235740ustar00rootroot00000000000000_extends: .github repository: # See https://developer.github.com/v3/repos/#edit for all available settings. # A short description of the repository that will show up on GitHub description: ⌨️ Read keyboard events in your terminal applications! (Arrow keys, Home, End, etc.) # A comma-separated list of topics to set on the repository topics: atomicgo, go, golang, keyboard, terminal, cli # Either `true` to make the repository private, or `false` to make it public. # private: false # Either `true` to enable issues for this repository, `false` to disable them. # has_issues: true # Either `true` to enable projects for this repository, or `false` to disable them. # If projects are disabled for the organization, passing `true` will cause an API error. # has_projects: false # Either `true` to enable the wiki for this repository, `false` to disable it. # has_wiki: false golang-github-atomicgo-keyboard-0.2.9/.github/workflows/000077500000000000000000000000001465012272000232435ustar00rootroot00000000000000golang-github-atomicgo-keyboard-0.2.9/.github/workflows/atomicgo.yml000066400000000000000000000004521465012272000255710ustar00rootroot00000000000000on: push name: AtomicGo jobs: docs: if: "!contains(github.event.head_commit.message, 'autoupdate')" runs-on: ubuntu-latest steps: - name: Update Docs uses: atomicgo/ci@main env: ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} TERM: xterm-256color golang-github-atomicgo-keyboard-0.2.9/.github/workflows/go.yml000066400000000000000000000013551465012272000243770ustar00rootroot00000000000000name: Go on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: name: Build runs-on: ${{ matrix.os }} strategy: matrix: os: [ ubuntu-latest, windows-latest, macos-latest ] steps: - name: Set up Go 1.x uses: actions/setup-go@v2 with: go-version: ^1 id: go - name: Check out code into the Go module directory uses: actions/checkout@v2 - name: Get dependencies run: go get -v -t -d ./... - name: Build run: go build -v . - name: Test run: go test -coverprofile="coverage.txt" -covermode=atomic -v -p 1 . - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 golang-github-atomicgo-keyboard-0.2.9/.github/workflows/golangci.yml000066400000000000000000000005011465012272000255450ustar00rootroot00000000000000name: golangci-lint on: [ pull_request ] jobs: golangci: name: lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Go uses: actions/setup-go@v2 - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: version: latest golang-github-atomicgo-keyboard-0.2.9/.github/workflows/tweet-release.yml000066400000000000000000000016161465012272000265400ustar00rootroot00000000000000name: tweet-release # Listen to the `release` event on: release: types: [published] jobs: tweet: runs-on: ubuntu-latest steps: - uses: Eomm/why-don-t-you-tweet@v1 # We don't want to tweet if the repository is not a public one if: ${{ !github.event.repository.private }} with: tweet-message: "New ${{ github.event.repository.name }} release: ${{ github.event.release.tag_name }}! 🎉 Try it out: ${{ github.event.release.html_url }} #go #golang #opensource #library #release #atomicgo" env: TWITTER_CONSUMER_API_KEY: ${{ secrets.TWITTER_CONSUMER_API_KEY }} TWITTER_CONSUMER_API_SECRET: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} golang-github-atomicgo-keyboard-0.2.9/.gitignore000066400000000000000000000006611465012272000216410ustar00rootroot00000000000000### Go template # Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib # Test binary, built with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # Dependency directories (remove the comment below to include it) vendor/ ### IntelliJ .idea *.iml out gen ### VisualStudioCode .vscode *.code-workspace ### macOS # General .DS_Store # Experimenting folder experimenting golang-github-atomicgo-keyboard-0.2.9/.golangci.yml000066400000000000000000000025251465012272000222360ustar00rootroot00000000000000linters-settings: gocritic: enabled-tags: - diagnostic - experimental - opinionated - performance - style disabled-checks: - dupImport - ifElseChain - octalLiteral - whyNoLint - wrapperFunc - exitAfterDefer - hugeParam - ptrToRefParam - paramTypeCombine - unnamedResult misspell: locale: US linters: disable-all: true enable: - errcheck - gosimple - govet - ineffassign - staticcheck - asciicheck - bodyclose - dupl - durationcheck - errorlint - exhaustive - gci - gocognit - gocritic - godot - godox - goerr113 - gofmt - goimports - goprintffuncname - misspell - nilerr - nlreturn - noctx - prealloc - predeclared - thelper - unconvert - unparam - wastedassign - wrapcheck issues: # Excluding configuration per-path, per-linter, per-text and per-source exclude-rules: - path: _test\.go linters: - errcheck - dupl - gocritic - wrapcheck - goerr113 # https://github.com/go-critic/go-critic/issues/926 - linters: - gocritic text: "unnecessaryDefer:" service: golangci-lint-version: 1.39.x # use the fixed version to not introduce new linters unexpectedly golang-github-atomicgo-keyboard-0.2.9/LICENSE000066400000000000000000000020741465012272000206560ustar00rootroot00000000000000MIT License Copyright (c) 2020 Marvin Wendt (MarvinJWendt) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-github-atomicgo-keyboard-0.2.9/README.md000066400000000000000000000136341465012272000211340ustar00rootroot00000000000000

AtomicGo | keyboard

Latest Release Tests Coverage Unit test count Issues License: MIT

---

Get The Module | Documentation | Contributing | Code of Conduct

---

AtomicGo


-----------------------------------------------------------------------------------------------------

go get atomicgo.dev/keyboard


-----------------------------------------------------------------------------------------------------

## Description Package keyboard can be used to read key presses from the keyboard, while in a terminal application. It's crossplatform and keypresses can be combined to check for ctrl+c, alt+4, ctrl-shift, alt+ctrl+right, etc. It can also be used to simulate (mock) keypresses for CI testing. Works nicely with https://atomicgo.dev/cursor ## Simple Usage ```go keyboard.Listen(func(key keys.Key) (stop bool, err error) { if key.Code == keys.CtrlC { return true, nil // Stop listener by returning true on Ctrl+C } fmt.Println("\r" + key.String()) // Print every key press return false, nil // Return false to continue listening }) ``` ## Advanced Usage ```go // Stop keyboard listener on Escape key press or CTRL+C. // Exit application on "q" key press. // Print every rune key press. // Print every other key press. keyboard.Listen(func(key keys.Key) (stop bool, err error) { switch key.Code { case keys.CtrlC, keys.Escape: return true, nil // Return true to stop listener case keys.RuneKey: // Check if key is a rune key (a, b, c, 1, 2, 3, ...) if key.String() == "q" { // Check if key is "q" fmt.Println("\rQuitting application") os.Exit(0) // Exit application } fmt.Printf("\rYou pressed the rune key: %s\n", key) default: fmt.Printf("\rYou pressed: %s\n", key) } return false, nil // Return false to continue listening }) ``` ## Simulate Key Presses (for mocking in tests) ```go go func() { keyboard.SimulateKeyPress("Hello") // Simulate key press for every letter in string keyboard.SimulateKeyPress(keys.Enter) // Simulate key press for Enter keyboard.SimulateKeyPress(keys.CtrlShiftRight) // Simulate key press for Ctrl+Shift+Right keyboard.SimulateKeyPress('x') // Simulate key press for a single rune keyboard.SimulateKeyPress('x', keys.Down, 'a') // Simulate key presses for multiple inputs keyboard.SimulateKeyPress(keys.Escape) // Simulate key press for Escape, which quits the program }() keyboard.Listen(func(key keys.Key) (stop bool, err error) { if key.Code == keys.Escape || key.Code == keys.CtrlC { os.Exit(0) // Exit program on Escape } fmt.Println("\r" + key.String()) // Print every key press return false, nil // Return false to continue listening }) ``` ## Usage #### func Listen ```go func Listen(onKeyPress func(key keys.Key) (stop bool, err error)) error ``` Listen calls a callback function when a key is pressed. Simple example: keyboard.Listen(func(key keys.Key) (stop bool, err error) { if key.Code == keys.CtrlC { return true, nil // Stop listener by returning true on Ctrl+C } fmt.Println("\r" + key.String()) // Print every key press return false, nil // Return false to continue listening }) #### func SimulateKeyPress ```go func SimulateKeyPress(input ...interface{}) error ``` SimulateKeyPress simulate a key press. It can be used to mock user input and test your application. Example: go func() { keyboard.SimulateKeyPress("Hello") // Simulate key press for every letter in string keyboard.SimulateKeyPress(keys.Enter) // Simulate key press for Enter keyboard.SimulateKeyPress(keys.CtrlShiftRight) // Simulate key press for Ctrl+Shift+Right keyboard.SimulateKeyPress('x') // Simulate key press for a single rune keyboard.SimulateKeyPress('x', keys.Down, 'a') // Simulate key presses for multiple inputs }() --- > [AtomicGo.dev](https://atomicgo.dev)  ·  > with ❤️ by [@MarvinJWendt](https://github.com/MarvinJWendt) | > [MarvinJWendt.com](https://marvinjwendt.com) golang-github-atomicgo-keyboard-0.2.9/codecov.yml000066400000000000000000000002021465012272000220050ustar00rootroot00000000000000coverage: status: project: default: informational: true patch: default: informational: true golang-github-atomicgo-keyboard-0.2.9/doc.go000066400000000000000000000044211465012272000207430ustar00rootroot00000000000000/* Package keyboard can be used to read key presses from the keyboard, while in a terminal application. It's crossplatform and keypresses can be combined to check for ctrl+c, alt+4, ctrl-shift, alt+ctrl+right, etc. It can also be used to simulate (mock) keypresses for CI testing. Works nicely with https://atomicgo.dev/cursor ## Simple Usage keyboard.Listen(func(key keys.Key) (stop bool, err error) { if key.Code == keys.CtrlC { return true, nil // Stop listener by returning true on Ctrl+C } fmt.Println("\r" + key.String()) // Print every key press return false, nil // Return false to continue listening }) ## Advanced Usage // Stop keyboard listener on Escape key press or CTRL+C. // Exit application on "q" key press. // Print every rune key press. // Print every other key press. keyboard.Listen(func(key keys.Key) (stop bool, err error) { switch key.Code { case keys.CtrlC, keys.Escape: return true, nil // Return true to stop listener case keys.RuneKey: // Check if key is a rune key (a, b, c, 1, 2, 3, ...) if key.String() == "q" { // Check if key is "q" fmt.Println("\rQuitting application") os.Exit(0) // Exit application } fmt.Printf("\rYou pressed the rune key: %s\n", key) default: fmt.Printf("\rYou pressed: %s\n", key) } return false, nil // Return false to continue listening }) ## Simulate Key Presses (for mocking in tests) go func() { keyboard.SimulateKeyPress("Hello") // Simulate key press for every letter in string keyboard.SimulateKeyPress(keys.Enter) // Simulate key press for Enter keyboard.SimulateKeyPress(keys.CtrlShiftRight) // Simulate key press for Ctrl+Shift+Right keyboard.SimulateKeyPress('x') // Simulate key press for a single rune keyboard.SimulateKeyPress('x', keys.Down, 'a') // Simulate key presses for multiple inputs keyboard.SimulateKeyPress(keys.Escape) // Simulate key press for Escape, which quits the program }() keyboard.Listen(func(key keys.Key) (stop bool, err error) { if key.Code == keys.Escape || key.Code == keys.CtrlC { os.Exit(0) // Exit program on Escape } fmt.Println("\r" + key.String()) // Print every key press return false, nil // Return false to continue listening }) */ package keyboard golang-github-atomicgo-keyboard-0.2.9/doc_test.go000066400000000000000000000036701465012272000220070ustar00rootroot00000000000000package keyboard import ( "fmt" "os" "atomicgo.dev/keyboard/keys" ) func ExampleListen_simple() { Listen(func(key keys.Key) (stop bool, err error) { if key.Code == keys.CtrlC { return true, nil // Stop listener by returning true on Ctrl+C } fmt.Println("\r" + key.String()) // Print every key press return false, nil // Return false to continue listening }) } func ExampleListen_advanced() { // Stop keyboard listener on Escape key press or CTRL+C. // Exit application on "q" key press. // Print every rune key press. // Print every other key press. Listen(func(key keys.Key) (stop bool, err error) { switch key.Code { case keys.CtrlC, keys.Escape: return true, nil // Return true to stop listener case keys.RuneKey: // Check if key is a rune key (a, b, c, 1, 2, 3, ...) if key.String() == "q" { // Check if key is "q" fmt.Println("\rQuitting application") os.Exit(0) // Exit application } fmt.Printf("\rYou pressed the rune key: %s\n", key) default: fmt.Printf("\rYou pressed: %s\n", key) } return false, nil // Return false to continue listening }) } func ExampleSimulateKeyPress() { go func() { SimulateKeyPress("Hello") // Simulate key press for every letter in string SimulateKeyPress(keys.Enter) // Simulate key press for Enter SimulateKeyPress(keys.CtrlShiftRight) // Simulate key press for Ctrl+Shift+Right SimulateKeyPress('x') // Simulate key press for a single rune SimulateKeyPress('x', keys.Down, 'a') // Simulate key presses for multiple inputs SimulateKeyPress(keys.Escape) // Simulate key press for Escape, which quits the program }() Listen(func(key keys.Key) (stop bool, err error) { if key.Code == keys.Escape || key.Code == keys.CtrlC { os.Exit(0) // Exit program on Escape } fmt.Println("\r" + key.String()) // Print every key press return false, nil // Return false to continue listening }) } golang-github-atomicgo-keyboard-0.2.9/go.mod000066400000000000000000000002001465012272000207440ustar00rootroot00000000000000module atomicgo.dev/keyboard go 1.15 require ( github.com/MarvinJWendt/testza v0.4.2 github.com/containerd/console v1.0.3 ) golang-github-atomicgo-keyboard-0.2.9/go.sum000066400000000000000000000143121465012272000210020ustar00rootroot00000000000000github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= github.com/MarvinJWendt/testza v0.4.2 h1:Vbw9GkSB5erJI2BPnBL9SVGV9myE+XmUSFahBGUhW2Q= github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= github.com/pterm/pterm v0.12.40 h1:LvQE43RYegVH+y5sCDcqjlbsRu0DlAecEn9FDfs9ePs= github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= golang-github-atomicgo-keyboard-0.2.9/input.go000066400000000000000000000176141465012272000213450ustar00rootroot00000000000000package keyboard import ( "errors" "fmt" "os" "unicode/utf8" "atomicgo.dev/keyboard/internal" "atomicgo.dev/keyboard/keys" ) // Sequence mappings. var sequences = map[string]keys.Key{ // Arrow keys "\x1b[A": {Code: keys.Up}, "\x1b[B": {Code: keys.Down}, "\x1b[C": {Code: keys.Right}, "\x1b[D": {Code: keys.Left}, "\x1b[1;2A": {Code: keys.ShiftUp}, "\x1b[1;2B": {Code: keys.ShiftDown}, "\x1b[1;2C": {Code: keys.ShiftRight}, "\x1b[1;2D": {Code: keys.ShiftLeft}, "\x1b[OA": {Code: keys.ShiftUp}, "\x1b[OB": {Code: keys.ShiftDown}, "\x1b[OC": {Code: keys.ShiftRight}, "\x1b[OD": {Code: keys.ShiftLeft}, "\x1b[a": {Code: keys.ShiftUp}, "\x1b[b": {Code: keys.ShiftDown}, "\x1b[c": {Code: keys.ShiftRight}, "\x1b[d": {Code: keys.ShiftLeft}, "\x1b[1;3A": {Code: keys.Up, AltPressed: true}, "\x1b[1;3B": {Code: keys.Down, AltPressed: true}, "\x1b[1;3C": {Code: keys.Right, AltPressed: true}, "\x1b[1;3D": {Code: keys.Left, AltPressed: true}, "\x1b\x1b[A": {Code: keys.Up, AltPressed: true}, "\x1b\x1b[B": {Code: keys.Down, AltPressed: true}, "\x1b\x1b[C": {Code: keys.Right, AltPressed: true}, "\x1b\x1b[D": {Code: keys.Left, AltPressed: true}, "\x1b[1;4A": {Code: keys.ShiftUp, AltPressed: true}, "\x1b[1;4B": {Code: keys.ShiftDown, AltPressed: true}, "\x1b[1;4C": {Code: keys.ShiftRight, AltPressed: true}, "\x1b[1;4D": {Code: keys.ShiftLeft, AltPressed: true}, "\x1b\x1b[a": {Code: keys.ShiftUp, AltPressed: true}, "\x1b\x1b[b": {Code: keys.ShiftDown, AltPressed: true}, "\x1b\x1b[c": {Code: keys.ShiftRight, AltPressed: true}, "\x1b\x1b[d": {Code: keys.ShiftLeft, AltPressed: true}, "\x1b[1;5A": {Code: keys.CtrlUp}, "\x1b[1;5B": {Code: keys.CtrlDown}, "\x1b[1;5C": {Code: keys.CtrlRight}, "\x1b[1;5D": {Code: keys.CtrlLeft}, "\x1b[Oa": {Code: keys.CtrlUp, AltPressed: true}, "\x1b[Ob": {Code: keys.CtrlDown, AltPressed: true}, "\x1b[Oc": {Code: keys.CtrlRight, AltPressed: true}, "\x1b[Od": {Code: keys.CtrlLeft, AltPressed: true}, "\x1b[1;6A": {Code: keys.CtrlShiftUp}, "\x1b[1;6B": {Code: keys.CtrlShiftDown}, "\x1b[1;6C": {Code: keys.CtrlShiftRight}, "\x1b[1;6D": {Code: keys.CtrlShiftLeft}, "\x1b[1;7A": {Code: keys.CtrlUp, AltPressed: true}, "\x1b[1;7B": {Code: keys.CtrlDown, AltPressed: true}, "\x1b[1;7C": {Code: keys.CtrlRight, AltPressed: true}, "\x1b[1;7D": {Code: keys.CtrlLeft, AltPressed: true}, "\x1b[1;8A": {Code: keys.CtrlShiftUp, AltPressed: true}, "\x1b[1;8B": {Code: keys.CtrlShiftDown, AltPressed: true}, "\x1b[1;8C": {Code: keys.CtrlShiftRight, AltPressed: true}, "\x1b[1;8D": {Code: keys.CtrlShiftLeft, AltPressed: true}, // Miscellaneous keys "\x1b[Z": {Code: keys.ShiftTab}, "\x1b[3~": {Code: keys.Delete}, "\x1b[3;3~": {Code: keys.Delete, AltPressed: true}, "\x1b[1~": {Code: keys.Home}, "\x1b[1;3H~": {Code: keys.Home, AltPressed: true}, "\x1b[4~": {Code: keys.End}, "\x1b[1;3F~": {Code: keys.End, AltPressed: true}, "\x1b[5~": {Code: keys.PgUp}, "\x1b[5;3~": {Code: keys.PgUp, AltPressed: true}, "\x1b[6~": {Code: keys.PgDown}, "\x1b[6;3~": {Code: keys.PgDown, AltPressed: true}, "\x1b[7~": {Code: keys.Home}, "\x1b[8~": {Code: keys.End}, "\x1b\x1b[3~": {Code: keys.Delete, AltPressed: true}, "\x1b\x1b[5~": {Code: keys.PgUp, AltPressed: true}, "\x1b\x1b[6~": {Code: keys.PgDown, AltPressed: true}, "\x1b\x1b[7~": {Code: keys.Home, AltPressed: true}, "\x1b\x1b[8~": {Code: keys.End, AltPressed: true}, // Function keys "\x1bOP": {Code: keys.F1}, "\x1bOQ": {Code: keys.F2}, "\x1bOR": {Code: keys.F3}, "\x1bOS": {Code: keys.F4}, "\x1b[15~": {Code: keys.F5}, "\x1b[17~": {Code: keys.F6}, "\x1b[18~": {Code: keys.F7}, "\x1b[19~": {Code: keys.F8}, "\x1b[20~": {Code: keys.F9}, "\x1b[21~": {Code: keys.F10}, "\x1b[23~": {Code: keys.F11}, "\x1b[24~": {Code: keys.F12}, "\x1b[1;2P": {Code: keys.F13}, "\x1b[1;2Q": {Code: keys.F14}, "\x1b[1;2R": {Code: keys.F15}, "\x1b[1;2S": {Code: keys.F16}, "\x1b[15;2~": {Code: keys.F17}, "\x1b[17;2~": {Code: keys.F18}, "\x1b[18;2~": {Code: keys.F19}, "\x1b[19;2~": {Code: keys.F20}, // Function keys with the alt modifier "\x1b[1;3P": {Code: keys.F1, AltPressed: true}, "\x1b[1;3Q": {Code: keys.F2, AltPressed: true}, "\x1b[1;3R": {Code: keys.F3, AltPressed: true}, "\x1b[1;3S": {Code: keys.F4, AltPressed: true}, "\x1b[15;3~": {Code: keys.F5, AltPressed: true}, "\x1b[17;3~": {Code: keys.F6, AltPressed: true}, "\x1b[18;3~": {Code: keys.F7, AltPressed: true}, "\x1b[19;3~": {Code: keys.F8, AltPressed: true}, "\x1b[20;3~": {Code: keys.F9, AltPressed: true}, "\x1b[21;3~": {Code: keys.F10, AltPressed: true}, "\x1b[23;3~": {Code: keys.F11, AltPressed: true}, "\x1b[24;3~": {Code: keys.F12, AltPressed: true}, // Function keys, urxvt "\x1b[11~": {Code: keys.F1}, "\x1b[12~": {Code: keys.F2}, "\x1b[13~": {Code: keys.F3}, "\x1b[14~": {Code: keys.F4}, "\x1b[25~": {Code: keys.F13}, "\x1b[26~": {Code: keys.F14}, "\x1b[28~": {Code: keys.F15}, "\x1b[29~": {Code: keys.F16}, "\x1b[31~": {Code: keys.F17}, "\x1b[32~": {Code: keys.F18}, "\x1b[33~": {Code: keys.F19}, "\x1b[34~": {Code: keys.F20}, // Function keys with the alt modifier, urxvt "\x1b\x1b[11~": {Code: keys.F1, AltPressed: true}, "\x1b\x1b[12~": {Code: keys.F2, AltPressed: true}, "\x1b\x1b[13~": {Code: keys.F3, AltPressed: true}, "\x1b\x1b[14~": {Code: keys.F4, AltPressed: true}, "\x1b\x1b[25~": {Code: keys.F13, AltPressed: true}, "\x1b\x1b[26~": {Code: keys.F14, AltPressed: true}, "\x1b\x1b[28~": {Code: keys.F15, AltPressed: true}, "\x1b\x1b[29~": {Code: keys.F16, AltPressed: true}, "\x1b\x1b[31~": {Code: keys.F17, AltPressed: true}, "\x1b\x1b[32~": {Code: keys.F18, AltPressed: true}, "\x1b\x1b[33~": {Code: keys.F19, AltPressed: true}, "\x1b\x1b[34~": {Code: keys.F20, AltPressed: true}, } var hexCodes = map[string]keys.Key{ "1b0d": {Code: keys.Enter, AltPressed: true}, "1b7f": {Code: keys.Backspace, AltPressed: true}, // support other backspace variants "1b08": {Code: keys.Backspace, AltPressed: true}, "08": {Code: keys.Backspace}, // Powershell "1b4f41": {Code: keys.Up, AltPressed: false}, "1b4f42": {Code: keys.Down, AltPressed: false}, "1b4f43": {Code: keys.Right, AltPressed: false}, "1b4f44": {Code: keys.Left, AltPressed: false}, } func getKeyPress() (keys.Key, error) { var buf [256]byte // Read numBytes, err := inputTTY.Read(buf[:]) if err != nil { if errors.Is(err, os.ErrClosed) { return keys.Key{}, nil } if err.Error() == "EOF" { return keys.Key{}, nil } else if err.Error() == "invalid argument" { return keys.Key{}, nil } return keys.Key{}, nil } // Check if it's a sequence if k, ok := sequences[string(buf[:numBytes])]; ok { return k, nil } hex := fmt.Sprintf("%x", buf[:numBytes]) if k, ok := hexCodes[hex]; ok { return k, nil } // Check if the alt key is pressed. if numBytes > 1 && buf[0] == 0x1b { // Remove the initial escape sequence c, _ := utf8.DecodeRune(buf[1:]) if c == utf8.RuneError { return keys.Key{}, fmt.Errorf("could not decode rune after removing initial escape sequence") } return keys.Key{AltPressed: true, Code: keys.RuneKey, Runes: []rune{c}}, nil } var runes []rune b := buf[:numBytes] // Translate stdin into runes. for i, w := 0, 0; i < len(b); i += w { //nolint:wastedassign r, width := utf8.DecodeRune(b[i:]) if r == utf8.RuneError { return keys.Key{}, fmt.Errorf("could not decode rune: %w", err) } runes = append(runes, r) w = width } if len(runes) == 0 { return keys.Key{}, fmt.Errorf("received 0 runes from stdin") } else if len(runes) > 1 { return keys.Key{Code: keys.RuneKey, Runes: runes}, nil } r := keys.KeyCode(runes[0]) if numBytes == 1 && r <= internal.KeyUnitSeparator || r == internal.KeyDelete { return keys.Key{Code: r}, nil } if runes[0] == ' ' { return keys.Key{Code: keys.Space, Runes: runes}, nil } return keys.Key{Code: keys.RuneKey, Runes: runes}, nil } golang-github-atomicgo-keyboard-0.2.9/internal/000077500000000000000000000000001465012272000214625ustar00rootroot00000000000000golang-github-atomicgo-keyboard-0.2.9/internal/keys.go000066400000000000000000000021731465012272000227670ustar00rootroot00000000000000package internal // See: https://en.wikipedia.org/wiki/C0_and_C1_control_codes const ( KeyNull = 0 KeyStartOfHeading = 1 KeyStartOfText = 2 KeyExit = 3 // ctrl-c KeyEndOfTransimission = 4 KeyEnquiry = 5 KeyAcknowledge = 6 KeyBELL = 7 KeyBackspace = 8 KeyHorizontalTabulation = 9 KeyLineFeed = 10 KeyVerticalTabulation = 11 KeyFormFeed = 12 KeyCarriageReturn = 13 KeyShiftOut = 14 KeyShiftIn = 15 KeyDataLinkEscape = 16 KeyDeviceControl1 = 17 KeyDeviceControl2 = 18 KeyDeviceControl3 = 19 KeyDeviceControl4 = 20 KeyNegativeAcknowledge = 21 KeySynchronousIdle = 22 KeyEndOfTransmissionBlock = 23 KeyCancel = 24 KeyEndOfMedium = 25 KeySubstitution = 26 KeyEscape = 27 KeyFileSeparator = 28 KeyGroupSeparator = 29 KeyRecordSeparator = 30 KeyUnitSeparator = 31 KeyDelete = 127 ) golang-github-atomicgo-keyboard-0.2.9/keyboard.go000066400000000000000000000064231465012272000220020ustar00rootroot00000000000000package keyboard import ( "fmt" "os" "github.com/containerd/console" "atomicgo.dev/keyboard/keys" ) var windowsStdin *os.File var con console.Console var stdin = os.Stdin var inputTTY *os.File var mockChannel = make(chan keys.Key) var mocking = false func startListener() error { err := initInput() if err != nil { return err } if mocking { return nil } if con != nil { err := con.SetRaw() if err != nil { return fmt.Errorf("failed to set raw mode: %w", err) } } inputTTY, err = openInputTTY() if err != nil { return err } return nil } func stopListener() error { if con != nil { err := con.Reset() if err != nil { return fmt.Errorf("failed to reset console: %w", err) } } return restoreInput() } // Listen calls a callback function when a key is pressed. // // Simple example: // // keyboard.Listen(func(key keys.Key) (stop bool, err error) { // if key.Code == keys.CtrlC { // return true, nil // Stop listener by returning true on Ctrl+C // } // // fmt.Println("\r" + key.String()) // Print every key press // return false, nil // Return false to continue listening // }) func Listen(onKeyPress func(key keys.Key) (stop bool, err error)) error { cancel := make(chan bool) stopRoutine := false go func() { for { select { case c := <-cancel: if c { return } case keyInfo := <-mockChannel: stopRoutine, _ = onKeyPress(keyInfo) if stopRoutine { closeInput() inputTTY.Close() } } } }() err := startListener() if err != nil { if err.Error() != "provided file is not a console" { return err } } for !stopRoutine { key, err := getKeyPress() if err != nil { return err } // check if returned key is empty // if reflect.DeepEqual(key, keys.Key{}) { // return nil // } stop, err := onKeyPress(key) if err != nil { return err } if stop { closeInput() inputTTY.Close() break } } err = stopListener() if err != nil { return err } cancel <- true return nil } // SimulateKeyPress simulate a key press. It can be used to mock user stdin and test your application. // // Example: // // go func() { // keyboard.SimulateKeyPress("Hello") // Simulate key press for every letter in string // keyboard.SimulateKeyPress(keys.Enter) // Simulate key press for Enter // keyboard.SimulateKeyPress(keys.CtrlShiftRight) // Simulate key press for Ctrl+Shift+Right // keyboard.SimulateKeyPress('x') // Simulate key press for a single rune // keyboard.SimulateKeyPress('x', keys.Down, 'a') // Simulate key presses for multiple inputs // }() func SimulateKeyPress(input ...interface{}) error { for _, key := range input { // Check if key is a keys.Key if key, ok := key.(keys.Key); ok { mockChannel <- key return nil } // Check if key is a rune if key, ok := key.(rune); ok { mockChannel <- keys.Key{ Code: keys.RuneKey, Runes: []rune{key}, } return nil } // Check if key is a string if key, ok := key.(string); ok { for _, r := range key { mockChannel <- keys.Key{ Code: keys.RuneKey, Runes: []rune{r}, } } return nil } // Check if key is a KeyCode if key, ok := key.(keys.KeyCode); ok { mockChannel <- keys.Key{ Code: key, } return nil } } return nil } golang-github-atomicgo-keyboard-0.2.9/keyboard_test.go000066400000000000000000000022361465012272000230370ustar00rootroot00000000000000package keyboard_test import ( "testing" "atomicgo.dev/keyboard" "atomicgo.dev/keyboard/keys" "github.com/MarvinJWendt/testza" ) func TestMocking(t *testing.T) { go func() { keyboard.SimulateKeyPress('a') keyboard.SimulateKeyPress("b") keyboard.SimulateKeyPress("c") keyboard.SimulateKeyPress(keys.Enter) }() var aPressed, bPressed, cPressed, enterPressed bool var keyList []keys.Key err := keyboard.Listen(func(key keys.Key) (stop bool, err error) { keyList = append(keyList, key) switch key.Code { case keys.RuneKey: switch key.String() { case "a": println("a pressed") aPressed = true return false, nil case "b": println("b pressed") bPressed = true return false, nil case "c": println("c pressed") cPressed = true return false, nil } case keys.Enter: println("enter pressed") enterPressed = true return true, nil } return false, nil }) testza.AssertNoError(t, err) testza.AssertTrue(t, aPressed, "A | %s", keyList) testza.AssertTrue(t, bPressed, "B | %s", keyList) testza.AssertTrue(t, cPressed, "C | %s", keyList) testza.AssertTrue(t, enterPressed, "Enter | %s", keyList) } golang-github-atomicgo-keyboard-0.2.9/keys/000077500000000000000000000000001465012272000206215ustar00rootroot00000000000000golang-github-atomicgo-keyboard-0.2.9/keys/keys.go000066400000000000000000000141251465012272000221260ustar00rootroot00000000000000package keys import "atomicgo.dev/keyboard/internal" // Key contains information about a keypress. type Key struct { Code KeyCode Runes []rune // Runes that the key produced. Most key pressed produce one single rune. AltPressed bool // True when alt is pressed while the key is typed. } // String returns a string representation of the key. // (e.g. "a", "B", "alt+a", "enter", "ctrl+c", "shift-down", etc.) // // Example: // // k := keys.Key{Code: keys.Enter} // fmt.Println(k) // // Output: enter func (k Key) String() (str string) { if k.AltPressed { str += "alt+" } if k.Code == RuneKey { str += string(k.Runes) return str } else if s, ok := keyNames[k.Code]; ok { str += s return str } return "" } // KeyCode is an integer representation of a non-rune key, such as Escape, Enter, etc. // All other keys are represented by a rune and have the KeyCode: RuneKey. // // Example: // // k := Key{Code: RuneKey, Runes: []rune{'x'}, AltPressed: true} // if k.Code == RuneKey { // fmt.Println(k.Runes) // // Output: x // // fmt.Println(k.String()) // // Output: alt+x // } type KeyCode int func (k KeyCode) String() (str string) { if s, ok := keyNames[k]; ok { return s } return "" } // All control keys. const ( Null KeyCode = internal.KeyNull Break KeyCode = internal.KeyExit Enter KeyCode = internal.KeyCarriageReturn Backspace KeyCode = internal.KeyDelete Tab KeyCode = internal.KeyHorizontalTabulation Esc KeyCode = internal.KeyEscape Escape KeyCode = internal.KeyEscape CtrlAt KeyCode = internal.KeyNull CtrlA KeyCode = internal.KeyStartOfHeading CtrlB KeyCode = internal.KeyStartOfText CtrlC KeyCode = internal.KeyExit CtrlD KeyCode = internal.KeyEndOfTransimission CtrlE KeyCode = internal.KeyEnquiry CtrlF KeyCode = internal.KeyAcknowledge CtrlG KeyCode = internal.KeyBELL CtrlH KeyCode = internal.KeyBackspace CtrlI KeyCode = internal.KeyHorizontalTabulation CtrlJ KeyCode = internal.KeyLineFeed CtrlK KeyCode = internal.KeyVerticalTabulation CtrlL KeyCode = internal.KeyFormFeed CtrlM KeyCode = internal.KeyCarriageReturn CtrlN KeyCode = internal.KeyShiftOut CtrlO KeyCode = internal.KeyShiftIn CtrlP KeyCode = internal.KeyDataLinkEscape CtrlQ KeyCode = internal.KeyDeviceControl1 CtrlR KeyCode = internal.KeyDeviceControl2 CtrlS KeyCode = internal.KeyDeviceControl3 CtrlT KeyCode = internal.KeyDeviceControl4 CtrlU KeyCode = internal.KeyNegativeAcknowledge CtrlV KeyCode = internal.KeySynchronousIdle CtrlW KeyCode = internal.KeyEndOfTransmissionBlock CtrlX KeyCode = internal.KeyCancel CtrlY KeyCode = internal.KeyEndOfMedium CtrlZ KeyCode = internal.KeySubstitution CtrlOpenBracket KeyCode = internal.KeyEscape CtrlBackslash KeyCode = internal.KeyFileSeparator CtrlCloseBracket KeyCode = internal.KeyGroupSeparator CtrlCaret KeyCode = internal.KeyRecordSeparator CtrlUnderscore KeyCode = internal.KeyUnitSeparator CtrlQuestionMark KeyCode = internal.KeyDelete ) // Other keys. const ( RuneKey KeyCode = -(iota + 1) Up Down Right Left ShiftTab Home End PgUp PgDown Delete Space CtrlUp CtrlDown CtrlRight CtrlLeft ShiftUp ShiftDown ShiftRight ShiftLeft CtrlShiftUp CtrlShiftDown CtrlShiftLeft CtrlShiftRight F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 ) var keyNames = map[KeyCode]string{ // Control keys. internal.KeyNull: "ctrl+@", // also ctrl+backtick internal.KeyStartOfHeading: "ctrl+a", internal.KeyStartOfText: "ctrl+b", internal.KeyExit: "ctrl+c", internal.KeyEndOfTransimission: "ctrl+d", internal.KeyEnquiry: "ctrl+e", internal.KeyAcknowledge: "ctrl+f", internal.KeyBELL: "ctrl+g", internal.KeyBackspace: "ctrl+h", internal.KeyHorizontalTabulation: "tab", // also ctrl+i internal.KeyLineFeed: "ctrl+j", internal.KeyVerticalTabulation: "ctrl+k", internal.KeyFormFeed: "ctrl+l", internal.KeyCarriageReturn: "enter", internal.KeyShiftOut: "ctrl+n", internal.KeyShiftIn: "ctrl+o", internal.KeyDataLinkEscape: "ctrl+p", internal.KeyDeviceControl1: "ctrl+q", internal.KeyDeviceControl2: "ctrl+r", internal.KeyDeviceControl3: "ctrl+s", internal.KeyDeviceControl4: "ctrl+t", internal.KeyNegativeAcknowledge: "ctrl+u", internal.KeySynchronousIdle: "ctrl+v", internal.KeyEndOfTransmissionBlock: "ctrl+w", internal.KeyCancel: "ctrl+x", internal.KeyEndOfMedium: "ctrl+y", internal.KeySubstitution: "ctrl+z", internal.KeyEscape: "esc", internal.KeyFileSeparator: "ctrl+\\", internal.KeyGroupSeparator: "ctrl+]", internal.KeyRecordSeparator: "ctrl+^", internal.KeyUnitSeparator: "ctrl+_", internal.KeyDelete: "backspace", // Other keys. RuneKey: "runes", Up: "up", Down: "down", Right: "right", Space: "space", Left: "left", ShiftTab: "shift+tab", Home: "home", End: "end", PgUp: "pgup", PgDown: "pgdown", Delete: "delete", CtrlUp: "ctrl+up", CtrlDown: "ctrl+down", CtrlRight: "ctrl+right", CtrlLeft: "ctrl+left", ShiftUp: "shift+up", ShiftDown: "shift+down", ShiftRight: "shift+right", ShiftLeft: "shift+left", CtrlShiftUp: "ctrl+shift+up", CtrlShiftDown: "ctrl+shift+down", CtrlShiftLeft: "ctrl+shift+left", CtrlShiftRight: "ctrl+shift+right", F1: "f1", F2: "f2", F3: "f3", F4: "f4", F5: "f5", F6: "f6", F7: "f7", F8: "f8", F9: "f9", F10: "f10", F11: "f11", F12: "f12", F13: "f13", F14: "f14", F15: "f15", F16: "f16", F17: "f17", F18: "f18", F19: "f19", F20: "f20", } golang-github-atomicgo-keyboard-0.2.9/tty_unix.go000066400000000000000000000010511465012272000220550ustar00rootroot00000000000000//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build darwin dragonfly freebsd linux netbsd openbsd solaris package keyboard import ( "os" "github.com/containerd/console" ) func restoreInput() error { if con != nil { return con.Reset() } return nil } func initInput() error { c, err := console.ConsoleFromFile(stdin) if err != nil { return err } con = c return nil } func openInputTTY() (*os.File, error) { f, err := os.Open("/dev/tty") if err != nil { return nil, err } return f, nil } golang-github-atomicgo-keyboard-0.2.9/tty_windows.go000066400000000000000000000012101465012272000225610ustar00rootroot00000000000000//go:build windows // +build windows package keyboard import ( "fmt" "os" "syscall" "github.com/containerd/console" ) func restoreInput() error { if windowsStdin != nil { os.Stdin = windowsStdin } return nil } func initInput() error { windowsStdin = os.Stdin os.Stdin = stdin var mode uint32 err := syscall.GetConsoleMode(syscall.Stdin, &mode) if err != nil { mocking = true return nil } con = console.Current() return nil } func openInputTTY() (*os.File, error) { f, err := os.OpenFile("CONIN$", os.O_RDWR, 0644) if err != nil { return nil, fmt.Errorf("failed to open stdin TTY: %w", err) } return f, nil } golang-github-atomicgo-keyboard-0.2.9/utils.go000066400000000000000000000002751465012272000213410ustar00rootroot00000000000000//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build darwin dragonfly freebsd linux netbsd openbsd solaris package keyboard func closeInput() { } golang-github-atomicgo-keyboard-0.2.9/utils_windows.go000066400000000000000000000001621465012272000231060ustar00rootroot00000000000000package keyboard import "syscall" func closeInput() { syscall.CancelIoEx(syscall.Handle(inputTTY.Fd()), nil) }