├── .github ├── issue_template.md └── pull_request_template.md ├── .gitignore ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── components ├── channels.go ├── chat.go ├── debug.go ├── input.go ├── message.go ├── mode.go └── threads.go ├── config ├── config.go ├── emoji.go └── theme.go ├── context └── context.go ├── go.mod ├── go.sum ├── handlers └── event.go ├── main.go ├── screenshot.png ├── service └── slack.go ├── vendor ├── github.com │ ├── 0xAX │ │ └── notificator │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── notification.go │ ├── OpenPeeDeeP │ │ └── xdg │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── appveyor.yml │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ ├── xdg.go │ │ │ ├── xdg_darwin.go │ │ │ ├── xdg_linux.go │ │ │ └── xdg_windows.go │ ├── erroneousboat │ │ └── termui │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── barchart.go │ │ │ ├── block.go │ │ │ ├── block_common.go │ │ │ ├── block_windows.go │ │ │ ├── buffer.go │ │ │ ├── canvas.go │ │ │ ├── config.py │ │ │ ├── doc.go │ │ │ ├── events.go │ │ │ ├── gauge.go │ │ │ ├── glide.lock │ │ │ ├── glide.yaml │ │ │ ├── grid.go │ │ │ ├── helper.go │ │ │ ├── linechart.go │ │ │ ├── linechart_others.go │ │ │ ├── linechart_windows.go │ │ │ ├── list.go │ │ │ ├── mbarchart.go │ │ │ ├── mkdocs.yml │ │ │ ├── par.go │ │ │ ├── pos.go │ │ │ ├── render.go │ │ │ ├── sparkline.go │ │ │ ├── table.go │ │ │ ├── textbuilder.go │ │ │ ├── theme.go │ │ │ └── widget.go │ ├── gorilla │ │ └── websocket │ │ │ ├── .gitignore │ │ │ ├── AUTHORS │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── client.go │ │ │ ├── client_clone.go │ │ │ ├── client_clone_legacy.go │ │ │ ├── compression.go │ │ │ ├── conn.go │ │ │ ├── conn_write.go │ │ │ ├── conn_write_legacy.go │ │ │ ├── doc.go │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ ├── join.go │ │ │ ├── json.go │ │ │ ├── mask.go │ │ │ ├── mask_safe.go │ │ │ ├── prepared.go │ │ │ ├── proxy.go │ │ │ ├── server.go │ │ │ ├── trace.go │ │ │ ├── trace_17.go │ │ │ ├── util.go │ │ │ └── x_net_proxy.go │ ├── lithammer │ │ └── fuzzysearch │ │ │ ├── LICENSE │ │ │ └── fuzzy │ │ │ ├── fuzzy.go │ │ │ └── levenshtein.go │ ├── maruel │ │ └── panicparse │ │ │ ├── LICENSE │ │ │ └── stack │ │ │ ├── bucket.go │ │ │ ├── source.go │ │ │ ├── stack.go │ │ │ └── ui.go │ ├── mattn │ │ └── go-runewidth │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.mkd │ │ │ ├── go.mod │ │ │ ├── runewidth.go │ │ │ ├── runewidth_appengine.go │ │ │ ├── runewidth_js.go │ │ │ ├── runewidth_posix.go │ │ │ ├── runewidth_table.go │ │ │ └── runewidth_windows.go │ ├── mitchellh │ │ └── go-wordwrap │ │ │ ├── LICENSE.md │ │ │ ├── README.md │ │ │ └── wordwrap.go │ ├── nsf │ │ └── termbox-go │ │ │ ├── AUTHORS │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── api.go │ │ │ ├── api_common.go │ │ │ ├── api_windows.go │ │ │ ├── collect_terminfo.py │ │ │ ├── escwait.go │ │ │ ├── escwait_darwin.go │ │ │ ├── syscalls_darwin.go │ │ │ ├── syscalls_darwin_amd64.go │ │ │ ├── syscalls_dragonfly.go │ │ │ ├── syscalls_freebsd.go │ │ │ ├── syscalls_linux.go │ │ │ ├── syscalls_netbsd.go │ │ │ ├── syscalls_openbsd.go │ │ │ ├── syscalls_windows.go │ │ │ ├── termbox.go │ │ │ ├── termbox_common.go │ │ │ ├── termbox_windows.go │ │ │ ├── terminfo.go │ │ │ └── terminfo_builtin.go │ ├── pkg │ │ └── errors │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── appveyor.yml │ │ │ ├── errors.go │ │ │ ├── go113.go │ │ │ └── stack.go │ └── slack-go │ │ └── slack │ │ ├── .gitignore │ │ ├── .gometalinter.json │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── TODO.txt │ │ ├── admin.go │ │ ├── attachments.go │ │ ├── auth.go │ │ ├── backoff.go │ │ ├── block.go │ │ ├── block_action.go │ │ ├── block_context.go │ │ ├── block_conv.go │ │ ├── block_divider.go │ │ ├── block_element.go │ │ ├── block_file.go │ │ ├── block_image.go │ │ ├── block_input.go │ │ ├── block_object.go │ │ ├── block_section.go │ │ ├── block_unknown.go │ │ ├── bots.go │ │ ├── channels.go │ │ ├── chat.go │ │ ├── comment.go │ │ ├── conversation.go │ │ ├── dialog.go │ │ ├── dialog_select.go │ │ ├── dialog_text.go │ │ ├── dnd.go │ │ ├── emoji.go │ │ ├── errors.go │ │ ├── files.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── groups.go │ │ ├── history.go │ │ ├── im.go │ │ ├── info.go │ │ ├── interactions.go │ │ ├── internal │ │ ├── errorsx │ │ │ └── errorsx.go │ │ └── timex │ │ │ └── timex.go │ │ ├── item.go │ │ ├── logger.go │ │ ├── messageID.go │ │ ├── messages.go │ │ ├── misc.go │ │ ├── oauth.go │ │ ├── pagination.go │ │ ├── pins.go │ │ ├── reactions.go │ │ ├── reminders.go │ │ ├── rtm.go │ │ ├── search.go │ │ ├── security.go │ │ ├── slack.go │ │ ├── slackutilsx │ │ └── slackutilsx.go │ │ ├── slash.go │ │ ├── stars.go │ │ ├── team.go │ │ ├── usergroups.go │ │ ├── users.go │ │ ├── views.go │ │ ├── webhooks.go │ │ ├── webhooks_go112.go │ │ ├── webhooks_go113.go │ │ ├── websocket.go │ │ ├── websocket_channels.go │ │ ├── websocket_desktop_notification.go │ │ ├── websocket_dm.go │ │ ├── websocket_dnd.go │ │ ├── websocket_files.go │ │ ├── websocket_groups.go │ │ ├── websocket_internals.go │ │ ├── websocket_managed_conn.go │ │ ├── websocket_misc.go │ │ ├── websocket_mobile_in_app_notification.go │ │ ├── websocket_pins.go │ │ ├── websocket_reactions.go │ │ ├── websocket_stars.go │ │ ├── websocket_subteam.go │ │ └── websocket_teams.go ├── golang.org │ └── x │ │ └── text │ │ ├── AUTHORS │ │ ├── CONTRIBUTORS │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── runes │ │ ├── cond.go │ │ └── runes.go │ │ ├── transform │ │ └── transform.go │ │ └── unicode │ │ └── norm │ │ ├── composition.go │ │ ├── forminfo.go │ │ ├── input.go │ │ ├── iter.go │ │ ├── normalize.go │ │ ├── readwriter.go │ │ ├── tables10.0.0.go │ │ ├── tables11.0.0.go │ │ ├── tables9.0.0.go │ │ ├── transform.go │ │ └── trie.go └── modules.txt └── views ├── load.go └── view.go /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | Please read [CONTRIBUTING.md](https://github.com/erroneousboat/slack-term/blob/master/CONTRIBUTING.md) 2 | 3 | --- 4 | 5 | Version: 6 | Installation method: 7 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Please read [CONTRIBUTING.md](https://github.com/erroneousboat/slack-term/blob/master/CONTRIBUTING.md) 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | Purpose 5 | ------- 6 | 7 | First and foremost, slack-term is a personal project. With this project I 8 | never set out to create a "better" slack version than the official slack 9 | client. And as such, my intention for the project is not to create a feature 10 | complete alternative to the official slack client. It's cool that people 11 | want to use slack-term as an alternative, but I started this project because 12 | I wanted to be able to send and receive slack messages from the terminal to 13 | slack. 14 | 15 | Issues 16 | ------ 17 | 18 | When posting issues please mention the following: 19 | 20 | * Which version of slack-term you're using 21 | * Method of installation (binary, go, or make) 22 | 23 | Feature requests 24 | ---------------- 25 | 26 | When creating an issue that is a feature request, I will label it as such, 27 | however this doesn't mean that it is an approved feature request. I will 28 | leave it open for discussion and decide whether it is feasible and/or 29 | desirable. 30 | 31 | Pull requests 32 | ------------- 33 | 34 | Before creating a solution, please create an issue that is open for discussion 35 | first. This is to avoid dissappointment, for all the work you might have 36 | done, that might not get merged or needs to be refactored. 37 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:alpine as builder 2 | 3 | ENV PATH /go/bin:/usr/local/go/bin:$PATH 4 | ENV GOPATH /go 5 | 6 | RUN apk add --no-cache \ 7 | ca-certificates 8 | 9 | COPY . /go/src/github.com/erroneousboat/slack-term 10 | 11 | RUN set -x \ 12 | && apk add --no-cache --virtual .build-deps \ 13 | git \ 14 | gcc \ 15 | libc-dev \ 16 | libgcc \ 17 | make \ 18 | && cd /go/src/github.com/erroneousboat/slack-term \ 19 | && make build \ 20 | && mv ./bin/slack-term /usr/bin/slack-term \ 21 | && apk del .build-deps \ 22 | && rm -rf /go 23 | 24 | FROM alpine:latest 25 | 26 | ENV USER root 27 | 28 | COPY --from=builder /usr/bin/slack-term /usr/bin/slack-term 29 | COPY --from=builder /etc/ssl/certs/ /etc/ssl/certs 30 | 31 | ENTRYPOINT stty cols 25 && slack-term -config config 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 J.P.H. Bruins Slot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: test 2 | 3 | # -timeout timout in seconds 4 | # -v verbose output 5 | test: 6 | @ echo "+ $@" 7 | @ go test -timeout=5s -v 8 | 9 | dev: build 10 | @ ./bin/slack-term -debug 11 | 12 | # `CGO_ENABLED=0` 13 | # Because of dynamically linked libraries, this will statically compile the 14 | # app with all libraries built in. You won't be able to cross-compile if CGO 15 | # is enabled. This is because Go binary is looking for libraries on the 16 | # operating system it’s running in. We compiled our app, but it still is 17 | # dynamically linked to the libraries it needs to run 18 | # (i.e., all the C libraries it binds to). When using a minimal docker image 19 | # the operating system doesn't have these libraries. 20 | # 21 | # `GOOS=linux` 22 | # We're setting the OS to linux (in case someone builds the binary on Mac or 23 | # Windows) 24 | # 25 | # `-mod=vendor` 26 | # This ensures that the build process will use the modules in the vendor 27 | # folder. 28 | # 29 | # `-a` 30 | # Force rebuilding of package, all import will be rebuilt with cgo disabled, 31 | # which means all the imports will be rebuilt with cgo disabled. 32 | # 33 | # `-installsuffix cgo` 34 | # A suffix to use in the name of the package installation directory 35 | # 36 | # `-o` 37 | # Output 38 | # 39 | # `./bin/slack-term` 40 | # Placement of the binary 41 | # 42 | # `.` 43 | # Location of the source files 44 | build: 45 | @ echo "+ $@" 46 | @ CGO_ENABLED=0 go build -mod=vendor -a -installsuffix cgo -o ./bin/slack-term . 47 | 48 | # Cross-compile 49 | # http://dave.cheney.net/2015/08/22/cross-compilation-with-go-1-5 50 | build-linux: 51 | @ echo "+ $@" 52 | @ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -mod=vendor -a -installsuffix cgo -o ./bin/slack-term-linux-amd64 . 53 | 54 | build-mac: 55 | @ echo "+ $@" 56 | @ GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -mod=vendor -a -installsuffix cgo -o ./bin/slack-term-darwin-amd64 . 57 | 58 | run: build 59 | @ echo "+ $@" 60 | @ ./bin/slack-term 61 | 62 | install: 63 | @ echo "+ $@" 64 | @ go install . 65 | 66 | modules: 67 | @ echo "+ $@" 68 | @ go mod tidy 69 | @ go mod vendor 70 | 71 | build-all: build build-linux build-mac 72 | 73 | .PHONY: default test build build-linux build-mac run install 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | slack-term 2 | ========== 3 | 4 | A [Slack](https://slack.com) client for your terminal. 5 | 6 | ![Screenshot](/screenshot.png?raw=true) 7 | 8 | Installation 9 | ------------ 10 | 11 | #### Binary installation 12 | 13 | [Download](https://github.com/erroneousboat/slack-term/releases) a 14 | compatible binary for your system. For convenience, place `slack-term` in a 15 | directory where you can access it from the command line. Usually this is 16 | `/usr/local/bin`. 17 | 18 | ```bash 19 | $ mv slack-term /usr/local/bin 20 | ``` 21 | 22 | #### Via Go 23 | 24 | If you want, you can also get `slack-term` via Go: 25 | 26 | ```bash 27 | $ go get -u github.com/erroneousboat/slack-term 28 | $ cd $GOPATH/src/github.com/erroneousboat/slack-term 29 | $ go install . 30 | ``` 31 | 32 | #### Via docker 33 | 34 | You can also run it with docker, make sure you have a valid config file 35 | on your host system. 36 | 37 | ```bash 38 | docker run -it -v [config-file]:/config erroneousboat/slack-term 39 | ``` 40 | 41 | Setup 42 | ----- 43 | 44 | 1. Get a slack token, click [here](https://github.com/erroneousboat/slack-term/wiki#running-slack-term-without-legacy-tokens) 45 | 46 | 2. Running `slack-term` for the first time, will create a default config file at 47 | `~/.config/slack-term/config`. 48 | 49 | ```bash 50 | $ slack-term 51 | ``` 52 | 53 | 3. Update the config file and update your `slack_token` For more configuration 54 | options of the `config` file, see the [wiki](https://github.com/erroneousboat/slack-term/wiki). 55 | 56 | ```javascript 57 | { 58 | "slack_token": "yourslacktokenhere" 59 | } 60 | ``` 61 | 62 | Usage 63 | ----- 64 | 65 | When everything is setup correctly you can run `slack-term` with the following 66 | command: 67 | 68 | ```bash 69 | $ slack-term 70 | ``` 71 | 72 | Default Key Mapping 73 | ------------------- 74 | 75 | Below are the default key-mappings for `slack-term`, you can change them 76 | in your `config` file. 77 | 78 | | mode | key | action | 79 | |---------|-----------|----------------------------| 80 | | command | `i` | insert mode | 81 | | command | `/` | search mode | 82 | | command | `k` | move channel cursor up | 83 | | command | `j` | move channel cursor down | 84 | | command | `g` | move channel cursor top | 85 | | command | `G` | move channel cursor bottom | 86 | | command | `K` | thread up | 87 | | command | `J` | thread down | 88 | | command | `G` | move channel cursor bottom | 89 | | command | `pg-up` | scroll chat pane up | 90 | | command | `ctrl-b` | scroll chat pane up | 91 | | command | `ctrl-u` | scroll chat pane up | 92 | | command | `pg-down` | scroll chat pane down | 93 | | command | `ctrl-f` | scroll chat pane down | 94 | | command | `ctrl-d` | scroll chat pane down | 95 | | command | `n` | next search match | 96 | | command | `N` | previous search match | 97 | | command | `,` | jump to next notification | 98 | | command | `q` | quit | 99 | | command | `f1` | help | 100 | | insert | `left` | move input cursor left | 101 | | insert | `right` | move input cursor right | 102 | | insert | `enter` | send message | 103 | | insert | `esc` | command mode | 104 | | search | `esc` | command mode | 105 | | search | `enter` | command mode | 106 | -------------------------------------------------------------------------------- /components/debug.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/erroneousboat/termui" 7 | ) 8 | 9 | // Debug can be used to relay debugging information in the Debug component, 10 | // see event.go on how to use it 11 | type Debug struct { 12 | Par *termui.Par 13 | List *termui.List 14 | } 15 | 16 | func CreateDebugComponent(inputHeight int) *Debug { 17 | debug := &Debug{ 18 | List: termui.NewList(), 19 | } 20 | 21 | debug.List.BorderLabel = "Debug" 22 | debug.List.Height = termui.TermHeight() - inputHeight 23 | debug.List.Overflow = "wrap" 24 | 25 | return debug 26 | } 27 | 28 | // Buffer implements interface termui.Bufferer 29 | func (d *Debug) Buffer() termui.Buffer { 30 | return d.List.Buffer() 31 | } 32 | 33 | // GetHeight implements interface termui.GridBufferer 34 | func (d *Debug) GetHeight() int { 35 | return d.List.Block.GetHeight() 36 | } 37 | 38 | // SetWidth implements interface termui.GridBufferer 39 | func (d *Debug) SetWidth(w int) { 40 | d.List.SetWidth(w) 41 | } 42 | 43 | // SetX implements interface termui.GridBufferer 44 | func (d *Debug) SetX(x int) { 45 | d.List.SetX(x) 46 | } 47 | 48 | // SetY implements interface termui.GridBufferer 49 | func (d *Debug) SetY(y int) { 50 | d.List.SetY(y) 51 | } 52 | 53 | // Println will add the text to the Debug component 54 | func (d *Debug) Println(text string) { 55 | d.List.Items = append(d.List.Items, text) 56 | 57 | // When at the end remove first item 58 | if len(d.List.Items) > d.List.InnerBounds().Max.Y-1 { 59 | d.List.Items = d.List.Items[1:] 60 | } 61 | 62 | termui.Render(d) 63 | } 64 | 65 | func (d *Debug) Sprintf(format string, a ...interface{}) { 66 | text := fmt.Sprintf(format, a...) 67 | d.List.Items = append(d.List.Items, text) 68 | 69 | // When at the end remove first item 70 | if len(d.List.Items) > d.List.InnerBounds().Max.Y-1 { 71 | d.List.Items = d.List.Items[1:] 72 | } 73 | 74 | termui.Render(d) 75 | } 76 | -------------------------------------------------------------------------------- /components/message.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | var ( 11 | COLORS = []string{ 12 | "fg-black", 13 | "fg-red", 14 | "fg-green", 15 | "fg-yellow", 16 | "fg-blue", 17 | "fg-magenta", 18 | "fg-cyan", 19 | "fg-white", 20 | } 21 | ) 22 | 23 | type Message struct { 24 | ID string 25 | Messages map[string]Message 26 | 27 | Time time.Time 28 | Thread string 29 | Name string 30 | Content string 31 | 32 | StyleTime string 33 | StyleThread string 34 | StyleName string 35 | StyleText string 36 | 37 | FormatTime string 38 | } 39 | 40 | func (m Message) GetTime() string { 41 | return fmt.Sprintf( 42 | "[[%s]](%s) ", 43 | m.Time.Format(m.FormatTime), 44 | m.StyleTime, 45 | ) 46 | } 47 | 48 | func (m Message) GetThread() string { 49 | return fmt.Sprintf("[%s](%s)", 50 | m.Thread, 51 | m.StyleThread, 52 | ) 53 | } 54 | 55 | func (m Message) GetName() string { 56 | return fmt.Sprintf("[<%s>](%s) ", 57 | m.Name, 58 | m.colorizeName(m.StyleName), 59 | ) 60 | } 61 | 62 | func (m Message) GetContent() string { 63 | return fmt.Sprintf("[.](%s)", m.StyleText) 64 | } 65 | 66 | func (m Message) colorizeName(styleName string) string { 67 | if strings.Contains(styleName, "colorize") { 68 | var sum int 69 | for _, c := range m.Name { 70 | sum = sum + int(c) 71 | } 72 | 73 | i := sum % len(COLORS) 74 | 75 | return strings.Replace(m.StyleName, "colorize", COLORS[i], -1) 76 | } 77 | 78 | return styleName 79 | } 80 | 81 | func SortMessages(msgs map[string]Message) []Message { 82 | keys := make([]string, 0) 83 | for k := range msgs { 84 | keys = append(keys, k) 85 | } 86 | 87 | sort.Strings(keys) 88 | 89 | sortedMessages := make([]Message, 0) 90 | for _, k := range keys { 91 | sortedMessages = append(sortedMessages, msgs[k]) 92 | } 93 | 94 | return sortedMessages 95 | } 96 | -------------------------------------------------------------------------------- /components/mode.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "github.com/erroneousboat/termui" 5 | ) 6 | 7 | const ( 8 | CommandMode = "NORMAL" 9 | InsertMode = "INSERT" 10 | SearchMode = "SEARCH" 11 | ) 12 | 13 | // Mode is the definition of Mode component 14 | type Mode struct { 15 | Par *termui.Par 16 | } 17 | 18 | // CreateMode is the constructor of the Mode struct 19 | func CreateModeComponent() *Mode { 20 | mode := &Mode{ 21 | Par: termui.NewPar(CommandMode), 22 | } 23 | 24 | mode.Par.Height = 3 25 | mode.SetCommandMode() 26 | 27 | return mode 28 | } 29 | 30 | // Buffer implements interface termui.Bufferer 31 | func (m *Mode) Buffer() termui.Buffer { 32 | buf := m.Par.Buffer() 33 | 34 | // Center text 35 | space := m.Par.InnerWidth() 36 | word := len(m.Par.Text) 37 | 38 | midSpace := space / 2 39 | midWord := word / 2 40 | 41 | start := midSpace - midWord 42 | 43 | cells := termui.DefaultTxBuilder.Build( 44 | m.Par.Text, m.Par.TextFgColor, m.Par.TextBgColor) 45 | 46 | i, j := 0, 0 47 | x := m.Par.InnerBounds().Min.X 48 | for x < m.Par.InnerBounds().Max.X { 49 | if i < start { 50 | buf.Set( 51 | x, m.Par.InnerY(), 52 | termui.Cell{ 53 | Ch: ' ', 54 | Fg: m.Par.TextFgColor, 55 | Bg: m.Par.TextBgColor, 56 | }, 57 | ) 58 | x++ 59 | i++ 60 | } else { 61 | if j < len(cells) { 62 | buf.Set(x, m.Par.InnerY(), cells[j]) 63 | i++ 64 | j++ 65 | } 66 | x++ 67 | } 68 | } 69 | 70 | return buf 71 | } 72 | 73 | // GetHeight implements interface termui.GridBufferer 74 | func (m *Mode) GetHeight() int { 75 | return m.Par.Block.GetHeight() 76 | } 77 | 78 | // SetWidth implements interface termui.GridBufferer 79 | func (m *Mode) SetWidth(w int) { 80 | m.Par.SetWidth(w) 81 | } 82 | 83 | // SetX implements interface termui.GridBufferer 84 | func (m *Mode) SetX(x int) { 85 | m.Par.SetX(x) 86 | } 87 | 88 | // SetY implements interface termui.GridBufferer 89 | func (m *Mode) SetY(y int) { 90 | m.Par.SetY(y) 91 | } 92 | 93 | func (m *Mode) SetInsertMode() { 94 | m.Par.Text = InsertMode 95 | termui.Render(m) 96 | } 97 | 98 | func (m *Mode) SetCommandMode() { 99 | m.Par.Text = CommandMode 100 | termui.Render(m) 101 | } 102 | 103 | func (m *Mode) SetSearchMode() { 104 | m.Par.Text = SearchMode 105 | termui.Render(m) 106 | } 107 | -------------------------------------------------------------------------------- /components/threads.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "github.com/erroneousboat/termui" 5 | ) 6 | 7 | type Threads struct { 8 | *Channels 9 | } 10 | 11 | func CreateThreadsComponent(height int) *Threads { 12 | threads := &Threads{ 13 | Channels: &Channels{ 14 | List: termui.NewList(), 15 | }, 16 | } 17 | 18 | threads.List.BorderLabel = "Threads" 19 | threads.List.Height = height 20 | 21 | threads.SelectedChannel = 0 22 | threads.Offset = 0 23 | threads.CursorPosition = threads.List.InnerBounds().Min.Y 24 | 25 | return threads 26 | } 27 | -------------------------------------------------------------------------------- /config/theme.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | type Theme struct { 4 | View View `json:"view"` 5 | Channel Channel `json:"channel"` 6 | Message Message `json:"message"` 7 | } 8 | 9 | type View struct { 10 | Fg string `json:"fg"` // Foreground text 11 | Bg string `json:"bg"` // Background text 12 | BorderFg string `json:"border_fg"` // Border foreground 13 | BorderBg string `json:"border_bg"` // Border background 14 | LabelFg string `json:"label_fg"` // Label text foreground 15 | LabelBg string `json:"label_bg"` // Label text background 16 | } 17 | 18 | type Message struct { 19 | Time string `json:"time"` 20 | Name string `json:"name"` 21 | Thread string `json:"thread"` 22 | Text string `json:"text"` 23 | TimeFormat string `json:"time_format"` 24 | } 25 | 26 | type Channel struct { 27 | Prefix string `json:"prefix"` 28 | Icon string `json:"icon"` 29 | Text string `json:"text"` 30 | } 31 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erroneousboat/slack-term 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/0xAX/notificator v0.0.0-20171022182052-88d57ee9043b 7 | github.com/OpenPeeDeeP/xdg v0.2.0 8 | github.com/erroneousboat/termui v0.0.0-20170923115141-80f245cdfa04 9 | github.com/gorilla/websocket v1.4.2 // indirect 10 | github.com/kr/pretty v0.1.0 // indirect 11 | github.com/lithammer/fuzzysearch v1.1.0 12 | github.com/maruel/panicparse v1.1.1 // indirect 13 | github.com/mattn/go-runewidth v0.0.7 14 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect 15 | github.com/nsf/termbox-go v0.0.0-20191229070316-58d4fcbce2a7 16 | github.com/pkg/errors v0.9.1 // indirect 17 | github.com/slack-go/slack v0.6.3 18 | github.com/stretchr/testify v1.4.0 // indirect 19 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect 20 | gopkg.in/yaml.v2 v2.2.4 // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | "github.com/OpenPeeDeeP/xdg" 10 | "github.com/erroneousboat/termui" 11 | termbox "github.com/nsf/termbox-go" 12 | 13 | "github.com/erroneousboat/slack-term/context" 14 | "github.com/erroneousboat/slack-term/handlers" 15 | ) 16 | 17 | const ( 18 | VERSION = "master" 19 | USAGE = `NAME: 20 | slack-term - slack client for your terminal 21 | 22 | USAGE: 23 | slack-term -config [path-to-config] 24 | 25 | VERSION: 26 | %s 27 | 28 | WEBSITE: 29 | https://github.com/erroneousboat/slack-term 30 | 31 | GLOBAL OPTIONS: 32 | -config [path-to-config-file] 33 | -token [slack-token] 34 | -debug 35 | -help, -h 36 | ` 37 | ) 38 | 39 | var ( 40 | flgConfig string 41 | flgToken string 42 | flgDebug bool 43 | flgUsage bool 44 | ) 45 | 46 | func init() { 47 | 48 | // Find the default config file 49 | configFile := xdg.New("slack-term", "").QueryConfig("config") 50 | 51 | // Parse flags 52 | flag.StringVar( 53 | &flgConfig, 54 | "config", 55 | configFile, 56 | "location of config file", 57 | ) 58 | 59 | flag.StringVar( 60 | &flgToken, 61 | "token", 62 | "", 63 | "the slack token", 64 | ) 65 | 66 | flag.BoolVar( 67 | &flgDebug, 68 | "debug", 69 | false, 70 | "turn on debugging", 71 | ) 72 | 73 | flag.Usage = func() { 74 | fmt.Printf(USAGE, VERSION) 75 | } 76 | 77 | flag.Parse() 78 | } 79 | 80 | func main() { 81 | // Start terminal user interface 82 | err := termui.Init() 83 | if err != nil { 84 | log.Fatal(err) 85 | } 86 | defer termui.Close() 87 | 88 | // Create custom event stream for termui because 89 | // termui's one has data race conditions with its 90 | // event handling. We're circumventing it here until 91 | // it has been fixed. 92 | customEvtStream := &termui.EvtStream{ 93 | Handlers: make(map[string]func(termui.Event)), 94 | } 95 | termui.DefaultEvtStream = customEvtStream 96 | 97 | // Create context 98 | usage := fmt.Sprintf(USAGE, VERSION) 99 | ctx, err := context.CreateAppContext( 100 | flgConfig, flgToken, flgDebug, VERSION, usage, 101 | ) 102 | if err != nil { 103 | termbox.Close() 104 | log.Println(err) 105 | os.Exit(0) 106 | } 107 | 108 | // Initialize handlers 109 | handlers.Initialize(ctx) 110 | 111 | termui.Loop() 112 | } 113 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpbruinsslot/slack-term/c19c20a3e5c597d6d60582fcba1a3523415e8fe4/screenshot.png -------------------------------------------------------------------------------- /vendor/github.com/0xAX/notificator/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | 25 | .idea 26 | -------------------------------------------------------------------------------- /vendor/github.com/0xAX/notificator/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, 0xAX 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/0xAX/notificator/README.md: -------------------------------------------------------------------------------- 1 | notificator 2 | =========================== 3 | 4 | Desktop notification with Golang for: 5 | 6 | * Windows with `growlnotify`; 7 | * Mac OS X with `terminal-notifier` (if installed) or `osascript` (native, 10.9 Mavericks or Up.); 8 | * Linux with `notify-send` for Gnome and `kdialog` for Kde. 9 | 10 | Usage 11 | ------ 12 | 13 | ```go 14 | package main 15 | 16 | import ( 17 | "github.com/0xAX/notificator" 18 | ) 19 | 20 | var notify *notificator.Notificator 21 | 22 | func main() { 23 | 24 | notify = notificator.New(notificator.Options{ 25 | DefaultIcon: "icon/default.png", 26 | AppName: "My test App", 27 | }) 28 | 29 | notify.Push("title", "text", "/home/user/icon.png", notificator.UR_CRITICAL) 30 | } 31 | ``` 32 | 33 | TODO 34 | ----- 35 | 36 | * Add more options for different notificators. 37 | 38 | Сontribution 39 | ------------ 40 | 41 | * Fork; 42 | * Make changes; 43 | * Send pull request; 44 | * Thank you. 45 | 46 | author 47 | ---------- 48 | 49 | [@0xAX](https://twitter.com/0xAX) 50 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/.gitignore: -------------------------------------------------------------------------------- 1 | *.test 2 | *.out 3 | .DS_STORE 4 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.11.x 4 | os: 5 | - linux 6 | - osx 7 | before_install: 8 | - go get -t -v ./... 9 | script: 10 | - go test -v -race -covermode=atomic -coverprofile=coverage.txt 11 | after_success: 12 | - bash <(curl -s https://codecov.io/bash) 13 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, OpenPeeDeeP 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/README.md: -------------------------------------------------------------------------------- 1 | # XDG [![Build status](https://ci.appveyor.com/api/projects/status/9eoupq9jgsu2p0jv?svg=true)](https://ci.appveyor.com/project/dixonwille/xdg) [![Build Status](https://travis-ci.org/OpenPeeDeeP/xdg.svg?branch=master)](https://travis-ci.org/OpenPeeDeeP/xdg) [![Go Report Card](https://goreportcard.com/badge/github.com/OpenPeeDeeP/xdg)](https://goreportcard.com/report/github.com/OpenPeeDeeP/xdg) [![GoDoc](https://godoc.org/github.com/OpenPeeDeeP/xdg?status.svg)](https://godoc.org/github.com/OpenPeeDeeP/xdg) [![codecov](https://codecov.io/gh/OpenPeeDeeP/xdg/branch/master/graph/badge.svg)](https://codecov.io/gh/OpenPeeDeeP/xdg) 2 | 3 | A cross platform package that tries to follow [XDG Standard](https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html) when possible. Since XDG is linux specific, I am only able to follow standards to the T on linux. But for the other operating systems I am finding similar best practice locations for the files. 4 | 5 | ## Locations Per OS 6 | 7 | The following table shows what is used if the envrionment variable is not set. If the variable is set then this package uses that. Linux follows the default standards. Mac does when it comes to the home directory but for system wide it uses the standard `/Library/Application Support`. As for Windows, the variable defaults are just other environment variables set up by the operation system. 8 | 9 | > When creating `XDG` application the `Vendor` and `Application` names are appeneded to the end of the path to keep projects unique. 10 | 11 | | | Linux | Mac | Windows | 12 | | ---: | :---: | :---: | :---: | 13 | | `XDG_DATA_DIRS` | [`/usr/local/share`, `/usr/share`] | [`/Library/Application Support`] | `%PROGRAMDATA%` | 14 | | `XDG_DATA_HOME` | `~/.local/share` | `~/Library/Application Support` | `%APPDATA%` | 15 | | `XDG_CONFIG_DIRS` | [`/etc/xdg`] | [`/Library/Application Support`] | `%PROGRAMDATA%` | 16 | | `XDG_CONFIG_HOME` | `~/.config` | `~/Library/Application Support` | `%APPDATA%` | 17 | | `XDG_CACHE_HOME` | `~/.cache` | `~/Library/Cache` | `%LOCALAPPDATA%` | 18 | 19 | ## Notes 20 | 21 | - This package does not merge files if they exist across different directories. 22 | - The `Query` methods search through the system variables, `DIRS`, first (when using environment variables first in the variable has presidence). It then checks home variables, `HOME`. 23 | - This package will not create any directories for you. In the standard, it states the following: 24 | 25 | > If, when attempting to write a file, the destination directory is non-existant an attempt should be made to create it with permission `0700`. If the destination directory exists already the permissions should not be changed. The application should be prepared to handle the case where the file could not be written, either because the directory was non-existant and could not be created, or for any other reason. In such case it may chose to present an error message to the user. 26 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 0.0.1_{build} 2 | build: off 3 | platform: x64 4 | clone_folder: c:\gopath\src\github.com\OpenPeeDeeP\xdg 5 | environment: 6 | GOPATH: c:\gopath 7 | stack: go 1.11 8 | install: 9 | - go get -t -v ./... 10 | - cinst codecov 11 | before_test: 12 | - go vet ./... 13 | test_script: 14 | - go test -v -race -covermode=atomic -coverprofile=coverage.txt 15 | on_success: 16 | - codecov -f coverage.txt 17 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/OpenPeeDeeP/xdg 2 | 3 | require ( 4 | github.com/davecgh/go-spew v1.1.1 // indirect 5 | github.com/pmezard/go-difflib v1.0.0 // indirect 6 | github.com/stretchr/objx v0.1.1 // indirect 7 | github.com/stretchr/testify v1.2.2 8 | ) 9 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= 6 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 7 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 8 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 9 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/xdg_darwin.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, OpenPeeDeeP. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xdg 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | ) 11 | 12 | func (o *osDefaulter) defaultDataHome() string { 13 | return filepath.Join(os.Getenv("HOME"), "Library", "Application Support") 14 | } 15 | 16 | func (o *osDefaulter) defaultDataDirs() []string { 17 | return []string{filepath.Join("/Library", "Application Support")} 18 | } 19 | 20 | func (o *osDefaulter) defaultConfigHome() string { 21 | return filepath.Join(os.Getenv("HOME"), "Library", "Application Support") 22 | } 23 | 24 | func (o *osDefaulter) defaultConfigDirs() []string { 25 | return []string{filepath.Join("/Library", "Application Support")} 26 | } 27 | 28 | func (o *osDefaulter) defaultCacheHome() string { 29 | return filepath.Join(os.Getenv("HOME"), "Library", "Caches") 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/xdg_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, OpenPeeDeeP. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xdg 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | ) 11 | 12 | func (o *osDefaulter) defaultDataHome() string { 13 | return filepath.Join(os.Getenv("HOME"), ".local", "share") 14 | } 15 | 16 | func (o *osDefaulter) defaultDataDirs() []string { 17 | return []string{"/usr/local/share/", "/usr/share/"} 18 | } 19 | 20 | func (o *osDefaulter) defaultConfigHome() string { 21 | return filepath.Join(os.Getenv("HOME"), ".config") 22 | } 23 | 24 | func (o *osDefaulter) defaultConfigDirs() []string { 25 | return []string{"/etc/xdg"} 26 | } 27 | 28 | func (o *osDefaulter) defaultCacheHome() string { 29 | return filepath.Join(os.Getenv("HOME"), ".cache") 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/OpenPeeDeeP/xdg/xdg_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, OpenPeeDeeP. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xdg 6 | 7 | import "os" 8 | 9 | func (o *osDefaulter) defaultDataHome() string { 10 | return os.Getenv("APPDATA") 11 | } 12 | 13 | func (o *osDefaulter) defaultDataDirs() []string { 14 | return []string{os.Getenv("PROGRAMDATA")} 15 | } 16 | 17 | func (o *osDefaulter) defaultConfigHome() string { 18 | return os.Getenv("APPDATA") 19 | } 20 | 21 | func (o *osDefaulter) defaultConfigDirs() []string { 22 | return []string{os.Getenv("PROGRAMDATA")} 23 | } 24 | 25 | func (o *osDefaulter) defaultCacheHome() string { 26 | return os.Getenv("LOCALAPPDATA") 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | .DS_Store 26 | /vendor 27 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - tip 5 | 6 | script: go test -v ./ -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Zack Guo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/block_common.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | // +build !windows 6 | 7 | package termui 8 | 9 | const TOP_RIGHT = '┐' 10 | const VERTICAL_LINE = '│' 11 | const HORIZONTAL_LINE = '─' 12 | const TOP_LEFT = '┌' 13 | const BOTTOM_RIGHT = '┘' 14 | const BOTTOM_LEFT = '└' 15 | const VERTICAL_LEFT = '┤' 16 | const VERTICAL_RIGHT = '├' 17 | const HORIZONTAL_DOWN = '┬' 18 | const HORIZONTAL_UP = '┴' 19 | const QUOTA_LEFT = '«' 20 | const QUOTA_RIGHT = '»' 21 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/block_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | // +build windows 6 | 7 | package termui 8 | 9 | const TOP_RIGHT = '+' 10 | const VERTICAL_LINE = '|' 11 | const HORIZONTAL_LINE = '-' 12 | const TOP_LEFT = '+' 13 | const BOTTOM_RIGHT = '+' 14 | const BOTTOM_LEFT = '+' 15 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/buffer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | package termui 6 | 7 | import "image" 8 | 9 | // Cell is a rune with assigned Fg and Bg 10 | type Cell struct { 11 | Ch rune 12 | Fg Attribute 13 | Bg Attribute 14 | } 15 | 16 | // Buffer is a renderable rectangle cell data container. 17 | type Buffer struct { 18 | Area image.Rectangle // selected drawing area 19 | CellMap map[image.Point]Cell 20 | } 21 | 22 | // At returns the cell at (x,y). 23 | func (b Buffer) At(x, y int) Cell { 24 | return b.CellMap[image.Pt(x, y)] 25 | } 26 | 27 | // Set assigns a char to (x,y) 28 | func (b Buffer) Set(x, y int, c Cell) { 29 | b.CellMap[image.Pt(x, y)] = c 30 | } 31 | 32 | // Bounds returns the domain for which At can return non-zero color. 33 | func (b Buffer) Bounds() image.Rectangle { 34 | x0, y0, x1, y1 := 0, 0, 0, 0 35 | for p := range b.CellMap { 36 | if p.X > x1 { 37 | x1 = p.X 38 | } 39 | if p.X < x0 { 40 | x0 = p.X 41 | } 42 | if p.Y > y1 { 43 | y1 = p.Y 44 | } 45 | if p.Y < y0 { 46 | y0 = p.Y 47 | } 48 | } 49 | return image.Rect(x0, y0, x1+1, y1+1) 50 | } 51 | 52 | // SetArea assigns a new rect area to Buffer b. 53 | func (b *Buffer) SetArea(r image.Rectangle) { 54 | b.Area.Max = r.Max 55 | b.Area.Min = r.Min 56 | } 57 | 58 | // Sync sets drawing area to the buffer's bound 59 | func (b *Buffer) Sync() { 60 | b.SetArea(b.Bounds()) 61 | } 62 | 63 | // NewCell returns a new cell 64 | func NewCell(ch rune, fg, bg Attribute) Cell { 65 | return Cell{ch, fg, bg} 66 | } 67 | 68 | // Merge merges bs Buffers onto b 69 | func (b *Buffer) Merge(bs ...Buffer) { 70 | for _, buf := range bs { 71 | for p, v := range buf.CellMap { 72 | b.Set(p.X, p.Y, v) 73 | } 74 | b.SetArea(b.Area.Union(buf.Area)) 75 | } 76 | } 77 | 78 | // NewBuffer returns a new Buffer 79 | func NewBuffer() Buffer { 80 | return Buffer{ 81 | CellMap: make(map[image.Point]Cell), 82 | Area: image.Rectangle{}} 83 | } 84 | 85 | // Fill fills the Buffer b with ch,fg and bg. 86 | func (b Buffer) Fill(ch rune, fg, bg Attribute) { 87 | for x := b.Area.Min.X; x < b.Area.Max.X; x++ { 88 | for y := b.Area.Min.Y; y < b.Area.Max.Y; y++ { 89 | b.Set(x, y, Cell{ch, fg, bg}) 90 | } 91 | } 92 | } 93 | 94 | // NewFilledBuffer returns a new Buffer filled with ch, fb and bg. 95 | func NewFilledBuffer(x0, y0, x1, y1 int, ch rune, fg, bg Attribute) Buffer { 96 | buf := NewBuffer() 97 | buf.Area.Min = image.Pt(x0, y0) 98 | buf.Area.Max = image.Pt(x1, y1) 99 | 100 | for x := buf.Area.Min.X; x < buf.Area.Max.X; x++ { 101 | for y := buf.Area.Min.Y; y < buf.Area.Max.Y; y++ { 102 | buf.Set(x, y, Cell{ch, fg, bg}) 103 | } 104 | } 105 | return buf 106 | } 107 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/canvas.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | package termui 6 | 7 | /* 8 | dots: 9 | ,___, 10 | |1 4| 11 | |2 5| 12 | |3 6| 13 | |7 8| 14 | ````` 15 | */ 16 | 17 | var brailleBase = '\u2800' 18 | 19 | var brailleOftMap = [4][2]rune{ 20 | {'\u0001', '\u0008'}, 21 | {'\u0002', '\u0010'}, 22 | {'\u0004', '\u0020'}, 23 | {'\u0040', '\u0080'}} 24 | 25 | // Canvas contains drawing map: i,j -> rune 26 | type Canvas map[[2]int]rune 27 | 28 | // NewCanvas returns an empty Canvas 29 | func NewCanvas() Canvas { 30 | return make(map[[2]int]rune) 31 | } 32 | 33 | func chOft(x, y int) rune { 34 | return brailleOftMap[y%4][x%2] 35 | } 36 | 37 | func (c Canvas) rawCh(x, y int) rune { 38 | if ch, ok := c[[2]int{x, y}]; ok { 39 | return ch 40 | } 41 | return '\u0000' //brailleOffset 42 | } 43 | 44 | // return coordinate in terminal 45 | func chPos(x, y int) (int, int) { 46 | return y / 4, x / 2 47 | } 48 | 49 | // Set sets a point (x,y) in the virtual coordinate 50 | func (c Canvas) Set(x, y int) { 51 | i, j := chPos(x, y) 52 | ch := c.rawCh(i, j) 53 | ch |= chOft(x, y) 54 | c[[2]int{i, j}] = ch 55 | } 56 | 57 | // Unset removes point (x,y) 58 | func (c Canvas) Unset(x, y int) { 59 | i, j := chPos(x, y) 60 | ch := c.rawCh(i, j) 61 | ch &= ^chOft(x, y) 62 | c[[2]int{i, j}] = ch 63 | } 64 | 65 | // Buffer returns un-styled points 66 | func (c Canvas) Buffer() Buffer { 67 | buf := NewBuffer() 68 | for k, v := range c { 69 | buf.Set(k[0], k[1], Cell{Ch: v + brailleBase}) 70 | } 71 | return buf 72 | } 73 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | import os 5 | import io 6 | 7 | copyright = """// Copyright 2017 Zack Guo . All rights reserved. 8 | // Use of this source code is governed by a MIT license that can 9 | // be found in the LICENSE file. 10 | 11 | """ 12 | 13 | exclude_dirs = [".git", "_docs"] 14 | exclude_files = [] 15 | include_dirs = [".", "debug", "extra", "test", "_example"] 16 | 17 | 18 | def is_target(fpath): 19 | if os.path.splitext(fpath)[-1] == ".go": 20 | return True 21 | return False 22 | 23 | 24 | def update_copyright(fpath): 25 | print("processing " + fpath) 26 | f = io.open(fpath, 'r', encoding='utf-8') 27 | fstr = f.read() 28 | f.close() 29 | 30 | # remove old 31 | m = re.search('^// Copyright .+?\r?\n\r?\n', fstr, re.MULTILINE|re.DOTALL) 32 | if m: 33 | fstr = fstr[m.end():] 34 | 35 | # add new 36 | fstr = copyright + fstr 37 | f = io.open(fpath, 'w',encoding='utf-8') 38 | f.write(fstr) 39 | f.close() 40 | 41 | 42 | def main(): 43 | for d in include_dirs: 44 | files = [ 45 | os.path.join(d, f) for f in os.listdir(d) 46 | if os.path.isfile(os.path.join(d, f)) 47 | ] 48 | for f in files: 49 | if is_target(f): 50 | update_copyright(f) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | /* 6 | Package termui is a library designed for creating command line UI. For more info, goto http://github.com/gizak/termui 7 | 8 | A simplest example: 9 | package main 10 | 11 | import ui "github.com/gizak/termui" 12 | 13 | func main() { 14 | if err:=ui.Init(); err != nil { 15 | panic(err) 16 | } 17 | defer ui.Close() 18 | 19 | g := ui.NewGauge() 20 | g.Percent = 50 21 | g.Width = 50 22 | g.BorderLabel = "Gauge" 23 | 24 | ui.Render(g) 25 | 26 | ui.Loop() 27 | } 28 | */ 29 | package termui 30 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/gauge.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | package termui 6 | 7 | import ( 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | // Gauge is a progress bar like widget. 13 | // A simple example: 14 | /* 15 | g := termui.NewGauge() 16 | g.Percent = 40 17 | g.Width = 50 18 | g.Height = 3 19 | g.BorderLabel = "Slim Gauge" 20 | g.BarColor = termui.ColorRed 21 | g.PercentColor = termui.ColorBlue 22 | */ 23 | 24 | const ColorUndef Attribute = Attribute(^uint16(0)) 25 | 26 | type Gauge struct { 27 | Block 28 | Percent int 29 | BarColor Attribute 30 | PercentColor Attribute 31 | PercentColorHighlighted Attribute 32 | Label string 33 | LabelAlign Align 34 | } 35 | 36 | // NewGauge return a new gauge with current theme. 37 | func NewGauge() *Gauge { 38 | g := &Gauge{ 39 | Block: *NewBlock(), 40 | PercentColor: ThemeAttr("gauge.percent.fg"), 41 | BarColor: ThemeAttr("gauge.bar.bg"), 42 | Label: "{{percent}}%", 43 | LabelAlign: AlignCenter, 44 | PercentColorHighlighted: ColorUndef, 45 | } 46 | 47 | g.Width = 12 48 | g.Height = 5 49 | return g 50 | } 51 | 52 | // Buffer implements Bufferer interface. 53 | func (g *Gauge) Buffer() Buffer { 54 | buf := g.Block.Buffer() 55 | 56 | // plot bar 57 | w := g.Percent * g.innerArea.Dx() / 100 58 | for i := 0; i < g.innerArea.Dy(); i++ { 59 | for j := 0; j < w; j++ { 60 | c := Cell{} 61 | c.Ch = ' ' 62 | c.Bg = g.BarColor 63 | if c.Bg == ColorDefault { 64 | c.Bg |= AttrReverse 65 | } 66 | buf.Set(g.innerArea.Min.X+j, g.innerArea.Min.Y+i, c) 67 | } 68 | } 69 | 70 | // plot percentage 71 | s := strings.Replace(g.Label, "{{percent}}", strconv.Itoa(g.Percent), -1) 72 | pry := g.innerArea.Min.Y + g.innerArea.Dy()/2 73 | rs := str2runes(s) 74 | var pos int 75 | switch g.LabelAlign { 76 | case AlignLeft: 77 | pos = 0 78 | 79 | case AlignCenter: 80 | pos = (g.innerArea.Dx() - strWidth(s)) / 2 81 | 82 | case AlignRight: 83 | pos = g.innerArea.Dx() - strWidth(s) - 1 84 | } 85 | pos += g.innerArea.Min.X 86 | 87 | for i, v := range rs { 88 | c := Cell{ 89 | Ch: v, 90 | Fg: g.PercentColor, 91 | } 92 | 93 | if w+g.innerArea.Min.X > pos+i { 94 | c.Bg = g.BarColor 95 | if c.Bg == ColorDefault { 96 | c.Bg |= AttrReverse 97 | } 98 | 99 | if g.PercentColorHighlighted != ColorUndef { 100 | c.Fg = g.PercentColorHighlighted 101 | } 102 | } else { 103 | c.Bg = g.Block.Bg 104 | } 105 | 106 | buf.Set(1+pos+i, pry, c) 107 | } 108 | return buf 109 | } 110 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/glide.lock: -------------------------------------------------------------------------------- 1 | hash: 7a754ba100256404a978b2fc8738aee337beb822458e4b6060399fb89ebd215c 2 | updated: 2016-11-03T17:39:24.323773674-04:00 3 | imports: 4 | - name: github.com/maruel/panicparse 5 | version: ad661195ed0e88491e0f14be6613304e3b1141d6 6 | subpackages: 7 | - stack 8 | - name: github.com/mattn/go-runewidth 9 | version: 737072b4e32b7a5018b4a7125da8d12de90e8045 10 | - name: github.com/mitchellh/go-wordwrap 11 | version: ad45545899c7b13c020ea92b2072220eefad42b8 12 | - name: github.com/nsf/termbox-go 13 | version: b6acae516ace002cb8105a89024544a1480655a5 14 | - name: golang.org/x/net 15 | version: 569280fa63be4e201b975e5411e30a92178f0118 16 | subpackages: 17 | - websocket 18 | testImports: 19 | - name: github.com/davecgh/go-spew 20 | version: 346938d642f2ec3594ed81d874461961cd0faa76 21 | subpackages: 22 | - spew 23 | - name: github.com/pmezard/go-difflib 24 | version: d8ed2627bdf02c080bf22230dbb337003b7aba2d 25 | subpackages: 26 | - difflib 27 | - name: github.com/stretchr/testify 28 | version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506 29 | subpackages: 30 | - assert 31 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/glide.yaml: -------------------------------------------------------------------------------- 1 | package: github.com/gizak/termui 2 | import: 3 | - package: github.com/mattn/go-runewidth 4 | - package: github.com/mitchellh/go-wordwrap 5 | - package: github.com/nsf/termbox-go 6 | - package: golang.org/x/net 7 | subpackages: 8 | - websocket 9 | - package: github.com/maruel/panicparse 10 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/linechart_others.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | // +build !windows 6 | 7 | package termui 8 | 9 | const VDASH = '┊' 10 | const HDASH = '┈' 11 | const ORIGIN = '└' 12 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/linechart_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | // +build windows 6 | 7 | package termui 8 | 9 | const VDASH = '|' 10 | const HDASH = '-' 11 | const ORIGIN = '+' 12 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/list.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | package termui 6 | 7 | import "strings" 8 | 9 | // List displays []string as its items, 10 | // it has a Overflow option (default is "hidden"), when set to "hidden", 11 | // the item exceeding List's width is truncated, but when set to "wrap", 12 | // the overflowed text breaks into next line. 13 | /* 14 | strs := []string{ 15 | "[0] github.com/gizak/termui", 16 | "[1] editbox.go", 17 | "[2] interrupt.go", 18 | "[3] keyboard.go", 19 | "[4] output.go", 20 | "[5] random_out.go", 21 | "[6] dashboard.go", 22 | "[7] nsf/termbox-go"} 23 | 24 | ls := termui.NewList() 25 | ls.Items = strs 26 | ls.ItemFgColor = termui.ColorYellow 27 | ls.BorderLabel = "List" 28 | ls.Height = 7 29 | ls.Width = 25 30 | ls.Y = 0 31 | */ 32 | type List struct { 33 | Block 34 | Items []string 35 | Overflow string 36 | ItemFgColor Attribute 37 | ItemBgColor Attribute 38 | } 39 | 40 | // NewList returns a new *List with current theme. 41 | func NewList() *List { 42 | l := &List{Block: *NewBlock()} 43 | l.Overflow = "hidden" 44 | l.ItemFgColor = ThemeAttr("list.item.fg") 45 | l.ItemBgColor = ThemeAttr("list.item.bg") 46 | return l 47 | } 48 | 49 | // Buffer implements Bufferer interface. 50 | func (l *List) Buffer() Buffer { 51 | buf := l.Block.Buffer() 52 | 53 | switch l.Overflow { 54 | case "wrap": 55 | cs := DefaultTxBuilder.Build(strings.Join(l.Items, "\n"), l.ItemFgColor, l.ItemBgColor) 56 | i, j, k := 0, 0, 0 57 | for i < l.innerArea.Dy() && k < len(cs) { 58 | w := cs[k].Width() 59 | if cs[k].Ch == '\n' || j+w > l.innerArea.Dx() { 60 | i++ 61 | j = 0 62 | if cs[k].Ch == '\n' { 63 | k++ 64 | } 65 | continue 66 | } 67 | buf.Set(l.innerArea.Min.X+j, l.innerArea.Min.Y+i, cs[k]) 68 | 69 | k++ 70 | j++ 71 | } 72 | 73 | case "hidden": 74 | trimItems := l.Items 75 | if len(trimItems) > l.innerArea.Dy() { 76 | trimItems = trimItems[:l.innerArea.Dy()] 77 | } 78 | for i, v := range trimItems { 79 | cs := DTrimTxCls(DefaultTxBuilder.Build(v, l.ItemFgColor, l.ItemBgColor), l.innerArea.Dx()) 80 | j := 0 81 | for _, vv := range cs { 82 | w := vv.Width() 83 | buf.Set(l.innerArea.Min.X+j, l.innerArea.Min.Y+i, vv) 84 | j += w 85 | } 86 | } 87 | } 88 | return buf 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/mkdocs.yml: -------------------------------------------------------------------------------- 1 | pages: 2 | - Home: 'index.md' 3 | - Quickstart: 'quickstart.md' 4 | - Recipes: 'recipes.md' 5 | - References: 6 | - Layouts: 'layouts.md' 7 | - Components: 'components.md' 8 | - Events: 'events.md' 9 | - Themes: 'themes.md' 10 | - Versions: 'versions.md' 11 | - About: 'about.md' 12 | 13 | site_name: termui 14 | repo_url: https://github.com/gizak/termui/ 15 | site_description: 'termui user guide' 16 | site_author: gizak 17 | 18 | docs_dir: '_docs' 19 | 20 | theme: readthedocs 21 | 22 | markdown_extensions: 23 | - smarty 24 | - admonition 25 | - toc 26 | 27 | extra: 28 | version: 1.0 29 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/par.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | package termui 6 | 7 | // Par displays a paragraph. 8 | /* 9 | par := termui.NewPar("Simple Text") 10 | par.Height = 3 11 | par.Width = 17 12 | par.BorderLabel = "Label" 13 | */ 14 | type Par struct { 15 | Block 16 | Text string 17 | TextFgColor Attribute 18 | TextBgColor Attribute 19 | WrapLength int // words wrap limit. Note it may not work properly with multi-width char 20 | } 21 | 22 | // NewPar returns a new *Par with given text as its content. 23 | func NewPar(s string) *Par { 24 | return &Par{ 25 | Block: *NewBlock(), 26 | Text: s, 27 | TextFgColor: ThemeAttr("par.text.fg"), 28 | TextBgColor: ThemeAttr("par.text.bg"), 29 | WrapLength: 0, 30 | } 31 | } 32 | 33 | // Buffer implements Bufferer interface. 34 | func (p *Par) Buffer() Buffer { 35 | buf := p.Block.Buffer() 36 | 37 | fg, bg := p.TextFgColor, p.TextBgColor 38 | cs := DefaultTxBuilder.Build(p.Text, fg, bg) 39 | 40 | // wrap if WrapLength set 41 | if p.WrapLength < 0 { 42 | cs = wrapTx(cs, p.Width-2) 43 | } else if p.WrapLength > 0 { 44 | cs = wrapTx(cs, p.WrapLength) 45 | } 46 | 47 | y, x, n := 0, 0, 0 48 | for y < p.innerArea.Dy() && n < len(cs) { 49 | w := cs[n].Width() 50 | if cs[n].Ch == '\n' || x+w > p.innerArea.Dx() { 51 | y++ 52 | x = 0 // set x = 0 53 | if cs[n].Ch == '\n' { 54 | n++ 55 | } 56 | 57 | if y >= p.innerArea.Dy() { 58 | buf.Set(p.innerArea.Min.X+p.innerArea.Dx()-1, 59 | p.innerArea.Min.Y+p.innerArea.Dy()-1, 60 | Cell{Ch: '…', Fg: p.TextFgColor, Bg: p.TextBgColor}) 61 | break 62 | } 63 | continue 64 | } 65 | 66 | buf.Set(p.innerArea.Min.X+x, p.innerArea.Min.Y+y, cs[n]) 67 | 68 | n++ 69 | x += w 70 | } 71 | 72 | return buf 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/pos.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | package termui 6 | 7 | import "image" 8 | 9 | // Align is the position of the gauge's label. 10 | type Align uint 11 | 12 | // All supported positions. 13 | const ( 14 | AlignNone Align = 0 15 | AlignLeft Align = 1 << iota 16 | AlignRight 17 | AlignBottom 18 | AlignTop 19 | AlignCenterVertical 20 | AlignCenterHorizontal 21 | AlignCenter = AlignCenterVertical | AlignCenterHorizontal 22 | ) 23 | 24 | func AlignArea(parent, child image.Rectangle, a Align) image.Rectangle { 25 | w, h := child.Dx(), child.Dy() 26 | 27 | // parent center 28 | pcx, pcy := parent.Min.X+parent.Dx()/2, parent.Min.Y+parent.Dy()/2 29 | // child center 30 | ccx, ccy := child.Min.X+child.Dx()/2, child.Min.Y+child.Dy()/2 31 | 32 | if a&AlignLeft == AlignLeft { 33 | child.Min.X = parent.Min.X 34 | child.Max.X = child.Min.X + w 35 | } 36 | 37 | if a&AlignRight == AlignRight { 38 | child.Max.X = parent.Max.X 39 | child.Min.X = child.Max.X - w 40 | } 41 | 42 | if a&AlignBottom == AlignBottom { 43 | child.Max.Y = parent.Max.Y 44 | child.Min.Y = child.Max.Y - h 45 | } 46 | 47 | if a&AlignTop == AlignRight { 48 | child.Min.Y = parent.Min.Y 49 | child.Max.Y = child.Min.Y + h 50 | } 51 | 52 | if a&AlignCenterHorizontal == AlignCenterHorizontal { 53 | child.Min.X += pcx - ccx 54 | child.Max.X = child.Min.X + w 55 | } 56 | 57 | if a&AlignCenterVertical == AlignCenterVertical { 58 | child.Min.Y += pcy - ccy 59 | child.Max.Y = child.Min.Y + h 60 | } 61 | 62 | return child 63 | } 64 | 65 | func MoveArea(a image.Rectangle, dx, dy int) image.Rectangle { 66 | a.Min.X += dx 67 | a.Max.X += dx 68 | a.Min.Y += dy 69 | a.Max.Y += dy 70 | return a 71 | } 72 | 73 | var termWidth int 74 | var termHeight int 75 | 76 | func TermRect() image.Rectangle { 77 | return image.Rect(0, 0, termWidth, termHeight) 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/theme.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | package termui 6 | 7 | import "strings" 8 | 9 | /* 10 | // A ColorScheme represents the current look-and-feel of the dashboard. 11 | type ColorScheme struct { 12 | BodyBg Attribute 13 | BlockBg Attribute 14 | HasBorder bool 15 | BorderFg Attribute 16 | BorderBg Attribute 17 | BorderLabelTextFg Attribute 18 | BorderLabelTextBg Attribute 19 | ParTextFg Attribute 20 | ParTextBg Attribute 21 | SparklineLine Attribute 22 | SparklineTitle Attribute 23 | GaugeBar Attribute 24 | GaugePercent Attribute 25 | LineChartLine Attribute 26 | LineChartAxes Attribute 27 | ListItemFg Attribute 28 | ListItemBg Attribute 29 | BarChartBar Attribute 30 | BarChartText Attribute 31 | BarChartNum Attribute 32 | MBarChartBar Attribute 33 | MBarChartText Attribute 34 | MBarChartNum Attribute 35 | TabActiveBg Attribute 36 | } 37 | 38 | // default color scheme depends on the user's terminal setting. 39 | var themeDefault = ColorScheme{HasBorder: true} 40 | 41 | var themeHelloWorld = ColorScheme{ 42 | BodyBg: ColorBlack, 43 | BlockBg: ColorBlack, 44 | HasBorder: true, 45 | BorderFg: ColorWhite, 46 | BorderBg: ColorBlack, 47 | BorderLabelTextBg: ColorBlack, 48 | BorderLabelTextFg: ColorGreen, 49 | ParTextBg: ColorBlack, 50 | ParTextFg: ColorWhite, 51 | SparklineLine: ColorMagenta, 52 | SparklineTitle: ColorWhite, 53 | GaugeBar: ColorRed, 54 | GaugePercent: ColorWhite, 55 | LineChartLine: ColorYellow | AttrBold, 56 | LineChartAxes: ColorWhite, 57 | ListItemBg: ColorBlack, 58 | ListItemFg: ColorYellow, 59 | BarChartBar: ColorRed, 60 | BarChartNum: ColorWhite, 61 | BarChartText: ColorCyan, 62 | MBarChartBar: ColorRed, 63 | MBarChartNum: ColorWhite, 64 | MBarChartText: ColorCyan, 65 | TabActiveBg: ColorMagenta, 66 | } 67 | 68 | var theme = themeDefault // global dep 69 | 70 | // Theme returns the currently used theme. 71 | func Theme() ColorScheme { 72 | return theme 73 | } 74 | 75 | // SetTheme sets a new, custom theme. 76 | func SetTheme(newTheme ColorScheme) { 77 | theme = newTheme 78 | } 79 | 80 | // UseTheme sets a predefined scheme. Currently available: "hello-world" and 81 | // "black-and-white". 82 | func UseTheme(th string) { 83 | switch th { 84 | case "helloworld": 85 | theme = themeHelloWorld 86 | default: 87 | theme = themeDefault 88 | } 89 | } 90 | */ 91 | 92 | var ColorMap = map[string]Attribute{ 93 | "fg": ColorWhite, 94 | "bg": ColorDefault, 95 | "border.fg": ColorWhite, 96 | "label.fg": ColorGreen, 97 | "par.fg": ColorYellow, 98 | "par.label.bg": ColorWhite, 99 | } 100 | 101 | func ThemeAttr(name string) Attribute { 102 | return lookUpAttr(ColorMap, name) 103 | } 104 | 105 | func lookUpAttr(clrmap map[string]Attribute, name string) Attribute { 106 | 107 | a, ok := clrmap[name] 108 | if ok { 109 | return a 110 | } 111 | 112 | ns := strings.Split(name, ".") 113 | for i := range ns { 114 | nn := strings.Join(ns[i:len(ns)], ".") 115 | a, ok = ColorMap[nn] 116 | if ok { 117 | break 118 | } 119 | } 120 | 121 | return a 122 | } 123 | 124 | // 0<=r,g,b <= 5 125 | func ColorRGB(r, g, b int) Attribute { 126 | within := func(n int) int { 127 | if n < 0 { 128 | return 0 129 | } 130 | 131 | if n > 5 { 132 | return 5 133 | } 134 | 135 | return n 136 | } 137 | 138 | r, b, g = within(r), within(b), within(g) 139 | return Attribute(0x0f + 36*r + 6*g + b) 140 | } 141 | -------------------------------------------------------------------------------- /vendor/github.com/erroneousboat/termui/widget.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Zack Guo . All rights reserved. 2 | // Use of this source code is governed by a MIT license that can 3 | // be found in the LICENSE file. 4 | 5 | package termui 6 | 7 | import ( 8 | "fmt" 9 | "sync" 10 | ) 11 | 12 | // event mixins 13 | type WgtMgr map[string]WgtInfo 14 | 15 | type WgtInfo struct { 16 | Handlers map[string]func(Event) 17 | WgtRef Widget 18 | Id string 19 | } 20 | 21 | type Widget interface { 22 | Id() string 23 | } 24 | 25 | func NewWgtInfo(wgt Widget) WgtInfo { 26 | return WgtInfo{ 27 | Handlers: make(map[string]func(Event)), 28 | WgtRef: wgt, 29 | Id: wgt.Id(), 30 | } 31 | } 32 | 33 | func NewWgtMgr() WgtMgr { 34 | wm := WgtMgr(make(map[string]WgtInfo)) 35 | return wm 36 | 37 | } 38 | 39 | func (wm WgtMgr) AddWgt(wgt Widget) { 40 | wm[wgt.Id()] = NewWgtInfo(wgt) 41 | } 42 | 43 | func (wm WgtMgr) RmWgt(wgt Widget) { 44 | wm.RmWgtById(wgt.Id()) 45 | } 46 | 47 | func (wm WgtMgr) RmWgtById(id string) { 48 | delete(wm, id) 49 | } 50 | 51 | func (wm WgtMgr) AddWgtHandler(id, path string, h func(Event)) { 52 | if w, ok := wm[id]; ok { 53 | w.Handlers[path] = h 54 | } 55 | } 56 | 57 | func (wm WgtMgr) RmWgtHandler(id, path string) { 58 | if w, ok := wm[id]; ok { 59 | delete(w.Handlers, path) 60 | } 61 | } 62 | 63 | var counter struct { 64 | sync.RWMutex 65 | count int 66 | } 67 | 68 | func GenId() string { 69 | counter.Lock() 70 | defer counter.Unlock() 71 | 72 | counter.count += 1 73 | return fmt.Sprintf("%d", counter.count) 74 | } 75 | 76 | func (wm WgtMgr) WgtHandlersHook() func(Event) { 77 | return func(e Event) { 78 | for _, v := range wm { 79 | if k := findMatch(v.Handlers, e.Path); k != "" { 80 | v.Handlers[k](e) 81 | } 82 | } 83 | } 84 | } 85 | 86 | var DefaultWgtMgr WgtMgr 87 | 88 | func (b *Block) Handle(path string, handler func(Event)) { 89 | if _, ok := DefaultWgtMgr[b.Id()]; !ok { 90 | DefaultWgtMgr.AddWgt(b) 91 | } 92 | 93 | DefaultWgtMgr.AddWgtHandler(b.Id(), path, handler) 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | .idea/ 25 | *.iml 26 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Gorilla WebSocket authors for copyright 2 | # purposes. 3 | # 4 | # Please keep the list sorted. 5 | 6 | Gary Burd 7 | Google LLC (https://opensource.google.com/) 8 | Joachim Bauch 9 | 10 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/client_clone.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | package websocket 8 | 9 | import "crypto/tls" 10 | 11 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 12 | if cfg == nil { 13 | return &tls.Config{} 14 | } 15 | return cfg.Clone() 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/client_clone_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | package websocket 8 | 9 | import "crypto/tls" 10 | 11 | // cloneTLSConfig clones all public fields except the fields 12 | // SessionTicketsDisabled and SessionTicketKey. This avoids copying the 13 | // sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a 14 | // config in active use. 15 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 16 | if cfg == nil { 17 | return &tls.Config{} 18 | } 19 | return &tls.Config{ 20 | Rand: cfg.Rand, 21 | Time: cfg.Time, 22 | Certificates: cfg.Certificates, 23 | NameToCertificate: cfg.NameToCertificate, 24 | GetCertificate: cfg.GetCertificate, 25 | RootCAs: cfg.RootCAs, 26 | NextProtos: cfg.NextProtos, 27 | ServerName: cfg.ServerName, 28 | ClientAuth: cfg.ClientAuth, 29 | ClientCAs: cfg.ClientCAs, 30 | InsecureSkipVerify: cfg.InsecureSkipVerify, 31 | CipherSuites: cfg.CipherSuites, 32 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 33 | ClientSessionCache: cfg.ClientSessionCache, 34 | MinVersion: cfg.MinVersion, 35 | MaxVersion: cfg.MaxVersion, 36 | CurvePreferences: cfg.CurvePreferences, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/conn_write.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | package websocket 8 | 9 | import "net" 10 | 11 | func (c *Conn) writeBufs(bufs ...[]byte) error { 12 | b := net.Buffers(bufs) 13 | _, err := b.WriteTo(c.conn) 14 | return err 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/conn_write_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | package websocket 8 | 9 | func (c *Conn) writeBufs(bufs ...[]byte) error { 10 | for _, buf := range bufs { 11 | if len(buf) > 0 { 12 | if _, err := c.conn.Write(buf); err != nil { 13 | return err 14 | } 15 | } 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gorilla/websocket 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpbruinsslot/slack-term/c19c20a3e5c597d6d60582fcba1a3523415e8fe4/vendor/github.com/gorilla/websocket/go.sum -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/join.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "io" 9 | "strings" 10 | ) 11 | 12 | // JoinMessages concatenates received messages to create a single io.Reader. 13 | // The string term is appended to each message. The returned reader does not 14 | // support concurrent calls to the Read method. 15 | func JoinMessages(c *Conn, term string) io.Reader { 16 | return &joinReader{c: c, term: term} 17 | } 18 | 19 | type joinReader struct { 20 | c *Conn 21 | term string 22 | r io.Reader 23 | } 24 | 25 | func (r *joinReader) Read(p []byte) (int, error) { 26 | if r.r == nil { 27 | var err error 28 | _, r.r, err = r.c.NextReader() 29 | if err != nil { 30 | return 0, err 31 | } 32 | if r.term != "" { 33 | r.r = io.MultiReader(r.r, strings.NewReader(r.term)) 34 | } 35 | } 36 | n, err := r.r.Read(p) 37 | if err == io.EOF { 38 | err = nil 39 | r.r = nil 40 | } 41 | return n, err 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "encoding/json" 9 | "io" 10 | ) 11 | 12 | // WriteJSON writes the JSON encoding of v as a message. 13 | // 14 | // Deprecated: Use c.WriteJSON instead. 15 | func WriteJSON(c *Conn, v interface{}) error { 16 | return c.WriteJSON(v) 17 | } 18 | 19 | // WriteJSON writes the JSON encoding of v as a message. 20 | // 21 | // See the documentation for encoding/json Marshal for details about the 22 | // conversion of Go values to JSON. 23 | func (c *Conn) WriteJSON(v interface{}) error { 24 | w, err := c.NextWriter(TextMessage) 25 | if err != nil { 26 | return err 27 | } 28 | err1 := json.NewEncoder(w).Encode(v) 29 | err2 := w.Close() 30 | if err1 != nil { 31 | return err1 32 | } 33 | return err2 34 | } 35 | 36 | // ReadJSON reads the next JSON-encoded message from the connection and stores 37 | // it in the value pointed to by v. 38 | // 39 | // Deprecated: Use c.ReadJSON instead. 40 | func ReadJSON(c *Conn, v interface{}) error { 41 | return c.ReadJSON(v) 42 | } 43 | 44 | // ReadJSON reads the next JSON-encoded message from the connection and stores 45 | // it in the value pointed to by v. 46 | // 47 | // See the documentation for the encoding/json Unmarshal function for details 48 | // about the conversion of JSON to a Go value. 49 | func (c *Conn) ReadJSON(v interface{}) error { 50 | _, r, err := c.NextReader() 51 | if err != nil { 52 | return err 53 | } 54 | err = json.NewDecoder(r).Decode(v) 55 | if err == io.EOF { 56 | // One value is expected in the message. 57 | err = io.ErrUnexpectedEOF 58 | } 59 | return err 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/mask.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build !appengine 6 | 7 | package websocket 8 | 9 | import "unsafe" 10 | 11 | const wordSize = int(unsafe.Sizeof(uintptr(0))) 12 | 13 | func maskBytes(key [4]byte, pos int, b []byte) int { 14 | // Mask one byte at a time for small buffers. 15 | if len(b) < 2*wordSize { 16 | for i := range b { 17 | b[i] ^= key[pos&3] 18 | pos++ 19 | } 20 | return pos & 3 21 | } 22 | 23 | // Mask one byte at a time to word boundary. 24 | if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 { 25 | n = wordSize - n 26 | for i := range b[:n] { 27 | b[i] ^= key[pos&3] 28 | pos++ 29 | } 30 | b = b[n:] 31 | } 32 | 33 | // Create aligned word size key. 34 | var k [wordSize]byte 35 | for i := range k { 36 | k[i] = key[(pos+i)&3] 37 | } 38 | kw := *(*uintptr)(unsafe.Pointer(&k)) 39 | 40 | // Mask one word at a time. 41 | n := (len(b) / wordSize) * wordSize 42 | for i := 0; i < n; i += wordSize { 43 | *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw 44 | } 45 | 46 | // Mask one byte at a time for remaining bytes. 47 | b = b[n:] 48 | for i := range b { 49 | b[i] ^= key[pos&3] 50 | pos++ 51 | } 52 | 53 | return pos & 3 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/mask_safe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build appengine 6 | 7 | package websocket 8 | 9 | func maskBytes(key [4]byte, pos int, b []byte) int { 10 | for i := range b { 11 | b[i] ^= key[pos&3] 12 | pos++ 13 | } 14 | return pos & 3 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/prepared.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bytes" 9 | "net" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | // PreparedMessage caches on the wire representations of a message payload. 15 | // Use PreparedMessage to efficiently send a message payload to multiple 16 | // connections. PreparedMessage is especially useful when compression is used 17 | // because the CPU and memory expensive compression operation can be executed 18 | // once for a given set of compression options. 19 | type PreparedMessage struct { 20 | messageType int 21 | data []byte 22 | mu sync.Mutex 23 | frames map[prepareKey]*preparedFrame 24 | } 25 | 26 | // prepareKey defines a unique set of options to cache prepared frames in PreparedMessage. 27 | type prepareKey struct { 28 | isServer bool 29 | compress bool 30 | compressionLevel int 31 | } 32 | 33 | // preparedFrame contains data in wire representation. 34 | type preparedFrame struct { 35 | once sync.Once 36 | data []byte 37 | } 38 | 39 | // NewPreparedMessage returns an initialized PreparedMessage. You can then send 40 | // it to connection using WritePreparedMessage method. Valid wire 41 | // representation will be calculated lazily only once for a set of current 42 | // connection options. 43 | func NewPreparedMessage(messageType int, data []byte) (*PreparedMessage, error) { 44 | pm := &PreparedMessage{ 45 | messageType: messageType, 46 | frames: make(map[prepareKey]*preparedFrame), 47 | data: data, 48 | } 49 | 50 | // Prepare a plain server frame. 51 | _, frameData, err := pm.frame(prepareKey{isServer: true, compress: false}) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | // To protect against caller modifying the data argument, remember the data 57 | // copied to the plain server frame. 58 | pm.data = frameData[len(frameData)-len(data):] 59 | return pm, nil 60 | } 61 | 62 | func (pm *PreparedMessage) frame(key prepareKey) (int, []byte, error) { 63 | pm.mu.Lock() 64 | frame, ok := pm.frames[key] 65 | if !ok { 66 | frame = &preparedFrame{} 67 | pm.frames[key] = frame 68 | } 69 | pm.mu.Unlock() 70 | 71 | var err error 72 | frame.once.Do(func() { 73 | // Prepare a frame using a 'fake' connection. 74 | // TODO: Refactor code in conn.go to allow more direct construction of 75 | // the frame. 76 | mu := make(chan struct{}, 1) 77 | mu <- struct{}{} 78 | var nc prepareConn 79 | c := &Conn{ 80 | conn: &nc, 81 | mu: mu, 82 | isServer: key.isServer, 83 | compressionLevel: key.compressionLevel, 84 | enableWriteCompression: true, 85 | writeBuf: make([]byte, defaultWriteBufferSize+maxFrameHeaderSize), 86 | } 87 | if key.compress { 88 | c.newCompressionWriter = compressNoContextTakeover 89 | } 90 | err = c.WriteMessage(pm.messageType, pm.data) 91 | frame.data = nc.buf.Bytes() 92 | }) 93 | return pm.messageType, frame.data, err 94 | } 95 | 96 | type prepareConn struct { 97 | buf bytes.Buffer 98 | net.Conn 99 | } 100 | 101 | func (pc *prepareConn) Write(p []byte) (int, error) { return pc.buf.Write(p) } 102 | func (pc *prepareConn) SetWriteDeadline(t time.Time) error { return nil } 103 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/proxy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bufio" 9 | "encoding/base64" 10 | "errors" 11 | "net" 12 | "net/http" 13 | "net/url" 14 | "strings" 15 | ) 16 | 17 | type netDialerFunc func(network, addr string) (net.Conn, error) 18 | 19 | func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) { 20 | return fn(network, addr) 21 | } 22 | 23 | func init() { 24 | proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) { 25 | return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil 26 | }) 27 | } 28 | 29 | type httpProxyDialer struct { 30 | proxyURL *url.URL 31 | forwardDial func(network, addr string) (net.Conn, error) 32 | } 33 | 34 | func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) { 35 | hostPort, _ := hostPortNoPort(hpd.proxyURL) 36 | conn, err := hpd.forwardDial(network, hostPort) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | connectHeader := make(http.Header) 42 | if user := hpd.proxyURL.User; user != nil { 43 | proxyUser := user.Username() 44 | if proxyPassword, passwordSet := user.Password(); passwordSet { 45 | credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword)) 46 | connectHeader.Set("Proxy-Authorization", "Basic "+credential) 47 | } 48 | } 49 | 50 | connectReq := &http.Request{ 51 | Method: "CONNECT", 52 | URL: &url.URL{Opaque: addr}, 53 | Host: addr, 54 | Header: connectHeader, 55 | } 56 | 57 | if err := connectReq.Write(conn); err != nil { 58 | conn.Close() 59 | return nil, err 60 | } 61 | 62 | // Read response. It's OK to use and discard buffered reader here becaue 63 | // the remote server does not speak until spoken to. 64 | br := bufio.NewReader(conn) 65 | resp, err := http.ReadResponse(br, connectReq) 66 | if err != nil { 67 | conn.Close() 68 | return nil, err 69 | } 70 | 71 | if resp.StatusCode != 200 { 72 | conn.Close() 73 | f := strings.SplitN(resp.Status, " ", 2) 74 | return nil, errors.New(f[1]) 75 | } 76 | return conn, nil 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/trace.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package websocket 4 | 5 | import ( 6 | "crypto/tls" 7 | "net/http/httptrace" 8 | ) 9 | 10 | func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { 11 | if trace.TLSHandshakeStart != nil { 12 | trace.TLSHandshakeStart() 13 | } 14 | err := doHandshake(tlsConn, cfg) 15 | if trace.TLSHandshakeDone != nil { 16 | trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) 17 | } 18 | return err 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/trace_17.go: -------------------------------------------------------------------------------- 1 | // +build !go1.8 2 | 3 | package websocket 4 | 5 | import ( 6 | "crypto/tls" 7 | "net/http/httptrace" 8 | ) 9 | 10 | func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { 11 | return doHandshake(tlsConn, cfg) 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/lithammer/fuzzysearch/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Peter Lithammer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/lithammer/fuzzysearch/fuzzy/levenshtein.go: -------------------------------------------------------------------------------- 1 | package fuzzy 2 | 3 | // LevenshteinDistance measures the difference between two strings. 4 | // The Levenshtein distance between two words is the minimum number of 5 | // single-character edits (i.e. insertions, deletions or substitutions) 6 | // required to change one word into the other. 7 | // 8 | // This implemention is optimized to use O(min(m,n)) space and is based on the 9 | // optimized C version found here: 10 | // http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#C 11 | func LevenshteinDistance(s, t string) int { 12 | r1, r2 := []rune(s), []rune(t) 13 | column := make([]int, len(r1)+1) 14 | 15 | for y := 1; y <= len(r1); y++ { 16 | column[y] = y 17 | } 18 | 19 | for x := 1; x <= len(r2); x++ { 20 | column[0] = x 21 | 22 | for y, lastDiag := 1, x-1; y <= len(r1); y++ { 23 | oldDiag := column[y] 24 | cost := 0 25 | if r1[y-1] != r2[x-1] { 26 | cost = 1 27 | } 28 | column[y] = min(column[y]+1, column[y-1]+1, lastDiag+cost) 29 | lastDiag = oldDiag 30 | } 31 | } 32 | 33 | return column[len(r1)] 34 | } 35 | 36 | func min(a, b, c int) int { 37 | if a < b && a < c { 38 | return a 39 | } else if b < c { 40 | return b 41 | } 42 | return c 43 | } 44 | -------------------------------------------------------------------------------- /vendor/github.com/maruel/panicparse/stack/bucket.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Marc-Antoine Ruel. All rights reserved. 2 | // Use of this source code is governed under the Apache License, Version 2.0 3 | // that can be found in the LICENSE file. 4 | 5 | package stack 6 | 7 | import ( 8 | "sort" 9 | ) 10 | 11 | // Similarity is the level at which two call lines arguments must match to be 12 | // considered similar enough to coalesce them. 13 | type Similarity int 14 | 15 | const ( 16 | // ExactFlags requires same bits (e.g. Locked). 17 | ExactFlags Similarity = iota 18 | // ExactLines requests the exact same arguments on the call line. 19 | ExactLines 20 | // AnyPointer considers different pointers a similar call line. 21 | AnyPointer 22 | // AnyValue accepts any value as similar call line. 23 | AnyValue 24 | ) 25 | 26 | // Bucketize returns the number of similar goroutines. 27 | func Bucketize(goroutines []Goroutine, similar Similarity) map[*Signature][]Goroutine { 28 | out := map[*Signature][]Goroutine{} 29 | // O(n²). Fix eventually. 30 | for _, routine := range goroutines { 31 | found := false 32 | for key := range out { 33 | // When a match is found, this effectively drops the other goroutine ID. 34 | if key.Similar(&routine.Signature, similar) { 35 | found = true 36 | if !key.Equal(&routine.Signature) { 37 | // Almost but not quite equal. There's different pointers passed 38 | // around but the same values. Zap out the different values. 39 | newKey := key.Merge(&routine.Signature) 40 | out[newKey] = append(out[key], routine) 41 | delete(out, key) 42 | } else { 43 | out[key] = append(out[key], routine) 44 | } 45 | break 46 | } 47 | } 48 | if !found { 49 | key := &Signature{} 50 | *key = routine.Signature 51 | out[key] = []Goroutine{routine} 52 | } 53 | } 54 | return out 55 | } 56 | 57 | // Bucket is a stack trace signature and the list of goroutines that fits this 58 | // signature. 59 | type Bucket struct { 60 | Signature 61 | Routines []Goroutine 62 | } 63 | 64 | // First returns true if it contains the first goroutine, e.g. the ones that 65 | // likely generated the panic() call, if any. 66 | func (b *Bucket) First() bool { 67 | for _, r := range b.Routines { 68 | if r.First { 69 | return true 70 | } 71 | } 72 | return false 73 | } 74 | 75 | // Less does reverse sort. 76 | func (b *Bucket) Less(r *Bucket) bool { 77 | if b.First() { 78 | return true 79 | } 80 | if r.First() { 81 | return false 82 | } 83 | return b.Signature.Less(&r.Signature) 84 | } 85 | 86 | // Buckets is a list of Bucket sorted by repeation count. 87 | type Buckets []Bucket 88 | 89 | func (b Buckets) Len() int { 90 | return len(b) 91 | } 92 | 93 | func (b Buckets) Less(i, j int) bool { 94 | return b[i].Less(&b[j]) 95 | } 96 | 97 | func (b Buckets) Swap(i, j int) { 98 | b[j], b[i] = b[i], b[j] 99 | } 100 | 101 | // SortBuckets creates a list of Bucket from each goroutine stack trace count. 102 | func SortBuckets(buckets map[*Signature][]Goroutine) Buckets { 103 | out := make(Buckets, 0, len(buckets)) 104 | for signature, count := range buckets { 105 | out = append(out, Bucket{*signature, count}) 106 | } 107 | sort.Sort(out) 108 | return out 109 | } 110 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - tip 4 | before_install: 5 | - go get github.com/mattn/goveralls 6 | - go get golang.org/x/tools/cmd/cover 7 | script: 8 | - $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL 9 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yasuhiro Matsumoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/README.mkd: -------------------------------------------------------------------------------- 1 | go-runewidth 2 | ============ 3 | 4 | [![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) 5 | [![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD) 6 | [![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) 7 | [![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth) 8 | 9 | Provides functions to get fixed width of the character or string. 10 | 11 | Usage 12 | ----- 13 | 14 | ```go 15 | runewidth.StringWidth("つのだ☆HIRO") == 12 16 | ``` 17 | 18 | 19 | Author 20 | ------ 21 | 22 | Yasuhiro Matsumoto 23 | 24 | License 25 | ------- 26 | 27 | under the MIT License: http://mattn.mit-license.org/2013 28 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mattn/go-runewidth 2 | 3 | go 1.9 4 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_appengine.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package runewidth 4 | 5 | // IsEastAsian return true if the current locale is CJK 6 | func IsEastAsian() bool { 7 | return false 8 | } 9 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !appengine 3 | 4 | package runewidth 5 | 6 | func IsEastAsian() bool { 7 | // TODO: Implement this for the web. Detect east asian in a compatible way, and return true. 8 | return false 9 | } 10 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_posix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | // +build !js 3 | // +build !appengine 4 | 5 | package runewidth 6 | 7 | import ( 8 | "os" 9 | "regexp" 10 | "strings" 11 | ) 12 | 13 | var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) 14 | 15 | var mblenTable = map[string]int{ 16 | "utf-8": 6, 17 | "utf8": 6, 18 | "jis": 8, 19 | "eucjp": 3, 20 | "euckr": 2, 21 | "euccn": 2, 22 | "sjis": 2, 23 | "cp932": 2, 24 | "cp51932": 2, 25 | "cp936": 2, 26 | "cp949": 2, 27 | "cp950": 2, 28 | "big5": 2, 29 | "gbk": 2, 30 | "gb2312": 2, 31 | } 32 | 33 | func isEastAsian(locale string) bool { 34 | charset := strings.ToLower(locale) 35 | r := reLoc.FindStringSubmatch(locale) 36 | if len(r) == 2 { 37 | charset = strings.ToLower(r[1]) 38 | } 39 | 40 | if strings.HasSuffix(charset, "@cjk_narrow") { 41 | return false 42 | } 43 | 44 | for pos, b := range []byte(charset) { 45 | if b == '@' { 46 | charset = charset[:pos] 47 | break 48 | } 49 | } 50 | max := 1 51 | if m, ok := mblenTable[charset]; ok { 52 | max = m 53 | } 54 | if max > 1 && (charset[0] != 'u' || 55 | strings.HasPrefix(locale, "ja") || 56 | strings.HasPrefix(locale, "ko") || 57 | strings.HasPrefix(locale, "zh")) { 58 | return true 59 | } 60 | return false 61 | } 62 | 63 | // IsEastAsian return true if the current locale is CJK 64 | func IsEastAsian() bool { 65 | locale := os.Getenv("LC_CTYPE") 66 | if locale == "" { 67 | locale = os.Getenv("LANG") 68 | } 69 | 70 | // ignore C locale 71 | if locale == "POSIX" || locale == "C" { 72 | return false 73 | } 74 | if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { 75 | return false 76 | } 77 | 78 | return isEastAsian(locale) 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | // +build !appengine 3 | 4 | package runewidth 5 | 6 | import ( 7 | "syscall" 8 | ) 9 | 10 | var ( 11 | kernel32 = syscall.NewLazyDLL("kernel32") 12 | procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") 13 | ) 14 | 15 | // IsEastAsian return true if the current locale is CJK 16 | func IsEastAsian() bool { 17 | r1, _, _ := procGetConsoleOutputCP.Call() 18 | if r1 == 0 { 19 | return false 20 | } 21 | 22 | switch int(r1) { 23 | case 932, 51932, 936, 949, 950: 24 | return true 25 | } 26 | 27 | return false 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-wordwrap/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Mitchell Hashimoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-wordwrap/README.md: -------------------------------------------------------------------------------- 1 | # go-wordwrap 2 | 3 | `go-wordwrap` (Golang package: `wordwrap`) is a package for Go that 4 | automatically wraps words into multiple lines. The primary use case for this 5 | is in formatting CLI output, but of course word wrapping is a generally useful 6 | thing to do. 7 | 8 | ## Installation and Usage 9 | 10 | Install using `go get github.com/mitchellh/go-wordwrap`. 11 | 12 | Full documentation is available at 13 | http://godoc.org/github.com/mitchellh/go-wordwrap 14 | 15 | Below is an example of its usage ignoring errors: 16 | 17 | ```go 18 | wrapped := wordwrap.WrapString("foo bar baz", 3) 19 | fmt.Println(wrapped) 20 | ``` 21 | 22 | Would output: 23 | 24 | ``` 25 | foo 26 | bar 27 | baz 28 | ``` 29 | 30 | ## Word Wrap Algorithm 31 | 32 | This library doesn't use any clever algorithm for word wrapping. The wrapping 33 | is actually very naive: whenever there is whitespace or an explicit linebreak. 34 | The goal of this library is for word wrapping CLI output, so the input is 35 | typically pretty well controlled human language. Because of this, the naive 36 | approach typically works just fine. 37 | 38 | In the future, we'd like to make the algorithm more advanced. We would do 39 | so without breaking the API. 40 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-wordwrap/wordwrap.go: -------------------------------------------------------------------------------- 1 | package wordwrap 2 | 3 | import ( 4 | "bytes" 5 | "unicode" 6 | ) 7 | 8 | // WrapString wraps the given string within lim width in characters. 9 | // 10 | // Wrapping is currently naive and only happens at white-space. A future 11 | // version of the library will implement smarter wrapping. This means that 12 | // pathological cases can dramatically reach past the limit, such as a very 13 | // long word. 14 | func WrapString(s string, lim uint) string { 15 | // Initialize a buffer with a slightly larger size to account for breaks 16 | init := make([]byte, 0, len(s)) 17 | buf := bytes.NewBuffer(init) 18 | 19 | var current uint 20 | var wordBuf, spaceBuf bytes.Buffer 21 | 22 | for _, char := range s { 23 | if char == '\n' { 24 | if wordBuf.Len() == 0 { 25 | if current+uint(spaceBuf.Len()) > lim { 26 | current = 0 27 | } else { 28 | current += uint(spaceBuf.Len()) 29 | spaceBuf.WriteTo(buf) 30 | } 31 | spaceBuf.Reset() 32 | } else { 33 | current += uint(spaceBuf.Len() + wordBuf.Len()) 34 | spaceBuf.WriteTo(buf) 35 | spaceBuf.Reset() 36 | wordBuf.WriteTo(buf) 37 | wordBuf.Reset() 38 | } 39 | buf.WriteRune(char) 40 | current = 0 41 | } else if unicode.IsSpace(char) { 42 | if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { 43 | current += uint(spaceBuf.Len() + wordBuf.Len()) 44 | spaceBuf.WriteTo(buf) 45 | spaceBuf.Reset() 46 | wordBuf.WriteTo(buf) 47 | wordBuf.Reset() 48 | } 49 | 50 | spaceBuf.WriteRune(char) 51 | } else { 52 | 53 | wordBuf.WriteRune(char) 54 | 55 | if current+uint(spaceBuf.Len()+wordBuf.Len()) > lim && uint(wordBuf.Len()) < lim { 56 | buf.WriteRune('\n') 57 | current = 0 58 | spaceBuf.Reset() 59 | } 60 | } 61 | } 62 | 63 | if wordBuf.Len() == 0 { 64 | if current+uint(spaceBuf.Len()) <= lim { 65 | spaceBuf.WriteTo(buf) 66 | } 67 | } else { 68 | spaceBuf.WriteTo(buf) 69 | wordBuf.WriteTo(buf) 70 | } 71 | 72 | return buf.String() 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/AUTHORS: -------------------------------------------------------------------------------- 1 | # Please keep this file sorted. 2 | 3 | Georg Reinke 4 | nsf 5 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 termbox-go authors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/collect_terminfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, os, subprocess 4 | 5 | def escaped(s): 6 | return repr(s)[1:-1] 7 | 8 | def tput(term, name): 9 | try: 10 | return subprocess.check_output(['tput', '-T%s' % term, name]).decode() 11 | except subprocess.CalledProcessError as e: 12 | return e.output.decode() 13 | 14 | 15 | def w(s): 16 | if s == None: 17 | return 18 | sys.stdout.write(s) 19 | 20 | terminals = { 21 | 'xterm' : 'xterm', 22 | 'rxvt-256color' : 'rxvt_256color', 23 | 'rxvt-unicode' : 'rxvt_unicode', 24 | 'linux' : 'linux', 25 | 'Eterm' : 'eterm', 26 | 'screen' : 'screen' 27 | } 28 | 29 | keys = [ 30 | "F1", "kf1", 31 | "F2", "kf2", 32 | "F3", "kf3", 33 | "F4", "kf4", 34 | "F5", "kf5", 35 | "F6", "kf6", 36 | "F7", "kf7", 37 | "F8", "kf8", 38 | "F9", "kf9", 39 | "F10", "kf10", 40 | "F11", "kf11", 41 | "F12", "kf12", 42 | "INSERT", "kich1", 43 | "DELETE", "kdch1", 44 | "HOME", "khome", 45 | "END", "kend", 46 | "PGUP", "kpp", 47 | "PGDN", "knp", 48 | "KEY_UP", "kcuu1", 49 | "KEY_DOWN", "kcud1", 50 | "KEY_LEFT", "kcub1", 51 | "KEY_RIGHT", "kcuf1" 52 | ] 53 | 54 | funcs = [ 55 | "T_ENTER_CA", "smcup", 56 | "T_EXIT_CA", "rmcup", 57 | "T_SHOW_CURSOR", "cnorm", 58 | "T_HIDE_CURSOR", "civis", 59 | "T_CLEAR_SCREEN", "clear", 60 | "T_SGR0", "sgr0", 61 | "T_UNDERLINE", "smul", 62 | "T_BOLD", "bold", 63 | "T_BLINK", "blink", 64 | "T_REVERSE", "rev", 65 | "T_ENTER_KEYPAD", "smkx", 66 | "T_EXIT_KEYPAD", "rmkx" 67 | ] 68 | 69 | def iter_pairs(iterable): 70 | iterable = iter(iterable) 71 | while True: 72 | yield (next(iterable), next(iterable)) 73 | 74 | def do_term(term, nick): 75 | w("// %s\n" % term) 76 | w("var %s_keys = []string{\n\t" % nick) 77 | for k, v in iter_pairs(keys): 78 | w('"') 79 | w(escaped(tput(term, v))) 80 | w('",') 81 | w("\n}\n") 82 | w("var %s_funcs = []string{\n\t" % nick) 83 | for k,v in iter_pairs(funcs): 84 | w('"') 85 | if v == "sgr": 86 | w("\\033[3%d;4%dm") 87 | elif v == "cup": 88 | w("\\033[%d;%dH") 89 | else: 90 | w(escaped(tput(term, v))) 91 | w('", ') 92 | w("\n}\n\n") 93 | 94 | def do_terms(d): 95 | w("var terms = []struct {\n") 96 | w("\tname string\n") 97 | w("\tkeys []string\n") 98 | w("\tfuncs []string\n") 99 | w("}{\n") 100 | for k, v in d.items(): 101 | w('\t{"%s", %s_keys, %s_funcs},\n' % (k, v, v)) 102 | w("}\n\n") 103 | 104 | w("// +build !windows\n\npackage termbox\n\n") 105 | 106 | for k,v in terminals.items(): 107 | do_term(k, v) 108 | 109 | do_terms(terminals) 110 | 111 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/escwait.go: -------------------------------------------------------------------------------- 1 | // +build !darwin 2 | 3 | package termbox 4 | 5 | // On all systems other than macOS, disable behavior which will wait before 6 | // deciding that the escape key was pressed, to account for partially send 7 | // escape sequences, especially with regard to lengthy mouse sequences. 8 | // See https://github.com/nsf/termbox-go/issues/132 9 | func enable_wait_for_escape_sequence() bool { 10 | return false 11 | } 12 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/escwait_darwin.go: -------------------------------------------------------------------------------- 1 | package termbox 2 | 3 | // On macOS, enable behavior which will wait before deciding that the escape 4 | // key was pressed, to account for partially send escape sequences, especially 5 | // with regard to lengthy mouse sequences. 6 | // See https://github.com/nsf/termbox-go/issues/132 7 | func enable_wait_for_escape_sequence() bool { 8 | return true 9 | } 10 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_darwin.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | // +build !amd64 5 | 6 | package termbox 7 | 8 | type syscall_Termios struct { 9 | Iflag uint32 10 | Oflag uint32 11 | Cflag uint32 12 | Lflag uint32 13 | Cc [20]uint8 14 | Ispeed uint32 15 | Ospeed uint32 16 | } 17 | 18 | const ( 19 | syscall_IGNBRK = 0x1 20 | syscall_BRKINT = 0x2 21 | syscall_PARMRK = 0x8 22 | syscall_ISTRIP = 0x20 23 | syscall_INLCR = 0x40 24 | syscall_IGNCR = 0x80 25 | syscall_ICRNL = 0x100 26 | syscall_IXON = 0x200 27 | syscall_OPOST = 0x1 28 | syscall_ECHO = 0x8 29 | syscall_ECHONL = 0x10 30 | syscall_ICANON = 0x100 31 | syscall_ISIG = 0x80 32 | syscall_IEXTEN = 0x400 33 | syscall_CSIZE = 0x300 34 | syscall_PARENB = 0x1000 35 | syscall_CS8 = 0x300 36 | syscall_VMIN = 0x10 37 | syscall_VTIME = 0x11 38 | 39 | syscall_TCGETS = 0x402c7413 40 | syscall_TCSETS = 0x802c7414 41 | ) 42 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_darwin_amd64.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint64 8 | Oflag uint64 9 | Cflag uint64 10 | Lflag uint64 11 | Cc [20]uint8 12 | Pad_cgo_0 [4]byte 13 | Ispeed uint64 14 | Ospeed uint64 15 | } 16 | 17 | const ( 18 | syscall_IGNBRK = 0x1 19 | syscall_BRKINT = 0x2 20 | syscall_PARMRK = 0x8 21 | syscall_ISTRIP = 0x20 22 | syscall_INLCR = 0x40 23 | syscall_IGNCR = 0x80 24 | syscall_ICRNL = 0x100 25 | syscall_IXON = 0x200 26 | syscall_OPOST = 0x1 27 | syscall_ECHO = 0x8 28 | syscall_ECHONL = 0x10 29 | syscall_ICANON = 0x100 30 | syscall_ISIG = 0x80 31 | syscall_IEXTEN = 0x400 32 | syscall_CSIZE = 0x300 33 | syscall_PARENB = 0x1000 34 | syscall_CS8 = 0x300 35 | syscall_VMIN = 0x10 36 | syscall_VTIME = 0x11 37 | 38 | syscall_TCGETS = 0x40487413 39 | syscall_TCSETS = 0x80487414 40 | ) 41 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_dragonfly.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint32 8 | Oflag uint32 9 | Cflag uint32 10 | Lflag uint32 11 | Cc [20]uint8 12 | Ispeed uint32 13 | Ospeed uint32 14 | } 15 | 16 | const ( 17 | syscall_IGNBRK = 0x1 18 | syscall_BRKINT = 0x2 19 | syscall_PARMRK = 0x8 20 | syscall_ISTRIP = 0x20 21 | syscall_INLCR = 0x40 22 | syscall_IGNCR = 0x80 23 | syscall_ICRNL = 0x100 24 | syscall_IXON = 0x200 25 | syscall_OPOST = 0x1 26 | syscall_ECHO = 0x8 27 | syscall_ECHONL = 0x10 28 | syscall_ICANON = 0x100 29 | syscall_ISIG = 0x80 30 | syscall_IEXTEN = 0x400 31 | syscall_CSIZE = 0x300 32 | syscall_PARENB = 0x1000 33 | syscall_CS8 = 0x300 34 | syscall_VMIN = 0x10 35 | syscall_VTIME = 0x11 36 | 37 | syscall_TCGETS = 0x402c7413 38 | syscall_TCSETS = 0x802c7414 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_freebsd.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint32 8 | Oflag uint32 9 | Cflag uint32 10 | Lflag uint32 11 | Cc [20]uint8 12 | Ispeed uint32 13 | Ospeed uint32 14 | } 15 | 16 | const ( 17 | syscall_IGNBRK = 0x1 18 | syscall_BRKINT = 0x2 19 | syscall_PARMRK = 0x8 20 | syscall_ISTRIP = 0x20 21 | syscall_INLCR = 0x40 22 | syscall_IGNCR = 0x80 23 | syscall_ICRNL = 0x100 24 | syscall_IXON = 0x200 25 | syscall_OPOST = 0x1 26 | syscall_ECHO = 0x8 27 | syscall_ECHONL = 0x10 28 | syscall_ICANON = 0x100 29 | syscall_ISIG = 0x80 30 | syscall_IEXTEN = 0x400 31 | syscall_CSIZE = 0x300 32 | syscall_PARENB = 0x1000 33 | syscall_CS8 = 0x300 34 | syscall_VMIN = 0x10 35 | syscall_VTIME = 0x11 36 | 37 | syscall_TCGETS = 0x402c7413 38 | syscall_TCSETS = 0x802c7414 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_linux.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | import "syscall" 7 | 8 | type syscall_Termios syscall.Termios 9 | 10 | const ( 11 | syscall_IGNBRK = syscall.IGNBRK 12 | syscall_BRKINT = syscall.BRKINT 13 | syscall_PARMRK = syscall.PARMRK 14 | syscall_ISTRIP = syscall.ISTRIP 15 | syscall_INLCR = syscall.INLCR 16 | syscall_IGNCR = syscall.IGNCR 17 | syscall_ICRNL = syscall.ICRNL 18 | syscall_IXON = syscall.IXON 19 | syscall_OPOST = syscall.OPOST 20 | syscall_ECHO = syscall.ECHO 21 | syscall_ECHONL = syscall.ECHONL 22 | syscall_ICANON = syscall.ICANON 23 | syscall_ISIG = syscall.ISIG 24 | syscall_IEXTEN = syscall.IEXTEN 25 | syscall_CSIZE = syscall.CSIZE 26 | syscall_PARENB = syscall.PARENB 27 | syscall_CS8 = syscall.CS8 28 | syscall_VMIN = syscall.VMIN 29 | syscall_VTIME = syscall.VTIME 30 | 31 | syscall_TCGETS = syscall.TCGETS 32 | syscall_TCSETS = syscall.TCSETS 33 | ) 34 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_netbsd.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint32 8 | Oflag uint32 9 | Cflag uint32 10 | Lflag uint32 11 | Cc [20]uint8 12 | Ispeed int32 13 | Ospeed int32 14 | } 15 | 16 | const ( 17 | syscall_IGNBRK = 0x1 18 | syscall_BRKINT = 0x2 19 | syscall_PARMRK = 0x8 20 | syscall_ISTRIP = 0x20 21 | syscall_INLCR = 0x40 22 | syscall_IGNCR = 0x80 23 | syscall_ICRNL = 0x100 24 | syscall_IXON = 0x200 25 | syscall_OPOST = 0x1 26 | syscall_ECHO = 0x8 27 | syscall_ECHONL = 0x10 28 | syscall_ICANON = 0x100 29 | syscall_ISIG = 0x80 30 | syscall_IEXTEN = 0x400 31 | syscall_CSIZE = 0x300 32 | syscall_PARENB = 0x1000 33 | syscall_CS8 = 0x300 34 | syscall_VMIN = 0x10 35 | syscall_VTIME = 0x11 36 | 37 | syscall_TCGETS = 0x402c7413 38 | syscall_TCSETS = 0x802c7414 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_openbsd.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint32 8 | Oflag uint32 9 | Cflag uint32 10 | Lflag uint32 11 | Cc [20]uint8 12 | Ispeed int32 13 | Ospeed int32 14 | } 15 | 16 | const ( 17 | syscall_IGNBRK = 0x1 18 | syscall_BRKINT = 0x2 19 | syscall_PARMRK = 0x8 20 | syscall_ISTRIP = 0x20 21 | syscall_INLCR = 0x40 22 | syscall_IGNCR = 0x80 23 | syscall_ICRNL = 0x100 24 | syscall_IXON = 0x200 25 | syscall_OPOST = 0x1 26 | syscall_ECHO = 0x8 27 | syscall_ECHONL = 0x10 28 | syscall_ICANON = 0x100 29 | syscall_ISIG = 0x80 30 | syscall_IEXTEN = 0x400 31 | syscall_CSIZE = 0x300 32 | syscall_PARENB = 0x1000 33 | syscall_CS8 = 0x300 34 | syscall_VMIN = 0x10 35 | syscall_VTIME = 0x11 36 | 37 | syscall_TCGETS = 0x402c7413 38 | syscall_TCSETS = 0x802c7414 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_windows.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs -- -DUNICODE syscalls.go 3 | 4 | package termbox 5 | 6 | const ( 7 | foreground_blue = 0x1 8 | foreground_green = 0x2 9 | foreground_red = 0x4 10 | foreground_intensity = 0x8 11 | background_blue = 0x10 12 | background_green = 0x20 13 | background_red = 0x40 14 | background_intensity = 0x80 15 | std_input_handle = -0xa 16 | std_output_handle = -0xb 17 | key_event = 0x1 18 | mouse_event = 0x2 19 | window_buffer_size_event = 0x4 20 | enable_window_input = 0x8 21 | enable_mouse_input = 0x10 22 | enable_extended_flags = 0x80 23 | 24 | vk_f1 = 0x70 25 | vk_f2 = 0x71 26 | vk_f3 = 0x72 27 | vk_f4 = 0x73 28 | vk_f5 = 0x74 29 | vk_f6 = 0x75 30 | vk_f7 = 0x76 31 | vk_f8 = 0x77 32 | vk_f9 = 0x78 33 | vk_f10 = 0x79 34 | vk_f11 = 0x7a 35 | vk_f12 = 0x7b 36 | vk_insert = 0x2d 37 | vk_delete = 0x2e 38 | vk_home = 0x24 39 | vk_end = 0x23 40 | vk_pgup = 0x21 41 | vk_pgdn = 0x22 42 | vk_arrow_up = 0x26 43 | vk_arrow_down = 0x28 44 | vk_arrow_left = 0x25 45 | vk_arrow_right = 0x27 46 | vk_backspace = 0x8 47 | vk_tab = 0x9 48 | vk_enter = 0xd 49 | vk_esc = 0x1b 50 | vk_space = 0x20 51 | 52 | left_alt_pressed = 0x2 53 | left_ctrl_pressed = 0x8 54 | right_alt_pressed = 0x1 55 | right_ctrl_pressed = 0x4 56 | shift_pressed = 0x10 57 | 58 | generic_read = 0x80000000 59 | generic_write = 0x40000000 60 | console_textmode_buffer = 0x1 61 | ) 62 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/termbox_common.go: -------------------------------------------------------------------------------- 1 | package termbox 2 | 3 | // private API, common OS agnostic part 4 | 5 | type cellbuf struct { 6 | width int 7 | height int 8 | cells []Cell 9 | } 10 | 11 | func (this *cellbuf) init(width, height int) { 12 | this.width = width 13 | this.height = height 14 | this.cells = make([]Cell, width*height) 15 | } 16 | 17 | func (this *cellbuf) resize(width, height int) { 18 | if this.width == width && this.height == height { 19 | return 20 | } 21 | 22 | oldw := this.width 23 | oldh := this.height 24 | oldcells := this.cells 25 | 26 | this.init(width, height) 27 | this.clear() 28 | 29 | minw, minh := oldw, oldh 30 | 31 | if width < minw { 32 | minw = width 33 | } 34 | if height < minh { 35 | minh = height 36 | } 37 | 38 | for i := 0; i < minh; i++ { 39 | srco, dsto := i*oldw, i*width 40 | src := oldcells[srco : srco+minw] 41 | dst := this.cells[dsto : dsto+minw] 42 | copy(dst, src) 43 | } 44 | } 45 | 46 | func (this *cellbuf) clear() { 47 | for i := range this.cells { 48 | c := &this.cells[i] 49 | c.Ch = ' ' 50 | c.Fg = foreground 51 | c.Bg = background 52 | } 53 | } 54 | 55 | const cursor_hidden = -1 56 | 57 | func is_cursor_hidden(x, y int) bool { 58 | return x == cursor_hidden || y == cursor_hidden 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/terminfo_builtin.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package termbox 4 | 5 | // Eterm 6 | var eterm_keys = []string{ 7 | "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", 8 | } 9 | var eterm_funcs = []string{ 10 | "\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "", 11 | } 12 | 13 | // screen 14 | var screen_keys = []string{ 15 | "\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC", 16 | } 17 | var screen_funcs = []string{ 18 | "\x1b[?1049h", "\x1b[?1049l", "\x1b[34h\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave, 19 | } 20 | 21 | // xterm 22 | var xterm_keys = []string{ 23 | "\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1bOH", "\x1bOF", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC", 24 | } 25 | var xterm_funcs = []string{ 26 | "\x1b[?1049h", "\x1b[?1049l", "\x1b[?12l\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b(B\x1b[m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave, 27 | } 28 | 29 | // rxvt-unicode 30 | var rxvt_unicode_keys = []string{ 31 | "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", 32 | } 33 | var rxvt_unicode_funcs = []string{ 34 | "\x1b[?1049h", "\x1b[r\x1b[?1049l", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x1b(B", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave, 35 | } 36 | 37 | // linux 38 | var linux_keys = []string{ 39 | "\x1b[[A", "\x1b[[B", "\x1b[[C", "\x1b[[D", "\x1b[[E", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", 40 | } 41 | var linux_funcs = []string{ 42 | "", "", "\x1b[?25h\x1b[?0c", "\x1b[?25l\x1b[?1c", "\x1b[H\x1b[J", "\x1b[0;10m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "", 43 | } 44 | 45 | // rxvt-256color 46 | var rxvt_256color_keys = []string{ 47 | "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", 48 | } 49 | var rxvt_256color_funcs = []string{ 50 | "\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave, 51 | } 52 | 53 | var terms = []struct { 54 | name string 55 | keys []string 56 | funcs []string 57 | }{ 58 | {"Eterm", eterm_keys, eterm_funcs}, 59 | {"screen", screen_keys, screen_funcs}, 60 | {"xterm", xterm_keys, xterm_funcs}, 61 | {"rxvt-unicode", rxvt_unicode_keys, rxvt_unicode_funcs}, 62 | {"linux", linux_keys, linux_funcs}, 63 | {"rxvt-256color", rxvt_256color_keys, rxvt_256color_funcs}, 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go_import_path: github.com/pkg/errors 3 | go: 4 | - 1.11.x 5 | - 1.12.x 6 | - 1.13.x 7 | - tip 8 | 9 | script: 10 | - make check 11 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Dave Cheney 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/Makefile: -------------------------------------------------------------------------------- 1 | PKGS := github.com/pkg/errors 2 | SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) 3 | GO := go 4 | 5 | check: test vet gofmt misspell unconvert staticcheck ineffassign unparam 6 | 7 | test: 8 | $(GO) test $(PKGS) 9 | 10 | vet: | test 11 | $(GO) vet $(PKGS) 12 | 13 | staticcheck: 14 | $(GO) get honnef.co/go/tools/cmd/staticcheck 15 | staticcheck -checks all $(PKGS) 16 | 17 | misspell: 18 | $(GO) get github.com/client9/misspell/cmd/misspell 19 | misspell \ 20 | -locale GB \ 21 | -error \ 22 | *.md *.go 23 | 24 | unconvert: 25 | $(GO) get github.com/mdempsky/unconvert 26 | unconvert -v $(PKGS) 27 | 28 | ineffassign: 29 | $(GO) get github.com/gordonklaus/ineffassign 30 | find $(SRCDIRS) -name '*.go' | xargs ineffassign 31 | 32 | pedantic: check errcheck 33 | 34 | unparam: 35 | $(GO) get mvdan.cc/unparam 36 | unparam ./... 37 | 38 | errcheck: 39 | $(GO) get github.com/kisielk/errcheck 40 | errcheck $(PKGS) 41 | 42 | gofmt: 43 | @echo Checking code is gofmted 44 | @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" 45 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/README.md: -------------------------------------------------------------------------------- 1 | # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) 2 | 3 | Package errors provides simple error handling primitives. 4 | 5 | `go get github.com/pkg/errors` 6 | 7 | The traditional error handling idiom in Go is roughly akin to 8 | ```go 9 | if err != nil { 10 | return err 11 | } 12 | ``` 13 | which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. 14 | 15 | ## Adding context to an error 16 | 17 | The errors.Wrap function returns a new error that adds context to the original error. For example 18 | ```go 19 | _, err := ioutil.ReadAll(r) 20 | if err != nil { 21 | return errors.Wrap(err, "read failed") 22 | } 23 | ``` 24 | ## Retrieving the cause of an error 25 | 26 | Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. 27 | ```go 28 | type causer interface { 29 | Cause() error 30 | } 31 | ``` 32 | `errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: 33 | ```go 34 | switch err := errors.Cause(err).(type) { 35 | case *MyError: 36 | // handle specifically 37 | default: 38 | // unknown error 39 | } 40 | ``` 41 | 42 | [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). 43 | 44 | ## Roadmap 45 | 46 | With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: 47 | 48 | - 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) 49 | - 1.0. Final release. 50 | 51 | ## Contributing 52 | 53 | Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. 54 | 55 | Before sending a PR, please discuss your change by raising an issue. 56 | 57 | ## License 58 | 59 | BSD-2-Clause 60 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: build-{build}.{branch} 2 | 3 | clone_folder: C:\gopath\src\github.com\pkg\errors 4 | shallow_clone: true # for startup speed 5 | 6 | environment: 7 | GOPATH: C:\gopath 8 | 9 | platform: 10 | - x64 11 | 12 | # http://www.appveyor.com/docs/installed-software 13 | install: 14 | # some helpful output for debugging builds 15 | - go version 16 | - go env 17 | # pre-installed MinGW at C:\MinGW is 32bit only 18 | # but MSYS2 at C:\msys64 has mingw64 19 | - set PATH=C:\msys64\mingw64\bin;%PATH% 20 | - gcc --version 21 | - g++ --version 22 | 23 | build_script: 24 | - go install -v ./... 25 | 26 | test_script: 27 | - set PATH=C:\gopath\bin;%PATH% 28 | - go test -v ./... 29 | 30 | #artifacts: 31 | # - path: '%GOPATH%\bin\*.exe' 32 | deploy: off 33 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/go113.go: -------------------------------------------------------------------------------- 1 | // +build go1.13 2 | 3 | package errors 4 | 5 | import ( 6 | stderrors "errors" 7 | ) 8 | 9 | // Is reports whether any error in err's chain matches target. 10 | // 11 | // The chain consists of err itself followed by the sequence of errors obtained by 12 | // repeatedly calling Unwrap. 13 | // 14 | // An error is considered to match a target if it is equal to that target or if 15 | // it implements a method Is(error) bool such that Is(target) returns true. 16 | func Is(err, target error) bool { return stderrors.Is(err, target) } 17 | 18 | // As finds the first error in err's chain that matches target, and if so, sets 19 | // target to that error value and returns true. 20 | // 21 | // The chain consists of err itself followed by the sequence of errors obtained by 22 | // repeatedly calling Unwrap. 23 | // 24 | // An error matches target if the error's concrete value is assignable to the value 25 | // pointed to by target, or if the error has a method As(interface{}) bool such that 26 | // As(target) returns true. In the latter case, the As method is responsible for 27 | // setting target. 28 | // 29 | // As will panic if target is not a non-nil pointer to either a type that implements 30 | // error, or to any interface type. As returns false if err is nil. 31 | func As(err error, target interface{}) bool { return stderrors.As(err, target) } 32 | 33 | // Unwrap returns the result of calling the Unwrap method on err, if err's 34 | // type contains an Unwrap method returning error. 35 | // Otherwise, Unwrap returns nil. 36 | func Unwrap(err error) error { 37 | return stderrors.Unwrap(err) 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/.gitignore: -------------------------------------------------------------------------------- 1 | *.test 2 | *~ 3 | .idea/ 4 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/.gometalinter.json: -------------------------------------------------------------------------------- 1 | { 2 | "DisableAll": true, 3 | "Enable": [ 4 | "structcheck", 5 | "vet", 6 | "misspell", 7 | "unconvert", 8 | "interfacer", 9 | "goimports" 10 | ], 11 | "Vendor": true, 12 | "Exclude": ["vendor"], 13 | "Deadline": "300s" 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | env: 4 | - GO111MODULE=on 5 | 6 | install: true 7 | 8 | before_install: 9 | - export PATH=$HOME/gopath/bin:$PATH 10 | # install gometalinter 11 | - curl -L https://git.io/vp6lP | sh 12 | 13 | script: 14 | - PATH=$PWD/bin:$PATH gometalinter ./... 15 | - go test -race -cover ./... 16 | 17 | matrix: 18 | allow_failures: 19 | - go: tip 20 | include: 21 | - go: "1.7.x" 22 | script: go test -v ./... 23 | - go: "1.8.x" 24 | script: go test -v ./... 25 | - go: "1.9.x" 26 | script: go test -v ./... 27 | - go: "1.10.x" 28 | script: go test -v ./... 29 | - go: "1.11.x" 30 | script: go test -v -mod=vendor ./... 31 | - go: "1.12.x" 32 | script: go test -v -mod=vendor ./... 33 | - go: "1.13.x" 34 | script: go test -v -mod=vendor ./... 35 | - go: "tip" 36 | script: go test -v -mod=vendor ./... 37 | 38 | git: 39 | depth: 10 40 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### v0.6.0 - August 31, 2019 2 | full differences can be viewed using `git log --oneline --decorate --color v0.5.0..v0.6.0` 3 | thanks to everyone who has contributed since January! 4 | 5 | 6 | #### Breaking Changes: 7 | - Info struct has had fields removed related to deprecated functionality by slack. 8 | - minor adjustments to some structs. 9 | - some internal default values have changed, usually to be more inline with slack defaults or to correct inability to set a particular value. (Message Parse for example.) 10 | 11 | ##### Highlights: 12 | - new slacktest package easy mocking for slack client. use, enjoy, please submit PRs for improvements and default behaviours! shamelessly taken from the [slack-test repo](https://github.com/lusis/slack-test) thank you lusis for letting us use it and bring it into the slack repo. 13 | - blocks, blocks, blocks. 14 | - RTM ManagedConnection has undergone a significant cleanup. 15 | in particular handles backoffs gracefully, removed many deadlocks, 16 | and Disconnect is now much more responsive. 17 | 18 | ### v0.5.0 - January 20, 2019 19 | full differences can be viewed using `git log --oneline --decorate --color v0.4.0..v0.5.0` 20 | - Breaking changes: various old struct fields have been removed or updated to match slack's api. 21 | - deadlock fix in RTM disconnect. 22 | 23 | ### v0.4.0 - October 06, 2018 24 | full differences can be viewed using `git log --oneline --decorate --color v0.3.0..v0.4.0` 25 | - Breaking Change: renamed ApplyMessageOption, to mark it as unsafe, 26 | this means it may break without warning in the future. 27 | - Breaking: Msg structure files field changed to an array. 28 | - General: implementation for new security headers. 29 | - RTM: deadlock fix between connect/disconnect. 30 | - Events: various new fields added. 31 | - Web: various fixes, new fields exposed, new methods added. 32 | - Interactions: minor additions expect breaking changes in next release for dialogs/button clicks. 33 | - Utils: new methods added. 34 | 35 | ### v0.3.0 - July 30, 2018 36 | full differences can be viewed using `git log --oneline --decorate --color v0.2.0..v0.3.0` 37 | - slack events initial support added. (still considered experimental and undergoing changes, stability not promised) 38 | - vendored depedencies using dep, ensure using up to date tooling before filing issues. 39 | - RTM has improved its ability to identify dead connections and reconnect automatically (worth calling out in case it has unintended side effects). 40 | - bug fixes (various timestamp handling, error handling, RTM locking, etc). 41 | 42 | ### v0.2.0 - Feb 10, 2018 43 | 44 | Release adds a bunch of functionality and improvements, mainly to give people a recent version to vendor against. 45 | 46 | Please check [0.2.0](https://github.com/nlopes/slack/releases/tag/v0.2.0) 47 | 48 | ### v0.1.0 - May 28, 2017 49 | 50 | This is released before adding context support. 51 | As the used context package is the one from Go 1.7 this will be the last 52 | compatible with Go < 1.7. 53 | 54 | Please check [0.1.0](https://github.com/nlopes/slack/releases/tag/v0.1.0) 55 | 56 | ### v0.0.1 - Jul 26, 2015 57 | 58 | If you just updated from master and it broke your implementation, please 59 | check [0.0.1](https://github.com/nlopes/slack/releases/tag/v0.0.1) 60 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Norberto Lopes 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: help deps fmt lint test test-race test-integration 2 | 3 | help: 4 | @echo "" 5 | @echo "Welcome to slack-go/slack make." 6 | @echo "The following commands are available:" 7 | @echo "" 8 | @echo " make deps : Fetch all dependencies" 9 | @echo " make fmt : Run go fmt to fix any formatting issues" 10 | @echo " make lint : Use go vet to check for linting issues" 11 | @echo " make test : Run all short tests" 12 | @echo " make test-race : Run all tests with race condition checking" 13 | @echo " make test-integration : Run all tests without limiting to short" 14 | @echo "" 15 | @echo " make pr-prep : Run this before making a PR to run fmt, lint and tests" 16 | @echo "" 17 | 18 | deps: 19 | @go mod tidy 20 | 21 | fmt: 22 | @go fmt . 23 | 24 | lint: 25 | @go vet . 26 | 27 | test: 28 | @go test -v -count=1 -timeout 300s -short ./... 29 | 30 | test-race: 31 | @go test -v -count=1 -timeout 300s -short -race ./... 32 | 33 | test-integration: 34 | @go test -v -count=1 -timeout 600s ./... 35 | 36 | pr-prep: fmt lint test-race test-integration 37 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/README.md: -------------------------------------------------------------------------------- 1 | Slack API in Go [![GoDoc](https://godoc.org/github.com/slack-go/slack?status.svg)](https://godoc.org/github.com/slack-go/slack) [![Build Status](https://travis-ci.org/slack-go/slack.svg)](https://travis-ci.org/slack-go/slack) 2 | =============== 3 | This is the original Slack library for Go created by Norberto Lopez, transferred to a Github organization. 4 | 5 | [![Join the chat at https://gitter.im/go-slack/Lobby](https://badges.gitter.im/go-slack/Lobby.svg)](https://gitter.im/go-slack/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | This library supports most if not all of the `api.slack.com` REST 8 | calls, as well as the Real-Time Messaging protocol over websocket, in 9 | a fully managed way. 10 | 11 | 12 | 13 | 14 | ## Changelog 15 | 16 | [CHANGELOG.md](https://github.com/slack-go/slack/blob/master/CHANGELOG.md) is available. Please visit it for updates. 17 | 18 | ## Installing 19 | 20 | ### *go get* 21 | 22 | $ go get -u github.com/slack-go/slack 23 | 24 | ## Example 25 | 26 | ### Getting all groups 27 | 28 | ```golang 29 | import ( 30 | "fmt" 31 | 32 | "github.com/slack-go/slack" 33 | ) 34 | 35 | func main() { 36 | api := slack.New("YOUR_TOKEN_HERE") 37 | // If you set debugging, it will log all requests to the console 38 | // Useful when encountering issues 39 | // slack.New("YOUR_TOKEN_HERE", slack.OptionDebug(true)) 40 | groups, err := api.GetGroups(false) 41 | if err != nil { 42 | fmt.Printf("%s\n", err) 43 | return 44 | } 45 | for _, group := range groups { 46 | fmt.Printf("ID: %s, Name: %s\n", group.ID, group.Name) 47 | } 48 | } 49 | ``` 50 | 51 | ### Getting User Information 52 | 53 | ```golang 54 | import ( 55 | "fmt" 56 | 57 | "github.com/slack-go/slack" 58 | ) 59 | 60 | func main() { 61 | api := slack.New("YOUR_TOKEN_HERE") 62 | user, err := api.GetUserInfo("U023BECGF") 63 | if err != nil { 64 | fmt.Printf("%s\n", err) 65 | return 66 | } 67 | fmt.Printf("ID: %s, Fullname: %s, Email: %s\n", user.ID, user.Profile.RealName, user.Profile.Email) 68 | } 69 | ``` 70 | 71 | ## Minimal RTM usage: 72 | 73 | See https://github.com/slack-go/slack/blob/master/examples/websocket/websocket.go 74 | 75 | 76 | ## Minimal EventsAPI usage: 77 | 78 | See https://github.com/slack-go/slack/blob/master/examples/eventsapi/events.go 79 | 80 | 81 | ## Contributing 82 | 83 | You are more than welcome to contribute to this project. Fork and 84 | make a Pull Request, or create an Issue if you see any problem. 85 | 86 | Before making any Pull Request please run the following: 87 | 88 | ``` 89 | make pr-prep 90 | ``` 91 | 92 | This will check/update code formatting, linting and then run all tests 93 | 94 | ## License 95 | 96 | BSD 2 Clause license 97 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/TODO.txt: -------------------------------------------------------------------------------- 1 | - Add more tests!!! 2 | - Add support to have markdown hints 3 | - See section Message Formatting at https://api.slack.com/docs/formatting 4 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/auth.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "context" 5 | "net/url" 6 | ) 7 | 8 | // AuthRevokeResponse contains our Auth response from the auth.revoke endpoint 9 | type AuthRevokeResponse struct { 10 | SlackResponse // Contains the "ok", and "Error", if any 11 | Revoked bool `json:"revoked,omitempty"` 12 | } 13 | 14 | // authRequest sends the actual request, and unmarshals the response 15 | func (api *Client) authRequest(ctx context.Context, path string, values url.Values) (*AuthRevokeResponse, error) { 16 | response := &AuthRevokeResponse{} 17 | err := api.postMethod(ctx, path, values, response) 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | return response, response.Err() 23 | } 24 | 25 | // SendAuthRevoke will send a revocation for our token 26 | func (api *Client) SendAuthRevoke(token string) (*AuthRevokeResponse, error) { 27 | return api.SendAuthRevokeContext(context.Background(), token) 28 | } 29 | 30 | // SendAuthRevokeContext will send a revocation request for our token to api.revoke with context 31 | func (api *Client) SendAuthRevokeContext(ctx context.Context, token string) (*AuthRevokeResponse, error) { 32 | if token == "" { 33 | token = api.token 34 | } 35 | values := url.Values{ 36 | "token": {token}, 37 | } 38 | 39 | return api.authRequest(ctx, "auth.revoke", values) 40 | } 41 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/backoff.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | // This one was ripped from https://github.com/jpillora/backoff/blob/master/backoff.go 9 | 10 | // Backoff is a time.Duration counter. It starts at Min. After every 11 | // call to Duration() it is multiplied by Factor. It is capped at 12 | // Max. It returns to Min on every call to Reset(). Used in 13 | // conjunction with the time package. 14 | type backoff struct { 15 | attempts int 16 | // Initial value to scale out 17 | Initial time.Duration 18 | // Jitter value randomizes an additional delay between 0 and Jitter 19 | Jitter time.Duration 20 | // Max maximum values of the backoff 21 | Max time.Duration 22 | } 23 | 24 | // Returns the current value of the counter and then multiplies it 25 | // Factor 26 | func (b *backoff) Duration() (dur time.Duration) { 27 | // Zero-values are nonsensical, so we use 28 | // them to apply defaults 29 | if b.Max == 0 { 30 | b.Max = 10 * time.Second 31 | } 32 | 33 | if b.Initial == 0 { 34 | b.Initial = 100 * time.Millisecond 35 | } 36 | 37 | // calculate this duration 38 | if dur = time.Duration(1 << uint(b.attempts)); dur > 0 { 39 | dur = dur * b.Initial 40 | } else { 41 | dur = b.Max 42 | } 43 | 44 | if b.Jitter > 0 { 45 | dur = dur + time.Duration(rand.Intn(int(b.Jitter))) 46 | } 47 | 48 | // bump attempts count 49 | b.attempts++ 50 | 51 | return dur 52 | } 53 | 54 | //Resets the current value of the counter back to Min 55 | func (b *backoff) Reset() { 56 | b.attempts = 0 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // @NOTE: Blocks are in beta and subject to change. 4 | 5 | // More Information: https://api.slack.com/block-kit 6 | 7 | // MessageBlockType defines a named string type to define each block type 8 | // as a constant for use within the package. 9 | type MessageBlockType string 10 | 11 | const ( 12 | MBTSection MessageBlockType = "section" 13 | MBTDivider MessageBlockType = "divider" 14 | MBTImage MessageBlockType = "image" 15 | MBTAction MessageBlockType = "actions" 16 | MBTContext MessageBlockType = "context" 17 | MBTFile MessageBlockType = "file" 18 | MBTInput MessageBlockType = "input" 19 | ) 20 | 21 | // Block defines an interface all block types should implement 22 | // to ensure consistency between blocks. 23 | type Block interface { 24 | BlockType() MessageBlockType 25 | } 26 | 27 | // Blocks is a convenience struct defined to allow dynamic unmarshalling of 28 | // the "blocks" value in Slack's JSON response, which varies depending on block type 29 | type Blocks struct { 30 | BlockSet []Block `json:"blocks,omitempty"` 31 | } 32 | 33 | // BlockAction is the action callback sent when a block is interacted with 34 | type BlockAction struct { 35 | ActionID string `json:"action_id"` 36 | BlockID string `json:"block_id"` 37 | Type actionType `json:"type"` 38 | Text TextBlockObject `json:"text"` 39 | Value string `json:"value"` 40 | ActionTs string `json:"action_ts"` 41 | SelectedOption OptionBlockObject `json:"selected_option"` 42 | SelectedOptions []OptionBlockObject `json:"selected_options"` 43 | SelectedUser string `json:"selected_user"` 44 | SelectedChannel string `json:"selected_channel"` 45 | SelectedConversation string `json:"selected_conversation"` 46 | SelectedDate string `json:"selected_date"` 47 | InitialOption OptionBlockObject `json:"initial_option"` 48 | InitialUser string `json:"initial_user"` 49 | InitialChannel string `json:"initial_channel"` 50 | InitialConversation string `json:"initial_conversation"` 51 | InitialDate string `json:"initial_date"` 52 | } 53 | 54 | // actionType returns the type of the action 55 | func (b BlockAction) actionType() actionType { 56 | return b.Type 57 | } 58 | 59 | // NewBlockMessage creates a new Message that contains one or more blocks to be displayed 60 | func NewBlockMessage(blocks ...Block) Message { 61 | return Message{ 62 | Msg: Msg{ 63 | Blocks: Blocks{ 64 | BlockSet: blocks, 65 | }, 66 | }, 67 | } 68 | } 69 | 70 | // AddBlockMessage appends a block to the end of the existing list of blocks 71 | func AddBlockMessage(message Message, newBlk Block) Message { 72 | message.Msg.Blocks.BlockSet = append(message.Msg.Blocks.BlockSet, newBlk) 73 | return message 74 | } 75 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block_action.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // ActionBlock defines data that is used to hold interactive elements. 4 | // 5 | // More Information: https://api.slack.com/reference/messaging/blocks#actions 6 | type ActionBlock struct { 7 | Type MessageBlockType `json:"type"` 8 | BlockID string `json:"block_id,omitempty"` 9 | Elements BlockElements `json:"elements"` 10 | } 11 | 12 | // BlockType returns the type of the block 13 | func (s ActionBlock) BlockType() MessageBlockType { 14 | return s.Type 15 | } 16 | 17 | // NewActionBlock returns a new instance of an Action Block 18 | func NewActionBlock(blockID string, elements ...BlockElement) *ActionBlock { 19 | return &ActionBlock{ 20 | Type: MBTAction, 21 | BlockID: blockID, 22 | Elements: BlockElements{ 23 | ElementSet: elements, 24 | }, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block_context.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // ContextBlock defines data that is used to display message context, which can 4 | // include both images and text. 5 | // 6 | // More Information: https://api.slack.com/reference/messaging/blocks#actions 7 | type ContextBlock struct { 8 | Type MessageBlockType `json:"type"` 9 | BlockID string `json:"block_id,omitempty"` 10 | ContextElements ContextElements `json:"elements"` 11 | } 12 | 13 | // BlockType returns the type of the block 14 | func (s ContextBlock) BlockType() MessageBlockType { 15 | return s.Type 16 | } 17 | 18 | type ContextElements struct { 19 | Elements []MixedElement 20 | } 21 | 22 | // NewContextBlock returns a new instance of a context block 23 | func NewContextBlock(blockID string, mixedElements ...MixedElement) *ContextBlock { 24 | elements := ContextElements{ 25 | Elements: mixedElements, 26 | } 27 | return &ContextBlock{ 28 | Type: MBTContext, 29 | BlockID: blockID, 30 | ContextElements: elements, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block_divider.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // DividerBlock for displaying a divider line between blocks (similar to
tag in html) 4 | // 5 | // More Information: https://api.slack.com/reference/messaging/blocks#divider 6 | type DividerBlock struct { 7 | Type MessageBlockType `json:"type"` 8 | BlockID string `json:"block_id,omitempty"` 9 | } 10 | 11 | // BlockType returns the type of the block 12 | func (s DividerBlock) BlockType() MessageBlockType { 13 | return s.Type 14 | } 15 | 16 | // NewDividerBlock returns a new instance of a divider block 17 | func NewDividerBlock() *DividerBlock { 18 | return &DividerBlock{ 19 | Type: MBTDivider, 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block_file.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // FileBlock defines data that is used to display a remote file. 4 | // 5 | // More Information: https://api.slack.com/reference/block-kit/blocks#file 6 | type FileBlock struct { 7 | Type MessageBlockType `json:"type"` 8 | BlockID string `json:"block_id,omitempty"` 9 | ExternalID string `json:"external_id"` 10 | Source string `json:"source"` 11 | } 12 | 13 | // BlockType returns the type of the block 14 | func (s FileBlock) BlockType() MessageBlockType { 15 | return s.Type 16 | } 17 | 18 | // NewFileBlock returns a new instance of a file block 19 | func NewFileBlock(blockID string, externalID string, source string) *FileBlock { 20 | return &FileBlock{ 21 | Type: MBTFile, 22 | BlockID: blockID, 23 | ExternalID: externalID, 24 | Source: source, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block_image.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // ImageBlock defines data required to display an image as a block element 4 | // 5 | // More Information: https://api.slack.com/reference/messaging/blocks#image 6 | type ImageBlock struct { 7 | Type MessageBlockType `json:"type"` 8 | ImageURL string `json:"image_url"` 9 | AltText string `json:"alt_text"` 10 | BlockID string `json:"block_id,omitempty"` 11 | Title *TextBlockObject `json:"title"` 12 | } 13 | 14 | // BlockType returns the type of the block 15 | func (s ImageBlock) BlockType() MessageBlockType { 16 | return s.Type 17 | } 18 | 19 | // NewImageBlock returns an instance of a new Image Block type 20 | func NewImageBlock(imageURL, altText, blockID string, title *TextBlockObject) *ImageBlock { 21 | return &ImageBlock{ 22 | Type: MBTImage, 23 | ImageURL: imageURL, 24 | AltText: altText, 25 | BlockID: blockID, 26 | Title: title, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block_input.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // InputBlock defines data that is used to display user input fields. 4 | // 5 | // More Information: https://api.slack.com/reference/block-kit/blocks#input 6 | type InputBlock struct { 7 | Type MessageBlockType `json:"type"` 8 | BlockID string `json:"block_id,omitempty"` 9 | Label *TextBlockObject `json:"label"` 10 | Element BlockElement `json:"element"` 11 | Hint *TextBlockObject `json:"hint,omitempty"` 12 | Optional bool `json:"optional,omitempty"` 13 | } 14 | 15 | // BlockType returns the type of the block 16 | func (s InputBlock) BlockType() MessageBlockType { 17 | return s.Type 18 | } 19 | 20 | // NewInputBlock returns a new instance of an input block 21 | func NewInputBlock(blockID string, label *TextBlockObject, element BlockElement) *InputBlock { 22 | return &InputBlock{ 23 | Type: MBTInput, 24 | BlockID: blockID, 25 | Label: label, 26 | Element: element, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block_section.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // SectionBlock defines a new block of type section 4 | // 5 | // More Information: https://api.slack.com/reference/messaging/blocks#section 6 | type SectionBlock struct { 7 | Type MessageBlockType `json:"type"` 8 | Text *TextBlockObject `json:"text,omitempty"` 9 | BlockID string `json:"block_id,omitempty"` 10 | Fields []*TextBlockObject `json:"fields,omitempty"` 11 | Accessory *Accessory `json:"accessory,omitempty"` 12 | } 13 | 14 | // BlockType returns the type of the block 15 | func (s SectionBlock) BlockType() MessageBlockType { 16 | return s.Type 17 | } 18 | 19 | // SectionBlockOption allows configuration of options for a new section block 20 | type SectionBlockOption func(*SectionBlock) 21 | 22 | func SectionBlockOptionBlockID(blockID string) SectionBlockOption { 23 | return func(block *SectionBlock) { 24 | block.BlockID = blockID 25 | } 26 | } 27 | 28 | // NewSectionBlock returns a new instance of a section block to be rendered 29 | func NewSectionBlock(textObj *TextBlockObject, fields []*TextBlockObject, accessory *Accessory, options ...SectionBlockOption) *SectionBlock { 30 | block := SectionBlock{ 31 | Type: MBTSection, 32 | Text: textObj, 33 | Fields: fields, 34 | Accessory: accessory, 35 | } 36 | 37 | for _, option := range options { 38 | option(&block) 39 | } 40 | 41 | return &block 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/block_unknown.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // UnknownBlock represents a block type that is not yet known. This block type exists to prevent Slack from introducing 4 | // new and unknown block types that break this library. 5 | type UnknownBlock struct { 6 | Type MessageBlockType `json:"type"` 7 | BlockID string `json:"block_id,omitempty"` 8 | } 9 | 10 | // BlockType returns the type of the block 11 | func (b UnknownBlock) BlockType() MessageBlockType { 12 | return b.Type 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/bots.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "context" 5 | "net/url" 6 | ) 7 | 8 | // Bot contains information about a bot 9 | type Bot struct { 10 | ID string `json:"id"` 11 | Name string `json:"name"` 12 | Deleted bool `json:"deleted"` 13 | UserID string `json:"user_id"` 14 | AppID string `json:"app_id"` 15 | Updated JSONTime `json:"updated"` 16 | Icons Icons `json:"icons"` 17 | } 18 | 19 | type botResponseFull struct { 20 | Bot `json:"bot,omitempty"` // GetBotInfo 21 | SlackResponse 22 | } 23 | 24 | func (api *Client) botRequest(ctx context.Context, path string, values url.Values) (*botResponseFull, error) { 25 | response := &botResponseFull{} 26 | err := api.postMethod(ctx, path, values, response) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | if err := response.Err(); err != nil { 32 | return nil, err 33 | } 34 | 35 | return response, nil 36 | } 37 | 38 | // GetBotInfo will retrieve the complete bot information 39 | func (api *Client) GetBotInfo(bot string) (*Bot, error) { 40 | return api.GetBotInfoContext(context.Background(), bot) 41 | } 42 | 43 | // GetBotInfoContext will retrieve the complete bot information using a custom context 44 | func (api *Client) GetBotInfoContext(ctx context.Context, bot string) (*Bot, error) { 45 | values := url.Values{ 46 | "token": {api.token}, 47 | } 48 | 49 | if bot != "" { 50 | values.Add("bot", bot) 51 | } 52 | 53 | response, err := api.botRequest(ctx, "bots.info", values) 54 | if err != nil { 55 | return nil, err 56 | } 57 | return &response.Bot, nil 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/comment.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // Comment contains all the information relative to a comment 4 | type Comment struct { 5 | ID string `json:"id,omitempty"` 6 | Created JSONTime `json:"created,omitempty"` 7 | Timestamp JSONTime `json:"timestamp,omitempty"` 8 | User string `json:"user,omitempty"` 9 | Comment string `json:"comment,omitempty"` 10 | } 11 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/dialog_text.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // TextInputSubtype Accepts email, number, tel, or url. In some form factors, optimized input is provided for this subtype. 4 | type TextInputSubtype string 5 | 6 | // TextInputOption handle to extra inputs options. 7 | type TextInputOption func(*TextInputElement) 8 | 9 | const ( 10 | // InputSubtypeEmail email keyboard 11 | InputSubtypeEmail TextInputSubtype = "email" 12 | // InputSubtypeNumber numeric keyboard 13 | InputSubtypeNumber TextInputSubtype = "number" 14 | // InputSubtypeTel Phone keyboard 15 | InputSubtypeTel TextInputSubtype = "tel" 16 | // InputSubtypeURL Phone keyboard 17 | InputSubtypeURL TextInputSubtype = "url" 18 | ) 19 | 20 | // TextInputElement subtype of DialogInput 21 | // https://api.slack.com/dialogs#option_element_attributes#text_element_attributes 22 | type TextInputElement struct { 23 | DialogInput 24 | MaxLength int `json:"max_length,omitempty"` 25 | MinLength int `json:"min_length,omitempty"` 26 | Hint string `json:"hint,omitempty"` 27 | Subtype TextInputSubtype `json:"subtype"` 28 | Value string `json:"value"` 29 | } 30 | 31 | // NewTextInput constructor for a `text` input 32 | func NewTextInput(name, label, text string, options ...TextInputOption) *TextInputElement { 33 | t := &TextInputElement{ 34 | DialogInput: DialogInput{ 35 | Type: InputTypeText, 36 | Name: name, 37 | Label: label, 38 | }, 39 | Value: text, 40 | } 41 | 42 | for _, opt := range options { 43 | opt(t) 44 | } 45 | 46 | return t 47 | } 48 | 49 | // NewTextAreaInput constructor for a `textarea` input 50 | func NewTextAreaInput(name, label, text string) *TextInputElement { 51 | return &TextInputElement{ 52 | DialogInput: DialogInput{ 53 | Type: InputTypeTextArea, 54 | Name: name, 55 | Label: label, 56 | }, 57 | Value: text, 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/emoji.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "context" 5 | "net/url" 6 | ) 7 | 8 | type emojiResponseFull struct { 9 | Emoji map[string]string `json:"emoji"` 10 | SlackResponse 11 | } 12 | 13 | // GetEmoji retrieves all the emojis 14 | func (api *Client) GetEmoji() (map[string]string, error) { 15 | return api.GetEmojiContext(context.Background()) 16 | } 17 | 18 | // GetEmojiContext retrieves all the emojis with a custom context 19 | func (api *Client) GetEmojiContext(ctx context.Context) (map[string]string, error) { 20 | values := url.Values{ 21 | "token": {api.token}, 22 | } 23 | response := &emojiResponseFull{} 24 | 25 | err := api.postMethod(ctx, "emoji.list", values, response) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | if response.Err() != nil { 31 | return nil, response.Err() 32 | } 33 | 34 | return response.Emoji, nil 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/errors.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import "github.com/slack-go/slack/internal/errorsx" 4 | 5 | // Errors returned by various methods. 6 | const ( 7 | ErrAlreadyDisconnected = errorsx.String("Invalid call to Disconnect - Slack API is already disconnected") 8 | ErrRTMDisconnected = errorsx.String("disconnect received while trying to connect") 9 | ErrRTMGoodbye = errorsx.String("goodbye detected") 10 | ErrRTMDeadman = errorsx.String("deadman switch triggered") 11 | ErrParametersMissing = errorsx.String("received empty parameters") 12 | ErrInvalidConfiguration = errorsx.String("invalid configuration") 13 | ErrMissingHeaders = errorsx.String("missing headers") 14 | ErrExpiredTimestamp = errorsx.String("timestamp is too old") 15 | ) 16 | 17 | // internal errors 18 | const ( 19 | errPaginationComplete = errorsx.String("pagination complete") 20 | ) 21 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/slack-go/slack 2 | 3 | require ( 4 | github.com/go-test/deep v1.0.4 5 | github.com/gorilla/websocket v1.2.0 6 | github.com/nlopes/slack v0.6.0 7 | github.com/pkg/errors v0.8.0 8 | github.com/stretchr/testify v1.2.2 9 | ) 10 | 11 | go 1.13 12 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= 4 | github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 5 | github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= 6 | github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 7 | github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA= 8 | github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk= 9 | github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= 10 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 11 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 12 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 13 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 14 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 15 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/history.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | const ( 4 | DEFAULT_HISTORY_LATEST = "" 5 | DEFAULT_HISTORY_OLDEST = "0" 6 | DEFAULT_HISTORY_COUNT = 100 7 | DEFAULT_HISTORY_INCLUSIVE = false 8 | DEFAULT_HISTORY_UNREADS = false 9 | ) 10 | 11 | // HistoryParameters contains all the necessary information to help in the retrieval of history for Channels/Groups/DMs 12 | type HistoryParameters struct { 13 | Latest string 14 | Oldest string 15 | Count int 16 | Inclusive bool 17 | Unreads bool 18 | } 19 | 20 | // History contains message history information needed to navigate a Channel / Group / DM history 21 | type History struct { 22 | Latest string `json:"latest"` 23 | Messages []Message `json:"messages"` 24 | HasMore bool `json:"has_more"` 25 | } 26 | 27 | // NewHistoryParameters provides an instance of HistoryParameters with all the sane default values set 28 | func NewHistoryParameters() HistoryParameters { 29 | return HistoryParameters{ 30 | Latest: DEFAULT_HISTORY_LATEST, 31 | Oldest: DEFAULT_HISTORY_OLDEST, 32 | Count: DEFAULT_HISTORY_COUNT, 33 | Inclusive: DEFAULT_HISTORY_INCLUSIVE, 34 | Unreads: DEFAULT_HISTORY_UNREADS, 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/internal/errorsx/errorsx.go: -------------------------------------------------------------------------------- 1 | package errorsx 2 | 3 | // String representing an error, useful for declaring string constants as errors. 4 | type String string 5 | 6 | func (t String) Error() string { 7 | return string(t) 8 | } 9 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/internal/timex/timex.go: -------------------------------------------------------------------------------- 1 | package timex 2 | 3 | import "time" 4 | 5 | // Max returns the maximum duration 6 | func Max(values ...time.Duration) time.Duration { 7 | var ( 8 | max time.Duration 9 | ) 10 | 11 | for _, v := range values { 12 | if v > max { 13 | max = v 14 | } 15 | } 16 | 17 | return max 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/item.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | const ( 4 | TYPE_MESSAGE = "message" 5 | TYPE_FILE = "file" 6 | TYPE_FILE_COMMENT = "file_comment" 7 | TYPE_CHANNEL = "channel" 8 | TYPE_IM = "im" 9 | TYPE_GROUP = "group" 10 | ) 11 | 12 | // Item is any type of slack message - message, file, or file comment. 13 | type Item struct { 14 | Type string `json:"type"` 15 | Channel string `json:"channel,omitempty"` 16 | Message *Message `json:"message,omitempty"` 17 | File *File `json:"file,omitempty"` 18 | Comment *Comment `json:"comment,omitempty"` 19 | Timestamp string `json:"ts,omitempty"` 20 | } 21 | 22 | // NewMessageItem turns a message on a channel into a typed message struct. 23 | func NewMessageItem(ch string, m *Message) Item { 24 | return Item{Type: TYPE_MESSAGE, Channel: ch, Message: m} 25 | } 26 | 27 | // NewFileItem turns a file into a typed file struct. 28 | func NewFileItem(f *File) Item { 29 | return Item{Type: TYPE_FILE, File: f} 30 | } 31 | 32 | // NewFileCommentItem turns a file and comment into a typed file_comment struct. 33 | func NewFileCommentItem(f *File, c *Comment) Item { 34 | return Item{Type: TYPE_FILE_COMMENT, File: f, Comment: c} 35 | } 36 | 37 | // NewChannelItem turns a channel id into a typed channel struct. 38 | func NewChannelItem(ch string) Item { 39 | return Item{Type: TYPE_CHANNEL, Channel: ch} 40 | } 41 | 42 | // NewIMItem turns a channel id into a typed im struct. 43 | func NewIMItem(ch string) Item { 44 | return Item{Type: TYPE_IM, Channel: ch} 45 | } 46 | 47 | // NewGroupItem turns a channel id into a typed group struct. 48 | func NewGroupItem(ch string) Item { 49 | return Item{Type: TYPE_GROUP, Channel: ch} 50 | } 51 | 52 | // ItemRef is a reference to a message of any type. One of FileID, 53 | // CommentId, or the combination of ChannelId and Timestamp must be 54 | // specified. 55 | type ItemRef struct { 56 | Channel string `json:"channel"` 57 | Timestamp string `json:"timestamp"` 58 | File string `json:"file"` 59 | Comment string `json:"file_comment"` 60 | } 61 | 62 | // NewRefToMessage initializes a reference to to a message. 63 | func NewRefToMessage(channel, timestamp string) ItemRef { 64 | return ItemRef{Channel: channel, Timestamp: timestamp} 65 | } 66 | 67 | // NewRefToFile initializes a reference to a file. 68 | func NewRefToFile(file string) ItemRef { 69 | return ItemRef{File: file} 70 | } 71 | 72 | // NewRefToComment initializes a reference to a file comment. 73 | func NewRefToComment(comment string) ItemRef { 74 | return ItemRef{Comment: comment} 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/logger.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // logger is a logger interface compatible with both stdlib and some 8 | // 3rd party loggers. 9 | type logger interface { 10 | Output(int, string) error 11 | } 12 | 13 | // ilogger represents the internal logging api we use. 14 | type ilogger interface { 15 | logger 16 | Print(...interface{}) 17 | Printf(string, ...interface{}) 18 | Println(...interface{}) 19 | } 20 | 21 | type debug interface { 22 | Debug() bool 23 | 24 | // Debugf print a formatted debug line. 25 | Debugf(format string, v ...interface{}) 26 | // Debugln print a debug line. 27 | Debugln(v ...interface{}) 28 | } 29 | 30 | // internalLog implements the additional methods used by our internal logging. 31 | type internalLog struct { 32 | logger 33 | } 34 | 35 | // Println replicates the behaviour of the standard logger. 36 | func (t internalLog) Println(v ...interface{}) { 37 | t.Output(2, fmt.Sprintln(v...)) 38 | } 39 | 40 | // Printf replicates the behaviour of the standard logger. 41 | func (t internalLog) Printf(format string, v ...interface{}) { 42 | t.Output(2, fmt.Sprintf(format, v...)) 43 | } 44 | 45 | // Print replicates the behaviour of the standard logger. 46 | func (t internalLog) Print(v ...interface{}) { 47 | t.Output(2, fmt.Sprint(v...)) 48 | } 49 | 50 | type discard struct{} 51 | 52 | func (t discard) Debug() bool { 53 | return false 54 | } 55 | 56 | // Debugf print a formatted debug line. 57 | func (t discard) Debugf(format string, v ...interface{}) {} 58 | 59 | // Debugln print a debug line. 60 | func (t discard) Debugln(v ...interface{}) {} 61 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/messageID.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import "sync" 4 | 5 | // IDGenerator provides an interface for generating integer ID values. 6 | type IDGenerator interface { 7 | Next() int 8 | } 9 | 10 | // NewSafeID returns a new instance of an IDGenerator which is safe for 11 | // concurrent use by multiple goroutines. 12 | func NewSafeID(startID int) IDGenerator { 13 | return &safeID{ 14 | nextID: startID, 15 | mutex: &sync.Mutex{}, 16 | } 17 | } 18 | 19 | type safeID struct { 20 | nextID int 21 | mutex *sync.Mutex 22 | } 23 | 24 | func (s *safeID) Next() int { 25 | s.mutex.Lock() 26 | defer s.mutex.Unlock() 27 | id := s.nextID 28 | s.nextID++ 29 | return id 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/pagination.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // Paging contains paging information 4 | type Paging struct { 5 | Count int `json:"count"` 6 | Total int `json:"total"` 7 | Page int `json:"page"` 8 | Pages int `json:"pages"` 9 | } 10 | 11 | // Pagination contains pagination information 12 | // This is different from Paging in that it contains additional details 13 | type Pagination struct { 14 | TotalCount int `json:"total_count"` 15 | Page int `json:"page"` 16 | PerPage int `json:"per_page"` 17 | PageCount int `json:"page_count"` 18 | First int `json:"first"` 19 | Last int `json:"last"` 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/pins.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "net/url" 7 | ) 8 | 9 | type listPinsResponseFull struct { 10 | Items []Item 11 | Paging `json:"paging"` 12 | SlackResponse 13 | } 14 | 15 | // AddPin pins an item in a channel 16 | func (api *Client) AddPin(channel string, item ItemRef) error { 17 | return api.AddPinContext(context.Background(), channel, item) 18 | } 19 | 20 | // AddPinContext pins an item in a channel with a custom context 21 | func (api *Client) AddPinContext(ctx context.Context, channel string, item ItemRef) error { 22 | values := url.Values{ 23 | "channel": {channel}, 24 | "token": {api.token}, 25 | } 26 | if item.Timestamp != "" { 27 | values.Set("timestamp", item.Timestamp) 28 | } 29 | if item.File != "" { 30 | values.Set("file", item.File) 31 | } 32 | if item.Comment != "" { 33 | values.Set("file_comment", item.Comment) 34 | } 35 | 36 | response := &SlackResponse{} 37 | if err := api.postMethod(ctx, "pins.add", values, response); err != nil { 38 | return err 39 | } 40 | 41 | return response.Err() 42 | } 43 | 44 | // RemovePin un-pins an item from a channel 45 | func (api *Client) RemovePin(channel string, item ItemRef) error { 46 | return api.RemovePinContext(context.Background(), channel, item) 47 | } 48 | 49 | // RemovePinContext un-pins an item from a channel with a custom context 50 | func (api *Client) RemovePinContext(ctx context.Context, channel string, item ItemRef) error { 51 | values := url.Values{ 52 | "channel": {channel}, 53 | "token": {api.token}, 54 | } 55 | if item.Timestamp != "" { 56 | values.Set("timestamp", item.Timestamp) 57 | } 58 | if item.File != "" { 59 | values.Set("file", item.File) 60 | } 61 | if item.Comment != "" { 62 | values.Set("file_comment", item.Comment) 63 | } 64 | 65 | response := &SlackResponse{} 66 | if err := api.postMethod(ctx, "pins.remove", values, response); err != nil { 67 | return err 68 | } 69 | 70 | return response.Err() 71 | } 72 | 73 | // ListPins returns information about the items a user reacted to. 74 | func (api *Client) ListPins(channel string) ([]Item, *Paging, error) { 75 | return api.ListPinsContext(context.Background(), channel) 76 | } 77 | 78 | // ListPinsContext returns information about the items a user reacted to with a custom context. 79 | func (api *Client) ListPinsContext(ctx context.Context, channel string) ([]Item, *Paging, error) { 80 | values := url.Values{ 81 | "channel": {channel}, 82 | "token": {api.token}, 83 | } 84 | 85 | response := &listPinsResponseFull{} 86 | err := api.postMethod(ctx, "pins.list", values, response) 87 | if err != nil { 88 | return nil, nil, err 89 | } 90 | if !response.Ok { 91 | return nil, nil, errors.New(response.Error) 92 | } 93 | return response.Items, &response.Paging, nil 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/reminders.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "context" 5 | "net/url" 6 | "time" 7 | ) 8 | 9 | type Reminder struct { 10 | ID string `json:"id"` 11 | Creator string `json:"creator"` 12 | User string `json:"user"` 13 | Text string `json:"text"` 14 | Recurring bool `json:"recurring"` 15 | Time time.Time `json:"time"` 16 | CompleteTS int `json:"complete_ts"` 17 | } 18 | 19 | type reminderResp struct { 20 | SlackResponse 21 | Reminder Reminder `json:"reminder"` 22 | } 23 | 24 | func (api *Client) doReminder(ctx context.Context, path string, values url.Values) (*Reminder, error) { 25 | response := &reminderResp{} 26 | if err := api.postMethod(ctx, path, values, response); err != nil { 27 | return nil, err 28 | } 29 | return &response.Reminder, response.Err() 30 | } 31 | 32 | // AddChannelReminder adds a reminder for a channel. 33 | // 34 | // See https://api.slack.com/methods/reminders.add (NOTE: the ability to set 35 | // reminders on a channel is currently undocumented but has been tested to 36 | // work) 37 | func (api *Client) AddChannelReminder(channelID, text, time string) (*Reminder, error) { 38 | values := url.Values{ 39 | "token": {api.token}, 40 | "text": {text}, 41 | "time": {time}, 42 | "channel": {channelID}, 43 | } 44 | return api.doReminder(context.Background(), "reminders.add", values) 45 | } 46 | 47 | // AddUserReminder adds a reminder for a user. 48 | // 49 | // See https://api.slack.com/methods/reminders.add (NOTE: the ability to set 50 | // reminders on a channel is currently undocumented but has been tested to 51 | // work) 52 | func (api *Client) AddUserReminder(userID, text, time string) (*Reminder, error) { 53 | values := url.Values{ 54 | "token": {api.token}, 55 | "text": {text}, 56 | "time": {time}, 57 | "user": {userID}, 58 | } 59 | return api.doReminder(context.Background(), "reminders.add", values) 60 | } 61 | 62 | // DeleteReminder deletes an existing reminder. 63 | // 64 | // See https://api.slack.com/methods/reminders.delete 65 | func (api *Client) DeleteReminder(id string) error { 66 | values := url.Values{ 67 | "token": {api.token}, 68 | "reminder": {id}, 69 | } 70 | response := &SlackResponse{} 71 | if err := api.postMethod(context.Background(), "reminders.delete", values, response); err != nil { 72 | return err 73 | } 74 | return response.Err() 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/security.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/hex" 7 | "fmt" 8 | "hash" 9 | "net/http" 10 | "strconv" 11 | "strings" 12 | "time" 13 | ) 14 | 15 | // Signature headers 16 | const ( 17 | hSignature = "X-Slack-Signature" 18 | hTimestamp = "X-Slack-Request-Timestamp" 19 | ) 20 | 21 | // SecretsVerifier contains the information needed to verify that the request comes from Slack 22 | type SecretsVerifier struct { 23 | signature []byte 24 | hmac hash.Hash 25 | } 26 | 27 | func unsafeSignatureVerifier(header http.Header, secret string) (_ SecretsVerifier, err error) { 28 | var ( 29 | bsignature []byte 30 | ) 31 | 32 | signature := header.Get(hSignature) 33 | stimestamp := header.Get(hTimestamp) 34 | 35 | if signature == "" || stimestamp == "" { 36 | return SecretsVerifier{}, ErrMissingHeaders 37 | } 38 | 39 | if bsignature, err = hex.DecodeString(strings.TrimPrefix(signature, "v0=")); err != nil { 40 | return SecretsVerifier{}, err 41 | } 42 | 43 | hash := hmac.New(sha256.New, []byte(secret)) 44 | if _, err = hash.Write([]byte(fmt.Sprintf("v0:%s:", stimestamp))); err != nil { 45 | return SecretsVerifier{}, err 46 | } 47 | 48 | return SecretsVerifier{ 49 | signature: bsignature, 50 | hmac: hash, 51 | }, nil 52 | } 53 | 54 | // NewSecretsVerifier returns a SecretsVerifier object in exchange for an http.Header object and signing secret 55 | func NewSecretsVerifier(header http.Header, secret string) (sv SecretsVerifier, err error) { 56 | var ( 57 | timestamp int64 58 | ) 59 | 60 | stimestamp := header.Get(hTimestamp) 61 | 62 | if sv, err = unsafeSignatureVerifier(header, secret); err != nil { 63 | return SecretsVerifier{}, err 64 | } 65 | 66 | if timestamp, err = strconv.ParseInt(stimestamp, 10, 64); err != nil { 67 | return SecretsVerifier{}, err 68 | } 69 | 70 | diff := absDuration(time.Since(time.Unix(timestamp, 0))) 71 | if diff > 5*time.Minute { 72 | return SecretsVerifier{}, ErrExpiredTimestamp 73 | } 74 | 75 | return sv, err 76 | } 77 | 78 | func (v *SecretsVerifier) Write(body []byte) (n int, err error) { 79 | return v.hmac.Write(body) 80 | } 81 | 82 | // Ensure compares the signature sent from Slack with the actual computed hash to judge validity 83 | func (v SecretsVerifier) Ensure() error { 84 | computed := v.hmac.Sum(nil) 85 | // use hmac.Equal prevent leaking timing information. 86 | if hmac.Equal(computed, v.signature) { 87 | return nil 88 | } 89 | 90 | return fmt.Errorf("Expected signing signature: %s, but computed: %s", hex.EncodeToString(v.signature), hex.EncodeToString(computed)) 91 | } 92 | 93 | func abs64(n int64) int64 { 94 | y := n >> 63 95 | return (n ^ y) - y 96 | } 97 | 98 | func absDuration(n time.Duration) time.Duration { 99 | return time.Duration(abs64(int64(n))) 100 | } 101 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/slackutilsx/slackutilsx.go: -------------------------------------------------------------------------------- 1 | // Package slackutilsx is a utility package that doesn't promise API stability. 2 | // its for experimental functionality and utilities. 3 | package slackutilsx 4 | 5 | import ( 6 | "strings" 7 | "unicode/utf8" 8 | ) 9 | 10 | // ChannelType the type of channel based on the channelID 11 | type ChannelType int 12 | 13 | func (t ChannelType) String() string { 14 | switch t { 15 | case CTypeDM: 16 | return "Direct" 17 | case CTypeGroup: 18 | return "Group" 19 | case CTypeChannel: 20 | return "Channel" 21 | default: 22 | return "Unknown" 23 | } 24 | } 25 | 26 | const ( 27 | // CTypeUnknown represents channels we cannot properly detect. 28 | CTypeUnknown ChannelType = iota 29 | // CTypeDM is a private channel between two slack users. 30 | CTypeDM 31 | // CTypeGroup is a group channel. 32 | CTypeGroup 33 | // CTypeChannel is a public channel. 34 | CTypeChannel 35 | ) 36 | 37 | // DetectChannelType converts a channelID to a ChannelType. 38 | // channelID must not be empty. However, if it is empty, the channel type will default to Unknown. 39 | func DetectChannelType(channelID string) ChannelType { 40 | // intentionally ignore the error and just default to CTypeUnknown 41 | switch r, _ := utf8.DecodeRuneInString(channelID); r { 42 | case 'C': 43 | return CTypeChannel 44 | case 'G': 45 | return CTypeGroup 46 | case 'D': 47 | return CTypeDM 48 | default: 49 | return CTypeUnknown 50 | } 51 | } 52 | 53 | // EscapeMessage text 54 | func EscapeMessage(message string) string { 55 | replacer := strings.NewReplacer("&", "&", "<", "<", ">", ">") 56 | return replacer.Replace(message) 57 | } 58 | 59 | // Retryable errors return true. 60 | type Retryable interface { 61 | Retryable() bool 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/slash.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // SlashCommand contains information about a request of the slash command 8 | type SlashCommand struct { 9 | Token string `json:"token"` 10 | TeamID string `json:"team_id"` 11 | TeamDomain string `json:"team_domain"` 12 | EnterpriseID string `json:"enterprise_id,omitempty"` 13 | EnterpriseName string `json:"enterprise_name,omitempty"` 14 | ChannelID string `json:"channel_id"` 15 | ChannelName string `json:"channel_name"` 16 | UserID string `json:"user_id"` 17 | UserName string `json:"user_name"` 18 | Command string `json:"command"` 19 | Text string `json:"text"` 20 | ResponseURL string `json:"response_url"` 21 | TriggerID string `json:"trigger_id"` 22 | } 23 | 24 | // SlashCommandParse will parse the request of the slash command 25 | func SlashCommandParse(r *http.Request) (s SlashCommand, err error) { 26 | if err = r.ParseForm(); err != nil { 27 | return s, err 28 | } 29 | s.Token = r.PostForm.Get("token") 30 | s.TeamID = r.PostForm.Get("team_id") 31 | s.TeamDomain = r.PostForm.Get("team_domain") 32 | s.EnterpriseID = r.PostForm.Get("enterprise_id") 33 | s.EnterpriseName = r.PostForm.Get("enterprise_name") 34 | s.ChannelID = r.PostForm.Get("channel_id") 35 | s.ChannelName = r.PostForm.Get("channel_name") 36 | s.UserID = r.PostForm.Get("user_id") 37 | s.UserName = r.PostForm.Get("user_name") 38 | s.Command = r.PostForm.Get("command") 39 | s.Text = r.PostForm.Get("text") 40 | s.ResponseURL = r.PostForm.Get("response_url") 41 | s.TriggerID = r.PostForm.Get("trigger_id") 42 | return s, nil 43 | } 44 | 45 | // ValidateToken validates verificationTokens 46 | func (s SlashCommand) ValidateToken(verificationTokens ...string) bool { 47 | for _, token := range verificationTokens { 48 | if s.Token == token { 49 | return true 50 | } 51 | } 52 | return false 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/webhooks.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | type WebhookMessage struct { 9 | Username string `json:"username,omitempty"` 10 | IconEmoji string `json:"icon_emoji,omitempty"` 11 | IconURL string `json:"icon_url,omitempty"` 12 | Channel string `json:"channel,omitempty"` 13 | ThreadTimestamp string `json:"thread_ts,omitempty"` 14 | Text string `json:"text,omitempty"` 15 | Attachments []Attachment `json:"attachments,omitempty"` 16 | Parse string `json:"parse,omitempty"` 17 | } 18 | 19 | func PostWebhook(url string, msg *WebhookMessage) error { 20 | return PostWebhookCustomHTTPContext(context.Background(), url, http.DefaultClient, msg) 21 | } 22 | 23 | func PostWebhookContext(ctx context.Context, url string, msg *WebhookMessage) error { 24 | return PostWebhookCustomHTTPContext(ctx, url, http.DefaultClient, msg) 25 | } 26 | 27 | func PostWebhookCustomHTTP(url string, httpClient *http.Client, msg *WebhookMessage) error { 28 | return PostWebhookCustomHTTPContext(context.Background(), url, httpClient, msg) 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/webhooks_go112.go: -------------------------------------------------------------------------------- 1 | // +build !go1.13 2 | 3 | package slack 4 | 5 | import ( 6 | "bytes" 7 | "context" 8 | "encoding/json" 9 | "net/http" 10 | 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | func PostWebhookCustomHTTPContext(ctx context.Context, url string, httpClient *http.Client, msg *WebhookMessage) error { 15 | raw, err := json.Marshal(msg) 16 | if err != nil { 17 | return errors.Wrap(err, "marshal failed") 18 | } 19 | 20 | req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(raw)) 21 | if err != nil { 22 | return errors.Wrap(err, "failed new request") 23 | } 24 | req = req.WithContext(ctx) 25 | req.Header.Set("Content-Type", "application/json") 26 | 27 | resp, err := httpClient.Do(req) 28 | if err != nil { 29 | return errors.Wrap(err, "failed to post webhook") 30 | } 31 | defer resp.Body.Close() 32 | 33 | return checkStatusCode(resp, discard{}) 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/webhooks_go113.go: -------------------------------------------------------------------------------- 1 | // +build go1.13 2 | 3 | package slack 4 | 5 | import ( 6 | "bytes" 7 | "context" 8 | "encoding/json" 9 | "net/http" 10 | 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | func PostWebhookCustomHTTPContext(ctx context.Context, url string, httpClient *http.Client, msg *WebhookMessage) error { 15 | raw, err := json.Marshal(msg) 16 | if err != nil { 17 | return errors.Wrap(err, "marshal failed") 18 | } 19 | 20 | req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(raw)) 21 | if err != nil { 22 | return errors.Wrap(err, "failed new request") 23 | } 24 | req.Header.Set("Content-Type", "application/json") 25 | 26 | resp, err := httpClient.Do(req) 27 | if err != nil { 28 | return errors.Wrap(err, "failed to post webhook") 29 | } 30 | defer resp.Body.Close() 31 | 32 | return checkStatusCode(resp, discard{}) 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "net/url" 5 | "sync" 6 | "time" 7 | 8 | "github.com/gorilla/websocket" 9 | ) 10 | 11 | const ( 12 | // MaxMessageTextLength is the current maximum message length in number of characters as defined here 13 | // https://api.slack.com/rtm#limits 14 | MaxMessageTextLength = 4000 15 | ) 16 | 17 | // RTM represents a managed websocket connection. It also supports 18 | // all the methods of the `Client` type. 19 | // 20 | // Create this element with Client's NewRTM() or NewRTMWithOptions(*RTMOptions) 21 | type RTM struct { 22 | // Client is the main API, embedded 23 | Client 24 | 25 | idGen IDGenerator 26 | pingInterval time.Duration 27 | pingDeadman *time.Timer 28 | 29 | // Connection life-cycle 30 | conn *websocket.Conn 31 | IncomingEvents chan RTMEvent 32 | outgoingMessages chan OutgoingMessage 33 | killChannel chan bool 34 | disconnected chan struct{} 35 | disconnectedm *sync.Once 36 | forcePing chan bool 37 | 38 | // UserDetails upon connection 39 | info *Info 40 | 41 | // useRTMStart should be set to true if you want to use 42 | // rtm.start to connect to Slack, otherwise it will use 43 | // rtm.connect 44 | useRTMStart bool 45 | 46 | // dialer is a gorilla/websocket Dialer. If nil, use the default 47 | // Dialer. 48 | dialer *websocket.Dialer 49 | 50 | // mu is mutex used to prevent RTM connection race conditions 51 | mu *sync.Mutex 52 | 53 | // connParams is a map of flags for connection parameters. 54 | connParams url.Values 55 | } 56 | 57 | // signal that we are disconnected by closing the channel. 58 | // protect it with a mutex to ensure it only happens once. 59 | func (rtm *RTM) disconnect() { 60 | rtm.disconnectedm.Do(func() { 61 | close(rtm.disconnected) 62 | }) 63 | } 64 | 65 | // Disconnect and wait, blocking until a successful disconnection. 66 | func (rtm *RTM) Disconnect() error { 67 | // always push into the kill channel when invoked, 68 | // this lets the ManagedConnection() function properly clean up. 69 | // if the buffer is full then just continue on. 70 | select { 71 | case rtm.killChannel <- true: 72 | return nil 73 | case <-rtm.disconnected: 74 | return ErrAlreadyDisconnected 75 | } 76 | } 77 | 78 | // GetInfo returns the info structure received when calling 79 | // "startrtm", holding metadata needed to implement a full 80 | // chat client. It will be non-nil after a call to StartRTM(). 81 | func (rtm *RTM) GetInfo() *Info { 82 | return rtm.info 83 | } 84 | 85 | // SendMessage submits a simple message through the websocket. For 86 | // more complicated messages, use `rtm.PostMessage` with a complete 87 | // struct describing your attachments and all. 88 | func (rtm *RTM) SendMessage(msg *OutgoingMessage) { 89 | if msg == nil { 90 | rtm.Debugln("Error: Attempted to SendMessage(nil)") 91 | return 92 | } 93 | 94 | rtm.outgoingMessages <- *msg 95 | } 96 | 97 | func (rtm *RTM) resetDeadman() { 98 | rtm.pingDeadman.Reset(deadmanDuration(rtm.pingInterval)) 99 | } 100 | 101 | func deadmanDuration(d time.Duration) time.Duration { 102 | return d * 4 103 | } 104 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_channels.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // ChannelCreatedEvent represents the Channel created event 4 | type ChannelCreatedEvent struct { 5 | Type string `json:"type"` 6 | Channel ChannelCreatedInfo `json:"channel"` 7 | EventTimestamp string `json:"event_ts"` 8 | } 9 | 10 | // ChannelCreatedInfo represents the information associated with the Channel created event 11 | type ChannelCreatedInfo struct { 12 | ID string `json:"id"` 13 | IsChannel bool `json:"is_channel"` 14 | Name string `json:"name"` 15 | Created int `json:"created"` 16 | Creator string `json:"creator"` 17 | } 18 | 19 | // ChannelJoinedEvent represents the Channel joined event 20 | type ChannelJoinedEvent struct { 21 | Type string `json:"type"` 22 | Channel Channel `json:"channel"` 23 | } 24 | 25 | // ChannelInfoEvent represents the Channel info event 26 | type ChannelInfoEvent struct { 27 | // channel_left 28 | // channel_deleted 29 | // channel_archive 30 | // channel_unarchive 31 | Type string `json:"type"` 32 | Channel string `json:"channel"` 33 | User string `json:"user,omitempty"` 34 | Timestamp string `json:"ts,omitempty"` 35 | } 36 | 37 | // ChannelRenameEvent represents the Channel rename event 38 | type ChannelRenameEvent struct { 39 | Type string `json:"type"` 40 | Channel ChannelRenameInfo `json:"channel"` 41 | Timestamp string `json:"event_ts"` 42 | } 43 | 44 | // ChannelRenameInfo represents the information associated with a Channel rename event 45 | type ChannelRenameInfo struct { 46 | ID string `json:"id"` 47 | Name string `json:"name"` 48 | Created int `json:"created"` 49 | } 50 | 51 | // ChannelHistoryChangedEvent represents the Channel history changed event 52 | type ChannelHistoryChangedEvent struct { 53 | Type string `json:"type"` 54 | Latest string `json:"latest"` 55 | Timestamp string `json:"ts"` 56 | EventTimestamp string `json:"event_ts"` 57 | } 58 | 59 | // ChannelMarkedEvent represents the Channel marked event 60 | type ChannelMarkedEvent ChannelInfoEvent 61 | 62 | // ChannelLeftEvent represents the Channel left event 63 | type ChannelLeftEvent ChannelInfoEvent 64 | 65 | // ChannelDeletedEvent represents the Channel deleted event 66 | type ChannelDeletedEvent ChannelInfoEvent 67 | 68 | // ChannelArchiveEvent represents the Channel archive event 69 | type ChannelArchiveEvent ChannelInfoEvent 70 | 71 | // ChannelUnarchiveEvent represents the Channel unarchive event 72 | type ChannelUnarchiveEvent ChannelInfoEvent 73 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_desktop_notification.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // DesktopNotificationEvent represents the update event for Desktop Notification. 4 | type DesktopNotificationEvent struct { 5 | Type string `json:"type"` 6 | Title string `json:"title"` 7 | Subtitle string `json:"subtitle"` 8 | Message string `json:"msg"` 9 | Timestamp string `json:"ts"` 10 | Content string `json:"content"` 11 | Channel string `json:"channel"` 12 | LaunchURI string `json:"launchUri"` 13 | AvatarImage string `json:"avatarImage"` 14 | SsbFilename string `json:"ssbFilename"` 15 | ImageURI string `json:"imageUri"` 16 | IsShared bool `json:"is_shared"` 17 | IsChannelInvite bool `json:"is_channel_invite"` 18 | EventTimestamp string `json:"event_ts"` 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_dm.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // IMCreatedEvent represents the IM created event 4 | type IMCreatedEvent struct { 5 | Type string `json:"type"` 6 | User string `json:"user"` 7 | Channel ChannelCreatedInfo `json:"channel"` 8 | } 9 | 10 | // IMHistoryChangedEvent represents the IM history changed event 11 | type IMHistoryChangedEvent ChannelHistoryChangedEvent 12 | 13 | // IMOpenEvent represents the IM open event 14 | type IMOpenEvent ChannelInfoEvent 15 | 16 | // IMCloseEvent represents the IM close event 17 | type IMCloseEvent ChannelInfoEvent 18 | 19 | // IMMarkedEvent represents the IM marked event 20 | type IMMarkedEvent ChannelInfoEvent 21 | 22 | // IMMarkedHistoryChanged represents the IM marked history changed event 23 | type IMMarkedHistoryChanged ChannelInfoEvent 24 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_dnd.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // DNDUpdatedEvent represents the update event for Do Not Disturb 4 | type DNDUpdatedEvent struct { 5 | Type string `json:"type"` 6 | User string `json:"user"` 7 | Status DNDStatus `json:"dnd_status"` 8 | } 9 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_files.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // FileActionEvent represents the File action event 4 | type fileActionEvent struct { 5 | Type string `json:"type"` 6 | EventTimestamp string `json:"event_ts"` 7 | File File `json:"file"` 8 | // FileID is used for FileDeletedEvent 9 | FileID string `json:"file_id,omitempty"` 10 | } 11 | 12 | // FileCreatedEvent represents the File created event 13 | type FileCreatedEvent fileActionEvent 14 | 15 | // FileSharedEvent represents the File shared event 16 | type FileSharedEvent fileActionEvent 17 | 18 | // FilePublicEvent represents the File public event 19 | type FilePublicEvent fileActionEvent 20 | 21 | // FileUnsharedEvent represents the File unshared event 22 | type FileUnsharedEvent fileActionEvent 23 | 24 | // FileChangeEvent represents the File change event 25 | type FileChangeEvent fileActionEvent 26 | 27 | // FileDeletedEvent represents the File deleted event 28 | type FileDeletedEvent fileActionEvent 29 | 30 | // FilePrivateEvent represents the File private event 31 | type FilePrivateEvent fileActionEvent 32 | 33 | // FileCommentAddedEvent represents the File comment added event 34 | type FileCommentAddedEvent struct { 35 | fileActionEvent 36 | Comment Comment `json:"comment"` 37 | } 38 | 39 | // FileCommentEditedEvent represents the File comment edited event 40 | type FileCommentEditedEvent struct { 41 | fileActionEvent 42 | Comment Comment `json:"comment"` 43 | } 44 | 45 | // FileCommentDeletedEvent represents the File comment deleted event 46 | type FileCommentDeletedEvent struct { 47 | fileActionEvent 48 | Comment string `json:"comment"` 49 | } 50 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_groups.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // GroupCreatedEvent represents the Group created event 4 | type GroupCreatedEvent struct { 5 | Type string `json:"type"` 6 | User string `json:"user"` 7 | Channel ChannelCreatedInfo `json:"channel"` 8 | } 9 | 10 | // XXX: Should we really do this? event.Group is probably nicer than event.Channel 11 | // even though the api returns "channel" 12 | 13 | // GroupMarkedEvent represents the Group marked event 14 | type GroupMarkedEvent ChannelInfoEvent 15 | 16 | // GroupOpenEvent represents the Group open event 17 | type GroupOpenEvent ChannelInfoEvent 18 | 19 | // GroupCloseEvent represents the Group close event 20 | type GroupCloseEvent ChannelInfoEvent 21 | 22 | // GroupArchiveEvent represents the Group archive event 23 | type GroupArchiveEvent ChannelInfoEvent 24 | 25 | // GroupUnarchiveEvent represents the Group unarchive event 26 | type GroupUnarchiveEvent ChannelInfoEvent 27 | 28 | // GroupLeftEvent represents the Group left event 29 | type GroupLeftEvent ChannelInfoEvent 30 | 31 | // GroupJoinedEvent represents the Group joined event 32 | type GroupJoinedEvent ChannelJoinedEvent 33 | 34 | // GroupRenameEvent represents the Group rename event 35 | type GroupRenameEvent struct { 36 | Type string `json:"type"` 37 | Group GroupRenameInfo `json:"channel"` 38 | Timestamp string `json:"ts"` 39 | } 40 | 41 | // GroupRenameInfo represents the group info related to the renamed group 42 | type GroupRenameInfo struct { 43 | ID string `json:"id"` 44 | Name string `json:"name"` 45 | Created string `json:"created"` 46 | } 47 | 48 | // GroupHistoryChangedEvent represents the Group history changed event 49 | type GroupHistoryChangedEvent ChannelHistoryChangedEvent 50 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_internals.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | /** 9 | * Internal events, created by this lib and not mapped to Slack APIs. 10 | */ 11 | 12 | // ConnectedEvent is used for when we connect to Slack 13 | type ConnectedEvent struct { 14 | ConnectionCount int // 1 = first time, 2 = second time 15 | Info *Info 16 | } 17 | 18 | // ConnectionErrorEvent contains information about a connection error 19 | type ConnectionErrorEvent struct { 20 | Attempt int 21 | Backoff time.Duration // how long we'll wait before the next attempt 22 | ErrorObj error 23 | } 24 | 25 | func (c *ConnectionErrorEvent) Error() string { 26 | return c.ErrorObj.Error() 27 | } 28 | 29 | // ConnectingEvent contains information about our connection attempt 30 | type ConnectingEvent struct { 31 | Attempt int // 1 = first attempt, 2 = second attempt 32 | ConnectionCount int 33 | } 34 | 35 | // DisconnectedEvent contains information about how we disconnected 36 | type DisconnectedEvent struct { 37 | Intentional bool 38 | Cause error 39 | } 40 | 41 | // LatencyReport contains information about connection latency 42 | type LatencyReport struct { 43 | Value time.Duration 44 | } 45 | 46 | // InvalidAuthEvent is used in case we can't even authenticate with the API 47 | type InvalidAuthEvent struct{} 48 | 49 | // UnmarshallingErrorEvent is used when there are issues deconstructing a response 50 | type UnmarshallingErrorEvent struct { 51 | ErrorObj error 52 | } 53 | 54 | func (u UnmarshallingErrorEvent) Error() string { 55 | return u.ErrorObj.Error() 56 | } 57 | 58 | // MessageTooLongEvent is used when sending a message that is too long 59 | type MessageTooLongEvent struct { 60 | Message OutgoingMessage 61 | MaxLength int 62 | } 63 | 64 | func (m *MessageTooLongEvent) Error() string { 65 | return fmt.Sprintf("Message too long (max %d characters)", m.MaxLength) 66 | } 67 | 68 | // RateLimitEvent is used when Slack warns that rate-limits are being hit. 69 | type RateLimitEvent struct{} 70 | 71 | func (e *RateLimitEvent) Error() string { 72 | return "Messages are being sent too fast." 73 | } 74 | 75 | // OutgoingErrorEvent contains information in case there were errors sending messages 76 | type OutgoingErrorEvent struct { 77 | Message OutgoingMessage 78 | ErrorObj error 79 | } 80 | 81 | func (o OutgoingErrorEvent) Error() string { 82 | return o.ErrorObj.Error() 83 | } 84 | 85 | // IncomingEventError contains information about an unexpected error receiving a websocket event 86 | type IncomingEventError struct { 87 | ErrorObj error 88 | } 89 | 90 | func (i *IncomingEventError) Error() string { 91 | return i.ErrorObj.Error() 92 | } 93 | 94 | // AckErrorEvent i 95 | type AckErrorEvent struct { 96 | ErrorObj error 97 | } 98 | 99 | func (a *AckErrorEvent) Error() string { 100 | return a.ErrorObj.Error() 101 | } 102 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_mobile_in_app_notification.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // MobileInAppNotificationEvent represents the update event for Mobile App Notification. 4 | type MobileInAppNotificationEvent struct { 5 | Type string `json:"type"` 6 | Title string `json:"title"` 7 | Subtitle string `json:"subtitle"` 8 | Timestamp string `json:"ts"` 9 | Channel string `json:"channel"` 10 | AvatarImage string `json:"avatarImage"` 11 | IsShared bool `json:"is_shared"` 12 | ChannelName string `json:"channel_name"` 13 | AuthorID string `json:"author_id"` 14 | AuthorDisplayName string `json:"author_display_name"` 15 | MessageText string `json:"msg_text"` 16 | PushID string `json:"push_id"` 17 | NotifcationID string `json:"notif_id"` 18 | MobileLaunchURI string `json:"mobileLaunchUri"` 19 | EventTimestamp string `json:"event_ts"` 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_pins.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | type pinEvent struct { 4 | Type string `json:"type"` 5 | User string `json:"user"` 6 | Item Item `json:"item"` 7 | Channel string `json:"channel_id"` 8 | EventTimestamp string `json:"event_ts"` 9 | HasPins bool `json:"has_pins,omitempty"` 10 | } 11 | 12 | // PinAddedEvent represents the Pin added event 13 | type PinAddedEvent pinEvent 14 | 15 | // PinRemovedEvent represents the Pin removed event 16 | type PinRemovedEvent pinEvent 17 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_reactions.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // reactionItem is a lighter-weight item than is returned by the reactions list. 4 | type reactionItem struct { 5 | Type string `json:"type"` 6 | Channel string `json:"channel,omitempty"` 7 | File string `json:"file,omitempty"` 8 | FileComment string `json:"file_comment,omitempty"` 9 | Timestamp string `json:"ts,omitempty"` 10 | } 11 | 12 | type reactionEvent struct { 13 | Type string `json:"type"` 14 | User string `json:"user"` 15 | ItemUser string `json:"item_user"` 16 | Item reactionItem `json:"item"` 17 | Reaction string `json:"reaction"` 18 | EventTimestamp string `json:"event_ts"` 19 | } 20 | 21 | // ReactionAddedEvent represents the Reaction added event 22 | type ReactionAddedEvent reactionEvent 23 | 24 | // ReactionRemovedEvent represents the Reaction removed event 25 | type ReactionRemovedEvent reactionEvent 26 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_stars.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | type starEvent struct { 4 | Type string `json:"type"` 5 | User string `json:"user"` 6 | Item StarredItem `json:"item"` 7 | EventTimestamp string `json:"event_ts"` 8 | } 9 | 10 | // StarAddedEvent represents the Star added event 11 | type StarAddedEvent starEvent 12 | 13 | // StarRemovedEvent represents the Star removed event 14 | type StarRemovedEvent starEvent 15 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_subteam.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // SubteamCreatedEvent represents the Subteam created event 4 | type SubteamCreatedEvent struct { 5 | Type string `json:"type"` 6 | Subteam UserGroup `json:"subteam"` 7 | } 8 | 9 | // SubteamCreatedEvent represents the membership of an existing User Group has changed event 10 | type SubteamMembersChangedEvent struct { 11 | Type string `json:"type"` 12 | SubteamID string `json:"subteam_id"` 13 | TeamID string `json:"team_id"` 14 | DatePreviousUpdate JSONTime `json:"date_previous_update"` 15 | DateUpdate JSONTime `json:"date_update"` 16 | AddedUsers []string `json:"added_users"` 17 | AddedUsersCount string `json:"added_users_count"` 18 | RemovedUsers []string `json:"removed_users"` 19 | RemovedUsersCount string `json:"removed_users_count"` 20 | } 21 | 22 | // SubteamSelfAddedEvent represents an event of you have been added to a User Group 23 | type SubteamSelfAddedEvent struct { 24 | Type string `json:"type"` 25 | SubteamID string `json:"subteam_id"` 26 | } 27 | 28 | // SubteamSelfRemovedEvent represents an event of you have been removed from a User Group 29 | type SubteamSelfRemovedEvent SubteamSelfAddedEvent 30 | 31 | // SubteamUpdatedEvent represents an event of an existing User Group has been updated or its members changed 32 | type SubteamUpdatedEvent struct { 33 | Type string `json:"type"` 34 | Subteam UserGroup `json:"subteam"` 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/slack-go/slack/websocket_teams.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | // TeamJoinEvent represents the Team join event 4 | type TeamJoinEvent struct { 5 | Type string `json:"type"` 6 | User User `json:"user"` 7 | } 8 | 9 | // TeamRenameEvent represents the Team rename event 10 | type TeamRenameEvent struct { 11 | Type string `json:"type"` 12 | Name string `json:"name,omitempty"` 13 | EventTimestamp string `json:"event_ts,omitempty"` 14 | } 15 | 16 | // TeamPrefChangeEvent represents the Team preference change event 17 | type TeamPrefChangeEvent struct { 18 | Type string `json:"type"` 19 | Name string `json:"name,omitempty"` 20 | Value []string `json:"value,omitempty"` 21 | } 22 | 23 | // TeamDomainChangeEvent represents the Team domain change event 24 | type TeamDomainChangeEvent struct { 25 | Type string `json:"type"` 26 | URL string `json:"url"` 27 | Domain string `json:"domain"` 28 | } 29 | 30 | // TeamMigrationStartedEvent represents the Team migration started event 31 | type TeamMigrationStartedEvent struct { 32 | Type string `json:"type"` 33 | } 34 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/unicode/norm/input.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm 6 | 7 | import "unicode/utf8" 8 | 9 | type input struct { 10 | str string 11 | bytes []byte 12 | } 13 | 14 | func inputBytes(str []byte) input { 15 | return input{bytes: str} 16 | } 17 | 18 | func inputString(str string) input { 19 | return input{str: str} 20 | } 21 | 22 | func (in *input) setBytes(str []byte) { 23 | in.str = "" 24 | in.bytes = str 25 | } 26 | 27 | func (in *input) setString(str string) { 28 | in.str = str 29 | in.bytes = nil 30 | } 31 | 32 | func (in *input) _byte(p int) byte { 33 | if in.bytes == nil { 34 | return in.str[p] 35 | } 36 | return in.bytes[p] 37 | } 38 | 39 | func (in *input) skipASCII(p, max int) int { 40 | if in.bytes == nil { 41 | for ; p < max && in.str[p] < utf8.RuneSelf; p++ { 42 | } 43 | } else { 44 | for ; p < max && in.bytes[p] < utf8.RuneSelf; p++ { 45 | } 46 | } 47 | return p 48 | } 49 | 50 | func (in *input) skipContinuationBytes(p int) int { 51 | if in.bytes == nil { 52 | for ; p < len(in.str) && !utf8.RuneStart(in.str[p]); p++ { 53 | } 54 | } else { 55 | for ; p < len(in.bytes) && !utf8.RuneStart(in.bytes[p]); p++ { 56 | } 57 | } 58 | return p 59 | } 60 | 61 | func (in *input) appendSlice(buf []byte, b, e int) []byte { 62 | if in.bytes != nil { 63 | return append(buf, in.bytes[b:e]...) 64 | } 65 | for i := b; i < e; i++ { 66 | buf = append(buf, in.str[i]) 67 | } 68 | return buf 69 | } 70 | 71 | func (in *input) copySlice(buf []byte, b, e int) int { 72 | if in.bytes == nil { 73 | return copy(buf, in.str[b:e]) 74 | } 75 | return copy(buf, in.bytes[b:e]) 76 | } 77 | 78 | func (in *input) charinfoNFC(p int) (uint16, int) { 79 | if in.bytes == nil { 80 | return nfcData.lookupString(in.str[p:]) 81 | } 82 | return nfcData.lookup(in.bytes[p:]) 83 | } 84 | 85 | func (in *input) charinfoNFKC(p int) (uint16, int) { 86 | if in.bytes == nil { 87 | return nfkcData.lookupString(in.str[p:]) 88 | } 89 | return nfkcData.lookup(in.bytes[p:]) 90 | } 91 | 92 | func (in *input) hangul(p int) (r rune) { 93 | var size int 94 | if in.bytes == nil { 95 | if !isHangulString(in.str[p:]) { 96 | return 0 97 | } 98 | r, size = utf8.DecodeRuneInString(in.str[p:]) 99 | } else { 100 | if !isHangul(in.bytes[p:]) { 101 | return 0 102 | } 103 | r, size = utf8.DecodeRune(in.bytes[p:]) 104 | } 105 | if size != hangulUTF8Size { 106 | return 0 107 | } 108 | return r 109 | } 110 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/unicode/norm/readwriter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm 6 | 7 | import "io" 8 | 9 | type normWriter struct { 10 | rb reorderBuffer 11 | w io.Writer 12 | buf []byte 13 | } 14 | 15 | // Write implements the standard write interface. If the last characters are 16 | // not at a normalization boundary, the bytes will be buffered for the next 17 | // write. The remaining bytes will be written on close. 18 | func (w *normWriter) Write(data []byte) (n int, err error) { 19 | // Process data in pieces to keep w.buf size bounded. 20 | const chunk = 4000 21 | 22 | for len(data) > 0 { 23 | // Normalize into w.buf. 24 | m := len(data) 25 | if m > chunk { 26 | m = chunk 27 | } 28 | w.rb.src = inputBytes(data[:m]) 29 | w.rb.nsrc = m 30 | w.buf = doAppend(&w.rb, w.buf, 0) 31 | data = data[m:] 32 | n += m 33 | 34 | // Write out complete prefix, save remainder. 35 | // Note that lastBoundary looks back at most 31 runes. 36 | i := lastBoundary(&w.rb.f, w.buf) 37 | if i == -1 { 38 | i = 0 39 | } 40 | if i > 0 { 41 | if _, err = w.w.Write(w.buf[:i]); err != nil { 42 | break 43 | } 44 | bn := copy(w.buf, w.buf[i:]) 45 | w.buf = w.buf[:bn] 46 | } 47 | } 48 | return n, err 49 | } 50 | 51 | // Close forces data that remains in the buffer to be written. 52 | func (w *normWriter) Close() error { 53 | if len(w.buf) > 0 { 54 | _, err := w.w.Write(w.buf) 55 | if err != nil { 56 | return err 57 | } 58 | } 59 | return nil 60 | } 61 | 62 | // Writer returns a new writer that implements Write(b) 63 | // by writing f(b) to w. The returned writer may use an 64 | // internal buffer to maintain state across Write calls. 65 | // Calling its Close method writes any buffered data to w. 66 | func (f Form) Writer(w io.Writer) io.WriteCloser { 67 | wr := &normWriter{rb: reorderBuffer{}, w: w} 68 | wr.rb.init(f, nil) 69 | return wr 70 | } 71 | 72 | type normReader struct { 73 | rb reorderBuffer 74 | r io.Reader 75 | inbuf []byte 76 | outbuf []byte 77 | bufStart int 78 | lastBoundary int 79 | err error 80 | } 81 | 82 | // Read implements the standard read interface. 83 | func (r *normReader) Read(p []byte) (int, error) { 84 | for { 85 | if r.lastBoundary-r.bufStart > 0 { 86 | n := copy(p, r.outbuf[r.bufStart:r.lastBoundary]) 87 | r.bufStart += n 88 | if r.lastBoundary-r.bufStart > 0 { 89 | return n, nil 90 | } 91 | return n, r.err 92 | } 93 | if r.err != nil { 94 | return 0, r.err 95 | } 96 | outn := copy(r.outbuf, r.outbuf[r.lastBoundary:]) 97 | r.outbuf = r.outbuf[0:outn] 98 | r.bufStart = 0 99 | 100 | n, err := r.r.Read(r.inbuf) 101 | r.rb.src = inputBytes(r.inbuf[0:n]) 102 | r.rb.nsrc, r.err = n, err 103 | if n > 0 { 104 | r.outbuf = doAppend(&r.rb, r.outbuf, 0) 105 | } 106 | if err == io.EOF { 107 | r.lastBoundary = len(r.outbuf) 108 | } else { 109 | r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf) 110 | if r.lastBoundary == -1 { 111 | r.lastBoundary = 0 112 | } 113 | } 114 | } 115 | } 116 | 117 | // Reader returns a new reader that implements Read 118 | // by reading data from r and returning f(data). 119 | func (f Form) Reader(r io.Reader) io.Reader { 120 | const chunk = 4000 121 | buf := make([]byte, chunk) 122 | rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf} 123 | rr.rb.init(f, buf) 124 | return rr 125 | } 126 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/unicode/norm/transform.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm 6 | 7 | import ( 8 | "unicode/utf8" 9 | 10 | "golang.org/x/text/transform" 11 | ) 12 | 13 | // Reset implements the Reset method of the transform.Transformer interface. 14 | func (Form) Reset() {} 15 | 16 | // Transform implements the Transform method of the transform.Transformer 17 | // interface. It may need to write segments of up to MaxSegmentSize at once. 18 | // Users should either catch ErrShortDst and allow dst to grow or have dst be at 19 | // least of size MaxTransformChunkSize to be guaranteed of progress. 20 | func (f Form) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { 21 | // Cap the maximum number of src bytes to check. 22 | b := src 23 | eof := atEOF 24 | if ns := len(dst); ns < len(b) { 25 | err = transform.ErrShortDst 26 | eof = false 27 | b = b[:ns] 28 | } 29 | i, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), eof) 30 | n := copy(dst, b[:i]) 31 | if !ok { 32 | nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF) 33 | return nDst + n, nSrc + n, err 34 | } 35 | 36 | if err == nil && n < len(src) && !atEOF { 37 | err = transform.ErrShortSrc 38 | } 39 | return n, n, err 40 | } 41 | 42 | func flushTransform(rb *reorderBuffer) bool { 43 | // Write out (must fully fit in dst, or else it is an ErrShortDst). 44 | if len(rb.out) < rb.nrune*utf8.UTFMax { 45 | return false 46 | } 47 | rb.out = rb.out[rb.flushCopy(rb.out):] 48 | return true 49 | } 50 | 51 | var errs = []error{nil, transform.ErrShortDst, transform.ErrShortSrc} 52 | 53 | // transform implements the transform.Transformer interface. It is only called 54 | // when quickSpan does not pass for a given string. 55 | func (f Form) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { 56 | // TODO: get rid of reorderBuffer. See CL 23460044. 57 | rb := reorderBuffer{} 58 | rb.init(f, src) 59 | for { 60 | // Load segment into reorder buffer. 61 | rb.setFlusher(dst[nDst:], flushTransform) 62 | end := decomposeSegment(&rb, nSrc, atEOF) 63 | if end < 0 { 64 | return nDst, nSrc, errs[-end] 65 | } 66 | nDst = len(dst) - len(rb.out) 67 | nSrc = end 68 | 69 | // Next quickSpan. 70 | end = rb.nsrc 71 | eof := atEOF 72 | if n := nSrc + len(dst) - nDst; n < end { 73 | err = transform.ErrShortDst 74 | end = n 75 | eof = false 76 | } 77 | end, ok := rb.f.quickSpan(rb.src, nSrc, end, eof) 78 | n := copy(dst[nDst:], rb.src.bytes[nSrc:end]) 79 | nSrc += n 80 | nDst += n 81 | if ok { 82 | if err == nil && n < rb.nsrc && !atEOF { 83 | err = transform.ErrShortSrc 84 | } 85 | return nDst, nSrc, err 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/unicode/norm/trie.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm 6 | 7 | type valueRange struct { 8 | value uint16 // header: value:stride 9 | lo, hi byte // header: lo:n 10 | } 11 | 12 | type sparseBlocks struct { 13 | values []valueRange 14 | offset []uint16 15 | } 16 | 17 | var nfcSparse = sparseBlocks{ 18 | values: nfcSparseValues[:], 19 | offset: nfcSparseOffset[:], 20 | } 21 | 22 | var nfkcSparse = sparseBlocks{ 23 | values: nfkcSparseValues[:], 24 | offset: nfkcSparseOffset[:], 25 | } 26 | 27 | var ( 28 | nfcData = newNfcTrie(0) 29 | nfkcData = newNfkcTrie(0) 30 | ) 31 | 32 | // lookupValue determines the type of block n and looks up the value for b. 33 | // For n < t.cutoff, the block is a simple lookup table. Otherwise, the block 34 | // is a list of ranges with an accompanying value. Given a matching range r, 35 | // the value for b is by r.value + (b - r.lo) * stride. 36 | func (t *sparseBlocks) lookup(n uint32, b byte) uint16 { 37 | offset := t.offset[n] 38 | header := t.values[offset] 39 | lo := offset + 1 40 | hi := lo + uint16(header.lo) 41 | for lo < hi { 42 | m := lo + (hi-lo)/2 43 | r := t.values[m] 44 | if r.lo <= b && b <= r.hi { 45 | return r.value + uint16(b-r.lo)*header.value 46 | } 47 | if b < r.lo { 48 | hi = m 49 | } else { 50 | lo = m + 1 51 | } 52 | } 53 | return 0 54 | } 55 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/0xAX/notificator v0.0.0-20171022182052-88d57ee9043b 2 | github.com/0xAX/notificator 3 | # github.com/OpenPeeDeeP/xdg v0.2.0 4 | github.com/OpenPeeDeeP/xdg 5 | # github.com/erroneousboat/termui v0.0.0-20170923115141-80f245cdfa04 6 | github.com/erroneousboat/termui 7 | # github.com/gorilla/websocket v1.4.2 8 | github.com/gorilla/websocket 9 | # github.com/lithammer/fuzzysearch v1.1.0 10 | github.com/lithammer/fuzzysearch/fuzzy 11 | # github.com/maruel/panicparse v1.1.1 12 | github.com/maruel/panicparse/stack 13 | # github.com/mattn/go-runewidth v0.0.7 14 | github.com/mattn/go-runewidth 15 | # github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 16 | github.com/mitchellh/go-wordwrap 17 | # github.com/nsf/termbox-go v0.0.0-20191229070316-58d4fcbce2a7 18 | github.com/nsf/termbox-go 19 | # github.com/pkg/errors v0.9.1 20 | github.com/pkg/errors 21 | # github.com/slack-go/slack v0.6.3 22 | github.com/slack-go/slack 23 | github.com/slack-go/slack/internal/errorsx 24 | github.com/slack-go/slack/internal/timex 25 | github.com/slack-go/slack/slackutilsx 26 | # golang.org/x/text v0.3.2 27 | golang.org/x/text/runes 28 | golang.org/x/text/transform 29 | golang.org/x/text/unicode/norm 30 | -------------------------------------------------------------------------------- /views/load.go: -------------------------------------------------------------------------------- 1 | package views 2 | 3 | import ( 4 | termbox "github.com/nsf/termbox-go" 5 | ) 6 | 7 | func Loading() { 8 | const loading string = "LOADING" 9 | 10 | w, h := termbox.Size() 11 | termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) 12 | 13 | offset := (w / 2) - (len(loading) / 2) 14 | y := h / 2 15 | 16 | for x := 0; x < len(loading); x++ { 17 | termbox.SetCell(offset+x, y, rune(loading[x]), termbox.ColorDefault, termbox.ColorDefault) 18 | } 19 | 20 | termbox.Flush() 21 | } 22 | -------------------------------------------------------------------------------- /views/view.go: -------------------------------------------------------------------------------- 1 | package views 2 | 3 | import ( 4 | "github.com/erroneousboat/termui" 5 | 6 | "github.com/erroneousboat/slack-term/components" 7 | "github.com/erroneousboat/slack-term/config" 8 | "github.com/erroneousboat/slack-term/service" 9 | ) 10 | 11 | type View struct { 12 | Config *config.Config 13 | Input *components.Input 14 | Chat *components.Chat 15 | Channels *components.Channels 16 | Threads *components.Threads 17 | Mode *components.Mode 18 | Debug *components.Debug 19 | } 20 | 21 | func CreateView(config *config.Config, svc *service.SlackService) (*View, error) { 22 | // Create Input component 23 | input := components.CreateInputComponent() 24 | 25 | // Channels: create the component 26 | sideBarHeight := termui.TermHeight() - input.Par.Height 27 | channels := components.CreateChannelsComponent(sideBarHeight) 28 | 29 | // Channels: fill the component 30 | slackChans, err := svc.GetChannels() 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | // Channels: set channels in component 36 | channels.SetChannels(slackChans) 37 | 38 | // Threads: create component 39 | threads := components.CreateThreadsComponent(sideBarHeight) 40 | 41 | // Chat: create the component 42 | chat := components.CreateChatComponent(input.Par.Height) 43 | 44 | // Chat: fill the component 45 | msgs, thr, err := svc.GetMessages( 46 | channels.ChannelItems[channels.SelectedChannel].ID, 47 | chat.GetMaxItems(), 48 | ) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | // Chat: set messages in component 54 | chat.SetMessages(msgs) 55 | 56 | chat.SetBorderLabel( 57 | channels.ChannelItems[channels.SelectedChannel].GetChannelName(), 58 | ) 59 | 60 | // Threads: set threads in component 61 | if len(thr) > 0 { 62 | 63 | // Make the first thread the current Channel 64 | threads.SetChannels( 65 | append( 66 | []components.ChannelItem{channels.GetSelectedChannel()}, 67 | thr..., 68 | ), 69 | ) 70 | } 71 | 72 | // Debug: create the component 73 | debug := components.CreateDebugComponent(input.Par.Height) 74 | 75 | // Mode: create the component 76 | mode := components.CreateModeComponent() 77 | 78 | view := &View{ 79 | Config: config, 80 | Input: input, 81 | Channels: channels, 82 | Threads: threads, 83 | Chat: chat, 84 | Mode: mode, 85 | Debug: debug, 86 | } 87 | 88 | return view, nil 89 | } 90 | 91 | func (v *View) Refresh() { 92 | termui.Render( 93 | v.Input, 94 | v.Chat, 95 | v.Channels, 96 | v.Threads, 97 | v.Mode, 98 | ) 99 | } 100 | --------------------------------------------------------------------------------