aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/awesome-gocui/gocui
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2020-02-05 22:03:19 +0100
committerMichael Muré <batolettre@gmail.com>2020-02-05 22:33:03 +0100
commit1d4bb7ceb0cef79d68df0bacc913b01e40e6ddd6 (patch)
treee088b0fa43058afde1db71541d8fcb4b94905d6e /vendor/github.com/awesome-gocui/gocui
parentf093be96e98284580d61664adecd0a2ff8b354e4 (diff)
downloadgit-bug-1d4bb7ceb0cef79d68df0bacc913b01e40e6ddd6.tar.gz
migrate to go modules
Diffstat (limited to 'vendor/github.com/awesome-gocui/gocui')
-rw-r--r--vendor/github.com/awesome-gocui/gocui/.gitignore1
-rw-r--r--vendor/github.com/awesome-gocui/gocui/AUTHORS30
-rw-r--r--vendor/github.com/awesome-gocui/gocui/CODE_OF_CONDUCT.md76
-rw-r--r--vendor/github.com/awesome-gocui/gocui/CONTRIBUTING.md33
-rw-r--r--vendor/github.com/awesome-gocui/gocui/LICENSE23
-rw-r--r--vendor/github.com/awesome-gocui/gocui/README.md135
-rw-r--r--vendor/github.com/awesome-gocui/gocui/attribute.go32
-rw-r--r--vendor/github.com/awesome-gocui/gocui/doc.go118
-rw-r--r--vendor/github.com/awesome-gocui/gocui/edit.go449
-rw-r--r--vendor/github.com/awesome-gocui/gocui/escape.go259
-rw-r--r--vendor/github.com/awesome-gocui/gocui/go.mod9
-rw-r--r--vendor/github.com/awesome-gocui/gocui/go.sum6
-rw-r--r--vendor/github.com/awesome-gocui/gocui/gui.go832
-rw-r--r--vendor/github.com/awesome-gocui/gocui/gui_others.go60
-rw-r--r--vendor/github.com/awesome-gocui/gocui/gui_windows.go53
-rw-r--r--vendor/github.com/awesome-gocui/gocui/keybinding.go285
-rw-r--r--vendor/github.com/awesome-gocui/gocui/loader.go46
-rw-r--r--vendor/github.com/awesome-gocui/gocui/view.go800
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")
-}