diff options
author | Michael Muré <batolettre@gmail.com> | 2020-02-05 22:03:19 +0100 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2020-02-05 22:33:03 +0100 |
commit | 1d4bb7ceb0cef79d68df0bacc913b01e40e6ddd6 (patch) | |
tree | e088b0fa43058afde1db71541d8fcb4b94905d6e /vendor/github.com/awesome-gocui/gocui | |
parent | f093be96e98284580d61664adecd0a2ff8b354e4 (diff) | |
download | git-bug-1d4bb7ceb0cef79d68df0bacc913b01e40e6ddd6.tar.gz |
migrate to go modules
Diffstat (limited to 'vendor/github.com/awesome-gocui/gocui')
18 files changed, 0 insertions, 3247 deletions
diff --git a/vendor/github.com/awesome-gocui/gocui/.gitignore b/vendor/github.com/awesome-gocui/gocui/.gitignore deleted file mode 100644 index 1377554e..00000000 --- a/vendor/github.com/awesome-gocui/gocui/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.swp diff --git a/vendor/github.com/awesome-gocui/gocui/AUTHORS b/vendor/github.com/awesome-gocui/gocui/AUTHORS deleted file mode 100644 index 43ec4cec..00000000 --- a/vendor/github.com/awesome-gocui/gocui/AUTHORS +++ /dev/null @@ -1,30 +0,0 @@ -# This is the official list of gocui authors for copyright purposes. - -# Names should be added to this file as -# Name or Organization <email address> contribution -# Contribution -# The email address is not required for organizations. - -Roi Martin <jroi.martin@gmail.com> - Main developer - -Ryan Sullivan <kayoticsully@gmail.com> - Toggleable view frames - -Matthieu Rakotojaona <matthieu.rakotojaona@gmail.com> - Wrapped views - -Harry Lawrence <hazbo@gmx.com> - Basic mouse support - -Danny Tylman <dtylman@gmail.com> - Masked views - -Frederik Deweerdt <frederik.deweerdt@gmail.com> - Colored fonts - -Henri Koski <henri.t.koski@gmail.com> - Custom current view color - -Dustin Willis Webber <dustin.webber@gmail.com> - 256-colors output mode support diff --git a/vendor/github.com/awesome-gocui/gocui/CODE_OF_CONDUCT.md b/vendor/github.com/awesome-gocui/gocui/CODE_OF_CONDUCT.md deleted file mode 100644 index 1bdac055..00000000 --- a/vendor/github.com/awesome-gocui/gocui/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,76 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at mkopenga@gmail.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq diff --git a/vendor/github.com/awesome-gocui/gocui/CONTRIBUTING.md b/vendor/github.com/awesome-gocui/gocui/CONTRIBUTING.md deleted file mode 100644 index b93e45b2..00000000 --- a/vendor/github.com/awesome-gocui/gocui/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -# Contributing - -Everyone is welcome to help make gocui better! - -When contributing to this repository, please first discuss the change you wish -to make via issue, email, or any other method with the owners of this repository -before making a change. - -## So all code changes happen through Pull Requests -Pull requests are the best way to propose changes to the codebase. We actively -welcome your pull requests: - -1. Fork the repo and create your branch from `master` with a name like `feature/contributors-guide`. -2. If you've added code that should be tested, add tests. -3. If you've added code that need documentation, update the documentation. -4. Make sure your code follows the [effective go](https://golang.org/doc/effective_go.html) guidelines as much as possible. -5. Be sure to test your modifications. -6. Make sure your branch is up to date with the master branch. -7. Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). -8. Create that pull request! - -## Code of conduct -Please note by participating in this project, you agree to abide by the [code of conduct]. - -[code of conduct]: https://github.com/awesome-gocui/gocui/blob/master/CODE-OF-CONDUCT.md - -## Any contributions you make will be under the license indicated in the [license](LICENSE.md) -In short, when you submit code changes, your submissions are understood to be -under the same license as the rest of project. Feel free to contact the maintainers if that's a concern. - -## Report bugs using Github's [issues](https://github.com/awesome-gocui/gocui/issues) -We use GitHub issues to track public bugs. Report a bug by [opening a new -issue](https://github.com/awesome-gocui/gocui/issues/new); it's that easy!
\ No newline at end of file diff --git a/vendor/github.com/awesome-gocui/gocui/LICENSE b/vendor/github.com/awesome-gocui/gocui/LICENSE deleted file mode 100644 index 8cb28215..00000000 --- a/vendor/github.com/awesome-gocui/gocui/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2014 The gocui Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the gocui Authors nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/awesome-gocui/gocui/README.md b/vendor/github.com/awesome-gocui/gocui/README.md deleted file mode 100644 index be212c58..00000000 --- a/vendor/github.com/awesome-gocui/gocui/README.md +++ /dev/null @@ -1,135 +0,0 @@ -# GOCUI - Go Console User Interface -[![CircleCI](https://circleci.com/gh/awesome-gocui/gocui/tree/master.svg?style=svg)](https://circleci.com/gh/awesome-gocui/gocui/tree/master) -[![CodeCov](https://codecov.io/gh/awesome-gocui/gocui/branch/master/graph/badge.svg)](https://codecov.io/gh/awesome-gocui/gocui) -[![Go Report Card](https://goreportcard.com/badge/github.com/awesome-gocui/gocui)](https://goreportcard.com/report/github.com/awesome-gocui/gocui) -[![GolangCI](https://golangci.com/badges/github.com/awesome-gocui/gocui.svg)](https://golangci.com/badges/github.com/awesome-gocui/gocui.svg) -[![GoDoc](https://godoc.org/github.com/awesome-gocui/gocui?status.svg)](https://godoc.org/github.com/awesome-gocui/gocui) -![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/awesome-gocui/gocui.svg) - -Minimalist Go package aimed at creating Console User Interfaces. -A community fork based on the amazing work of [jroimartin](https://github.com/jroimartin/gocui) - -## Features - -* Minimalist API. -* Views (the "windows" in the GUI) implement the interface io.ReadWriter. -* Support for overlapping views. -* The GUI can be modified at runtime (concurrent-safe). -* Global and view-level keybindings. -* Mouse support. -* Colored text. -* Customizable editing mode. -* Easy to build reusable widgets, complex layouts... - -## About fork - -This fork has many improvements over the original work from [jroimartin](https://github.com/jroimartin/gocui). - -* Better wide character support -* Support for 1 Line height views -* Better support for running in docker container -* Customize frame colors -* Improved code comments and quality -* Many small improvements -* Change Visibility of views - -For information about this org see: [awesome-gocui/about](https://github.com/awesome-gocui/about). - -## Installation - -Execute: - -``` -$ go get github.com/awesome-gocui/gocui -``` - -## Documentation - -Execute: - -``` -$ go doc github.com/awesome-gocui/gocui -``` - -Or visit [godoc.org](https://godoc.org/github.com/awesome-gocui/gocui) to read it -online. - -## Example -See the [_example](./_example/) folder for more examples - -```go -package main - -import ( - "fmt" - "log" - - "github.com/awesome-gocui/gocui" -) - -func main() { - g, err := gocui.NewGui(gocui.OutputNormal, false) - if err != nil { - log.Panicln(err) - } - defer g.Close() - - g.SetManagerFunc(layout) - - if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { - log.Panicln(err) - } - - if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) { - log.Panicln(err) - } -} - -func layout(g *gocui.Gui) error { - maxX, maxY := g.Size() - if v, err := g.SetView("hello", maxX/2-7, maxY/2, maxX/2+7, maxY/2+2, 0); err != nil { - if !gocui.IsUnknownView(err) { - return err - } - fmt.Fprintln(v, "Hello world!") - if _, err := g.SetCurrentView("hello"); err != nil { - return err - } - } - return nil -} - -func quit(g *gocui.Gui, v *gocui.View) error { - return gocui.ErrQuit -} -``` - -## Screenshots - -![r2cui](https://cloud.githubusercontent.com/assets/1223476/19418932/63645052-93ce-11e6-867c-da5e97e37237.png) - -![_examples/demo.go](https://cloud.githubusercontent.com/assets/1223476/5992750/720b84f0-aa36-11e4-88ec-296fa3247b52.png) - -![_examples/dynamic.go](https://cloud.githubusercontent.com/assets/1223476/5992751/76ad5cc2-aa36-11e4-8204-6a90269db827.png) - -## Projects using gocui - -* [komanda-cli](https://github.com/mephux/komanda-cli): IRC Client For Developers. -* [vuls](https://github.com/future-architect/vuls): Agentless vulnerability scanner for Linux/FreeBSD. -* [wuzz](https://github.com/asciimoo/wuzz): Interactive cli tool for HTTP inspection. -* [httplab](https://github.com/gchaincl/httplab): Interactive web server. -* [domainr](https://github.com/MichaelThessel/domainr): Tool that checks the availability of domains based on keywords. -* [gotime](https://github.com/nanohard/gotime): Time tracker for projects and tasks. -* [claws](https://github.com/thehowl/claws): Interactive command line client for testing websockets. -* [terminews](http://github.com/antavelos/terminews): Terminal based RSS reader. -* [diagram](https://github.com/esimov/diagram): Tool to convert ascii arts into hand drawn diagrams. -* [pody](https://github.com/JulienBreux/pody): CLI app to manage Pods in a Kubernetes cluster. -* [kubexp](https://github.com/alitari/kubexp): Kubernetes client. -* [kcli](https://github.com/cswank/kcli): Tool for inspecting kafka topics/partitions/messages. -* [fac](https://github.com/mkchoi212/fac): git merge conflict resolver -* [jsonui](https://github.com/gulyasm/jsonui): Interactive JSON explorer for your terminal. -* [cointop](https://github.com/miguelmota/cointop): Interactive terminal based UI application for tracking cryptocurrencies. -* [lazygit](https://github.com/jesseduffield/lazygit): simple terminal UI for git commands. -* [lazydocker](https://github.com/jesseduffield/lazydocker): The lazier way to manage everything docker. - -Note: if your project is not listed here, let us know! :) diff --git a/vendor/github.com/awesome-gocui/gocui/attribute.go b/vendor/github.com/awesome-gocui/gocui/attribute.go deleted file mode 100644 index 3d986a71..00000000 --- a/vendor/github.com/awesome-gocui/gocui/attribute.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gocui - -import "github.com/awesome-gocui/termbox-go" - -// Attribute represents a terminal attribute, like color, font style, etc. They -// can be combined using bitwise OR (|). Note that it is not possible to -// combine multiple color attributes. -type Attribute termbox.Attribute - -// Color attributes. -const ( - ColorDefault Attribute = Attribute(termbox.ColorDefault) - ColorBlack = Attribute(termbox.ColorBlack) - ColorRed = Attribute(termbox.ColorRed) - ColorGreen = Attribute(termbox.ColorGreen) - ColorYellow = Attribute(termbox.ColorYellow) - ColorBlue = Attribute(termbox.ColorBlue) - ColorMagenta = Attribute(termbox.ColorMagenta) - ColorCyan = Attribute(termbox.ColorCyan) - ColorWhite = Attribute(termbox.ColorWhite) -) - -// Text style attributes. -const ( - AttrBold Attribute = Attribute(termbox.AttrBold) - AttrUnderline = Attribute(termbox.AttrUnderline) - AttrReverse = Attribute(termbox.AttrReverse) -) diff --git a/vendor/github.com/awesome-gocui/gocui/doc.go b/vendor/github.com/awesome-gocui/gocui/doc.go deleted file mode 100644 index ca7113fa..00000000 --- a/vendor/github.com/awesome-gocui/gocui/doc.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package gocui allows to create console user interfaces. - -Create a new GUI: - - g, err := gocui.NewGui(gocui.OutputNormal) - if err != nil { - // handle error - } - defer g.Close() - - // Set GUI managers and key bindings - // ... - - if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) { - // handle error - } - -Set GUI managers: - - g.SetManager(mgr1, mgr2) - -Managers are in charge of GUI's layout and can be used to build widgets. On -each iteration of the GUI's main loop, the Layout function of each configured -manager is executed. Managers are used to set-up and update the application's -main views, being possible to freely change them during execution. Also, it is -important to mention that a main loop iteration is executed on each reported -event (key-press, mouse event, window resize, etc). - -GUIs are composed by Views, you can think of it as buffers. Views implement the -io.ReadWriter interface, so you can just write to them if you want to modify -their content. The same is valid for reading. - -Create and initialize a view with absolute coordinates: - - if v, err := g.SetView("viewname", 2, 2, 22, 7); err != nil { - if !gocui.IsUnknownView(err) { - // handle error - } - fmt.Fprintln(v, "This is a new view") - // ... - } - -Views can also be created using relative coordinates: - - maxX, maxY := g.Size() - if v, err := g.SetView("viewname", maxX/2-30, maxY/2, maxX/2+30, maxY/2+2); err != nil { - // ... - } - -Configure keybindings: - - if err := g.SetKeybinding("viewname", gocui.KeyEnter, gocui.ModNone, fcn); err != nil { - // handle error - } - -gocui implements full mouse support that can be enabled with: - - g.Mouse = true - -Mouse events are handled like any other keybinding: - - if err := g.SetKeybinding("viewname", gocui.MouseLeft, gocui.ModNone, fcn); err != nil { - // handle error - } - -IMPORTANT: Views can only be created, destroyed or updated in three ways: from -the Layout function within managers, from keybinding callbacks or via -*Gui.Update(). The reason for this is that it allows gocui to be -concurrent-safe. So, if you want to update your GUI from a goroutine, you must -use *Gui.Update(). For example: - - g.Update(func(g *gocui.Gui) error { - v, err := g.View("viewname") - if err != nil { - // handle error - } - v.Clear() - fmt.Fprintln(v, "Writing from different goroutines") - return nil - }) - -By default, gocui provides a basic editing mode. This mode can be extended -and customized creating a new Editor and assigning it to *View.Editor: - - type Editor interface { - Edit(v *View, key Key, ch rune, mod Modifier) - } - -DefaultEditor can be taken as example to create your own custom Editor: - - var DefaultEditor Editor = EditorFunc(simpleEditor) - - func simpleEditor(v *View, key Key, ch rune, mod Modifier) { - switch { - case ch != 0 && mod == 0: - v.EditWrite(ch) - case key == KeySpace: - v.EditWrite(' ') - case key == KeyBackspace || key == KeyBackspace2: - v.EditDelete(true) - // ... - } - } - -Colored text: - -Views allow to add colored text using ANSI colors. For example: - - fmt.Fprintln(v, "\x1b[0;31mHello world") - -For more information, see the examples in folder "_examples/". -*/ -package gocui diff --git a/vendor/github.com/awesome-gocui/gocui/edit.go b/vendor/github.com/awesome-gocui/gocui/edit.go deleted file mode 100644 index b5630df3..00000000 --- a/vendor/github.com/awesome-gocui/gocui/edit.go +++ /dev/null @@ -1,449 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gocui - -import ( - "github.com/go-errors/errors" - - "github.com/mattn/go-runewidth" -) - -const maxInt = int(^uint(0) >> 1) - -// Editor interface must be satisfied by gocui editors. -type Editor interface { - Edit(v *View, key Key, ch rune, mod Modifier) -} - -// The EditorFunc type is an adapter to allow the use of ordinary functions as -// Editors. If f is a function with the appropriate signature, EditorFunc(f) -// is an Editor object that calls f. -type EditorFunc func(v *View, key Key, ch rune, mod Modifier) - -// Edit calls f(v, key, ch, mod) -func (f EditorFunc) Edit(v *View, key Key, ch rune, mod Modifier) { - f(v, key, ch, mod) -} - -// DefaultEditor is the default editor. -var DefaultEditor Editor = EditorFunc(simpleEditor) - -// simpleEditor is used as the default gocui editor. -func simpleEditor(v *View, key Key, ch rune, mod Modifier) { - switch { - case ch != 0 && mod == 0: - v.EditWrite(ch) - case key == KeySpace: - v.EditWrite(' ') - case key == KeyBackspace || key == KeyBackspace2: - v.EditDelete(true) - case key == KeyDelete: - v.EditDelete(false) - case key == KeyInsert: - v.Overwrite = !v.Overwrite - case key == KeyEnter: - v.EditNewLine() - case key == KeyArrowDown: - v.MoveCursor(0, 1, false) - case key == KeyArrowUp: - v.MoveCursor(0, -1, false) - case key == KeyArrowLeft: - v.MoveCursor(-1, 0, false) - case key == KeyArrowRight: - v.MoveCursor(1, 0, false) - case key == KeyTab: - v.EditWrite('\t') - case key == KeySpace: - v.EditWrite(' ') - case key == KeyInsert: - v.Overwrite = !v.Overwrite - default: - v.EditWrite(ch) - } -} - -// EditWrite writes a rune at the cursor position. -func (v *View) EditWrite(ch rune) { - w := runewidth.RuneWidth(ch) - v.writeRune(v.cx, v.cy, ch) - v.moveCursor(w, 0, true) -} - -// EditDeleteToStartOfLine is the equivalent of pressing ctrl+U in your terminal, it deletes to the start of the line. Or if you are already at the start of the line, it deletes the newline character -func (v *View) EditDeleteToStartOfLine() { - x, _ := v.Cursor() - if x == 0 { - v.EditDelete(true) - } else { - // delete characters until we are the start of the line - for x > 0 { - v.EditDelete(true) - x, _ = v.Cursor() - } - } -} - -// EditGotoToStartOfLine takes you to the start of the current line -func (v *View) EditGotoToStartOfLine() { - x, _ := v.Cursor() - for x > 0 { - v.MoveCursor(-1, 0, false) - x, _ = v.Cursor() - } -} - -// EditGotoToEndOfLine takes you to the end of the line -func (v *View) EditGotoToEndOfLine() { - _, y := v.Cursor() - _ = v.SetCursor(0, y+1) - x, newY := v.Cursor() - if newY == y { - // we must be on the last line, so lets move to the very end - prevX := -1 - for prevX != x { - prevX = x - v.MoveCursor(1, 0, false) - x, _ = v.Cursor() - } - } else { - // most left so now we're at the end of the original line - v.MoveCursor(-1, 0, false) - } -} - -// EditDelete deletes a rune at the cursor position. back determines the -// direction. -func (v *View) EditDelete(back bool) { - x, y := v.ox+v.cx, v.oy+v.cy - if y < 0 { - return - } else if y >= len(v.viewLines) { - v.MoveCursor(-1, 0, true) - return - } - - maxX, _ := v.Size() - if back { - if x == 0 { // start of the line - if y < 1 { - return - } - - var maxPrevWidth int - if v.Wrap { - maxPrevWidth = maxX - } else { - maxPrevWidth = maxInt - } - - if v.viewLines[y].linesX == 0 { // regular line - v.mergeLines(v.cy - 1) - if len(v.viewLines[y-1].line) < maxPrevWidth { - v.MoveCursor(-1, 0, true) - } - } else { // wrapped line - n, _ := v.deleteRune(len(v.viewLines[y-1].line)-1, v.cy-1) - v.MoveCursor(-n, 0, true) - } - } else { // middle/end of the line - n, _ := v.deleteRune(v.cx-1, v.cy) - v.MoveCursor(-n, 0, true) - } - } else { - if x == len(v.viewLines[y].line) { // end of the line - v.mergeLines(v.cy) - } else { // start/middle of the line - v.deleteRune(v.cx, v.cy) - } - } -} - -// EditNewLine inserts a new line under the cursor. -func (v *View) EditNewLine() { - v.breakLine(v.cx, v.cy) - v.ox = 0 - v.cy = v.cy + 1 - v.cx = 0 -} - -// MoveCursor moves the cursor taking into account the width of the line/view, -// displacing the origin if necessary. -func (v *View) MoveCursor(dx, dy int, writeMode bool) { - ox, oy := v.cx+v.ox, v.cy+v.oy - x, y := ox+dx, oy+dy - - if y < 0 || y >= len(v.viewLines) { - v.moveCursor(dx, dy, writeMode) - return - } - - // Removing newline. - if x < 0 { - var prevLen int - if y-1 >= 0 && y-1 < len(v.viewLines) { - prevLen = lineWidth(v.viewLines[y-1].line) - } - - v.MoveCursor(prevLen, -1, writeMode) - return - } - - line := v.viewLines[y].line - var col int - var prevCol int - for i := range line { - prevCol = col - col += runewidth.RuneWidth(line[i].chr) - if dx > 0 { - if x <= col { - x = col - break - } - continue - } - - if x < col { - x = prevCol - break - } - } - - v.moveCursor(x-ox, y-oy, writeMode) -} - -func (v *View) moveCursor(dx, dy int, writeMode bool) { - maxX, maxY := v.Size() - cx, cy := v.cx+dx, v.cy+dy - x, y := v.ox+cx, v.oy+cy - - var curLineWidth, prevLineWidth int - // get the width of the current line - curLineWidth = maxInt - if v.Wrap { - curLineWidth = maxX - 1 - } - - if !writeMode { - curLineWidth = 0 - if y >= 0 && y < len(v.viewLines) { - curLineWidth = lineWidth(v.viewLines[y].line) - if v.Wrap && curLineWidth >= maxX { - curLineWidth = maxX - 1 - } - } - } - // get the width of the previous line - prevLineWidth = 0 - if y-1 >= 0 && y-1 < len(v.viewLines) { - prevLineWidth = lineWidth(v.viewLines[y-1].line) - } - // adjust cursor's x position and view's x origin - if x > curLineWidth { // move to next line - if dx > 0 { // horizontal movement - cy++ - if writeMode || v.oy+cy < len(v.viewLines) { - if !v.Wrap { - v.ox = 0 - } - v.cx = 0 - } - } else { // vertical movement - if curLineWidth > 0 { // move cursor to the EOL - if v.Wrap { - v.cx = curLineWidth - } else { - ncx := curLineWidth - v.ox - if ncx < 0 { - v.ox += ncx - if v.ox < 0 { - v.ox = 0 - } - v.cx = 0 - } else { - v.cx = ncx - } - } - } else { - if writeMode || v.oy+cy < len(v.viewLines) { - if !v.Wrap { - v.ox = 0 - } - v.cx = 0 - } - } - } - } else if cx < 0 { - if !v.Wrap && v.ox > 0 { // move origin to the left - v.ox += cx - v.cx = 0 - } else { // move to previous line - cy-- - if prevLineWidth > 0 { - if !v.Wrap { // set origin so the EOL is visible - nox := prevLineWidth - maxX + 1 - if nox < 0 { - nox = 0 - } - v.ox = nox - } - v.cx = prevLineWidth - } else { - if !v.Wrap { - v.ox = 0 - } - v.cx = 0 - } - } - } else { // stay on the same line - if v.Wrap { - v.cx = cx - } else { - if cx >= maxX { - v.ox += cx - maxX + 1 - v.cx = maxX - } else { - v.cx = cx - } - } - } - - // adjust cursor's y position and view's y origin - if cy < 0 { - if v.oy > 0 { - v.oy-- - } - } else if writeMode || v.oy+cy < len(v.viewLines) { - if cy >= maxY { - v.oy++ - } else { - v.cy = cy - } - } -} - -// writeRune writes a rune into the view's internal buffer, at the -// position corresponding to the point (x, y). The length of the internal -// buffer is increased if the point is out of bounds. Overwrite mode is -// governed by the value of View.overwrite. -func (v *View) writeRune(x, y int, ch rune) error { - v.tainted = true - - x, y, err := v.realPosition(x, y) - if err != nil { - return err - } - - if x < 0 || y < 0 { - return errors.New("invalid point") - } - - if y >= len(v.lines) { - s := make([][]cell, y-len(v.lines)+1) - v.lines = append(v.lines, s...) - } - - olen := len(v.lines[y]) - - var s []cell - if x >= len(v.lines[y]) { - s = make([]cell, x-len(v.lines[y])+1) - } else if !v.Overwrite { - s = make([]cell, 1) - } - v.lines[y] = append(v.lines[y], s...) - - if !v.Overwrite || (v.Overwrite && x >= olen-1) { - copy(v.lines[y][x+1:], v.lines[y][x:]) - } - v.lines[y][x] = cell{ - fgColor: v.FgColor, - bgColor: v.BgColor, - chr: ch, - } - - return nil -} - -// deleteRune removes a rune from the view's internal buffer, at the -// position corresponding to the point (x, y). -// returns the amount of columns that where removed. -func (v *View) deleteRune(x, y int) (int, error) { - v.tainted = true - - x, y, err := v.realPosition(x, y) - if err != nil { - return 0, err - } - - if x < 0 || y < 0 || y >= len(v.lines) || x >= len(v.lines[y]) { - return 0, errors.New("invalid point") - } - - var tw int - for i := range v.lines[y] { - w := runewidth.RuneWidth(v.lines[y][i].chr) - tw += w - if tw > x { - v.lines[y] = append(v.lines[y][:i], v.lines[y][i+1:]...) - return w, nil - } - - } - - return 0, nil -} - -// mergeLines merges the lines "y" and "y+1" if possible. -func (v *View) mergeLines(y int) error { - v.tainted = true - - _, y, err := v.realPosition(0, y) - if err != nil { - return err - } - - if y < 0 || y >= len(v.lines) { - return errors.New("invalid point") - } - - if y < len(v.lines)-1 { // otherwise we don't need to merge anything - v.lines[y] = append(v.lines[y], v.lines[y+1]...) - v.lines = append(v.lines[:y+1], v.lines[y+2:]...) - } - return nil -} - -// breakLine breaks a line of the internal buffer at the position corresponding -// to the point (x, y). -func (v *View) breakLine(x, y int) error { - v.tainted = true - - x, y, err := v.realPosition(x, y) - if err != nil { - return err - } - - if y < 0 || y >= len(v.lines) { - return errors.New("invalid point") - } - - var left, right []cell - if x < len(v.lines[y]) { // break line - left = make([]cell, len(v.lines[y][:x])) - copy(left, v.lines[y][:x]) - right = make([]cell, len(v.lines[y][x:])) - copy(right, v.lines[y][x:]) - } else { // new empty line - left = v.lines[y] - } - - lines := make([][]cell, len(v.lines)+1) - lines[y] = left - lines[y+1] = right - copy(lines, v.lines[:y]) - copy(lines[y+2:], v.lines[y+1:]) - v.lines = lines - return nil -} diff --git a/vendor/github.com/awesome-gocui/gocui/escape.go b/vendor/github.com/awesome-gocui/gocui/escape.go deleted file mode 100644 index 64360802..00000000 --- a/vendor/github.com/awesome-gocui/gocui/escape.go +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gocui - -import ( - "strconv" - - "github.com/go-errors/errors" -) - -type escapeInterpreter struct { - state escapeState - curch rune - csiParam []string - curFgColor, curBgColor Attribute - mode OutputMode -} - -type ( - escapeState int - fontEffect int -) - -const ( - stateNone escapeState = iota - stateEscape - stateCSI - stateParams - - bold fontEffect = 1 - underline fontEffect = 4 - reverse fontEffect = 7 - setForegroundColor fontEffect = 38 - setBackgroundColor fontEffect = 48 -) - -var ( - errNotCSI = errors.New("Not a CSI escape sequence") - errCSIParseError = errors.New("CSI escape sequence parsing error") - errCSITooLong = errors.New("CSI escape sequence is too long") -) - -// runes in case of error will output the non-parsed runes as a string. -func (ei *escapeInterpreter) runes() []rune { - switch ei.state { - case stateNone: - return []rune{0x1b} - case stateEscape: - return []rune{0x1b, ei.curch} - case stateCSI: - return []rune{0x1b, '[', ei.curch} - case stateParams: - ret := []rune{0x1b, '['} - for _, s := range ei.csiParam { - ret = append(ret, []rune(s)...) - ret = append(ret, ';') - } - return append(ret, ei.curch) - } - return nil -} - -// newEscapeInterpreter returns an escapeInterpreter that will be able to parse -// terminal escape sequences. -func newEscapeInterpreter(mode OutputMode) *escapeInterpreter { - ei := &escapeInterpreter{ - state: stateNone, - curFgColor: ColorDefault, - curBgColor: ColorDefault, - mode: mode, - } - return ei -} - -// reset sets the escapeInterpreter in initial state. -func (ei *escapeInterpreter) reset() { - ei.state = stateNone - ei.curFgColor = ColorDefault - ei.curBgColor = ColorDefault - ei.csiParam = nil -} - -// parseOne parses a rune. If isEscape is true, it means that the rune is part -// of an escape sequence, and as such should not be printed verbatim. Otherwise, -// it's not an escape sequence. -func (ei *escapeInterpreter) parseOne(ch rune) (isEscape bool, err error) { - // Sanity checks - if len(ei.csiParam) > 20 { - return false, errCSITooLong - } - if len(ei.csiParam) > 0 && len(ei.csiParam[len(ei.csiParam)-1]) > 255 { - return false, errCSITooLong - } - - ei.curch = ch - - switch ei.state { - case stateNone: - if ch == 0x1b { - ei.state = stateEscape - return true, nil - } - return false, nil - case stateEscape: - if ch == '[' { - ei.state = stateCSI - return true, nil - } - return false, errNotCSI - case stateCSI: - switch { - case ch >= '0' && ch <= '9': - ei.csiParam = append(ei.csiParam, "") - case ch == 'm': - ei.csiParam = append(ei.csiParam, "0") - default: - return false, errCSIParseError - } - ei.state = stateParams - fallthrough - case stateParams: - switch { - case ch >= '0' && ch <= '9': - ei.csiParam[len(ei.csiParam)-1] += string(ch) - return true, nil - case ch == ';': - ei.csiParam = append(ei.csiParam, "") - return true, nil - case ch == 'm': - var err error - switch ei.mode { - case OutputNormal: - err = ei.outputNormal() - case Output256: - err = ei.output256() - } - if err != nil { - return false, errCSIParseError - } - - ei.state = stateNone - ei.csiParam = nil - return true, nil - default: - return false, errCSIParseError - } - } - return false, nil -} - -// outputNormal provides 8 different colors: -// black, red, green, yellow, blue, magenta, cyan, white -func (ei *escapeInterpreter) outputNormal() error { - for _, param := range ei.csiParam { - p, err := strconv.Atoi(param) - if err != nil { - return errCSIParseError - } - - switch { - case p >= 30 && p <= 37: - ei.curFgColor = Attribute(p - 30 + 1) - case p == 39: - ei.curFgColor = ColorDefault - case p >= 40 && p <= 47: - ei.curBgColor = Attribute(p - 40 + 1) - case p == 49: - ei.curBgColor = ColorDefault - case p == 1: - ei.curFgColor |= AttrBold - case p == 4: - ei.curFgColor |= AttrUnderline - case p == 7: - ei.curFgColor |= AttrReverse - case p == 0: - ei.curFgColor = ColorDefault - ei.curBgColor = ColorDefault - } - } - - return nil -} - -// output256 allows you to leverage the 256-colors terminal mode: -// 0x01 - 0x08: the 8 colors as in OutputNormal -// 0x09 - 0x10: Color* | AttrBold -// 0x11 - 0xe8: 216 different colors -// 0xe9 - 0x1ff: 24 different shades of grey -func (ei *escapeInterpreter) output256() error { - if len(ei.csiParam) < 3 { - return ei.outputNormal() - } - - mode, err := strconv.Atoi(ei.csiParam[1]) - if err != nil { - return errCSIParseError - } - if mode != 5 { - return ei.outputNormal() - } - - for _, param := range splitFgBg(ei.csiParam) { - fgbg, err := strconv.Atoi(param[0]) - if err != nil { - return errCSIParseError - } - color, err := strconv.Atoi(param[2]) - if err != nil { - return errCSIParseError - } - - switch fontEffect(fgbg) { - case setForegroundColor: - ei.curFgColor = Attribute(color + 1) - - for _, s := range param[3:] { - p, err := strconv.Atoi(s) - if err != nil { - return errCSIParseError - } - - switch fontEffect(p) { - case bold: - ei.curFgColor |= AttrBold - case underline: - ei.curFgColor |= AttrUnderline - case reverse: - ei.curFgColor |= AttrReverse - - } - } - case setBackgroundColor: - ei.curBgColor = Attribute(color + 1) - default: - return errCSIParseError - } - } - return nil -} - -func splitFgBg(params []string) [][]string { - var out [][]string - var current []string - for _, p := range params { - if len(current) == 3 && (p == "48" || p == "38") { - out = append(out, current) - current = []string{} - } - current = append(current, p) - } - - if len(current) > 0 { - out = append(out, current) - } - - return out -} diff --git a/vendor/github.com/awesome-gocui/gocui/go.mod b/vendor/github.com/awesome-gocui/gocui/go.mod deleted file mode 100644 index 5791b4e4..00000000 --- a/vendor/github.com/awesome-gocui/gocui/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/awesome-gocui/gocui - -go 1.12 - -require ( - github.com/awesome-gocui/termbox-go v0.0.0-20190427202837-c0aef3d18bcc - github.com/go-errors/errors v1.0.1 - github.com/mattn/go-runewidth v0.0.4 -) diff --git a/vendor/github.com/awesome-gocui/gocui/go.sum b/vendor/github.com/awesome-gocui/gocui/go.sum deleted file mode 100644 index 25f1c037..00000000 --- a/vendor/github.com/awesome-gocui/gocui/go.sum +++ /dev/null @@ -1,6 +0,0 @@ -github.com/awesome-gocui/termbox-go v0.0.0-20190427202837-c0aef3d18bcc h1:wGNpKcHU8Aadr9yOzsT3GEsFLS7HQu8HxQIomnekqf0= -github.com/awesome-gocui/termbox-go v0.0.0-20190427202837-c0aef3d18bcc/go.mod h1:tOy3o5Nf1bA17mnK4W41gD7PS3u4Cv0P0pqFcoWMy8s= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= diff --git a/vendor/github.com/awesome-gocui/gocui/gui.go b/vendor/github.com/awesome-gocui/gocui/gui.go deleted file mode 100644 index 6fe0d5d8..00000000 --- a/vendor/github.com/awesome-gocui/gocui/gui.go +++ /dev/null @@ -1,832 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gocui - -import ( - standardErrors "errors" - "runtime" - - "github.com/go-errors/errors" - - "github.com/awesome-gocui/termbox-go" -) - -// OutputMode represents the terminal's output mode (8 or 256 colors). -type OutputMode termbox.OutputMode - -var ( - // ErrAlreadyBlacklisted is returned when the keybinding is already blacklisted. - ErrAlreadyBlacklisted = standardErrors.New("keybind already blacklisted") - - // ErrBlacklisted is returned when the keybinding being parsed / used is blacklisted. - ErrBlacklisted = standardErrors.New("keybind blacklisted") - - // ErrNotBlacklisted is returned when a keybinding being whitelisted is not blacklisted. - ErrNotBlacklisted = standardErrors.New("keybind not blacklisted") - - // ErrNoSuchKeybind is returned when the keybinding being parsed does not exist. - ErrNoSuchKeybind = standardErrors.New("no such keybind") - - // ErrUnknownView allows to assert if a View must be initialized. - ErrUnknownView = standardErrors.New("unknown view") - - // ErrQuit is used to decide if the MainLoop finished successfully. - ErrQuit = standardErrors.New("quit") -) - -const ( - // OutputNormal provides 8-colors terminal mode. - OutputNormal = OutputMode(termbox.OutputNormal) - - // Output256 provides 256-colors terminal mode. - Output256 = OutputMode(termbox.Output256) - - // OutputGrayScale provides greyscale terminal mode. - OutputGrayScale = OutputMode(termbox.OutputGrayscale) - - // Output216 provides greyscale terminal mode. - Output216 = OutputMode(termbox.Output216) -) - -// Gui represents the whole User Interface, including the views, layouts -// and keybindings. -type Gui struct { - tbEvents chan termbox.Event - userEvents chan userEvent - views []*View - currentView *View - managers []Manager - keybindings []*keybinding - maxX, maxY int - outputMode OutputMode - stop chan struct{} - blacklist []Key - - // BgColor and FgColor allow to configure the background and foreground - // colors of the GUI. - BgColor, FgColor, FrameColor Attribute - - // SelBgColor and SelFgColor allow to configure the background and - // foreground colors of the frame of the current view. - SelBgColor, SelFgColor, SelFrameColor Attribute - - // If Highlight is true, Sel{Bg,Fg}Colors will be used to draw the - // frame of the current view. - Highlight bool - - // If Cursor is true then the cursor is enabled. - Cursor bool - - // If Mouse is true then mouse events will be enabled. - Mouse bool - - // If InputEsc is true, when ESC sequence is in the buffer and it doesn't - // match any known sequence, ESC means KeyEsc. - InputEsc bool - - // If ASCII is true then use ASCII instead of unicode to draw the - // interface. Using ASCII is more portable. - ASCII bool - - // SupportOverlaps is true when we allow for view edges to overlap with other - // view edges - SupportOverlaps bool -} - -// NewGui returns a new Gui object with a given output mode. -func NewGui(mode OutputMode, supportOverlaps bool) (*Gui, error) { - err := termbox.Init() - if err != nil { - return nil, err - } - - g := &Gui{} - - g.outputMode = mode - termbox.SetOutputMode(termbox.OutputMode(mode)) - - g.stop = make(chan struct{}) - - g.tbEvents = make(chan termbox.Event, 20) - g.userEvents = make(chan userEvent, 20) - - if runtime.GOOS != "windows" { - g.maxX, g.maxY, err = g.getTermWindowSize() - if err != nil { - return nil, err - } - } else { - g.maxX, g.maxY = termbox.Size() - } - - g.BgColor, g.FgColor = ColorDefault, ColorDefault - g.SelBgColor, g.SelFgColor = ColorDefault, ColorDefault - - // SupportOverlaps is true when we allow for view edges to overlap with other - // view edges - g.SupportOverlaps = supportOverlaps - - return g, nil -} - -// Close finalizes the library. It should be called after a successful -// initialization and when gocui is not needed anymore. -func (g *Gui) Close() { - go func() { - g.stop <- struct{}{} - }() - termbox.Close() -} - -// Size returns the terminal's size. -func (g *Gui) Size() (x, y int) { - return g.maxX, g.maxY -} - -// SetRune writes a rune at the given point, relative to the top-left -// corner of the terminal. It checks if the position is valid and applies -// the given colors. -func (g *Gui) SetRune(x, y int, ch rune, fgColor, bgColor Attribute) error { - if x < 0 || y < 0 || x >= g.maxX || y >= g.maxY { - return errors.New("invalid point") - } - termbox.SetCell(x, y, ch, termbox.Attribute(fgColor), termbox.Attribute(bgColor)) - return nil -} - -// Rune returns the rune contained in the cell at the given position. -// It checks if the position is valid. -func (g *Gui) Rune(x, y int) (rune, error) { - if x < 0 || y < 0 || x >= g.maxX || y >= g.maxY { - return ' ', errors.New("invalid point") - } - c := termbox.CellBuffer()[y*g.maxX+x] - return c.Ch, nil -} - -// SetView creates a new view with its top-left corner at (x0, y0) -// and the bottom-right one at (x1, y1). If a view with the same name -// already exists, its dimensions are updated; otherwise, the error -// ErrUnknownView is returned, which allows to assert if the View must -// be initialized. It checks if the position is valid. -func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, error) { - if x0 >= x1 { - return nil, errors.New("invalid dimensions") - } - if name == "" { - return nil, errors.New("invalid name") - } - - if v, err := g.View(name); err == nil { - v.x0 = x0 - v.y0 = y0 - v.x1 = x1 - v.y1 = y1 - v.tainted = true - return v, nil - } - - v := newView(name, x0, y0, x1, y1, g.outputMode) - v.BgColor, v.FgColor = g.BgColor, g.FgColor - v.SelBgColor, v.SelFgColor = g.SelBgColor, g.SelFgColor - v.Overlaps = overlaps - g.views = append(g.views, v) - return v, errors.Wrap(ErrUnknownView, 0) -} - -// SetViewBeneath sets a view stacked beneath another view -func (g *Gui) SetViewBeneath(name string, aboveViewName string, height int) (*View, error) { - aboveView, err := g.View(aboveViewName) - if err != nil { - return nil, err - } - - viewTop := aboveView.y1 + 1 - return g.SetView(name, aboveView.x0, viewTop, aboveView.x1, viewTop+height-1, 0) -} - -// SetViewOnTop sets the given view on top of the existing ones. -func (g *Gui) SetViewOnTop(name string) (*View, error) { - for i, v := range g.views { - if v.name == name { - s := append(g.views[:i], g.views[i+1:]...) - g.views = append(s, v) - return v, nil - } - } - return nil, errors.Wrap(ErrUnknownView, 0) -} - -// SetViewOnBottom sets the given view on bottom of the existing ones. -func (g *Gui) SetViewOnBottom(name string) (*View, error) { - for i, v := range g.views { - if v.name == name { - s := append(g.views[:i], g.views[i+1:]...) - g.views = append([]*View{v}, s...) - return v, nil - } - } - return nil, errors.Wrap(ErrUnknownView, 0) -} - -// Views returns all the views in the GUI. -func (g *Gui) Views() []*View { - return g.views -} - -// View returns a pointer to the view with the given name, or error -// ErrUnknownView if a view with that name does not exist. -func (g *Gui) View(name string) (*View, error) { - for _, v := range g.views { - if v.name == name { - return v, nil - } - } - return nil, errors.Wrap(ErrUnknownView, 0) -} - -// ViewByPosition returns a pointer to a view matching the given position, or -// error ErrUnknownView if a view in that position does not exist. -func (g *Gui) ViewByPosition(x, y int) (*View, error) { - // traverse views in reverse order checking top views first - for i := len(g.views); i > 0; i-- { - v := g.views[i-1] - if x > v.x0 && x < v.x1 && y > v.y0 && y < v.y1 { - return v, nil - } - } - return nil, errors.Wrap(ErrUnknownView, 0) -} - -// ViewPosition returns the coordinates of the view with the given name, or -// error ErrUnknownView if a view with that name does not exist. -func (g *Gui) ViewPosition(name string) (x0, y0, x1, y1 int, err error) { - for _, v := range g.views { - if v.name == name { - return v.x0, v.y0, v.x1, v.y1, nil - } - } - return 0, 0, 0, 0, errors.Wrap(ErrUnknownView, 0) -} - -// DeleteView deletes a view by name. -func (g *Gui) DeleteView(name string) error { - for i, v := range g.views { - if v.name == name { - g.views = append(g.views[:i], g.views[i+1:]...) - return nil - } - } - return errors.Wrap(ErrUnknownView, 0) -} - -// SetCurrentView gives the focus to a given view. -func (g *Gui) SetCurrentView(name string) (*View, error) { - for _, v := range g.views { - if v.name == name { - g.currentView = v - return v, nil - } - } - return nil, errors.Wrap(ErrUnknownView, 0) -} - -// CurrentView returns the currently focused view, or nil if no view -// owns the focus. -func (g *Gui) CurrentView() *View { - return g.currentView -} - -// SetKeybinding creates a new keybinding. If viewname equals to "" -// (empty string) then the keybinding will apply to all views. key must -// be a rune or a Key. -func (g *Gui) SetKeybinding(viewname string, key interface{}, mod Modifier, handler func(*Gui, *View) error) error { - var kb *keybinding - - k, ch, err := getKey(key) - if err != nil { - return err - } - - if g.isBlacklisted(k) { - return ErrBlacklisted - } - - kb = newKeybinding(viewname, k, ch, mod, handler) - g.keybindings = append(g.keybindings, kb) - return nil -} - -// DeleteKeybinding deletes a keybinding. -func (g *Gui) DeleteKeybinding(viewname string, key interface{}, mod Modifier) error { - k, ch, err := getKey(key) - if err != nil { - return err - } - - for i, kb := range g.keybindings { - if kb.viewName == viewname && kb.ch == ch && kb.key == k && kb.mod == mod { - g.keybindings = append(g.keybindings[:i], g.keybindings[i+1:]...) - return nil - } - } - return errors.New("keybinding not found") -} - -// DeleteKeybindings deletes all keybindings of view. -func (g *Gui) DeleteKeybindings(viewname string) { - var s []*keybinding - for _, kb := range g.keybindings { - if kb.viewName != viewname { - s = append(s, kb) - } - } - g.keybindings = s -} - -// BlackListKeybinding adds a keybinding to the blacklist -func (g *Gui) BlacklistKeybinding(k Key) error { - for _, j := range g.blacklist { - if j == k { - return ErrAlreadyBlacklisted - } - } - g.blacklist = append(g.blacklist, k) - return nil -} - -// WhiteListKeybinding removes a keybinding from the blacklist -func (g *Gui) WhitelistKeybinding(k Key) error { - for i, j := range g.blacklist { - if j == k { - g.blacklist = append(g.blacklist[:i], g.blacklist[i+1:]...) - return nil - } - } - return ErrNotBlacklisted -} - -// getKey takes an empty interface with a key and returns the corresponding -// typed Key or rune. -func getKey(key interface{}) (Key, rune, error) { - switch t := key.(type) { - case Key: - return t, 0, nil - case rune: - return 0, t, nil - default: - return 0, 0, errors.New("unknown type") - } -} - -// userEvent represents an event triggered by the user. -type userEvent struct { - f func(*Gui) error -} - -// Update executes the passed function. This method can be called safely from a -// goroutine in order to update the GUI. It is important to note that the -// passed function won't be executed immediately, instead it will be added to -// the user events queue. Given that Update spawns a goroutine, the order in -// which the user events will be handled is not guaranteed. -func (g *Gui) Update(f func(*Gui) error) { - go func() { g.userEvents <- userEvent{f: f} }() -} - -// A Manager is in charge of GUI's layout and can be used to build widgets. -type Manager interface { - // Layout is called every time the GUI is redrawn, it must contain the - // base views and its initializations. - Layout(*Gui) error -} - -// The ManagerFunc type is an adapter to allow the use of ordinary functions as -// Managers. If f is a function with the appropriate signature, ManagerFunc(f) -// is an Manager object that calls f. -type ManagerFunc func(*Gui) error - -// Layout calls f(g) -func (f ManagerFunc) Layout(g *Gui) error { - return f(g) -} - -// SetManager sets the given GUI managers. It deletes all views and -// keybindings. -func (g *Gui) SetManager(managers ...Manager) { - g.managers = managers - g.currentView = nil - g.views = nil - g.keybindings = nil - - go func() { g.tbEvents <- termbox.Event{Type: termbox.EventResize} }() -} - -// SetManagerFunc sets the given manager function. It deletes all views and -// keybindings. -func (g *Gui) SetManagerFunc(manager func(*Gui) error) { - g.SetManager(ManagerFunc(manager)) -} - -// MainLoop runs the main loop until an error is returned. A successful -// finish should return ErrQuit. -func (g *Gui) MainLoop() error { - g.loaderTick() - if err := g.flush(); err != nil { - return err - } - - go func() { - for { - select { - case <-g.stop: - return - default: - g.tbEvents <- termbox.PollEvent() - } - } - }() - - inputMode := termbox.InputAlt - if true { // previously g.InputEsc, but didn't seem to work - inputMode = termbox.InputEsc - } - if g.Mouse { - inputMode |= termbox.InputMouse - } - termbox.SetInputMode(inputMode) - - if err := g.flush(); err != nil { - return err - } - for { - select { - case ev := <-g.tbEvents: - if err := g.handleEvent(&ev); err != nil { - return err - } - case ev := <-g.userEvents: - if err := ev.f(g); err != nil { - return err - } - } - if err := g.consumeevents(); err != nil { - return err - } - if err := g.flush(); err != nil { - return err - } - } -} - -// consumeevents handles the remaining events in the events pool. -func (g *Gui) consumeevents() error { - for { - select { - case ev := <-g.tbEvents: - if err := g.handleEvent(&ev); err != nil { - return err - } - case ev := <-g.userEvents: - if err := ev.f(g); err != nil { - return err - } - default: - return nil - } - } -} - -// handleEvent handles an event, based on its type (key-press, error, -// etc.) -func (g *Gui) handleEvent(ev *termbox.Event) error { - switch ev.Type { - case termbox.EventKey, termbox.EventMouse: - return g.onKey(ev) - case termbox.EventError: - return ev.Err - default: - return nil - } -} - -// flush updates the gui, re-drawing frames and buffers. -func (g *Gui) flush() error { - termbox.Clear(termbox.Attribute(g.FgColor), termbox.Attribute(g.BgColor)) - - maxX, maxY := termbox.Size() - // if GUI's size has changed, we need to redraw all views - if maxX != g.maxX || maxY != g.maxY { - for _, v := range g.views { - v.tainted = true - } - } - g.maxX, g.maxY = maxX, maxY - - for _, m := range g.managers { - if err := m.Layout(g); err != nil { - return err - } - } - for _, v := range g.views { - if !v.Visible || v.y1 < v.y0 { - continue - } - if v.Frame { - var fgColor, bgColor, frameColor Attribute - if g.Highlight && v == g.currentView { - fgColor = g.SelFgColor - bgColor = g.SelBgColor - frameColor = g.SelFrameColor - } else { - fgColor = g.FgColor - bgColor = g.BgColor - frameColor = g.FrameColor - } - - if err := g.drawFrameEdges(v, frameColor, bgColor); err != nil { - return err - } - if err := g.drawFrameCorners(v, frameColor, bgColor); err != nil { - return err - } - if v.Title != "" { - if err := g.drawTitle(v, fgColor, bgColor); err != nil { - return err - } - } - if v.Subtitle != "" { - if err := g.drawSubtitle(v, fgColor, bgColor); err != nil { - return err - } - } - } - if err := g.draw(v); err != nil { - return err - } - } - termbox.Flush() - return nil -} - -// drawFrameEdges draws the horizontal and vertical edges of a view. -func (g *Gui) drawFrameEdges(v *View, fgColor, bgColor Attribute) error { - runeH, runeV := '─', '│' - if g.ASCII { - runeH, runeV = '-', '|' - } - - for x := v.x0 + 1; x < v.x1 && x < g.maxX; x++ { - if x < 0 { - continue - } - if v.y0 > -1 && v.y0 < g.maxY { - if err := g.SetRune(x, v.y0, runeH, fgColor, bgColor); err != nil { - return err - } - } - if v.y1 > -1 && v.y1 < g.maxY { - if err := g.SetRune(x, v.y1, runeH, fgColor, bgColor); err != nil { - return err - } - } - } - for y := v.y0 + 1; y < v.y1 && y < g.maxY; y++ { - if y < 0 { - continue - } - if v.x0 > -1 && v.x0 < g.maxX { - if err := g.SetRune(v.x0, y, runeV, fgColor, bgColor); err != nil { - return err - } - } - if v.x1 > -1 && v.x1 < g.maxX { - if err := g.SetRune(v.x1, y, runeV, fgColor, bgColor); err != nil { - return err - } - } - } - return nil -} - -func cornerRune(index byte) rune { - return []rune{' ', '│', '│', '│', '─', '┘', '┐', '┤', '─', '└', '┌', '├', '├', '┴', '┬', '┼'}[index] -} - -func corner(v *View, directions byte) rune { - index := v.Overlaps | directions - return cornerRune(index) -} - -// drawFrameCorners draws the corners of the view. -func (g *Gui) drawFrameCorners(v *View, fgColor, bgColor Attribute) error { - if v.y0 == v.y1 { - if !g.SupportOverlaps && v.x0 >= 0 && v.x1 >= 0 && v.y0 >= 0 && v.x0 < g.maxX && v.x1 < g.maxX && v.y0 < g.maxY { - if err := g.SetRune(v.x0, v.y0, '╶', fgColor, bgColor); err != nil { - return err - } - if err := g.SetRune(v.x1, v.y0, '╴', fgColor, bgColor); err != nil { - return err - } - } - return nil - } - - runeTL, runeTR, runeBL, runeBR := '┌', '┐', '└', '┘' - if g.SupportOverlaps { - runeTL = corner(v, BOTTOM|RIGHT) - runeTR = corner(v, BOTTOM|LEFT) - runeBL = corner(v, TOP|RIGHT) - runeBR = corner(v, TOP|LEFT) - } - if g.ASCII { - runeTL, runeTR, runeBL, runeBR = '+', '+', '+', '+' - } - - corners := []struct { - x, y int - ch rune - }{{v.x0, v.y0, runeTL}, {v.x1, v.y0, runeTR}, {v.x0, v.y1, runeBL}, {v.x1, v.y1, runeBR}} - - for _, c := range corners { - if c.x >= 0 && c.y >= 0 && c.x < g.maxX && c.y < g.maxY { - if err := g.SetRune(c.x, c.y, c.ch, fgColor, bgColor); err != nil { - return err - } - } - } - return nil -} - -// drawTitle draws the title of the view. -func (g *Gui) drawTitle(v *View, fgColor, bgColor Attribute) error { - if v.y0 < 0 || v.y0 >= g.maxY { - return nil - } - - for i, ch := range v.Title { - x := v.x0 + i + 2 - if x < 0 { - continue - } else if x > v.x1-2 || x >= g.maxX { - break - } - if err := g.SetRune(x, v.y0, ch, fgColor, bgColor); err != nil { - return err - } - } - return nil -} - -// drawSubtitle draws the subtitle of the view. -func (g *Gui) drawSubtitle(v *View, fgColor, bgColor Attribute) error { - if v.y0 < 0 || v.y0 >= g.maxY { - return nil - } - - start := v.x1 - 5 - len(v.Subtitle) - if start < v.x0 { - return nil - } - for i, ch := range v.Subtitle { - x := start + i - if x >= v.x1 { - break - } - if err := g.SetRune(x, v.y0, ch, fgColor, bgColor); err != nil { - return err - } - } - return nil -} - -// draw manages the cursor and calls the draw function of a view. -func (g *Gui) draw(v *View) error { - if g.Cursor { - if curview := g.currentView; curview != nil { - vMaxX, vMaxY := curview.Size() - if curview.cx < 0 { - curview.cx = 0 - } else if curview.cx >= vMaxX { - curview.cx = vMaxX - 1 - } - if curview.cy < 0 { - curview.cy = 0 - } else if curview.cy >= vMaxY { - curview.cy = vMaxY - 1 - } - - gMaxX, gMaxY := g.Size() - cx, cy := curview.x0+curview.cx+1, curview.y0+curview.cy+1 - if cx >= 0 && cx < gMaxX && cy >= 0 && cy < gMaxY { - termbox.SetCursor(cx, cy) - } else { - termbox.HideCursor() - } - } - } else { - termbox.HideCursor() - } - - v.clearRunes() - if err := v.draw(); err != nil { - return err - } - return nil -} - -// onKey manages key-press events. A keybinding handler is called when -// a key-press or mouse event satisfies a configured keybinding. Furthermore, -// currentView's internal buffer is modified if currentView.Editable is true. -func (g *Gui) onKey(ev *termbox.Event) error { - switch ev.Type { - case termbox.EventKey: - matched, err := g.execKeybindings(g.currentView, ev) - if err != nil { - return err - } - if matched { - break - } - if g.currentView != nil && g.currentView.Editable && g.currentView.Editor != nil { - g.currentView.Editor.Edit(g.currentView, Key(ev.Key), ev.Ch, Modifier(ev.Mod)) - } - case termbox.EventMouse: - mx, my := ev.MouseX, ev.MouseY - v, err := g.ViewByPosition(mx, my) - if err != nil { - break - } - if err := v.SetCursor(mx-v.x0-1, my-v.y0-1); err != nil { - return err - } - if _, err := g.execKeybindings(v, ev); err != nil { - return err - } - } - - return nil -} - -// execKeybindings executes the keybinding handlers that match the passed view -// and event. The value of matched is true if there is a match and no errors. -func (g *Gui) execKeybindings(v *View, ev *termbox.Event) (matched bool, err error) { - var globalKb *keybinding - - for _, kb := range g.keybindings { - if kb.handler == nil { - continue - } - - if !kb.matchKeypress(Key(ev.Key), ev.Ch, Modifier(ev.Mod)) { - continue - } - - if kb.matchView(v) { - return g.execKeybinding(v, kb) - } - - if kb.viewName == "" && ((v != nil && !v.Editable) || kb.ch == 0) { - globalKb = kb - } - } - - if globalKb != nil { - return g.execKeybinding(v, globalKb) - } - - return false, nil -} - -// execKeybinding executes a given keybinding -func (g *Gui) execKeybinding(v *View, kb *keybinding) (bool, error) { - if g.isBlacklisted(kb.key) { - return true, nil - } - - if err := kb.handler(g, v); err != nil { - return false, err - } - return true, nil -} - -// isBlacklisted reports whether the key is blacklisted -func (g *Gui) isBlacklisted(k Key) bool { - for _, j := range g.blacklist { - if j == k { - return true - } - } - return false -} - -// IsUnknownView reports whether the contents of an error is "unknown view". -func IsUnknownView(err error) bool { - return err != nil && err.Error() == ErrUnknownView.Error() -} - -// IsQuit reports whether the contents of an error is "quit". -func IsQuit(err error) bool { - return err != nil && err.Error() == ErrQuit.Error() -} diff --git a/vendor/github.com/awesome-gocui/gocui/gui_others.go b/vendor/github.com/awesome-gocui/gocui/gui_others.go deleted file mode 100644 index 5d247a19..00000000 --- a/vendor/github.com/awesome-gocui/gocui/gui_others.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !windows - -package gocui - -import ( - "os" - "os/signal" - "syscall" - "unsafe" - - "github.com/go-errors/errors" -) - -// getTermWindowSize is get terminal window size on linux or unix. -// When gocui run inside the docker contaienr need to check and get the window size. -func (g *Gui) getTermWindowSize() (int, int, error) { - var sz struct { - rows uint16 - cols uint16 - _ [2]uint16 // to match underlying syscall; see https://github.com/awesome-gocui/gocui/issues/33 - } - - var termw, termh int - - out, err := os.OpenFile("/dev/tty", os.O_RDWR, 0) - if err != nil { - return 0, 0, err - } - defer out.Close() - - signalCh := make(chan os.Signal, 1) - signal.Notify(signalCh, syscall.SIGWINCH, syscall.SIGINT) - - for { - _, _, _ = syscall.Syscall(syscall.SYS_IOCTL, - out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz))) - - // check terminal window size - termw, termh = int(sz.cols), int(sz.rows) - if termw > 0 && termh > 0 { - return termw, termh, nil - } - - select { - case signal := <-signalCh: - switch signal { - // when the terminal window size is changed - case syscall.SIGWINCH: - continue - // ctrl + c to cancel - case syscall.SIGINT: - return 0, 0, errors.New("stop to get term window size") - } - } - } -} diff --git a/vendor/github.com/awesome-gocui/gocui/gui_windows.go b/vendor/github.com/awesome-gocui/gocui/gui_windows.go deleted file mode 100644 index db1faab7..00000000 --- a/vendor/github.com/awesome-gocui/gocui/gui_windows.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows - -package gocui - -import ( - "os" - "syscall" - "unsafe" -) - -type wchar uint16 -type short int16 -type dword uint32 -type word uint16 - -type coord struct { - x short - y short -} - -type smallRect struct { - left short - top short - right short - bottom short -} - -type consoleScreenBufferInfo struct { - size coord - cursorPosition coord - attributes word - window smallRect - maximumWindowSize coord -} - -var ( - kernel32 = syscall.NewLazyDLL("kernel32.dll") - procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") -) - -// getTermWindowSize is get terminal window size on windows. -func (g *Gui) getTermWindowSize() (int, int, error) { - var csbi consoleScreenBufferInfo - r1, _, err := procGetConsoleScreenBufferInfo.Call(os.Stdout.Fd(), uintptr(unsafe.Pointer(&csbi))) - if r1 == 0 { - return 0, 0, err - } - return int(csbi.window.right - csbi.window.left + 1), int(csbi.window.bottom - csbi.window.top + 1), nil -} diff --git a/vendor/github.com/awesome-gocui/gocui/keybinding.go b/vendor/github.com/awesome-gocui/gocui/keybinding.go deleted file mode 100644 index d294e70d..00000000 --- a/vendor/github.com/awesome-gocui/gocui/keybinding.go +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gocui - -import ( - "strings" - - "github.com/awesome-gocui/termbox-go" -) - -// Key represents special keys or keys combinations. -type Key termbox.Key - -// Modifier allows to define special keys combinations. They can be used -// in combination with Keys or Runes when a new keybinding is defined. -type Modifier termbox.Modifier - -// Keybidings are used to link a given key-press event with a handler. -type keybinding struct { - viewName string - key Key - ch rune - mod Modifier - handler func(*Gui, *View) error -} - -// Parse takes the input string and extracts the keybinding. -// Returns a Key / rune, a Modifier and an error. -func Parse(input string) (interface{}, Modifier, error) { - if len(input) == 1 { - _, r, err := getKey(rune(input[0])) - if err != nil { - return nil, ModNone, err - } - return r, ModNone, nil - } - - var modifier Modifier - cleaned := make([]string, 0) - - tokens := strings.Split(input, "+") - for _, t := range tokens { - normalized := strings.Title(strings.ToLower(t)) - if t == "Alt" { - modifier = ModAlt - continue - } - cleaned = append(cleaned, normalized) - } - - key, exist := translate[strings.Join(cleaned, "")] - if !exist { - return nil, ModNone, ErrNoSuchKeybind - } - - return key, modifier, nil -} - -// ParseAll takes an array of strings and returns a map of all keybindings. -func ParseAll(input []string) (map[interface{}]Modifier, error) { - ret := make(map[interface{}]Modifier) - for _, i := range input { - k, m, err := Parse(i) - if err != nil { - return ret, err - } - ret[k] = m - } - return ret, nil -} - -// MustParse takes the input string and returns a Key / rune and a Modifier. -// It will panic if any error occured. -func MustParse(input string) (interface{}, Modifier) { - k, m, err := Parse(input) - if err != nil { - panic(err) - } - return k, m -} - -// MustParseAll takes an array of strings and returns a map of all keybindings. -// It will panic if any error occured. -func MustParseAll(input []string) map[interface{}]Modifier { - result, err := ParseAll(input) - if err != nil { - panic(err) - } - return result -} - -// newKeybinding returns a new Keybinding object. -func newKeybinding(viewname string, key Key, ch rune, mod Modifier, handler func(*Gui, *View) error) (kb *keybinding) { - kb = &keybinding{ - viewName: viewname, - key: key, - ch: ch, - mod: mod, - handler: handler, - } - return kb -} - -// matchKeypress returns if the keybinding matches the keypress. -func (kb *keybinding) matchKeypress(key Key, ch rune, mod Modifier) bool { - return kb.key == key && kb.ch == ch && kb.mod == mod -} - -// matchView returns if the keybinding matches the current view. -func (kb *keybinding) matchView(v *View) bool { - // if the user is typing in a field, ignore char keys - if v == nil || (v.Editable && kb.ch != 0) { - return false - } - return kb.viewName == v.name -} - -// translations for strings to keys -var translate = map[string]Key{ - "F1": KeyF1, - "F2": KeyF2, - "F3": KeyF3, - "F4": KeyF4, - "F5": KeyF5, - "F6": KeyF6, - "F7": KeyF7, - "F8": KeyF8, - "F9": KeyF9, - "F10": KeyF10, - "F11": KeyF11, - "F12": KeyF12, - "Insert": KeyInsert, - "Delete": KeyDelete, - "Home": KeyHome, - "End": KeyEnd, - "Pgup": KeyPgup, - "Pgdn": KeyPgdn, - "ArrowUp": KeyArrowUp, - "ArrowDown": KeyArrowDown, - "ArrowLeft": KeyArrowLeft, - "ArrowRight": KeyArrowRight, - "CtrlTilde": KeyCtrlTilde, - "Ctrl2": KeyCtrl2, - "CtrlSpace": KeyCtrlSpace, - "CtrlA": KeyCtrlA, - "CtrlB": KeyCtrlB, - "CtrlC": KeyCtrlC, - "CtrlD": KeyCtrlD, - "CtrlE": KeyCtrlE, - "CtrlF": KeyCtrlF, - "CtrlG": KeyCtrlG, - "Backspace": KeyBackspace, - "CtrlH": KeyCtrlH, - "Tab": KeyTab, - "CtrlI": KeyCtrlI, - "CtrlJ": KeyCtrlJ, - "CtrlK": KeyCtrlK, - "CtrlL": KeyCtrlL, - "Enter": KeyEnter, - "CtrlM": KeyCtrlM, - "CtrlN": KeyCtrlN, - "CtrlO": KeyCtrlO, - "CtrlP": KeyCtrlP, - "CtrlQ": KeyCtrlQ, - "CtrlR": KeyCtrlR, - "CtrlS": KeyCtrlS, - "CtrlT": KeyCtrlT, - "CtrlU": KeyCtrlU, - "CtrlV": KeyCtrlV, - "CtrlW": KeyCtrlW, - "CtrlX": KeyCtrlX, - "CtrlY": KeyCtrlY, - "CtrlZ": KeyCtrlZ, - "Esc": KeyEsc, - "CtrlLsqBracket": KeyCtrlLsqBracket, - "Ctrl3": KeyCtrl3, - "Ctrl4": KeyCtrl4, - "CtrlBackslash": KeyCtrlBackslash, - "Ctrl5": KeyCtrl5, - "CtrlRsqBracket": KeyCtrlRsqBracket, - "Ctrl6": KeyCtrl6, - "Ctrl7": KeyCtrl7, - "CtrlSlash": KeyCtrlSlash, - "CtrlUnderscore": KeyCtrlUnderscore, - "Space": KeySpace, - "Backspace2": KeyBackspace2, - "Ctrl8": KeyCtrl8, - "Mouseleft": MouseLeft, - "Mousemiddle": MouseMiddle, - "Mouseright": MouseRight, - "Mouserelease": MouseRelease, - "MousewheelUp": MouseWheelUp, - "MousewheelDown": MouseWheelDown, -} - -// Special keys. -const ( - KeyF1 Key = Key(termbox.KeyF1) - KeyF2 = Key(termbox.KeyF2) - KeyF3 = Key(termbox.KeyF3) - KeyF4 = Key(termbox.KeyF4) - KeyF5 = Key(termbox.KeyF5) - KeyF6 = Key(termbox.KeyF6) - KeyF7 = Key(termbox.KeyF7) - KeyF8 = Key(termbox.KeyF8) - KeyF9 = Key(termbox.KeyF9) - KeyF10 = Key(termbox.KeyF10) - KeyF11 = Key(termbox.KeyF11) - KeyF12 = Key(termbox.KeyF12) - KeyInsert = Key(termbox.KeyInsert) - KeyDelete = Key(termbox.KeyDelete) - KeyHome = Key(termbox.KeyHome) - KeyEnd = Key(termbox.KeyEnd) - KeyPgup = Key(termbox.KeyPgup) - KeyPgdn = Key(termbox.KeyPgdn) - KeyArrowUp = Key(termbox.KeyArrowUp) - KeyArrowDown = Key(termbox.KeyArrowDown) - KeyArrowLeft = Key(termbox.KeyArrowLeft) - KeyArrowRight = Key(termbox.KeyArrowRight) - - MouseLeft = Key(termbox.MouseLeft) - MouseMiddle = Key(termbox.MouseMiddle) - MouseRight = Key(termbox.MouseRight) - MouseRelease = Key(termbox.MouseRelease) - MouseWheelUp = Key(termbox.MouseWheelUp) - MouseWheelDown = Key(termbox.MouseWheelDown) -) - -// Keys combinations. -const ( - KeyCtrlTilde Key = Key(termbox.KeyCtrlTilde) - KeyCtrl2 = Key(termbox.KeyCtrl2) - KeyCtrlSpace = Key(termbox.KeyCtrlSpace) - KeyCtrlA = Key(termbox.KeyCtrlA) - KeyCtrlB = Key(termbox.KeyCtrlB) - KeyCtrlC = Key(termbox.KeyCtrlC) - KeyCtrlD = Key(termbox.KeyCtrlD) - KeyCtrlE = Key(termbox.KeyCtrlE) - KeyCtrlF = Key(termbox.KeyCtrlF) - KeyCtrlG = Key(termbox.KeyCtrlG) - KeyBackspace = Key(termbox.KeyBackspace) - KeyCtrlH = Key(termbox.KeyCtrlH) - KeyTab = Key(termbox.KeyTab) - KeyCtrlI = Key(termbox.KeyCtrlI) - KeyCtrlJ = Key(termbox.KeyCtrlJ) - KeyCtrlK = Key(termbox.KeyCtrlK) - KeyCtrlL = Key(termbox.KeyCtrlL) - KeyEnter = Key(termbox.KeyEnter) - KeyCtrlM = Key(termbox.KeyCtrlM) - KeyCtrlN = Key(termbox.KeyCtrlN) - KeyCtrlO = Key(termbox.KeyCtrlO) - KeyCtrlP = Key(termbox.KeyCtrlP) - KeyCtrlQ = Key(termbox.KeyCtrlQ) - KeyCtrlR = Key(termbox.KeyCtrlR) - KeyCtrlS = Key(termbox.KeyCtrlS) - KeyCtrlT = Key(termbox.KeyCtrlT) - KeyCtrlU = Key(termbox.KeyCtrlU) - KeyCtrlV = Key(termbox.KeyCtrlV) - KeyCtrlW = Key(termbox.KeyCtrlW) - KeyCtrlX = Key(termbox.KeyCtrlX) - KeyCtrlY = Key(termbox.KeyCtrlY) - KeyCtrlZ = Key(termbox.KeyCtrlZ) - KeyEsc = Key(termbox.KeyEsc) - KeyCtrlLsqBracket = Key(termbox.KeyCtrlLsqBracket) - KeyCtrl3 = Key(termbox.KeyCtrl3) - KeyCtrl4 = Key(termbox.KeyCtrl4) - KeyCtrlBackslash = Key(termbox.KeyCtrlBackslash) - KeyCtrl5 = Key(termbox.KeyCtrl5) - KeyCtrlRsqBracket = Key(termbox.KeyCtrlRsqBracket) - KeyCtrl6 = Key(termbox.KeyCtrl6) - KeyCtrl7 = Key(termbox.KeyCtrl7) - KeyCtrlSlash = Key(termbox.KeyCtrlSlash) - KeyCtrlUnderscore = Key(termbox.KeyCtrlUnderscore) - KeySpace = Key(termbox.KeySpace) - KeyBackspace2 = Key(termbox.KeyBackspace2) - KeyCtrl8 = Key(termbox.KeyCtrl8) -) - -// Modifiers. -const ( - ModNone Modifier = Modifier(0) - ModAlt = Modifier(termbox.ModAlt) -) diff --git a/vendor/github.com/awesome-gocui/gocui/loader.go b/vendor/github.com/awesome-gocui/gocui/loader.go deleted file mode 100644 index d6715ac6..00000000 --- a/vendor/github.com/awesome-gocui/gocui/loader.go +++ /dev/null @@ -1,46 +0,0 @@ -package gocui - -import "time" - -func (g *Gui) loaderTick() { - go func() { - for range time.Tick(time.Millisecond * 50) { - for _, view := range g.Views() { - if view.HasLoader { - g.userEvents <- userEvent{func(g *Gui) error { return nil }} - break - } - } - } - }() -} - -func (v *View) loaderLines() [][]cell { - duplicate := make([][]cell, len(v.lines)) - for i := range v.lines { - if i < len(v.lines)-1 { - duplicate[i] = make([]cell, len(v.lines[i])) - copy(duplicate[i], v.lines[i]) - } else { - duplicate[i] = make([]cell, len(v.lines[i])+2) - copy(duplicate[i], v.lines[i]) - duplicate[i][len(duplicate[i])-2] = cell{chr: ' '} - duplicate[i][len(duplicate[i])-1] = Loader() - } - } - - return duplicate -} - -// Loader can show a loading animation -func Loader() cell { - characters := "|/-\\" - now := time.Now() - nanos := now.UnixNano() - index := nanos / 50000000 % int64(len(characters)) - str := characters[index : index+1] - chr := []rune(str)[0] - return cell{ - chr: chr, - } -} diff --git a/vendor/github.com/awesome-gocui/gocui/view.go b/vendor/github.com/awesome-gocui/gocui/view.go deleted file mode 100644 index 81f90603..00000000 --- a/vendor/github.com/awesome-gocui/gocui/view.go +++ /dev/null @@ -1,800 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gocui - -import ( - "bytes" - "io" - "strings" - "sync" - "unicode/utf8" - - "github.com/go-errors/errors" - - "github.com/awesome-gocui/termbox-go" - "github.com/mattn/go-runewidth" -) - -// Constants for overlapping edges -const ( - TOP = 1 // view is overlapping at top edge - BOTTOM = 2 // view is overlapping at bottom edge - LEFT = 4 // view is overlapping at left edge - RIGHT = 8 // view is overlapping at right edge -) - -var ( - // ErrInvalidPoint is returned when client passed invalid coordinates of a cell. - // Most likely client has passed negative coordinates of a cell. - ErrInvalidPoint = errors.New("invalid point") -) - -// A View is a window. It maintains its own internal buffer and cursor -// position. -type View struct { - name string - x0, y0, x1, y1 int // left top right bottom - ox, oy int // view offsets - cx, cy int // cursor position - rx, ry int // Read() offsets - wx, wy int // Write() offsets - lines [][]cell // All the data - - // readBuffer is used for storing unread bytes - readBuffer []byte - - // tained is true if the viewLines must be updated - tainted bool - - // internal representation of the view's buffer - viewLines []viewLine - - // writeMutex protects locks the write process - writeMutex sync.Mutex - - // ei is used to decode ESC sequences on Write - ei *escapeInterpreter - - // Visible specifies whether the view is visible. - Visible bool - - // BgColor and FgColor allow to configure the background and foreground - // colors of the View. - BgColor, FgColor Attribute - - // SelBgColor and SelFgColor are used to configure the background and - // foreground colors of the selected line, when it is highlighted. - SelBgColor, SelFgColor Attribute - - // If Editable is true, keystrokes will be added to the view's internal - // buffer at the cursor position. - Editable bool - - // Editor allows to define the editor that manages the editing mode, - // including keybindings or cursor behaviour. DefaultEditor is used by - // default. - Editor Editor - - // Overwrite enables or disables the overwrite mode of the view. - Overwrite bool - - // If Highlight is true, Sel{Bg,Fg}Colors will be used - // for the line under the cursor position. - Highlight bool - - // If Frame is true, a border will be drawn around the view. - Frame bool - - // If Wrap is true, the content that is written to this View is - // automatically wrapped when it is longer than its width. If true the - // view's x-origin will be ignored. - Wrap bool - - // If Autoscroll is true, the View will automatically scroll down when the - // text overflows. If true the view's y-origin will be ignored. - Autoscroll bool - - // If Frame is true, Title allows to configure a title for the view. - Title string - - // If Frame is true, Subtitle allows to configure a subtitle for the view. - Subtitle string - - // If Mask is true, the View will display the mask instead of the real - // content - Mask rune - - // Overlaps describes which edges are overlapping with another view's edges - Overlaps byte - - // If HasLoader is true, the message will be appended with a spinning loader animation - HasLoader bool -} - -type viewLine struct { - linesX, linesY int // coordinates relative to v.lines - line []cell -} - -type cell struct { - chr rune - bgColor, fgColor Attribute -} - -type lineType []cell - -// String returns a string from a given cell slice. -func (l lineType) String() string { - str := "" - for _, c := range l { - str += string(c.chr) - } - return str -} - -// newView returns a new View object. -func newView(name string, x0, y0, x1, y1 int, mode OutputMode) *View { - v := &View{ - name: name, - x0: x0, - y0: y0, - x1: x1, - y1: y1, - Visible: true, - Frame: true, - Editor: DefaultEditor, - tainted: true, - ei: newEscapeInterpreter(mode), - } - return v -} - -// Dimensions returns the dimensions of the View -func (v *View) Dimensions() (int, int, int, int) { - return v.x0, v.y0, v.x1, v.y1 -} - -// Size returns the number of visible columns and rows in the View. -func (v *View) Size() (x, y int) { - return v.x1 - v.x0 - 1, v.y1 - v.y0 - 1 -} - -// Name returns the name of the view. -func (v *View) Name() string { - return v.name -} - -// setRune sets a rune at the given point relative to the view. It applies the -// specified colors, taking into account if the cell must be highlighted. Also, -// it checks if the position is valid. -func (v *View) setRune(x, y int, ch rune, fgColor, bgColor Attribute) error { - maxX, maxY := v.Size() - if x < 0 || x >= maxX || y < 0 || y >= maxY { - return ErrInvalidPoint - } - var ( - ry, rcy int - err error - ) - if v.Highlight { - _, ry, err = v.realPosition(x, y) - if err != nil { - return err - } - _, rcy, err = v.realPosition(v.cx, v.cy) - if err != nil { - return err - } - } - - if v.Mask != 0 { - fgColor = v.FgColor - bgColor = v.BgColor - ch = v.Mask - } else if v.Highlight && ry == rcy { - fgColor = fgColor | AttrBold - } - - // Don't display NUL characters - if ch == 0 { - ch = ' ' - } - - termbox.SetCell(v.x0+x+1, v.y0+y+1, ch, - termbox.Attribute(fgColor), termbox.Attribute(bgColor)) - - return nil -} - -// SetCursor sets the cursor position of the view at the given point, -// relative to the view. It checks if the position is valid. -func (v *View) SetCursor(x, y int) error { - maxX, maxY := v.Size() - if x < 0 || x >= maxX || y < 0 || y >= maxY { - return ErrInvalidPoint - } - v.cx = x - v.cy = y - return nil -} - -// Cursor returns the cursor position of the view. -func (v *View) Cursor() (x, y int) { - return v.cx, v.cy -} - -// SetOrigin sets the origin position of the view's internal buffer, -// so the buffer starts to be printed from this point, which means that -// it is linked with the origin point of view. It can be used to -// implement Horizontal and Vertical scrolling with just incrementing -// or decrementing ox and oy. -func (v *View) SetOrigin(x, y int) error { - if x < 0 || y < 0 { - return ErrInvalidPoint - } - v.ox = x - v.oy = y - return nil -} - -// Origin returns the origin position of the view. -func (v *View) Origin() (x, y int) { - return v.ox, v.oy -} - -// SetWritePos sets the write position of the view's internal buffer. -// So the next Write call would write directly to the specified position. -func (v *View) SetWritePos(x, y int) error { - if x < 0 || y < 0 { - return ErrInvalidPoint - } - v.wx = x - v.wy = y - return nil -} - -// WritePos returns the current write position of the view's internal buffer. -func (v *View) WritePos() (x, y int) { - return v.wx, v.wy -} - -// SetReadPos sets the read position of the view's internal buffer. -// So the next Read call would read from the specified position. -func (v *View) SetReadPos(x, y int) error { - if x < 0 || y < 0 { - return ErrInvalidPoint - } - v.readBuffer = nil - v.rx = x - v.ry = y - return nil -} - -// ReadPos returns the current read position of the view's internal buffer. -func (v *View) ReadPos() (x, y int) { - return v.rx, v.ry -} - -// makeWriteable creates empty cells if required to make position (x, y) writeable. -func (v *View) makeWriteable(x, y int) { - // TODO: make this more efficient - - // line `y` must be index-able (that's why `<=`) - for len(v.lines) <= y { - if cap(v.lines) > len(v.lines) { - newLen := cap(v.lines) - if newLen > y { - newLen = y + 1 - } - v.lines = v.lines[:newLen] - } else { - v.lines = append(v.lines, nil) - } - } - // cell `x` must not be index-able (that's why `<`) - // append should be used by `lines[y]` user if he wants to write beyond `x` - for len(v.lines[y]) < x { - if cap(v.lines[y]) > len(v.lines[y]) { - newLen := cap(v.lines[y]) - if newLen > x { - newLen = x - } - v.lines[y] = v.lines[y][:newLen] - } else { - v.lines[y] = append(v.lines[y], cell{}) - } - } -} - -// writeCells copies []cell to specified location (x, y) -// !!! caller MUST ensure that specified location (x, y) is writeable by calling makeWriteable -func (v *View) writeCells(x, y int, cells []cell) { - var newLen int - // use maximum len available - line := v.lines[y][:cap(v.lines[y])] - maxCopy := len(line) - x - if maxCopy < len(cells) { - copy(line[x:], cells[:maxCopy]) - line = append(line, cells[maxCopy:]...) - newLen = len(line) - } else { // maxCopy >= len(cells) - copy(line[x:], cells) - newLen = x + len(cells) - if newLen < len(v.lines[y]) { - newLen = len(v.lines[y]) - } - } - v.lines[y] = line[:newLen] -} - -// Write appends a byte slice into the view's internal buffer. Because -// View implements the io.Writer interface, it can be passed as parameter -// of functions like fmt.Fprintf, fmt.Fprintln, io.Copy, etc. Clear must -// be called to clear the view's buffer. -func (v *View) Write(p []byte) (n int, err error) { - v.tainted = true - v.writeMutex.Lock() - v.makeWriteable(v.wx, v.wy) - v.writeRunes(bytes.Runes(p)) - v.writeMutex.Unlock() - - return len(p), nil -} - -func (v *View) WriteRunes(p []rune) { - v.tainted = true - - // Fill with empty cells, if writing outside current view buffer - v.makeWriteable(v.wx, v.wy) - v.writeRunes(p) -} - -func (v *View) WriteString(s string) { - v.WriteRunes([]rune(s)) -} - -// writeRunes copies slice of runes into internal lines buffer. -// caller must make sure that writing position is accessable. -func (v *View) writeRunes(p []rune) { - for _, r := range p { - switch r { - case '\n': - v.wy++ - if v.wy >= len(v.lines) { - v.lines = append(v.lines, nil) - } - - fallthrough - // not valid in every OS, but making runtime OS checks in cycle is bad. - case '\r': - v.wx = 0 - default: - cells := v.parseInput(r) - if cells == nil { - continue - } - v.writeCells(v.wx, v.wy, cells) - v.wx += len(cells) - } - } -} - -// parseInput parses char by char the input written to the View. It returns nil -// while processing ESC sequences. Otherwise, it returns a cell slice that -// contains the processed data. -func (v *View) parseInput(ch rune) []cell { - cells := []cell{} - - isEscape, err := v.ei.parseOne(ch) - if err != nil { - for _, r := range v.ei.runes() { - c := cell{ - fgColor: v.FgColor, - bgColor: v.BgColor, - chr: r, - } - cells = append(cells, c) - } - v.ei.reset() - } else { - if isEscape { - return nil - } - repeatCount := 1 - if ch == '\t' { - ch = ' ' - repeatCount = 4 - } - for i := 0; i < repeatCount; i++ { - c := cell{ - fgColor: v.ei.curFgColor, - bgColor: v.ei.curBgColor, - chr: ch, - } - cells = append(cells, c) - } - } - - return cells -} - -// Read reads data into p from the current reading position set by SetReadPos. -// It returns the number of bytes read into p. -// At EOF, err will be io.EOF. -func (v *View) Read(p []byte) (n int, err error) { - buffer := make([]byte, utf8.UTFMax) - offset := 0 - if v.readBuffer != nil { - copy(p, v.readBuffer) - if len(v.readBuffer) >= len(p) { - if len(v.readBuffer) > len(p) { - v.readBuffer = v.readBuffer[len(p):] - } - return len(p), nil - } - v.readBuffer = nil - } - for v.ry < len(v.lines) { - for v.rx < len(v.lines[v.ry]) { - count := utf8.EncodeRune(buffer, v.lines[v.ry][v.rx].chr) - copy(p[offset:], buffer[:count]) - v.rx++ - newOffset := offset + count - if newOffset >= len(p) { - if newOffset > len(p) { - v.readBuffer = buffer[newOffset-len(p):] - } - return len(p), nil - } - offset += count - } - v.rx = 0 - v.ry++ - } - return offset, io.EOF -} - -// Rewind sets read and write pos to (0, 0). -func (v *View) Rewind() { - if err := v.SetReadPos(0, 0); err != nil { - // SetReadPos returns error only if x and y are negative - // we are passing 0, 0, thus no error should occur. - panic(err) - } - if err := v.SetWritePos(0, 0); err != nil { - // SetWritePos returns error only if x and y are negative - // we are passing 0, 0, thus no error should occur. - panic(err) - } -} - -// IsTainted tells us if the view is tainted -func (v *View) IsTainted() bool { - return v.tainted -} - -// draw re-draws the view's contents. -func (v *View) draw() error { - if !v.Visible { - return nil - } - - maxX, maxY := v.Size() - - if v.Wrap { - if maxX == 0 { - return errors.New("X size of the view cannot be 0") - } - v.ox = 0 - } - if v.tainted { - v.viewLines = nil - lines := v.lines - if v.HasLoader { - lines = v.loaderLines() - } - for i, line := range lines { - wrap := 0 - if v.Wrap { - wrap = maxX - } - - ls := lineWrap(line, wrap) - for j := range ls { - vline := viewLine{linesX: j, linesY: i, line: ls[j]} - v.viewLines = append(v.viewLines, vline) - } - } - if !v.HasLoader { - v.tainted = false - } - } - - if v.Autoscroll && len(v.viewLines) > maxY { - v.oy = len(v.viewLines) - maxY - } - y := 0 - for i, vline := range v.viewLines { - if i < v.oy { - continue - } - if y >= maxY { - break - } - x := 0 - for j, c := range vline.line { - if j < v.ox { - continue - } - if x >= maxX { - break - } - - fgColor := c.fgColor - if fgColor == ColorDefault { - fgColor = v.FgColor - } - bgColor := c.bgColor - if bgColor == ColorDefault { - bgColor = v.BgColor - } - - if err := v.setRune(x, y, c.chr, fgColor, bgColor); err != nil { - return err - } - - if c.chr != 0 { - // If it is a rune, add rune width - x += runewidth.RuneWidth(c.chr) - } else { - // If it is NULL rune, add 1 to be able to use SetWritePos - // (runewidth.RuneWidth of space is 1) - x++ - } - } - y++ - } - return nil -} - -// realPosition returns the position in the internal buffer corresponding to the -// point (x, y) of the view. -func (v *View) realPosition(vx, vy int) (x, y int, err error) { - vx = v.ox + vx - vy = v.oy + vy - - if vx < 0 || vy < 0 { - return 0, 0, ErrInvalidPoint - } - - if len(v.viewLines) == 0 { - return vx, vy, nil - } - - if vy < len(v.viewLines) { - vline := v.viewLines[vy] - x = vline.linesX + vx - y = vline.linesY - } else { - vline := v.viewLines[len(v.viewLines)-1] - x = vx - y = vline.linesY + vy - len(v.viewLines) + 1 - } - - return x, y, nil -} - -// Clear empties the view's internal buffer. -// And resets reading and writing offsets. -func (v *View) Clear() { - v.writeMutex.Lock() - v.Rewind() - v.tainted = true - v.ei.reset() - v.lines = nil - v.viewLines = nil - v.clearRunes() - v.writeMutex.Unlock() -} - -// clearRunes erases all the cells in the view. -func (v *View) clearRunes() { - maxX, maxY := v.Size() - for x := 0; x < maxX; x++ { - for y := 0; y < maxY; y++ { - termbox.SetCell(v.x0+x+1, v.y0+y+1, ' ', - termbox.Attribute(v.FgColor), termbox.Attribute(v.BgColor)) - } - } -} - -// BufferLines returns the lines in the view's internal -// buffer. -func (v *View) BufferLines() []string { - lines := make([]string, len(v.lines)) - for i, l := range v.lines { - str := lineType(l).String() - str = strings.Replace(str, "\x00", " ", -1) - lines[i] = str - } - return lines -} - -// Buffer returns a string with the contents of the view's internal -// buffer. -func (v *View) Buffer() string { - return linesToString(v.lines) -} - -// ViewBufferLines returns the lines in the view's internal -// buffer that is shown to the user. -func (v *View) ViewBufferLines() []string { - lines := make([]string, len(v.viewLines)) - for i, l := range v.viewLines { - str := lineType(l.line).String() - str = strings.Replace(str, "\x00", " ", -1) - lines[i] = str - } - return lines -} - -// LinesHeight is the count of view lines (i.e. lines excluding wrapping) -func (v *View) LinesHeight() int { - return len(v.lines) -} - -// ViewLinesHeight is the count of view lines (i.e. lines including wrapping) -func (v *View) ViewLinesHeight() int { - return len(v.viewLines) -} - -// ViewBuffer returns a string with the contents of the view's buffer that is -// shown to the user. -func (v *View) ViewBuffer() string { - lines := make([][]cell, len(v.viewLines)) - for i := range v.viewLines { - lines[i] = v.viewLines[i].line - } - - return linesToString(lines) -} - -// Line returns a string with the line of the view's internal buffer -// at the position corresponding to the point (x, y). -func (v *View) Line(y int) (string, error) { - _, y, err := v.realPosition(0, y) - if err != nil { - return "", err - } - - if y < 0 || y >= len(v.lines) { - return "", ErrInvalidPoint - } - - return lineType(v.lines[y]).String(), nil -} - -// Word returns a string with the word of the view's internal buffer -// at the position corresponding to the point (x, y). -func (v *View) Word(x, y int) (string, error) { - x, y, err := v.realPosition(x, y) - if err != nil { - return "", err - } - - if x < 0 || y < 0 || y >= len(v.lines) || x >= len(v.lines[y]) { - return "", ErrInvalidPoint - } - - str := lineType(v.lines[y]).String() - - nl := strings.LastIndexFunc(str[:x], indexFunc) - if nl == -1 { - nl = 0 - } else { - nl = nl + 1 - } - nr := strings.IndexFunc(str[x:], indexFunc) - if nr == -1 { - nr = len(str) - } else { - nr = nr + x - } - return string(str[nl:nr]), nil -} - -// indexFunc allows to split lines by words taking into account spaces -// and 0. -func indexFunc(r rune) bool { - return r == ' ' || r == 0 -} - -// SetLine changes the contents of an existing line. -func (v *View) SetLine(y int, text string) error { - if y < 0 || y >= len(v.lines) { - err := ErrInvalidPoint - return err - } - - v.tainted = true - line := make([]cell, 0) - for _, r := range text { - c := v.parseInput(r) - line = append(line, c...) - } - v.lines[y] = line - return nil -} - -// SetHighlight toggles highlighting of separate lines, for custom lists -// or multiple selection in views. -func (v *View) SetHighlight(y int, on bool) error { - if y < 0 || y >= len(v.lines) { - err := ErrInvalidPoint - return err - } - - line := v.lines[y] - cells := make([]cell, 0) - for _, c := range line { - if on { - c.bgColor = v.SelBgColor - c.fgColor = v.SelFgColor - } else { - c.bgColor = v.BgColor - c.fgColor = v.FgColor - } - cells = append(cells, c) - } - v.tainted = true - v.lines[y] = cells - return nil -} - -func lineWidth(line []cell) (n int) { - for i := range line { - n += runewidth.RuneWidth(line[i].chr) - } - - return -} - -func lineWrap(line []cell, columns int) [][]cell { - if columns == 0 { - return [][]cell{line} - } - - var n int - var offset int - lines := make([][]cell, 0, 1) - for i := range line { - rw := runewidth.RuneWidth(line[i].chr) - n += rw - if n > columns { - n = rw - lines = append(lines, line[offset:i]) - offset = i - } - } - - lines = append(lines, line[offset:]) - return lines -} - -func linesToString(lines [][]cell) string { - str := make([]string, len(lines)) - for i := range lines { - rns := make([]rune, 0, len(lines[i])) - line := lineType(lines[i]).String() - for _, c := range line { - if c != '\x00' { - rns = append(rns, c) - } - } - str[i] = string(rns) - } - - return strings.Join(str, "\n") -} |