1
0

Add gocui dependency to vendor

Along with its dependencies.

4f518eddb0
97311d9f77
10cefba34b
This commit is contained in:
Tony Grosinger 2017-10-22 13:45:29 -07:00
parent a1e0fb3b7e
commit 086b8e5f4e
67 changed files with 10851 additions and 0 deletions

1
vendor/github.com/jroimartin/gocui/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
*.swp

30
vendor/github.com/jroimartin/gocui/AUTHORS generated vendored Normal file
View File

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

23
vendor/github.com/jroimartin/gocui/LICENSE generated vendored Normal file
View File

@ -0,0 +1,23 @@
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.

105
vendor/github.com/jroimartin/gocui/README.md generated vendored Normal file
View File

@ -0,0 +1,105 @@
# GOCUI - Go Console User Interface
[![GoDoc](https://godoc.org/github.com/jroimartin/gocui?status.svg)](https://godoc.org/github.com/jroimartin/gocui)
Minimalist Go package aimed at creating Console User Interfaces.
## 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 edition mode.
* Easy to build reusable widgets, complex layouts...
## Installation
Execute:
```
$ go get github.com/jroimartin/gocui
```
## Documentation
Execute:
```
$ go doc github.com/jroimartin/gocui
```
Or visit [godoc.org](https://godoc.org/github.com/jroimartin/gocui) to read it
online.
## Example
```go
package main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
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 && err != gocui.ErrQuit {
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); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, "Hello world!")
}
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.
Note: if your project is not listed here, let us know! :)

View File

@ -0,0 +1,420 @@
The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
by Mark Twain (Samuel Clemens)
This eBook is for the use of anyone anywhere at no cost and with
almost no restrictions whatsoever. You may copy it, give it away or
re-use it under the terms of the Project Gutenberg License included
with this eBook or online at www.gutenberg.net
Title: The Adventures of Tom Sawyer, Complete
Author: Mark Twain (Samuel Clemens)
Release Date: August 20, 2006 [EBook #74]
[Last updated: May 3, 2011]
Language: English
*** START OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
Produced by David Widger. The previous edition was updated by Jose
Menendez.
THE ADVENTURES OF TOM SAWYER
BY
MARK TWAIN
(Samuel Langhorne Clemens)
P R E F A C E
MOST of the adventures recorded in this book really occurred; one or
two were experiences of my own, the rest those of boys who were
schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
not from an individual--he is a combination of the characteristics of
three boys whom I knew, and therefore belongs to the composite order of
architecture.
The odd superstitions touched upon were all prevalent among children
and slaves in the West at the period of this story--that is to say,
thirty or forty years ago.
Although my book is intended mainly for the entertainment of boys and
girls, I hope it will not be shunned by men and women on that account,
for part of my plan has been to try to pleasantly remind adults of what
they once were themselves, and of how they felt and thought and talked,
and what queer enterprises they sometimes engaged in.
THE AUTHOR.
HARTFORD, 1876.
T O M S A W Y E R
CHAPTER I
"TOM!"
No answer.
"TOM!"
No answer.
"What's gone with that boy, I wonder? You TOM!"
No answer.
The old lady pulled her spectacles down and looked over them about the
room; then she put them up and looked out under them. She seldom or
never looked THROUGH them for so small a thing as a boy; they were her
state pair, the pride of her heart, and were built for "style," not
service--she could have seen through a pair of stove-lids just as well.
She looked perplexed for a moment, and then said, not fiercely, but
still loud enough for the furniture to hear:
"Well, I lay if I get hold of you I'll--"
She did not finish, for by this time she was bending down and punching
under the bed with the broom, and so she needed breath to punctuate the
punches with. She resurrected nothing but the cat.
"I never did see the beat of that boy!"
She went to the open door and stood in it and looked out among the
tomato vines and "jimpson" weeds that constituted the garden. No Tom.
So she lifted up her voice at an angle calculated for distance and
shouted:
"Y-o-u-u TOM!"
There was a slight noise behind her and she turned just in time to
seize a small boy by the slack of his roundabout and arrest his flight.
"There! I might 'a' thought of that closet. What you been doing in
there?"
"Nothing."
"Nothing! Look at your hands. And look at your mouth. What IS that
truck?"
"I don't know, aunt."
"Well, I know. It's jam--that's what it is. Forty times I've said if
you didn't let that jam alone I'd skin you. Hand me that switch."
The switch hovered in the air--the peril was desperate--
"My! Look behind you, aunt!"
The old lady whirled round, and snatched her skirts out of danger. The
lad fled on the instant, scrambled up the high board-fence, and
disappeared over it.
His aunt Polly stood surprised a moment, and then broke into a gentle
laugh.
"Hang the boy, can't I never learn anything? Ain't he played me tricks
enough like that for me to be looking out for him by this time? But old
fools is the biggest fools there is. Can't learn an old dog new tricks,
as the saying is. But my goodness, he never plays them alike, two days,
and how is a body to know what's coming? He 'pears to know just how
long he can torment me before I get my dander up, and he knows if he
can make out to put me off for a minute or make me laugh, it's all down
again and I can't hit him a lick. I ain't doing my duty by that boy,
and that's the Lord's truth, goodness knows. Spare the rod and spile
the child, as the Good Book says. I'm a laying up sin and suffering for
us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
own dead sister's boy, poor thing, and I ain't got the heart to lash
him, somehow. Every time I let him off, my conscience does hurt me so,
and every time I hit him my old heart most breaks. Well-a-well, man
that is born of woman is of few days and full of trouble, as the
Scripture says, and I reckon it's so. He'll play hookey this evening, *
and [* Southwestern for "afternoon"] I'll just be obleeged to make him
work, to-morrow, to punish him. It's mighty hard to make him work
Saturdays, when all the boys is having holiday, but he hates work more
than he hates anything else, and I've GOT to do some of my duty by him,
or I'll be the ruination of the child."
Tom did play hookey, and he had a very good time. He got back home
barely in season to help Jim, the small colored boy, saw next-day's
wood and split the kindlings before supper--at least he was there in
time to tell his adventures to Jim while Jim did three-fourths of the
work. Tom's younger brother (or rather half-brother) Sid was already
through with his part of the work (picking up chips), for he was a
quiet boy, and had no adventurous, troublesome ways.
While Tom was eating his supper, and stealing sugar as opportunity
offered, Aunt Polly asked him questions that were full of guile, and
very deep--for she wanted to trap him into damaging revealments. Like
many other simple-hearted souls, it was her pet vanity to believe she
was endowed with a talent for dark and mysterious diplomacy, and she
loved to contemplate her most transparent devices as marvels of low
cunning. Said she:
"Tom, it was middling warm in school, warn't it?"
"Yes'm."
"Powerful warm, warn't it?"
"Yes'm."
"Didn't you want to go in a-swimming, Tom?"
A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
He searched Aunt Polly's face, but it told him nothing. So he said:
"No'm--well, not very much."
The old lady reached out her hand and felt Tom's shirt, and said:
"But you ain't too warm now, though." And it flattered her to reflect
that she had discovered that the shirt was dry without anybody knowing
that that was what she had in her mind. But in spite of her, Tom knew
where the wind lay, now. So he forestalled what might be the next move:
"Some of us pumped on our heads--mine's damp yet. See?"
Aunt Polly was vexed to think she had overlooked that bit of
circumstantial evidence, and missed a trick. Then she had a new
inspiration:
"Tom, you didn't have to undo your shirt collar where I sewed it, to
pump on your head, did you? Unbutton your jacket!"
The trouble vanished out of Tom's face. He opened his jacket. His
shirt collar was securely sewed.
"Bother! Well, go 'long with you. I'd made sure you'd played hookey
and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
singed cat, as the saying is--better'n you look. THIS time."
She was half sorry her sagacity had miscarried, and half glad that Tom
had stumbled into obedient conduct for once.
But Sidney said:
"Well, now, if I didn't think you sewed his collar with white thread,
but it's black."
"Why, I did sew it with white! Tom!"
But Tom did not wait for the rest. As he went out at the door he said:
"Siddy, I'll lick you for that."
In a safe place Tom examined two large needles which were thrust into
the lapels of his jacket, and had thread bound about them--one needle
carried white thread and the other black. He said:
"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
she sews it with white, and sometimes she sews it with black. I wish to
geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
I bet you I'll lam Sid for that. I'll learn him!"
He was not the Model Boy of the village. He knew the model boy very
well though--and loathed him.
Within two minutes, or even less, he had forgotten all his troubles.
Not because his troubles were one whit less heavy and bitter to him
than a man's are to a man, but because a new and powerful interest bore
them down and drove them out of his mind for the time--just as men's
misfortunes are forgotten in the excitement of new enterprises. This
new interest was a valued novelty in whistling, which he had just
acquired from a negro, and he was suffering to practise it undisturbed.
It consisted in a peculiar bird-like turn, a sort of liquid warble,
produced by touching the tongue to the roof of the mouth at short
intervals in the midst of the music--the reader probably remembers how
to do it, if he has ever been a boy. Diligence and attention soon gave
him the knack of it, and he strode down the street with his mouth full
of harmony and his soul full of gratitude. He felt much as an
astronomer feels who has discovered a new planet--no doubt, as far as
strong, deep, unalloyed pleasure is concerned, the advantage was with
the boy, not the astronomer.
The summer evenings were long. It was not dark, yet. Presently Tom
checked his whistle. A stranger was before him--a boy a shade larger
than himself. A new-comer of any age or either sex was an impressive
curiosity in the poor little shabby village of St. Petersburg. This boy
was well dressed, too--well dressed on a week-day. This was simply
astounding. His cap was a dainty thing, his close-buttoned blue cloth
roundabout was new and natty, and so were his pantaloons. He had shoes
on--and it was only Friday. He even wore a necktie, a bright bit of
ribbon. He had a citified air about him that ate into Tom's vitals. The
more Tom stared at the splendid marvel, the higher he turned up his
nose at his finery and the shabbier and shabbier his own outfit seemed
to him to grow. Neither boy spoke. If one moved, the other moved--but
only sidewise, in a circle; they kept face to face and eye to eye all
the time. Finally Tom said:
"I can lick you!"
"I'd like to see you try it."
"Well, I can do it."
"No you can't, either."
"Yes I can."
"No you can't."
"I can."
"You can't."
"Can!"
"Can't!"
An uncomfortable pause. Then Tom said:
"What's your name?"
"'Tisn't any of your business, maybe."
"Well I 'low I'll MAKE it my business."
"Well why don't you?"
"If you say much, I will."
"Much--much--MUCH. There now."
"Oh, you think you're mighty smart, DON'T you? I could lick you with
one hand tied behind me, if I wanted to."
"Well why don't you DO it? You SAY you can do it."
"Well I WILL, if you fool with me."
"Oh yes--I've seen whole families in the same fix."
"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
"You can lump that hat if you don't like it. I dare you to knock it
off--and anybody that'll take a dare will suck eggs."
"You're a liar!"
"You're another."
"You're a fighting liar and dasn't take it up."
"Aw--take a walk!"
"Say--if you give me much more of your sass I'll take and bounce a
rock off'n your head."
"Oh, of COURSE you will."
"Well I WILL."
"Well why don't you DO it then? What do you keep SAYING you will for?
Why don't you DO it? It's because you're afraid."
"I AIN'T afraid."
"You are."
"I ain't."
"You are."
Another pause, and more eying and sidling around each other. Presently
they were shoulder to shoulder. Tom said:
"Get away from here!"
"Go away yourself!"
"I won't."
"I won't either."
So they stood, each with a foot placed at an angle as a brace, and
both shoving with might and main, and glowering at each other with
hate. But neither could get an advantage. After struggling till both
were hot and flushed, each relaxed his strain with watchful caution,
and Tom said:
"You're a coward and a pup. I'll tell my big brother on you, and he
can thrash you with his little finger, and I'll make him do it, too."
"What do I care for your big brother? I've got a brother that's bigger
than he is--and what's more, he can throw him over that fence, too."
[Both brothers were imaginary.]
"That's a lie."
"YOUR saying so don't make it so."
Tom drew a line in the dust with his big toe, and said:
"I dare you to step over that, and I'll lick you till you can't stand
up. Anybody that'll take a dare will steal sheep."
The new boy stepped over promptly, and said:
"Now you said you'd do it, now let's see you do it."
"Don't you crowd me now; you better look out."
"Well, you SAID you'd do it--why don't you do it?"
"By jingo! for two cents I WILL do it."
The new boy took two broad coppers out of his pocket and held them out
with derision. Tom struck them to the ground. In an instant both boys
were rolling and tumbling in the dirt, gripped together like cats; and
for the space of a minute they tugged and tore at each other's hair and
clothes, punched and scratched each other's nose, and covered
themselves with dust and glory. Presently the confusion took form, and
through the fog of battle Tom appeared, seated astride the new boy, and
pounding him with his fists. "Holler 'nuff!" said he.
The boy only struggled to free himself. He was crying--mainly from rage.
"Holler 'nuff!"--and the pounding went on.
At last the stranger got out a smothered "'Nuff!" and Tom let him up
and said:
"Now that'll learn you. Better look out who you're fooling with next
time."
The new boy went off brushing the dust from his clothes, sobbing,
snuffling, and occasionally looking back and shaking his head and
threatening what he would do to Tom the "next time he caught him out."
To which Tom responded with jeers, and started off in high feather, and
as soon as his back was turned the new boy snatched up a stone, threw
it and hit him between the shoulders and then turned tail and ran like
an antelope. Tom chased the traitor home, and thus found out where he
lived. He then held a position at the gate for some time, daring the
enemy to come outside, but the enemy only made faces at him through the
window and declined. At last the enemy's mother appeared, and called
Tom a bad, vicious, vulgar child, and ordered him away. So he went
away; but he said he "'lowed" to "lay" for that boy.
He got home pretty late that night, and when he climbed cautiously in
at the window, he uncovered an ambuscade, in the person of his aunt;
and when she saw the state his clothes were in her resolution to turn
his Saturday holiday into captivity at hard labor became adamantine in
its firmness.

119
vendor/github.com/jroimartin/gocui/_examples/active.go generated vendored Normal file
View File

@ -0,0 +1,119 @@
// 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 main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
var (
viewArr = []string{"v1", "v2", "v3", "v4"}
active = 0
)
func setCurrentViewOnTop(g *gocui.Gui, name string) (*gocui.View, error) {
if _, err := g.SetCurrentView(name); err != nil {
return nil, err
}
return g.SetViewOnTop(name)
}
func nextView(g *gocui.Gui, v *gocui.View) error {
nextIndex := (active + 1) % len(viewArr)
name := viewArr[nextIndex]
out, err := g.View("v2")
if err != nil {
return err
}
fmt.Fprintln(out, "Going from view "+v.Name()+" to "+name)
if _, err := setCurrentViewOnTop(g, name); err != nil {
return err
}
if nextIndex == 0 || nextIndex == 3 {
g.Cursor = true
} else {
g.Cursor = false
}
active = nextIndex
return nil
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if v, err := g.SetView("v1", 0, 0, maxX/2-1, maxY/2-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "v1 (editable)"
v.Editable = true
v.Wrap = true
if _, err = setCurrentViewOnTop(g, "v1"); err != nil {
return err
}
}
if v, err := g.SetView("v2", maxX/2-1, 0, maxX-1, maxY/2-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "v2"
v.Wrap = true
v.Autoscroll = true
}
if v, err := g.SetView("v3", 0, maxY/2-1, maxX/2-1, maxY-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "v3"
v.Wrap = true
v.Autoscroll = true
fmt.Fprint(v, "Press TAB to change current view")
}
if v, err := g.SetView("v4", maxX/2, maxY/2, maxX-1, maxY-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "v4 (editable)"
v.Editable = true
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.Highlight = true
g.Cursor = true
g.SelFgColor = gocui.ColorGreen
g.SetManagerFunc(layout)
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, nextView); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}

70
vendor/github.com/jroimartin/gocui/_examples/bufs.go generated vendored Normal file
View File

@ -0,0 +1,70 @@
// 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.
// WARNING: tricky code just for testing purposes, do not use as reference.
package main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
var vbuf, buf string
func quit(g *gocui.Gui, v *gocui.View) error {
vbuf = v.ViewBuffer()
buf = v.Buffer()
return gocui.ErrQuit
}
func overwrite(g *gocui.Gui, v *gocui.View) error {
v.Overwrite = !v.Overwrite
return nil
}
func layout(g *gocui.Gui) error {
_, maxY := g.Size()
if v, err := g.SetView("main", 0, 0, 20, maxY-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Editable = true
v.Wrap = true
if _, err := g.SetCurrentView("main"); err != nil {
return err
}
}
return nil
}
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
g.Cursor = true
g.Mouse = true
g.SetManagerFunc(layout)
if err := g.SetKeybinding("main", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("main", gocui.KeyCtrlI, gocui.ModNone, overwrite); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
g.Close()
fmt.Printf("VBUF:\n%s\n", vbuf)
fmt.Printf("BUF:\n%s\n", buf)
}

49
vendor/github.com/jroimartin/gocui/_examples/colors.go generated vendored Normal file
View File

@ -0,0 +1,49 @@
// 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 main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
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 && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if v, err := g.SetView("colors", maxX/2-7, maxY/2-12, maxX/2+7, maxY/2+13); err != nil {
if err != gocui.ErrUnknownView {
return err
}
for i := 0; i <= 7; i++ {
for _, j := range []int{1, 4, 7} {
fmt.Fprintf(v, "Hello \033[3%d;%dmcolors!\033[0m\n", i, j)
}
}
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}

View File

@ -0,0 +1,74 @@
// 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 main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.Output256)
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 && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if v, err := g.SetView("colors", -1, -1, maxX, maxY); err != nil {
if err != gocui.ErrUnknownView {
return err
}
// 256-colors escape codes
for i := 0; i < 256; i++ {
str := fmt.Sprintf("\x1b[48;5;%dm\x1b[30m%3d\x1b[0m ", i, i)
str += fmt.Sprintf("\x1b[38;5;%dm%3d\x1b[0m ", i, i)
if (i+1)%10 == 0 {
str += "\n"
}
fmt.Fprint(v, str)
}
fmt.Fprint(v, "\n\n")
// 8-colors escape codes
ctr := 0
for i := 0; i <= 7; i++ {
for _, j := range []int{1, 4, 7} {
str := fmt.Sprintf("\x1b[3%d;%dm%d:%d\x1b[0m ", i, j, i, j)
if (ctr+1)%20 == 0 {
str += "\n"
}
fmt.Fprint(v, str)
ctr++
}
}
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}

211
vendor/github.com/jroimartin/gocui/_examples/demo.go generated vendored Normal file
View File

@ -0,0 +1,211 @@
// 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 main
import (
"fmt"
"io"
"io/ioutil"
"log"
"strings"
"github.com/jroimartin/gocui"
)
func nextView(g *gocui.Gui, v *gocui.View) error {
if v == nil || v.Name() == "side" {
_, err := g.SetCurrentView("main")
return err
}
_, err := g.SetCurrentView("side")
return err
}
func cursorDown(g *gocui.Gui, v *gocui.View) error {
if v != nil {
cx, cy := v.Cursor()
if err := v.SetCursor(cx, cy+1); err != nil {
ox, oy := v.Origin()
if err := v.SetOrigin(ox, oy+1); err != nil {
return err
}
}
}
return nil
}
func cursorUp(g *gocui.Gui, v *gocui.View) error {
if v != nil {
ox, oy := v.Origin()
cx, cy := v.Cursor()
if err := v.SetCursor(cx, cy-1); err != nil && oy > 0 {
if err := v.SetOrigin(ox, oy-1); err != nil {
return err
}
}
}
return nil
}
func getLine(g *gocui.Gui, v *gocui.View) error {
var l string
var err error
_, cy := v.Cursor()
if l, err = v.Line(cy); err != nil {
l = ""
}
maxX, maxY := g.Size()
if v, err := g.SetView("msg", maxX/2-30, maxY/2, maxX/2+30, maxY/2+2); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, l)
if _, err := g.SetCurrentView("msg"); err != nil {
return err
}
}
return nil
}
func delMsg(g *gocui.Gui, v *gocui.View) error {
if err := g.DeleteView("msg"); err != nil {
return err
}
if _, err := g.SetCurrentView("side"); err != nil {
return err
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func keybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("side", gocui.KeyCtrlSpace, gocui.ModNone, nextView); err != nil {
return err
}
if err := g.SetKeybinding("main", gocui.KeyCtrlSpace, gocui.ModNone, nextView); err != nil {
return err
}
if err := g.SetKeybinding("side", gocui.KeyArrowDown, gocui.ModNone, cursorDown); err != nil {
return err
}
if err := g.SetKeybinding("side", gocui.KeyArrowUp, gocui.ModNone, cursorUp); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
return err
}
if err := g.SetKeybinding("side", gocui.KeyEnter, gocui.ModNone, getLine); err != nil {
return err
}
if err := g.SetKeybinding("msg", gocui.KeyEnter, gocui.ModNone, delMsg); err != nil {
return err
}
if err := g.SetKeybinding("main", gocui.KeyCtrlS, gocui.ModNone, saveMain); err != nil {
return err
}
if err := g.SetKeybinding("main", gocui.KeyCtrlW, gocui.ModNone, saveVisualMain); err != nil {
return err
}
return nil
}
func saveMain(g *gocui.Gui, v *gocui.View) error {
f, err := ioutil.TempFile("", "gocui_demo_")
if err != nil {
return err
}
defer f.Close()
p := make([]byte, 5)
v.Rewind()
for {
n, err := v.Read(p)
if n > 0 {
if _, err := f.Write(p[:n]); err != nil {
return err
}
}
if err == io.EOF {
break
}
if err != nil {
return err
}
}
return nil
}
func saveVisualMain(g *gocui.Gui, v *gocui.View) error {
f, err := ioutil.TempFile("", "gocui_demo_")
if err != nil {
return err
}
defer f.Close()
vb := v.ViewBuffer()
if _, err := io.Copy(f, strings.NewReader(vb)); err != nil {
return err
}
return nil
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if v, err := g.SetView("side", -1, -1, 30, maxY); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Highlight = true
v.SelBgColor = gocui.ColorGreen
v.SelFgColor = gocui.ColorBlack
fmt.Fprintln(v, "Item 1")
fmt.Fprintln(v, "Item 2")
fmt.Fprintln(v, "Item 3")
fmt.Fprint(v, "\rWill be")
fmt.Fprint(v, "deleted\rItem 4\nItem 5")
}
if v, err := g.SetView("main", 30, -1, maxX, maxY); err != nil {
if err != gocui.ErrUnknownView {
return err
}
b, err := ioutil.ReadFile("Mark.Twain-Tom.Sawyer.txt")
if err != nil {
panic(err)
}
fmt.Fprintf(v, "%s", b)
v.Editable = true
v.Wrap = true
if _, err := g.SetCurrentView("main"); err != nil {
return err
}
}
return nil
}
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.Cursor = true
g.SetManagerFunc(layout)
if err := keybindings(g); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}

190
vendor/github.com/jroimartin/gocui/_examples/dynamic.go generated vendored Normal file
View File

@ -0,0 +1,190 @@
// 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 main
import (
"fmt"
"log"
"strings"
"github.com/jroimartin/gocui"
)
const delta = 1
var (
views = []string{}
curView = -1
idxView = 0
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.Highlight = true
g.SelFgColor = gocui.ColorRed
g.SetManagerFunc(layout)
if err := initKeybindings(g); err != nil {
log.Panicln(err)
}
if err := newView(g); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func layout(g *gocui.Gui) error {
maxX, _ := g.Size()
v, err := g.SetView("help", maxX-25, 0, maxX-1, 9)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, "KEYBINDINGS")
fmt.Fprintln(v, "Space: New View")
fmt.Fprintln(v, "Tab: Next View")
fmt.Fprintln(v, "← ↑ → ↓: Move View")
fmt.Fprintln(v, "Backspace: Delete View")
fmt.Fprintln(v, "t: Set view on top")
fmt.Fprintln(v, "b: Set view on bottom")
fmt.Fprintln(v, "^C: Exit")
}
return nil
}
func initKeybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeySpace, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return newView(g)
}); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeyBackspace2, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return delView(g)
}); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return nextView(g, true)
}); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeyArrowLeft, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return moveView(g, v, -delta, 0)
}); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeyArrowRight, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return moveView(g, v, delta, 0)
}); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return moveView(g, v, 0, delta)
}); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return moveView(g, v, 0, -delta)
}); err != nil {
return err
}
if err := g.SetKeybinding("", 't', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
_, err := g.SetViewOnTop(views[curView])
return err
}); err != nil {
return err
}
if err := g.SetKeybinding("", 'b', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
_, err := g.SetViewOnBottom(views[curView])
return err
}); err != nil {
return err
}
return nil
}
func newView(g *gocui.Gui) error {
maxX, maxY := g.Size()
name := fmt.Sprintf("v%v", idxView)
v, err := g.SetView(name, maxX/2-5, maxY/2-5, maxX/2+5, maxY/2+5)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Wrap = true
fmt.Fprintln(v, strings.Repeat(name+" ", 30))
}
if _, err := g.SetCurrentView(name); err != nil {
return err
}
views = append(views, name)
curView = len(views) - 1
idxView += 1
return nil
}
func delView(g *gocui.Gui) error {
if len(views) <= 1 {
return nil
}
if err := g.DeleteView(views[curView]); err != nil {
return err
}
views = append(views[:curView], views[curView+1:]...)
return nextView(g, false)
}
func nextView(g *gocui.Gui, disableCurrent bool) error {
next := curView + 1
if next > len(views)-1 {
next = 0
}
if _, err := g.SetCurrentView(views[next]); err != nil {
return err
}
curView = next
return nil
}
func moveView(g *gocui.Gui, v *gocui.View, dx, dy int) error {
name := v.Name()
x0, y0, x1, y1, err := g.ViewPosition(name)
if err != nil {
return err
}
if _, err := g.SetView(name, x0+dx, y0+dy, x1+dx, y1+dy); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,87 @@
// 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 main
import (
"fmt"
"log"
"strings"
"github.com/jroimartin/gocui"
)
type Label struct {
name string
w, h int
body string
}
func NewLabel(name string, body string) *Label {
lines := strings.Split(body, "\n")
w := 0
for _, l := range lines {
if len(l) > w {
w = len(l)
}
}
h := len(lines) + 1
w = w + 1
return &Label{name: name, w: w, h: h, body: body}
}
func (w *Label) Layout(g *gocui.Gui) error {
v, err := g.SetView(w.name, 0, 0, w.w, w.h)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprint(v, w.body)
}
return nil
}
func flowLayout(g *gocui.Gui) error {
views := g.Views()
x := 0
for _, v := range views {
w, h := v.Size()
_, err := g.SetView(v.Name(), x, 0, x+w+1, h+1)
if err != nil && err != gocui.ErrUnknownView {
return err
}
x += w + 2
}
return nil
}
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
defer g.Close()
l1 := NewLabel("l1", "This")
l2 := NewLabel("l2", "is")
l3 := NewLabel("l3", "a")
l4 := NewLabel("l4", "flow\nlayout")
l5 := NewLabel("l5", "!")
fl := gocui.ManagerFunc(flowLayout)
g.SetManager(l1, l2, l3, l4, l5, fl)
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}

View File

@ -0,0 +1,97 @@
// 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 main
import (
"fmt"
"log"
"sync"
"time"
"github.com/jroimartin/gocui"
)
const NumGoroutines = 10
var (
done = make(chan struct{})
wg sync.WaitGroup
mu sync.Mutex // protects ctr
ctr = 0
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.SetManagerFunc(layout)
if err := keybindings(g); err != nil {
log.Panicln(err)
}
for i := 0; i < NumGoroutines; i++ {
wg.Add(1)
go counter(g)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
wg.Wait()
}
func layout(g *gocui.Gui) error {
if v, err := g.SetView("ctr", 2, 2, 12, 4); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, "0")
}
return nil
}
func keybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
return err
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
close(done)
return gocui.ErrQuit
}
func counter(g *gocui.Gui) {
defer wg.Done()
for {
select {
case <-done:
return
case <-time.After(500 * time.Millisecond):
mu.Lock()
n := ctr
ctr++
mu.Unlock()
g.Update(func(g *gocui.Gui) error {
v, err := g.View("ctr")
if err != nil {
return err
}
v.Clear()
fmt.Fprintln(v, n)
return nil
})
}
}
}

45
vendor/github.com/jroimartin/gocui/_examples/hello.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
// 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 main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
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 && err != gocui.ErrQuit {
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); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, "Hello world!")
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}

50
vendor/github.com/jroimartin/gocui/_examples/layout.go generated vendored Normal file
View File

@ -0,0 +1,50 @@
// 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 main
import (
"log"
"github.com/jroimartin/gocui"
)
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if _, err := g.SetView("side", -1, -1, int(0.2*float32(maxX)), maxY-5); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("main", int(0.2*float32(maxX)), -1, maxX, maxY-5); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("cmdline", -1, maxY-5, maxX, maxY); err != nil &&
err != gocui.ErrUnknownView {
return err
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
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 && err != gocui.ErrQuit {
log.Panicln(err)
}
}

75
vendor/github.com/jroimartin/gocui/_examples/mask.go generated vendored Normal file
View File

@ -0,0 +1,75 @@
// Copyright 2015 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 main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Fatalln(err)
}
defer g.Close()
g.Cursor = true
g.SetManagerFunc(layout)
if err := initKeybindings(g); err != nil {
log.Fatalln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Fatalln(err)
}
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if v, err := g.SetView("help", maxX-23, 0, maxX-1, 3); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Keybindings"
fmt.Fprintln(v, "^a: Set mask")
fmt.Fprintln(v, "^c: Exit")
}
if v, err := g.SetView("input", 0, 0, maxX-24, maxY-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetCurrentView("input"); err != nil {
return err
}
v.Editable = true
v.Wrap = true
}
return nil
}
func initKeybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}); err != nil {
return err
}
if err := g.SetKeybinding("input", gocui.KeyCtrlA, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
v.Mask ^= '*'
return nil
}); err != nil {
return err
}
return nil
}

107
vendor/github.com/jroimartin/gocui/_examples/mouse.go generated vendored Normal file
View File

@ -0,0 +1,107 @@
// 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 main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.Cursor = true
g.Mouse = true
g.SetManagerFunc(layout)
if err := keybindings(g); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func layout(g *gocui.Gui) error {
if v, err := g.SetView("but1", 2, 2, 22, 7); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Highlight = true
v.SelBgColor = gocui.ColorGreen
v.SelFgColor = gocui.ColorBlack
fmt.Fprintln(v, "Button 1 - line 1")
fmt.Fprintln(v, "Button 1 - line 2")
fmt.Fprintln(v, "Button 1 - line 3")
fmt.Fprintln(v, "Button 1 - line 4")
}
if v, err := g.SetView("but2", 24, 2, 44, 4); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Highlight = true
v.SelBgColor = gocui.ColorGreen
v.SelFgColor = gocui.ColorBlack
fmt.Fprintln(v, "Button 2 - line 1")
}
return nil
}
func keybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
return err
}
for _, n := range []string{"but1", "but2"} {
if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil {
return err
}
}
if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, delMsg); err != nil {
return err
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func showMsg(g *gocui.Gui, v *gocui.View) error {
var l string
var err error
if _, err := g.SetCurrentView(v.Name()); err != nil {
return err
}
_, cy := v.Cursor()
if l, err = v.Line(cy); err != nil {
l = ""
}
maxX, maxY := g.Size()
if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, l)
}
return nil
}
func delMsg(g *gocui.Gui, v *gocui.View) error {
if err := g.DeleteView("msg"); err != nil {
return err
}
return nil
}

88
vendor/github.com/jroimartin/gocui/_examples/ontop.go generated vendored Normal file
View File

@ -0,0 +1,88 @@
// 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 main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.SetManagerFunc(layout)
if err := keybindings(g); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func layout(g *gocui.Gui) error {
if v, err := g.SetView("v1", 10, 2, 30, 6); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, "View #1")
}
if v, err := g.SetView("v2", 20, 4, 40, 8); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, "View #2")
}
if v, err := g.SetView("v3", 30, 6, 50, 10); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, "View #3")
}
return nil
}
func keybindings(g *gocui.Gui) error {
err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
})
if err != nil {
return err
}
err = g.SetKeybinding("", '1', gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
_, err := g.SetViewOnTop("v1")
return err
})
if err != nil {
return err
}
err = g.SetKeybinding("", '2', gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
_, err := g.SetViewOnTop("v2")
return err
})
if err != nil {
return err
}
err = g.SetKeybinding("", '3', gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error {
_, err := g.SetViewOnTop("v3")
return err
})
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,74 @@
// 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 main
import (
"log"
"github.com/jroimartin/gocui"
)
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if _, err := g.SetView("v1", -1, -1, 10, 10); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("v2", maxX-10, -1, maxX, 10); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("v3", maxX/2-5, -1, maxX/2+5, 10); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("v4", -1, maxY/2-5, 10, maxY/2+5); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("v5", maxX-10, maxY/2-5, maxX, maxY/2+5); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("v6", -1, maxY-10, 10, maxY); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("v7", maxX-10, maxY-10, maxX, maxY); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("v8", maxX/2-5, maxY-10, maxX/2+5, maxY); err != nil &&
err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetView("v9", maxX/2-5, maxY/2-5, maxX/2+5, maxY/2+5); err != nil &&
err != gocui.ErrUnknownView {
return err
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
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 && err != gocui.ErrQuit {
log.Panicln(err)
}
}

45
vendor/github.com/jroimartin/gocui/_examples/size.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
// 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 main
import (
"fmt"
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
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 && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
v, err := g.SetView("size", maxX/2-7, maxY/2, maxX/2+7, maxY/2+2)
if err != nil && err != gocui.ErrUnknownView {
return err
}
v.Clear()
fmt.Fprintf(v, "%d, %d", maxX, maxY)
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}

109
vendor/github.com/jroimartin/gocui/_examples/stdin.go generated vendored Normal file
View File

@ -0,0 +1,109 @@
// Copyright 2015 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 main
import (
"encoding/hex"
"fmt"
"io"
"log"
"os"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Fatalln(err)
}
defer g.Close()
g.Cursor = true
g.SetManagerFunc(layout)
if err := initKeybindings(g); err != nil {
log.Fatalln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Fatalln(err)
}
}
func layout(g *gocui.Gui) error {
maxX, _ := g.Size()
if v, err := g.SetView("help", maxX-23, 0, maxX-1, 5); err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprintln(v, "KEYBINDINGS")
fmt.Fprintln(v, "↑ ↓: Seek input")
fmt.Fprintln(v, "a: Enable autoscroll")
fmt.Fprintln(v, "^C: Exit")
}
if v, err := g.SetView("stdin", 0, 0, 80, 35); err != nil {
if err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetCurrentView("stdin"); err != nil {
return err
}
dumper := hex.Dumper(v)
if _, err := io.Copy(dumper, os.Stdin); err != nil {
return err
}
v.Wrap = true
}
return nil
}
func initKeybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
return err
}
if err := g.SetKeybinding("stdin", 'a', gocui.ModNone, autoscroll); err != nil {
return err
}
if err := g.SetKeybinding("stdin", gocui.KeyArrowUp, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
scrollView(v, -1)
return nil
}); err != nil {
return err
}
if err := g.SetKeybinding("stdin", gocui.KeyArrowDown, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
scrollView(v, 1)
return nil
}); err != nil {
return err
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func autoscroll(g *gocui.Gui, v *gocui.View) error {
v.Autoscroll = true
return nil
}
func scrollView(v *gocui.View, dy int) error {
if v != nil {
v.Autoscroll = false
ox, oy := v.Origin()
if err := v.SetOrigin(ox, oy+dy); err != nil {
return err
}
}
return nil
}

162
vendor/github.com/jroimartin/gocui/_examples/title.go generated vendored Normal file
View File

@ -0,0 +1,162 @@
// 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 main
import (
"log"
"github.com/jroimartin/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
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 && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
// Overlap (front)
if v, err := g.SetView("v1", 10, 2, 30, 6); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v2", 20, 4, 40, 8); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
// Overlap (back)
if v, err := g.SetView("v3", 60, 4, 80, 8); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v4", 50, 2, 70, 6); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
// Overlap (frame)
if v, err := g.SetView("v15", 90, 2, 110, 5); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v16", 100, 5, 120, 8); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v17", 140, 5, 160, 8); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v18", 130, 2, 150, 5); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
// Long title
if v, err := g.SetView("v5", 10, 12, 30, 16); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Long long long long title"
}
// No title
if v, err := g.SetView("v6", 35, 12, 55, 16); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = ""
}
if _, err := g.SetView("v7", 60, 12, 80, 16); err != nil {
if err != gocui.ErrUnknownView {
return err
}
}
// Small view
if v, err := g.SetView("v8", 85, 12, 88, 16); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
// Screen borders
if v, err := g.SetView("v9", -10, 20, 10, 24); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v10", maxX-10, 20, maxX+10, 24); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
// Out of screen
if v, err := g.SetView("v11", -21, 28, -1, 32); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v12", maxX, 28, maxX+20, 32); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v13", 10, -7, 30, -1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
if v, err := g.SetView("v14", 10, maxY, 30, maxY+6); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = "Regular title"
}
return nil
}

179
vendor/github.com/jroimartin/gocui/_examples/widgets.go generated vendored Normal file
View File

@ -0,0 +1,179 @@
// 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 main
import (
"errors"
"fmt"
"log"
"strings"
"github.com/jroimartin/gocui"
)
const delta = 0.2
type HelpWidget struct {
name string
x, y int
w, h int
body string
}
func NewHelpWidget(name string, x, y int, body string) *HelpWidget {
lines := strings.Split(body, "\n")
w := 0
for _, l := range lines {
if len(l) > w {
w = len(l)
}
}
h := len(lines) + 1
w = w + 1
return &HelpWidget{name: name, x: x, y: y, w: w, h: h, body: body}
}
func (w *HelpWidget) Layout(g *gocui.Gui) error {
v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+w.h)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
fmt.Fprint(v, w.body)
}
return nil
}
type StatusbarWidget struct {
name string
x, y int
w int
val float64
}
func NewStatusbarWidget(name string, x, y, w int) *StatusbarWidget {
return &StatusbarWidget{name: name, x: x, y: y, w: w}
}
func (w *StatusbarWidget) SetVal(val float64) error {
if val < 0 || val > 1 {
return errors.New("invalid value")
}
w.val = val
return nil
}
func (w *StatusbarWidget) Val() float64 {
return w.val
}
func (w *StatusbarWidget) Layout(g *gocui.Gui) error {
v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+2)
if err != nil && err != gocui.ErrUnknownView {
return err
}
v.Clear()
rep := int(w.val * float64(w.w-1))
fmt.Fprint(v, strings.Repeat("▒", rep))
return nil
}
type ButtonWidget struct {
name string
x, y int
w int
label string
handler func(g *gocui.Gui, v *gocui.View) error
}
func NewButtonWidget(name string, x, y int, label string, handler func(g *gocui.Gui, v *gocui.View) error) *ButtonWidget {
return &ButtonWidget{name: name, x: x, y: y, w: len(label) + 1, label: label, handler: handler}
}
func (w *ButtonWidget) Layout(g *gocui.Gui) error {
v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+2)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
if _, err := g.SetCurrentView(w.name); err != nil {
return err
}
if err := g.SetKeybinding(w.name, gocui.KeyEnter, gocui.ModNone, w.handler); err != nil {
return err
}
fmt.Fprint(v, w.label)
}
return nil
}
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.Highlight = true
g.SelFgColor = gocui.ColorRed
help := NewHelpWidget("help", 1, 1, helpText)
status := NewStatusbarWidget("status", 1, 7, 50)
butdown := NewButtonWidget("butdown", 52, 7, "DOWN", statusDown(status))
butup := NewButtonWidget("butup", 58, 7, "UP", statusUp(status))
g.SetManager(help, status, butdown, butup)
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, toggleButton); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func toggleButton(g *gocui.Gui, v *gocui.View) error {
nextview := "butdown"
if v != nil && v.Name() == "butdown" {
nextview = "butup"
}
_, err := g.SetCurrentView(nextview)
return err
}
func statusUp(status *StatusbarWidget) func(g *gocui.Gui, v *gocui.View) error {
return func(g *gocui.Gui, v *gocui.View) error {
return statusSet(status, delta)
}
}
func statusDown(status *StatusbarWidget) func(g *gocui.Gui, v *gocui.View) error {
return func(g *gocui.Gui, v *gocui.View) error {
return statusSet(status, -delta)
}
}
func statusSet(sw *StatusbarWidget, inc float64) error {
val := sw.Val() + inc
if val < 0 || val > 1 {
return nil
}
return sw.SetVal(val)
}
const helpText = `KEYBINDINGS
Tab: Move between buttons
Enter: Push button
^C: Exit`

50
vendor/github.com/jroimartin/gocui/_examples/wrap.go generated vendored Normal file
View File

@ -0,0 +1,50 @@
// 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 main
import (
"fmt"
"log"
"strings"
"github.com/jroimartin/gocui"
)
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if v, err := g.SetView("main", 1, 1, maxX-1, maxY-1); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Wrap = true
line := strings.Repeat("This is a long line -- ", 10)
fmt.Fprintf(v, "%s\n\n", line)
fmt.Fprintln(v, "Short")
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func main() {
g, err := gocui.NewGui(gocui.OutputNormal)
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 && err != gocui.ErrQuit {
log.Panicln(err)
}
}

32
vendor/github.com/jroimartin/gocui/attribute.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
// 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/nsf/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)
)

118
vendor/github.com/jroimartin/gocui/doc.go generated vendored Normal file
View File

@ -0,0 +1,118 @@
// 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 && err != gocui.ErrQuit {
// 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 err != gocui.ErrUnknownView {
// 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 edition 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

344
vendor/github.com/jroimartin/gocui/edit.go generated vendored Normal file
View File

@ -0,0 +1,344 @@
// 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 "errors"
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)
}
}
// EditWrite writes a rune at the cursor position.
func (v *View) EditWrite(ch rune) {
v.writeRune(v.cx, v.cy, ch)
v.MoveCursor(1, 0, true)
}
// 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
v.deleteRune(len(v.viewLines[y-1].line)-1, v.cy-1)
v.MoveCursor(-1, 0, true)
}
} else { // middle/end of the line
v.deleteRune(v.cx-1, v.cy)
v.MoveCursor(-1, 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.cx = 0
v.MoveCursor(0, 1, true)
}
// 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) {
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
if writeMode {
if v.Wrap {
curLineWidth = maxX - 1
} else {
curLineWidth = maxInt
}
} else {
if y >= 0 && y < len(v.viewLines) {
curLineWidth = len(v.viewLines[y].line)
if v.Wrap && curLineWidth >= maxX {
curLineWidth = maxX - 1
}
} else {
curLineWidth = 0
}
}
// get the width of the previous line
if y-1 >= 0 && y-1 < len(v.viewLines) {
prevLineWidth = len(v.viewLines[y-1].line)
} else {
prevLineWidth = 0
}
// 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 {
v.ox = 0
} else {
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).
func (v *View) deleteRune(x, y int) error {
v.tainted = true
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 errors.New("invalid point")
}
v.lines[y] = append(v.lines[y][:x], v.lines[y][x+1:]...)
return 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
}

229
vendor/github.com/jroimartin/gocui/escape.go generated vendored Normal file
View File

@ -0,0 +1,229 @@
// 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 (
"errors"
"strconv"
)
type escapeInterpreter struct {
state escapeState
curch rune
csiParam []string
curFgColor, curBgColor Attribute
mode OutputMode
}
type escapeState int
const (
stateNone escapeState = iota
stateEscape
stateCSI
stateParams
)
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()
}
fgbg, err := strconv.Atoi(ei.csiParam[0])
if err != nil {
return errCSIParseError
}
color, err := strconv.Atoi(ei.csiParam[2])
if err != nil {
return errCSIParseError
}
switch fgbg {
case 38:
ei.curFgColor = Attribute(color + 1)
for _, param := range ei.csiParam[3:] {
p, err := strconv.Atoi(param)
if err != nil {
return errCSIParseError
}
switch {
case p == 1:
ei.curFgColor |= AttrBold
case p == 4:
ei.curFgColor |= AttrUnderline
case p == 7:
ei.curFgColor |= AttrReverse
}
}
case 48:
ei.curBgColor = Attribute(color + 1)
default:
return errCSIParseError
}
return nil
}

636
vendor/github.com/jroimartin/gocui/gui.go generated vendored Normal file
View File

@ -0,0 +1,636 @@
// 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 (
"errors"
"github.com/nsf/termbox-go"
)
var (
// ErrQuit is used to decide if the MainLoop finished successfully.
ErrQuit = errors.New("quit")
// ErrUnknownView allows to assert if a View must be initialized.
ErrUnknownView = errors.New("unknown view")
)
// OutputMode represents the terminal's output mode (8 or 256 colors).
type OutputMode termbox.OutputMode
const (
// OutputNormal provides 8-colors terminal mode.
OutputNormal = OutputMode(termbox.OutputNormal)
// Output256 provides 256-colors terminal mode.
Output256 = OutputMode(termbox.Output256)
)
// 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
// BgColor and FgColor allow to configure the background and foreground
// colors of the GUI.
BgColor, FgColor Attribute
// SelBgColor and SelFgColor allow to configure the background and
// foreground colors of the frame of the current view.
SelBgColor, SelFgColor 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
}
// NewGui returns a new Gui object with a given output mode.
func NewGui(mode OutputMode) (*Gui, error) {
if err := termbox.Init(); err != nil {
return nil, err
}
g := &Gui{}
g.outputMode = mode
termbox.SetOutputMode(termbox.OutputMode(mode))
g.tbEvents = make(chan termbox.Event, 20)
g.userEvents = make(chan userEvent, 20)
g.maxX, g.maxY = termbox.Size()
g.BgColor, g.FgColor = ColorDefault, ColorDefault
g.SelBgColor, g.SelFgColor = ColorDefault, ColorDefault
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() {
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) (*View, error) {
if x0 >= x1 || y0 >= y1 {
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
g.views = append(g.views, v)
return v, ErrUnknownView
}
// 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, ErrUnknownView
}
// 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, ErrUnknownView
}
// 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, ErrUnknownView
}
// 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, ErrUnknownView
}
// 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, ErrUnknownView
}
// 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 ErrUnknownView
}
// 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, ErrUnknownView
}
// 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
}
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
}
// 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 {
go func() {
for {
g.tbEvents <- termbox.PollEvent()
}
}()
inputMode := termbox.InputAlt
if g.InputEsc {
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.Frame {
var fgColor, bgColor Attribute
if g.Highlight && v == g.currentView {
fgColor = g.SelFgColor
bgColor = g.SelBgColor
} else {
fgColor = g.FgColor
bgColor = g.BgColor
}
if err := g.drawFrameEdges(v, fgColor, bgColor); err != nil {
return err
}
if err := g.drawFrameCorners(v, fgColor, bgColor); err != nil {
return err
}
if v.Title != "" {
if err := g.drawTitle(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
}
// drawFrameCorners draws the corners of the view.
func (g *Gui) drawFrameCorners(v *View, fgColor, bgColor Attribute) error {
runeTL, runeTR, runeBL, runeBR := '┌', '┐', '└', '┘'
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
}
// 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) {
matched = false
for _, kb := range g.keybindings {
if kb.handler == nil {
continue
}
if kb.matchKeypress(Key(ev.Key), ev.Ch, Modifier(ev.Mod)) && kb.matchView(v) {
if err := kb.handler(g, v); err != nil {
return false, err
}
matched = true
}
}
return matched, nil
}

137
vendor/github.com/jroimartin/gocui/keybinding.go generated vendored Normal file
View File

@ -0,0 +1,137 @@
// 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/nsf/termbox-go"
// 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
}
// 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 kb.viewName == "" {
return true
}
return v != nil && kb.viewName == v.name
}
// Key represents special keys or keys combinations.
type Key termbox.Key
// 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)
)
// 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
// Modifiers.
const (
ModNone Modifier = Modifier(0)
ModAlt = Modifier(termbox.ModAlt)
)

479
vendor/github.com/jroimartin/gocui/view.go generated vendored Normal file
View File

@ -0,0 +1,479 @@
// 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"
"errors"
"io"
"strings"
"github.com/nsf/termbox-go"
)
// A View is a window. It maintains its own internal buffer and cursor
// position.
type View struct {
name string
x0, y0, x1, y1 int
ox, oy int
cx, cy int
lines [][]cell
readOffset int
readCache string
tainted bool // marks if the viewBuffer must be updated
viewLines []viewLine // internal representation of the view's buffer
ei *escapeInterpreter // used to decode ESC sequences on Write
// 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 edition 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 Mask is true, the View will display the mask instead of the real
// content
Mask rune
}
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,
Frame: true,
Editor: DefaultEditor,
tainted: true,
ei: newEscapeInterpreter(mode),
}
return v
}
// 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 errors.New("invalid point")
}
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 = v.SelFgColor
bgColor = v.SelBgColor
}
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 errors.New("invalid point")
}
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 errors.New("invalid point")
}
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
}
// 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
for _, ch := range bytes.Runes(p) {
switch ch {
case '\n':
v.lines = append(v.lines, nil)
case '\r':
nl := len(v.lines)
if nl > 0 {
v.lines[nl-1] = nil
} else {
v.lines = make([][]cell, 1)
}
default:
cells := v.parseInput(ch)
if cells == nil {
continue
}
nl := len(v.lines)
if nl > 0 {
v.lines[nl-1] = append(v.lines[nl-1], cells...)
} else {
v.lines = append(v.lines, cells)
}
}
}
return len(p), nil
}
// 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
}
c := cell{
fgColor: v.ei.curFgColor,
bgColor: v.ei.curBgColor,
chr: ch,
}
cells = append(cells, c)
}
return cells
}
// Read reads data into p. It returns the number of bytes read into p.
// At EOF, err will be io.EOF. Calling Read() after Rewind() makes the
// cache to be refreshed with the contents of the view.
func (v *View) Read(p []byte) (n int, err error) {
if v.readOffset == 0 {
v.readCache = v.Buffer()
}
if v.readOffset < len(v.readCache) {
n = copy(p, v.readCache[v.readOffset:])
v.readOffset += n
} else {
err = io.EOF
}
return
}
// Rewind sets the offset for the next Read to 0, which also refresh the
// read cache.
func (v *View) Rewind() {
v.readOffset = 0
}
// draw re-draws the view's contents.
func (v *View) draw() error {
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
for i, line := range v.lines {
if v.Wrap {
if len(line) < maxX {
vline := viewLine{linesX: 0, linesY: i, line: line}
v.viewLines = append(v.viewLines, vline)
continue
} else {
for n := 0; n <= len(line); n += maxX {
if len(line[n:]) <= maxX {
vline := viewLine{linesX: n, linesY: i, line: line[n:]}
v.viewLines = append(v.viewLines, vline)
} else {
vline := viewLine{linesX: n, linesY: i, line: line[n : n+maxX]}
v.viewLines = append(v.viewLines, vline)
}
}
}
} else {
vline := viewLine{linesX: 0, linesY: i, line: line}
v.viewLines = append(v.viewLines, vline)
}
}
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
}
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, errors.New("invalid point")
}
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.
func (v *View) Clear() {
v.tainted = true
v.lines = nil
v.viewLines = nil
v.readOffset = 0
v.clearRunes()
}
// 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))
}
}
}
// Buffer returns a string with the contents of the view's internal
// buffer.
func (v *View) Buffer() string {
str := ""
for _, l := range v.lines {
str += lineType(l).String() + "\n"
}
return strings.Replace(str, "\x00", " ", -1)
}
// ViewBuffer returns a string with the contents of the view's buffer that is
// shown to the user.
func (v *View) ViewBuffer() string {
str := ""
for _, l := range v.viewLines {
str += lineType(l.line).String() + "\n"
}
return strings.Replace(str, "\x00", " ", -1)
}
// 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 "", errors.New("invalid point")
}
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 "", errors.New("invalid point")
}
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
}

8
vendor/github.com/mattn/go-runewidth/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,8 @@
language: go
go:
- tip
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL

21
vendor/github.com/mattn/go-runewidth/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Yasuhiro Matsumoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

27
vendor/github.com/mattn/go-runewidth/README.mkd generated vendored Normal file
View File

@ -0,0 +1,27 @@
go-runewidth
============
[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth)
[![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD)
[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth)
[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth)
Provides functions to get fixed width of the character or string.
Usage
-----
```go
runewidth.StringWidth("つのだ☆HIRO") == 12
```
Author
------
Yasuhiro Matsumoto
License
-------
under the MIT License: http://mattn.mit-license.org/2013

1224
vendor/github.com/mattn/go-runewidth/runewidth.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

8
vendor/github.com/mattn/go-runewidth/runewidth_js.go generated vendored Normal file
View File

@ -0,0 +1,8 @@
// +build js
package runewidth
func IsEastAsian() bool {
// TODO: Implement this for the web. Detect east asian in a compatible way, and return true.
return false
}

View File

@ -0,0 +1,77 @@
// +build !windows,!js
package runewidth
import (
"os"
"regexp"
"strings"
)
var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`)
var mblenTable = map[string]int{
"utf-8": 6,
"utf8": 6,
"jis": 8,
"eucjp": 3,
"euckr": 2,
"euccn": 2,
"sjis": 2,
"cp932": 2,
"cp51932": 2,
"cp936": 2,
"cp949": 2,
"cp950": 2,
"big5": 2,
"gbk": 2,
"gb2312": 2,
}
func isEastAsian(locale string) bool {
charset := strings.ToLower(locale)
r := reLoc.FindStringSubmatch(locale)
if len(r) == 2 {
charset = strings.ToLower(r[1])
}
if strings.HasSuffix(charset, "@cjk_narrow") {
return false
}
for pos, b := range []byte(charset) {
if b == '@' {
charset = charset[:pos]
break
}
}
max := 1
if m, ok := mblenTable[charset]; ok {
max = m
}
if max > 1 && (charset[0] != 'u' ||
strings.HasPrefix(locale, "ja") ||
strings.HasPrefix(locale, "ko") ||
strings.HasPrefix(locale, "zh")) {
return true
}
return false
}
// IsEastAsian return true if the current locale is CJK
func IsEastAsian() bool {
locale := os.Getenv("LC_CTYPE")
if locale == "" {
locale = os.Getenv("LANG")
}
// ignore C locale
if locale == "POSIX" || locale == "C" {
return false
}
if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') {
return false
}
return isEastAsian(locale)
}

279
vendor/github.com/mattn/go-runewidth/runewidth_test.go generated vendored Normal file
View File

@ -0,0 +1,279 @@
package runewidth
import (
"sort"
"testing"
)
var _ sort.Interface = (*table)(nil)
func (t table) Len() int {
return len(t)
}
func (t table) Less(i, j int) bool {
return t[i].first < t[j].first
}
func (t *table) Swap(i, j int) {
(*t)[i], (*t)[j] = (*t)[j], (*t)[i]
}
var tables = []table{
private,
nonprint,
combining,
doublewidth,
ambiguous,
emoji,
notassigned,
neutral,
}
func TestSorted(t *testing.T) {
for _, tbl := range tables {
if !sort.IsSorted(&tbl) {
t.Errorf("not sorted")
}
}
}
var runewidthtests = []struct {
in rune
out int
eaout int
}{
{'世', 2, 2},
{'界', 2, 2},
{'セ', 1, 1},
{'カ', 1, 1},
{'イ', 1, 1},
{'☆', 1, 2}, // double width in ambiguous
{'\x00', 0, 0},
{'\x01', 0, 0},
{'\u0300', 0, 0},
{'\u2028', 0, 0},
{'\u2029', 0, 0},
}
func TestRuneWidth(t *testing.T) {
c := NewCondition()
c.EastAsianWidth = false
for _, tt := range runewidthtests {
if out := c.RuneWidth(tt.in); out != tt.out {
t.Errorf("RuneWidth(%q) = %d, want %d", tt.in, out, tt.out)
}
}
c.EastAsianWidth = true
for _, tt := range runewidthtests {
if out := c.RuneWidth(tt.in); out != tt.eaout {
t.Errorf("RuneWidth(%q) = %d, want %d", tt.in, out, tt.eaout)
}
}
}
var isambiguouswidthtests = []struct {
in rune
out bool
}{
{'世', false},
{'■', true},
{'界', false},
{'○', true},
{'㈱', false},
{'①', true},
{'②', true},
{'③', true},
{'④', true},
{'⑤', true},
{'⑥', true},
{'⑦', true},
{'⑧', true},
{'⑨', true},
{'⑩', true},
{'⑪', true},
{'⑫', true},
{'⑬', true},
{'⑭', true},
{'⑮', true},
{'⑯', true},
{'⑰', true},
{'⑱', true},
{'⑲', true},
{'⑳', true},
{'☆', true},
}
func TestIsAmbiguousWidth(t *testing.T) {
for _, tt := range isambiguouswidthtests {
if out := IsAmbiguousWidth(tt.in); out != tt.out {
t.Errorf("IsAmbiguousWidth(%q) = %v, want %v", tt.in, out, tt.out)
}
}
}
var stringwidthtests = []struct {
in string
out int
eaout int
}{
{"■㈱の世界①", 10, 12},
{"スター☆", 7, 8},
{"つのだ☆HIRO", 11, 12},
}
func TestStringWidth(t *testing.T) {
c := NewCondition()
c.EastAsianWidth = false
for _, tt := range stringwidthtests {
if out := c.StringWidth(tt.in); out != tt.out {
t.Errorf("StringWidth(%q) = %d, want %d", tt.in, out, tt.out)
}
}
c.EastAsianWidth = true
for _, tt := range stringwidthtests {
if out := c.StringWidth(tt.in); out != tt.eaout {
t.Errorf("StringWidth(%q) = %d, want %d", tt.in, out, tt.eaout)
}
}
}
func TestStringWidthInvalid(t *testing.T) {
s := "こんにちわ\x00世界"
if out := StringWidth(s); out != 14 {
t.Errorf("StringWidth(%q) = %d, want %d", s, out, 14)
}
}
func TestTruncateSmaller(t *testing.T) {
s := "あいうえお"
expected := "あいうえお"
if out := Truncate(s, 10, "..."); out != expected {
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
}
}
func TestTruncate(t *testing.T) {
s := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお"
expected := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおお..."
out := Truncate(s, 80, "...")
if out != expected {
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
}
width := StringWidth(out)
if width != 79 {
t.Errorf("width of Truncate(%q) should be %d, but %d", s, 79, width)
}
}
func TestTruncateFit(t *testing.T) {
s := "aあいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお"
expected := "aあいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおお..."
out := Truncate(s, 80, "...")
if out != expected {
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
}
width := StringWidth(out)
if width != 80 {
t.Errorf("width of Truncate(%q) should be %d, but %d", s, 80, width)
}
}
func TestTruncateJustFit(t *testing.T) {
s := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおお"
expected := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおお"
out := Truncate(s, 80, "...")
if out != expected {
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
}
width := StringWidth(out)
if width != 80 {
t.Errorf("width of Truncate(%q) should be %d, but %d", s, 80, width)
}
}
func TestWrap(t *testing.T) {
s := `東京特許許可局局長はよく柿喰う客だ/東京特許許可局局長はよく柿喰う客だ
123456789012345678901234567890
END`
expected := `東京特許許可局局長はよく柿喰う
客だ/東京特許許可局局長はよく
柿喰う客だ
123456789012345678901234567890
END`
if out := Wrap(s, 30); out != expected {
t.Errorf("Wrap(%q) = %q, want %q", s, out, expected)
}
}
func TestTruncateNoNeeded(t *testing.T) {
s := "あいうえおあい"
expected := "あいうえおあい"
if out := Truncate(s, 80, "..."); out != expected {
t.Errorf("Truncate(%q) = %q, want %q", s, out, expected)
}
}
var isneutralwidthtests = []struct {
in rune
out bool
}{
{'→', false},
{'┊', false},
{'┈', false},
{'', false},
{'└', false},
{'⣀', true},
{'⣀', true},
}
func TestIsNeutralWidth(t *testing.T) {
for _, tt := range isneutralwidthtests {
if out := IsNeutralWidth(tt.in); out != tt.out {
t.Errorf("IsNeutralWidth(%q) = %v, want %v", tt.in, out, tt.out)
}
}
}
func TestFillLeft(t *testing.T) {
s := "あxいうえお"
expected := " あxいうえお"
if out := FillLeft(s, 15); out != expected {
t.Errorf("FillLeft(%q) = %q, want %q", s, out, expected)
}
}
func TestFillLeftFit(t *testing.T) {
s := "あいうえお"
expected := "あいうえお"
if out := FillLeft(s, 10); out != expected {
t.Errorf("FillLeft(%q) = %q, want %q", s, out, expected)
}
}
func TestFillRight(t *testing.T) {
s := "あxいうえお"
expected := "あxいうえお "
if out := FillRight(s, 15); out != expected {
t.Errorf("FillRight(%q) = %q, want %q", s, out, expected)
}
}
func TestFillRightFit(t *testing.T) {
s := "あいうえお"
expected := "あいうえお"
if out := FillRight(s, 10); out != expected {
t.Errorf("FillRight(%q) = %q, want %q", s, out, expected)
}
}

View File

@ -0,0 +1,25 @@
package runewidth
import (
"syscall"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32")
procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP")
)
// IsEastAsian return true if the current locale is CJK
func IsEastAsian() bool {
r1, _, _ := procGetConsoleOutputCP.Call()
if r1 == 0 {
return false
}
switch int(r1) {
case 932, 51932, 936, 949, 950:
return true
}
return false
}

4
vendor/github.com/nsf/termbox-go/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,4 @@
# Please keep this file sorted.
Georg Reinke <guelfey@googlemail.com>
nsf <no.smile.face@gmail.com>

19
vendor/github.com/nsf/termbox-go/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (C) 2012 termbox-go authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

38
vendor/github.com/nsf/termbox-go/README.md generated vendored Normal file
View File

@ -0,0 +1,38 @@
## Termbox
Termbox is a library that provides a minimalistic API which allows the programmer to write text-based user interfaces. The library is crossplatform and has both terminal-based implementations on *nix operating systems and a winapi console based implementation for windows operating systems. The basic idea is an abstraction of the greatest common subset of features available on all major terminals and other terminal-like APIs in a minimalistic fashion. Small API means it is easy to implement, test, maintain and learn it, that's what makes the termbox a distinct library in its area.
### Installation
Install and update this go package with `go get -u github.com/nsf/termbox-go`
### Examples
For examples of what can be done take a look at demos in the _demos directory. You can try them with go run: `go run _demos/keyboard.go`
There are also some interesting projects using termbox-go:
- [godit](https://github.com/nsf/godit) is an emacsish lightweight text editor written using termbox.
- [gomatrix](https://github.com/GeertJohan/gomatrix) connects to The Matrix and displays its data streams in your terminal.
- [gotetris](https://github.com/jjinux/gotetris) is an implementation of Tetris.
- [sokoban-go](https://github.com/rn2dy/sokoban-go) is an implementation of sokoban game.
- [hecate](https://github.com/evanmiller/hecate) is a hex editor designed by Satan.
- [httopd](https://github.com/verdverm/httopd) is top for httpd logs.
- [mop](https://github.com/michaeldv/mop) is stock market tracker for hackers.
- [termui](https://github.com/gizak/termui) is a terminal dashboard.
- [termloop](https://github.com/JoelOtter/termloop) is a terminal game engine.
- [xterm-color-chart](https://github.com/kutuluk/xterm-color-chart) is a XTerm 256 color chart.
- [gocui](https://github.com/jroimartin/gocui) is a minimalist Go library aimed at creating console user interfaces.
- [dry](https://github.com/moncho/dry) is an interactive cli to manage Docker containers.
- [pxl](https://github.com/ichinaski/pxl) displays images in the terminal.
- [snake-game](https://github.com/DyegoCosta/snake-game) is an implementation of the Snake game.
- [gone](https://github.com/guillaumebreton/gone) is a CLI pomodoro® timer.
- [Spoof.go](https://github.com/sabey/spoofgo) controllable movement spoofing from the cli
- [lf](https://github.com/gokcehan/lf) is a terminal file manager
- [rat](https://github.com/ericfreese/rat) lets you compose shell commands to build terminal applications.
- [httplab](https://github.com/gchaincl/httplab) An interactive web server.
- [tetris](https://github.com/MichaelS11/tetris) Go Tetris with AI option
- [wot](https://github.com/kyu-suke/wot) Wait time during command is completed.
- [2048-go](https://github.com/1984weed/2048-go) is 2048 in Go
- [jv](https://github.com/maxzender/jv) helps you view JSON on the command-line.
- [pinger](https://github.com/hirose31/pinger) helps you to monitor numerous hosts using ICMP ECHO_REQUEST.
- [vixl44](https://github.com/sebashwa/vixl44) lets you create pixel art inside your terminal using vim movements
### API reference
[godoc.org/github.com/nsf/termbox-go](http://godoc.org/github.com/nsf/termbox-go)

300
vendor/github.com/nsf/termbox-go/_demos/editbox.go generated vendored Normal file
View File

@ -0,0 +1,300 @@
package main
import (
"github.com/mattn/go-runewidth"
"github.com/nsf/termbox-go"
"unicode/utf8"
)
func tbprint(x, y int, fg, bg termbox.Attribute, msg string) {
for _, c := range msg {
termbox.SetCell(x, y, c, fg, bg)
x += runewidth.RuneWidth(c)
}
}
func fill(x, y, w, h int, cell termbox.Cell) {
for ly := 0; ly < h; ly++ {
for lx := 0; lx < w; lx++ {
termbox.SetCell(x+lx, y+ly, cell.Ch, cell.Fg, cell.Bg)
}
}
}
func rune_advance_len(r rune, pos int) int {
if r == '\t' {
return tabstop_length - pos%tabstop_length
}
return runewidth.RuneWidth(r)
}
func voffset_coffset(text []byte, boffset int) (voffset, coffset int) {
text = text[:boffset]
for len(text) > 0 {
r, size := utf8.DecodeRune(text)
text = text[size:]
coffset += 1
voffset += rune_advance_len(r, voffset)
}
return
}
func byte_slice_grow(s []byte, desired_cap int) []byte {
if cap(s) < desired_cap {
ns := make([]byte, len(s), desired_cap)
copy(ns, s)
return ns
}
return s
}
func byte_slice_remove(text []byte, from, to int) []byte {
size := to - from
copy(text[from:], text[to:])
text = text[:len(text)-size]
return text
}
func byte_slice_insert(text []byte, offset int, what []byte) []byte {
n := len(text) + len(what)
text = byte_slice_grow(text, n)
text = text[:n]
copy(text[offset+len(what):], text[offset:])
copy(text[offset:], what)
return text
}
const preferred_horizontal_threshold = 5
const tabstop_length = 8
type EditBox struct {
text []byte
line_voffset int
cursor_boffset int // cursor offset in bytes
cursor_voffset int // visual cursor offset in termbox cells
cursor_coffset int // cursor offset in unicode code points
}
// Draws the EditBox in the given location, 'h' is not used at the moment
func (eb *EditBox) Draw(x, y, w, h int) {
eb.AdjustVOffset(w)
const coldef = termbox.ColorDefault
fill(x, y, w, h, termbox.Cell{Ch: ' '})
t := eb.text
lx := 0
tabstop := 0
for {
rx := lx - eb.line_voffset
if len(t) == 0 {
break
}
if lx == tabstop {
tabstop += tabstop_length
}
if rx >= w {
termbox.SetCell(x+w-1, y, '→',
coldef, coldef)
break
}
r, size := utf8.DecodeRune(t)
if r == '\t' {
for ; lx < tabstop; lx++ {
rx = lx - eb.line_voffset
if rx >= w {
goto next
}
if rx >= 0 {
termbox.SetCell(x+rx, y, ' ', coldef, coldef)
}
}
} else {
if rx >= 0 {
termbox.SetCell(x+rx, y, r, coldef, coldef)
}
lx += runewidth.RuneWidth(r)
}
next:
t = t[size:]
}
if eb.line_voffset != 0 {
termbox.SetCell(x, y, '←', coldef, coldef)
}
}
// Adjusts line visual offset to a proper value depending on width
func (eb *EditBox) AdjustVOffset(width int) {
ht := preferred_horizontal_threshold
max_h_threshold := (width - 1) / 2
if ht > max_h_threshold {
ht = max_h_threshold
}
threshold := width - 1
if eb.line_voffset != 0 {
threshold = width - ht
}
if eb.cursor_voffset-eb.line_voffset >= threshold {
eb.line_voffset = eb.cursor_voffset + (ht - width + 1)
}
if eb.line_voffset != 0 && eb.cursor_voffset-eb.line_voffset < ht {
eb.line_voffset = eb.cursor_voffset - ht
if eb.line_voffset < 0 {
eb.line_voffset = 0
}
}
}
func (eb *EditBox) MoveCursorTo(boffset int) {
eb.cursor_boffset = boffset
eb.cursor_voffset, eb.cursor_coffset = voffset_coffset(eb.text, boffset)
}
func (eb *EditBox) RuneUnderCursor() (rune, int) {
return utf8.DecodeRune(eb.text[eb.cursor_boffset:])
}
func (eb *EditBox) RuneBeforeCursor() (rune, int) {
return utf8.DecodeLastRune(eb.text[:eb.cursor_boffset])
}
func (eb *EditBox) MoveCursorOneRuneBackward() {
if eb.cursor_boffset == 0 {
return
}
_, size := eb.RuneBeforeCursor()
eb.MoveCursorTo(eb.cursor_boffset - size)
}
func (eb *EditBox) MoveCursorOneRuneForward() {
if eb.cursor_boffset == len(eb.text) {
return
}
_, size := eb.RuneUnderCursor()
eb.MoveCursorTo(eb.cursor_boffset + size)
}
func (eb *EditBox) MoveCursorToBeginningOfTheLine() {
eb.MoveCursorTo(0)
}
func (eb *EditBox) MoveCursorToEndOfTheLine() {
eb.MoveCursorTo(len(eb.text))
}
func (eb *EditBox) DeleteRuneBackward() {
if eb.cursor_boffset == 0 {
return
}
eb.MoveCursorOneRuneBackward()
_, size := eb.RuneUnderCursor()
eb.text = byte_slice_remove(eb.text, eb.cursor_boffset, eb.cursor_boffset+size)
}
func (eb *EditBox) DeleteRuneForward() {
if eb.cursor_boffset == len(eb.text) {
return
}
_, size := eb.RuneUnderCursor()
eb.text = byte_slice_remove(eb.text, eb.cursor_boffset, eb.cursor_boffset+size)
}
func (eb *EditBox) DeleteTheRestOfTheLine() {
eb.text = eb.text[:eb.cursor_boffset]
}
func (eb *EditBox) InsertRune(r rune) {
var buf [utf8.UTFMax]byte
n := utf8.EncodeRune(buf[:], r)
eb.text = byte_slice_insert(eb.text, eb.cursor_boffset, buf[:n])
eb.MoveCursorOneRuneForward()
}
// Please, keep in mind that cursor depends on the value of line_voffset, which
// is being set on Draw() call, so.. call this method after Draw() one.
func (eb *EditBox) CursorX() int {
return eb.cursor_voffset - eb.line_voffset
}
var edit_box EditBox
const edit_box_width = 30
func redraw_all() {
const coldef = termbox.ColorDefault
termbox.Clear(coldef, coldef)
w, h := termbox.Size()
midy := h / 2
midx := (w - edit_box_width) / 2
// unicode box drawing chars around the edit box
termbox.SetCell(midx-1, midy, '│', coldef, coldef)
termbox.SetCell(midx+edit_box_width, midy, '│', coldef, coldef)
termbox.SetCell(midx-1, midy-1, '┌', coldef, coldef)
termbox.SetCell(midx-1, midy+1, '└', coldef, coldef)
termbox.SetCell(midx+edit_box_width, midy-1, '┐', coldef, coldef)
termbox.SetCell(midx+edit_box_width, midy+1, '┘', coldef, coldef)
fill(midx, midy-1, edit_box_width, 1, termbox.Cell{Ch: '─'})
fill(midx, midy+1, edit_box_width, 1, termbox.Cell{Ch: '─'})
edit_box.Draw(midx, midy, edit_box_width, 1)
termbox.SetCursor(midx+edit_box.CursorX(), midy)
tbprint(midx+6, midy+3, coldef, coldef, "Press ESC to quit")
termbox.Flush()
}
func main() {
err := termbox.Init()
if err != nil {
panic(err)
}
defer termbox.Close()
termbox.SetInputMode(termbox.InputEsc)
redraw_all()
mainloop:
for {
switch ev := termbox.PollEvent(); ev.Type {
case termbox.EventKey:
switch ev.Key {
case termbox.KeyEsc:
break mainloop
case termbox.KeyArrowLeft, termbox.KeyCtrlB:
edit_box.MoveCursorOneRuneBackward()
case termbox.KeyArrowRight, termbox.KeyCtrlF:
edit_box.MoveCursorOneRuneForward()
case termbox.KeyBackspace, termbox.KeyBackspace2:
edit_box.DeleteRuneBackward()
case termbox.KeyDelete, termbox.KeyCtrlD:
edit_box.DeleteRuneForward()
case termbox.KeyTab:
edit_box.InsertRune('\t')
case termbox.KeySpace:
edit_box.InsertRune(' ')
case termbox.KeyCtrlK:
edit_box.DeleteTheRestOfTheLine()
case termbox.KeyHome, termbox.KeyCtrlA:
edit_box.MoveCursorToBeginningOfTheLine()
case termbox.KeyEnd, termbox.KeyCtrlE:
edit_box.MoveCursorToEndOfTheLine()
default:
if ev.Ch != 0 {
edit_box.InsertRune(ev.Ch)
}
}
case termbox.EventError:
panic(ev.Err)
}
redraw_all()
}
}

69
vendor/github.com/nsf/termbox-go/_demos/interrupt.go generated vendored Normal file
View File

@ -0,0 +1,69 @@
package main
import (
"fmt"
"github.com/nsf/termbox-go"
"time"
)
func tbPrint(x, y int, fg, bg termbox.Attribute, msg string) {
for _, c := range msg {
termbox.SetCell(x, y, c, fg, bg)
x++
}
}
func draw(i int) {
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
defer termbox.Flush()
w, h := termbox.Size()
s := fmt.Sprintf("count = %d", i)
tbPrint((w/2)-(len(s)/2), h/2, termbox.ColorRed, termbox.ColorDefault, s)
}
func main() {
err := termbox.Init()
if err != nil {
panic(err)
}
termbox.SetInputMode(termbox.InputEsc)
go func() {
time.Sleep(5 * time.Second)
termbox.Interrupt()
// This should never run - the Interrupt(), above, should cause the event
// loop below to exit, which then exits the process. If something goes
// wrong, this panic will trigger and show what happened.
time.Sleep(1 * time.Second)
panic("this should never run")
}()
var count int
draw(count)
mainloop:
for {
switch ev := termbox.PollEvent(); ev.Type {
case termbox.EventKey:
if ev.Ch == '+' {
count++
} else if ev.Ch == '-' {
count--
}
case termbox.EventError:
panic(ev.Err)
case termbox.EventInterrupt:
break mainloop
}
draw(count)
}
termbox.Close()
fmt.Println("Finished")
}

722
vendor/github.com/nsf/termbox-go/_demos/keyboard.go generated vendored Normal file
View File

@ -0,0 +1,722 @@
package main
import "github.com/nsf/termbox-go"
import "fmt"
type key struct {
x int
y int
ch rune
}
var K_ESC = []key{{1, 1, 'E'}, {2, 1, 'S'}, {3, 1, 'C'}}
var K_F1 = []key{{6, 1, 'F'}, {7, 1, '1'}}
var K_F2 = []key{{9, 1, 'F'}, {10, 1, '2'}}
var K_F3 = []key{{12, 1, 'F'}, {13, 1, '3'}}
var K_F4 = []key{{15, 1, 'F'}, {16, 1, '4'}}
var K_F5 = []key{{19, 1, 'F'}, {20, 1, '5'}}
var K_F6 = []key{{22, 1, 'F'}, {23, 1, '6'}}
var K_F7 = []key{{25, 1, 'F'}, {26, 1, '7'}}
var K_F8 = []key{{28, 1, 'F'}, {29, 1, '8'}}
var K_F9 = []key{{33, 1, 'F'}, {34, 1, '9'}}
var K_F10 = []key{{36, 1, 'F'}, {37, 1, '1'}, {38, 1, '0'}}
var K_F11 = []key{{40, 1, 'F'}, {41, 1, '1'}, {42, 1, '1'}}
var K_F12 = []key{{44, 1, 'F'}, {45, 1, '1'}, {46, 1, '2'}}
var K_PRN = []key{{50, 1, 'P'}, {51, 1, 'R'}, {52, 1, 'N'}}
var K_SCR = []key{{54, 1, 'S'}, {55, 1, 'C'}, {56, 1, 'R'}}
var K_BRK = []key{{58, 1, 'B'}, {59, 1, 'R'}, {60, 1, 'K'}}
var K_LED1 = []key{{66, 1, '-'}}
var K_LED2 = []key{{70, 1, '-'}}
var K_LED3 = []key{{74, 1, '-'}}
var K_TILDE = []key{{1, 4, '`'}}
var K_TILDE_SHIFT = []key{{1, 4, '~'}}
var K_1 = []key{{4, 4, '1'}}
var K_1_SHIFT = []key{{4, 4, '!'}}
var K_2 = []key{{7, 4, '2'}}
var K_2_SHIFT = []key{{7, 4, '@'}}
var K_3 = []key{{10, 4, '3'}}
var K_3_SHIFT = []key{{10, 4, '#'}}
var K_4 = []key{{13, 4, '4'}}
var K_4_SHIFT = []key{{13, 4, '$'}}
var K_5 = []key{{16, 4, '5'}}
var K_5_SHIFT = []key{{16, 4, '%'}}
var K_6 = []key{{19, 4, '6'}}
var K_6_SHIFT = []key{{19, 4, '^'}}
var K_7 = []key{{22, 4, '7'}}
var K_7_SHIFT = []key{{22, 4, '&'}}
var K_8 = []key{{25, 4, '8'}}
var K_8_SHIFT = []key{{25, 4, '*'}}
var K_9 = []key{{28, 4, '9'}}
var K_9_SHIFT = []key{{28, 4, '('}}
var K_0 = []key{{31, 4, '0'}}
var K_0_SHIFT = []key{{31, 4, ')'}}
var K_MINUS = []key{{34, 4, '-'}}
var K_MINUS_SHIFT = []key{{34, 4, '_'}}
var K_EQUALS = []key{{37, 4, '='}}
var K_EQUALS_SHIFT = []key{{37, 4, '+'}}
var K_BACKSLASH = []key{{40, 4, '\\'}}
var K_BACKSLASH_SHIFT = []key{{40, 4, '|'}}
var K_BACKSPACE = []key{{44, 4, 0x2190}, {45, 4, 0x2500}, {46, 4, 0x2500}}
var K_INS = []key{{50, 4, 'I'}, {51, 4, 'N'}, {52, 4, 'S'}}
var K_HOM = []key{{54, 4, 'H'}, {55, 4, 'O'}, {56, 4, 'M'}}
var K_PGU = []key{{58, 4, 'P'}, {59, 4, 'G'}, {60, 4, 'U'}}
var K_K_NUMLOCK = []key{{65, 4, 'N'}}
var K_K_SLASH = []key{{68, 4, '/'}}
var K_K_STAR = []key{{71, 4, '*'}}
var K_K_MINUS = []key{{74, 4, '-'}}
var K_TAB = []key{{1, 6, 'T'}, {2, 6, 'A'}, {3, 6, 'B'}}
var K_q = []key{{6, 6, 'q'}}
var K_Q = []key{{6, 6, 'Q'}}
var K_w = []key{{9, 6, 'w'}}
var K_W = []key{{9, 6, 'W'}}
var K_e = []key{{12, 6, 'e'}}
var K_E = []key{{12, 6, 'E'}}
var K_r = []key{{15, 6, 'r'}}
var K_R = []key{{15, 6, 'R'}}
var K_t = []key{{18, 6, 't'}}
var K_T = []key{{18, 6, 'T'}}
var K_y = []key{{21, 6, 'y'}}
var K_Y = []key{{21, 6, 'Y'}}
var K_u = []key{{24, 6, 'u'}}
var K_U = []key{{24, 6, 'U'}}
var K_i = []key{{27, 6, 'i'}}
var K_I = []key{{27, 6, 'I'}}
var K_o = []key{{30, 6, 'o'}}
var K_O = []key{{30, 6, 'O'}}
var K_p = []key{{33, 6, 'p'}}
var K_P = []key{{33, 6, 'P'}}
var K_LSQB = []key{{36, 6, '['}}
var K_LCUB = []key{{36, 6, '{'}}
var K_RSQB = []key{{39, 6, ']'}}
var K_RCUB = []key{{39, 6, '}'}}
var K_ENTER = []key{
{43, 6, 0x2591}, {44, 6, 0x2591}, {45, 6, 0x2591}, {46, 6, 0x2591},
{43, 7, 0x2591}, {44, 7, 0x2591}, {45, 7, 0x21B5}, {46, 7, 0x2591},
{41, 8, 0x2591}, {42, 8, 0x2591}, {43, 8, 0x2591}, {44, 8, 0x2591},
{45, 8, 0x2591}, {46, 8, 0x2591},
}
var K_DEL = []key{{50, 6, 'D'}, {51, 6, 'E'}, {52, 6, 'L'}}
var K_END = []key{{54, 6, 'E'}, {55, 6, 'N'}, {56, 6, 'D'}}
var K_PGD = []key{{58, 6, 'P'}, {59, 6, 'G'}, {60, 6, 'D'}}
var K_K_7 = []key{{65, 6, '7'}}
var K_K_8 = []key{{68, 6, '8'}}
var K_K_9 = []key{{71, 6, '9'}}
var K_K_PLUS = []key{{74, 6, ' '}, {74, 7, '+'}, {74, 8, ' '}}
var K_CAPS = []key{{1, 8, 'C'}, {2, 8, 'A'}, {3, 8, 'P'}, {4, 8, 'S'}}
var K_a = []key{{7, 8, 'a'}}
var K_A = []key{{7, 8, 'A'}}
var K_s = []key{{10, 8, 's'}}
var K_S = []key{{10, 8, 'S'}}
var K_d = []key{{13, 8, 'd'}}
var K_D = []key{{13, 8, 'D'}}
var K_f = []key{{16, 8, 'f'}}
var K_F = []key{{16, 8, 'F'}}
var K_g = []key{{19, 8, 'g'}}
var K_G = []key{{19, 8, 'G'}}
var K_h = []key{{22, 8, 'h'}}
var K_H = []key{{22, 8, 'H'}}
var K_j = []key{{25, 8, 'j'}}
var K_J = []key{{25, 8, 'J'}}
var K_k = []key{{28, 8, 'k'}}
var K_K = []key{{28, 8, 'K'}}
var K_l = []key{{31, 8, 'l'}}
var K_L = []key{{31, 8, 'L'}}
var K_SEMICOLON = []key{{34, 8, ';'}}
var K_PARENTHESIS = []key{{34, 8, ':'}}
var K_QUOTE = []key{{37, 8, '\''}}
var K_DOUBLEQUOTE = []key{{37, 8, '"'}}
var K_K_4 = []key{{65, 8, '4'}}
var K_K_5 = []key{{68, 8, '5'}}
var K_K_6 = []key{{71, 8, '6'}}
var K_LSHIFT = []key{{1, 10, 'S'}, {2, 10, 'H'}, {3, 10, 'I'}, {4, 10, 'F'}, {5, 10, 'T'}}
var K_z = []key{{9, 10, 'z'}}
var K_Z = []key{{9, 10, 'Z'}}
var K_x = []key{{12, 10, 'x'}}
var K_X = []key{{12, 10, 'X'}}
var K_c = []key{{15, 10, 'c'}}
var K_C = []key{{15, 10, 'C'}}
var K_v = []key{{18, 10, 'v'}}
var K_V = []key{{18, 10, 'V'}}
var K_b = []key{{21, 10, 'b'}}
var K_B = []key{{21, 10, 'B'}}
var K_n = []key{{24, 10, 'n'}}
var K_N = []key{{24, 10, 'N'}}
var K_m = []key{{27, 10, 'm'}}
var K_M = []key{{27, 10, 'M'}}
var K_COMMA = []key{{30, 10, ','}}
var K_LANB = []key{{30, 10, '<'}}
var K_PERIOD = []key{{33, 10, '.'}}
var K_RANB = []key{{33, 10, '>'}}
var K_SLASH = []key{{36, 10, '/'}}
var K_QUESTION = []key{{36, 10, '?'}}
var K_RSHIFT = []key{{42, 10, 'S'}, {43, 10, 'H'}, {44, 10, 'I'}, {45, 10, 'F'}, {46, 10, 'T'}}
var K_ARROW_UP = []key{{54, 10, '('}, {55, 10, 0x2191}, {56, 10, ')'}}
var K_K_1 = []key{{65, 10, '1'}}
var K_K_2 = []key{{68, 10, '2'}}
var K_K_3 = []key{{71, 10, '3'}}
var K_K_ENTER = []key{{74, 10, 0x2591}, {74, 11, 0x2591}, {74, 12, 0x2591}}
var K_LCTRL = []key{{1, 12, 'C'}, {2, 12, 'T'}, {3, 12, 'R'}, {4, 12, 'L'}}
var K_LWIN = []key{{6, 12, 'W'}, {7, 12, 'I'}, {8, 12, 'N'}}
var K_LALT = []key{{10, 12, 'A'}, {11, 12, 'L'}, {12, 12, 'T'}}
var K_SPACE = []key{
{14, 12, ' '}, {15, 12, ' '}, {16, 12, ' '}, {17, 12, ' '}, {18, 12, ' '},
{19, 12, 'S'}, {20, 12, 'P'}, {21, 12, 'A'}, {22, 12, 'C'}, {23, 12, 'E'},
{24, 12, ' '}, {25, 12, ' '}, {26, 12, ' '}, {27, 12, ' '}, {28, 12, ' '},
}
var K_RALT = []key{{30, 12, 'A'}, {31, 12, 'L'}, {32, 12, 'T'}}
var K_RWIN = []key{{34, 12, 'W'}, {35, 12, 'I'}, {36, 12, 'N'}}
var K_RPROP = []key{{38, 12, 'P'}, {39, 12, 'R'}, {40, 12, 'O'}, {41, 12, 'P'}}
var K_RCTRL = []key{{43, 12, 'C'}, {44, 12, 'T'}, {45, 12, 'R'}, {46, 12, 'L'}}
var K_ARROW_LEFT = []key{{50, 12, '('}, {51, 12, 0x2190}, {52, 12, ')'}}
var K_ARROW_DOWN = []key{{54, 12, '('}, {55, 12, 0x2193}, {56, 12, ')'}}
var K_ARROW_RIGHT = []key{{58, 12, '('}, {59, 12, 0x2192}, {60, 12, ')'}}
var K_K_0 = []key{{65, 12, ' '}, {66, 12, '0'}, {67, 12, ' '}, {68, 12, ' '}}
var K_K_PERIOD = []key{{71, 12, '.'}}
type combo struct {
keys [][]key
}
var combos = []combo{
{[][]key{K_TILDE, K_2, K_SPACE, K_LCTRL, K_RCTRL}},
{[][]key{K_A, K_LCTRL, K_RCTRL}},
{[][]key{K_B, K_LCTRL, K_RCTRL}},
{[][]key{K_C, K_LCTRL, K_RCTRL}},
{[][]key{K_D, K_LCTRL, K_RCTRL}},
{[][]key{K_E, K_LCTRL, K_RCTRL}},
{[][]key{K_F, K_LCTRL, K_RCTRL}},
{[][]key{K_G, K_LCTRL, K_RCTRL}},
{[][]key{K_H, K_BACKSPACE, K_LCTRL, K_RCTRL}},
{[][]key{K_I, K_TAB, K_LCTRL, K_RCTRL}},
{[][]key{K_J, K_LCTRL, K_RCTRL}},
{[][]key{K_K, K_LCTRL, K_RCTRL}},
{[][]key{K_L, K_LCTRL, K_RCTRL}},
{[][]key{K_M, K_ENTER, K_K_ENTER, K_LCTRL, K_RCTRL}},
{[][]key{K_N, K_LCTRL, K_RCTRL}},
{[][]key{K_O, K_LCTRL, K_RCTRL}},
{[][]key{K_P, K_LCTRL, K_RCTRL}},
{[][]key{K_Q, K_LCTRL, K_RCTRL}},
{[][]key{K_R, K_LCTRL, K_RCTRL}},
{[][]key{K_S, K_LCTRL, K_RCTRL}},
{[][]key{K_T, K_LCTRL, K_RCTRL}},
{[][]key{K_U, K_LCTRL, K_RCTRL}},
{[][]key{K_V, K_LCTRL, K_RCTRL}},
{[][]key{K_W, K_LCTRL, K_RCTRL}},
{[][]key{K_X, K_LCTRL, K_RCTRL}},
{[][]key{K_Y, K_LCTRL, K_RCTRL}},
{[][]key{K_Z, K_LCTRL, K_RCTRL}},
{[][]key{K_LSQB, K_ESC, K_3, K_LCTRL, K_RCTRL}},
{[][]key{K_4, K_BACKSLASH, K_LCTRL, K_RCTRL}},
{[][]key{K_RSQB, K_5, K_LCTRL, K_RCTRL}},
{[][]key{K_6, K_LCTRL, K_RCTRL}},
{[][]key{K_7, K_SLASH, K_MINUS_SHIFT, K_LCTRL, K_RCTRL}},
{[][]key{K_SPACE}},
{[][]key{K_1_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_DOUBLEQUOTE, K_LSHIFT, K_RSHIFT}},
{[][]key{K_3_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_4_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_5_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_7_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_QUOTE}},
{[][]key{K_9_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_0_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_8_SHIFT, K_K_STAR, K_LSHIFT, K_RSHIFT}},
{[][]key{K_EQUALS_SHIFT, K_K_PLUS, K_LSHIFT, K_RSHIFT}},
{[][]key{K_COMMA}},
{[][]key{K_MINUS, K_K_MINUS}},
{[][]key{K_PERIOD, K_K_PERIOD}},
{[][]key{K_SLASH, K_K_SLASH}},
{[][]key{K_0, K_K_0}},
{[][]key{K_1, K_K_1}},
{[][]key{K_2, K_K_2}},
{[][]key{K_3, K_K_3}},
{[][]key{K_4, K_K_4}},
{[][]key{K_5, K_K_5}},
{[][]key{K_6, K_K_6}},
{[][]key{K_7, K_K_7}},
{[][]key{K_8, K_K_8}},
{[][]key{K_9, K_K_9}},
{[][]key{K_PARENTHESIS, K_LSHIFT, K_RSHIFT}},
{[][]key{K_SEMICOLON}},
{[][]key{K_LANB, K_LSHIFT, K_RSHIFT}},
{[][]key{K_EQUALS}},
{[][]key{K_RANB, K_LSHIFT, K_RSHIFT}},
{[][]key{K_QUESTION, K_LSHIFT, K_RSHIFT}},
{[][]key{K_2_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_A, K_LSHIFT, K_RSHIFT}},
{[][]key{K_B, K_LSHIFT, K_RSHIFT}},
{[][]key{K_C, K_LSHIFT, K_RSHIFT}},
{[][]key{K_D, K_LSHIFT, K_RSHIFT}},
{[][]key{K_E, K_LSHIFT, K_RSHIFT}},
{[][]key{K_F, K_LSHIFT, K_RSHIFT}},
{[][]key{K_G, K_LSHIFT, K_RSHIFT}},
{[][]key{K_H, K_LSHIFT, K_RSHIFT}},
{[][]key{K_I, K_LSHIFT, K_RSHIFT}},
{[][]key{K_J, K_LSHIFT, K_RSHIFT}},
{[][]key{K_K, K_LSHIFT, K_RSHIFT}},
{[][]key{K_L, K_LSHIFT, K_RSHIFT}},
{[][]key{K_M, K_LSHIFT, K_RSHIFT}},
{[][]key{K_N, K_LSHIFT, K_RSHIFT}},
{[][]key{K_O, K_LSHIFT, K_RSHIFT}},
{[][]key{K_P, K_LSHIFT, K_RSHIFT}},
{[][]key{K_Q, K_LSHIFT, K_RSHIFT}},
{[][]key{K_R, K_LSHIFT, K_RSHIFT}},
{[][]key{K_S, K_LSHIFT, K_RSHIFT}},
{[][]key{K_T, K_LSHIFT, K_RSHIFT}},
{[][]key{K_U, K_LSHIFT, K_RSHIFT}},
{[][]key{K_V, K_LSHIFT, K_RSHIFT}},
{[][]key{K_W, K_LSHIFT, K_RSHIFT}},
{[][]key{K_X, K_LSHIFT, K_RSHIFT}},
{[][]key{K_Y, K_LSHIFT, K_RSHIFT}},
{[][]key{K_Z, K_LSHIFT, K_RSHIFT}},
{[][]key{K_LSQB}},
{[][]key{K_BACKSLASH}},
{[][]key{K_RSQB}},
{[][]key{K_6_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_MINUS_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_TILDE}},
{[][]key{K_a}},
{[][]key{K_b}},
{[][]key{K_c}},
{[][]key{K_d}},
{[][]key{K_e}},
{[][]key{K_f}},
{[][]key{K_g}},
{[][]key{K_h}},
{[][]key{K_i}},
{[][]key{K_j}},
{[][]key{K_k}},
{[][]key{K_l}},
{[][]key{K_m}},
{[][]key{K_n}},
{[][]key{K_o}},
{[][]key{K_p}},
{[][]key{K_q}},
{[][]key{K_r}},
{[][]key{K_s}},
{[][]key{K_t}},
{[][]key{K_u}},
{[][]key{K_v}},
{[][]key{K_w}},
{[][]key{K_x}},
{[][]key{K_y}},
{[][]key{K_z}},
{[][]key{K_LCUB, K_LSHIFT, K_RSHIFT}},
{[][]key{K_BACKSLASH_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_RCUB, K_LSHIFT, K_RSHIFT}},
{[][]key{K_TILDE_SHIFT, K_LSHIFT, K_RSHIFT}},
{[][]key{K_8, K_BACKSPACE, K_LCTRL, K_RCTRL}},
}
var func_combos = []combo{
{[][]key{K_F1}},
{[][]key{K_F2}},
{[][]key{K_F3}},
{[][]key{K_F4}},
{[][]key{K_F5}},
{[][]key{K_F6}},
{[][]key{K_F7}},
{[][]key{K_F8}},
{[][]key{K_F9}},
{[][]key{K_F10}},
{[][]key{K_F11}},
{[][]key{K_F12}},
{[][]key{K_INS}},
{[][]key{K_DEL}},
{[][]key{K_HOM}},
{[][]key{K_END}},
{[][]key{K_PGU}},
{[][]key{K_PGD}},
{[][]key{K_ARROW_UP}},
{[][]key{K_ARROW_DOWN}},
{[][]key{K_ARROW_LEFT}},
{[][]key{K_ARROW_RIGHT}},
}
func print_tb(x, y int, fg, bg termbox.Attribute, msg string) {
for _, c := range msg {
termbox.SetCell(x, y, c, fg, bg)
x++
}
}
func printf_tb(x, y int, fg, bg termbox.Attribute, format string, args ...interface{}) {
s := fmt.Sprintf(format, args...)
print_tb(x, y, fg, bg, s)
}
func draw_key(k []key, fg, bg termbox.Attribute) {
for _, k := range k {
termbox.SetCell(k.x+2, k.y+4, k.ch, fg, bg)
}
}
func draw_keyboard() {
termbox.SetCell(0, 0, 0x250C, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(79, 0, 0x2510, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(0, 23, 0x2514, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(79, 23, 0x2518, termbox.ColorWhite, termbox.ColorBlack)
for i := 1; i < 79; i++ {
termbox.SetCell(i, 0, 0x2500, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(i, 23, 0x2500, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(i, 17, 0x2500, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(i, 4, 0x2500, termbox.ColorWhite, termbox.ColorBlack)
}
for i := 1; i < 23; i++ {
termbox.SetCell(0, i, 0x2502, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(79, i, 0x2502, termbox.ColorWhite, termbox.ColorBlack)
}
termbox.SetCell(0, 17, 0x251C, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(79, 17, 0x2524, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(0, 4, 0x251C, termbox.ColorWhite, termbox.ColorBlack)
termbox.SetCell(79, 4, 0x2524, termbox.ColorWhite, termbox.ColorBlack)
for i := 5; i < 17; i++ {
termbox.SetCell(1, i, 0x2588, termbox.ColorYellow, termbox.ColorYellow)
termbox.SetCell(78, i, 0x2588, termbox.ColorYellow, termbox.ColorYellow)
}
draw_key(K_ESC, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F1, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F2, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F3, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F4, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F5, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F6, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F7, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F8, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F9, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F10, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F11, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_F12, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_PRN, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_SCR, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_BRK, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_LED1, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_LED2, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_LED3, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_TILDE, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_1, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_2, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_3, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_4, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_5, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_6, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_7, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_8, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_9, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_0, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_MINUS, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_EQUALS, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_BACKSLASH, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_BACKSPACE, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_INS, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_HOM, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_PGU, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_NUMLOCK, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_SLASH, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_STAR, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_MINUS, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_TAB, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_q, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_w, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_e, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_r, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_t, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_y, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_u, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_i, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_o, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_p, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_LSQB, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_RSQB, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_ENTER, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_DEL, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_END, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_PGD, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_7, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_8, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_9, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_PLUS, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_CAPS, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_a, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_s, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_d, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_f, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_g, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_h, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_j, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_k, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_l, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_SEMICOLON, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_QUOTE, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_4, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_5, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_6, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_LSHIFT, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_z, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_x, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_c, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_v, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_b, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_n, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_m, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_COMMA, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_PERIOD, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_SLASH, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_RSHIFT, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_ARROW_UP, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_1, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_2, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_3, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_ENTER, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_LCTRL, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_LWIN, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_LALT, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_SPACE, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_RCTRL, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_RPROP, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_RWIN, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_RALT, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_ARROW_LEFT, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_ARROW_DOWN, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_ARROW_RIGHT, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_0, termbox.ColorWhite, termbox.ColorBlue)
draw_key(K_K_PERIOD, termbox.ColorWhite, termbox.ColorBlue)
printf_tb(33, 1, termbox.ColorMagenta|termbox.AttrBold, termbox.ColorBlack, "Keyboard demo!")
printf_tb(21, 2, termbox.ColorMagenta, termbox.ColorBlack, "(press CTRL+X and then CTRL+Q to exit)")
printf_tb(15, 3, termbox.ColorMagenta, termbox.ColorBlack, "(press CTRL+X and then CTRL+C to change input mode)")
inputmode := termbox.SetInputMode(termbox.InputCurrent)
inputmode_str := ""
switch {
case inputmode&termbox.InputEsc != 0:
inputmode_str = "termbox.InputEsc"
case inputmode&termbox.InputAlt != 0:
inputmode_str = "termbox.InputAlt"
}
if inputmode&termbox.InputMouse != 0 {
inputmode_str += " | termbox.InputMouse"
}
printf_tb(3, 18, termbox.ColorWhite, termbox.ColorBlack, "Input mode: %s", inputmode_str)
}
var fcmap = []string{
"CTRL+2, CTRL+~",
"CTRL+A",
"CTRL+B",
"CTRL+C",
"CTRL+D",
"CTRL+E",
"CTRL+F",
"CTRL+G",
"CTRL+H, BACKSPACE",
"CTRL+I, TAB",
"CTRL+J",
"CTRL+K",
"CTRL+L",
"CTRL+M, ENTER",
"CTRL+N",
"CTRL+O",
"CTRL+P",
"CTRL+Q",
"CTRL+R",
"CTRL+S",
"CTRL+T",
"CTRL+U",
"CTRL+V",
"CTRL+W",
"CTRL+X",
"CTRL+Y",
"CTRL+Z",
"CTRL+3, ESC, CTRL+[",
"CTRL+4, CTRL+\\",
"CTRL+5, CTRL+]",
"CTRL+6",
"CTRL+7, CTRL+/, CTRL+_",
"SPACE",
}
var fkmap = []string{
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
"INSERT",
"DELETE",
"HOME",
"END",
"PGUP",
"PGDN",
"ARROW UP",
"ARROW DOWN",
"ARROW LEFT",
"ARROW RIGHT",
}
func funckeymap(k termbox.Key) string {
if k == termbox.KeyCtrl8 {
return "CTRL+8, BACKSPACE 2" /* 0x7F */
} else if k >= termbox.KeyArrowRight && k <= 0xFFFF {
return fkmap[0xFFFF-k]
} else if k <= termbox.KeySpace {
return fcmap[k]
}
return "UNKNOWN"
}
func pretty_print_press(ev *termbox.Event) {
printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Key: ")
printf_tb(8, 19, termbox.ColorYellow, termbox.ColorBlack, "decimal: %d", ev.Key)
printf_tb(8, 20, termbox.ColorGreen, termbox.ColorBlack, "hex: 0x%X", ev.Key)
printf_tb(8, 21, termbox.ColorCyan, termbox.ColorBlack, "octal: 0%o", ev.Key)
printf_tb(8, 22, termbox.ColorRed, termbox.ColorBlack, "string: %s", funckeymap(ev.Key))
printf_tb(54, 19, termbox.ColorWhite, termbox.ColorBlack, "Char: ")
printf_tb(60, 19, termbox.ColorYellow, termbox.ColorBlack, "decimal: %d", ev.Ch)
printf_tb(60, 20, termbox.ColorGreen, termbox.ColorBlack, "hex: 0x%X", ev.Ch)
printf_tb(60, 21, termbox.ColorCyan, termbox.ColorBlack, "octal: 0%o", ev.Ch)
printf_tb(60, 22, termbox.ColorRed, termbox.ColorBlack, "string: %s", string(ev.Ch))
modifier := "none"
if ev.Mod != 0 {
modifier = "termbox.ModAlt"
}
printf_tb(54, 18, termbox.ColorWhite, termbox.ColorBlack, "Modifier: %s", modifier)
}
func pretty_print_resize(ev *termbox.Event) {
printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Resize event: %d x %d", ev.Width, ev.Height)
}
var counter = 0
func pretty_print_mouse(ev *termbox.Event) {
printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Mouse event: %d x %d", ev.MouseX, ev.MouseY)
button := ""
switch ev.Key {
case termbox.MouseLeft:
button = "MouseLeft: %d"
case termbox.MouseMiddle:
button = "MouseMiddle: %d"
case termbox.MouseRight:
button = "MouseRight: %d"
case termbox.MouseWheelUp:
button = "MouseWheelUp: %d"
case termbox.MouseWheelDown:
button = "MouseWheelDown: %d"
case termbox.MouseRelease:
button = "MouseRelease: %d"
}
if ev.Mod&termbox.ModMotion != 0 {
button += "*"
}
counter++
printf_tb(43, 19, termbox.ColorWhite, termbox.ColorBlack, "Key: ")
printf_tb(48, 19, termbox.ColorYellow, termbox.ColorBlack, button, counter)
}
func dispatch_press(ev *termbox.Event) {
if ev.Mod&termbox.ModAlt != 0 {
draw_key(K_LALT, termbox.ColorWhite, termbox.ColorRed)
draw_key(K_RALT, termbox.ColorWhite, termbox.ColorRed)
}
var k *combo
if ev.Key >= termbox.KeyArrowRight {
k = &func_combos[0xFFFF-ev.Key]
} else if ev.Ch < 128 {
if ev.Ch == 0 && ev.Key < 128 {
k = &combos[ev.Key]
} else {
k = &combos[ev.Ch]
}
}
if k == nil {
return
}
keys := k.keys
for _, k := range keys {
draw_key(k, termbox.ColorWhite, termbox.ColorRed)
}
}
func main() {
err := termbox.Init()
if err != nil {
panic(err)
}
defer termbox.Close()
termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse)
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
draw_keyboard()
termbox.Flush()
inputmode := 0
ctrlxpressed := false
loop:
for {
switch ev := termbox.PollEvent(); ev.Type {
case termbox.EventKey:
if ev.Key == termbox.KeyCtrlS && ctrlxpressed {
termbox.Sync()
}
if ev.Key == termbox.KeyCtrlQ && ctrlxpressed {
break loop
}
if ev.Key == termbox.KeyCtrlC && ctrlxpressed {
chmap := []termbox.InputMode{
termbox.InputEsc | termbox.InputMouse,
termbox.InputAlt | termbox.InputMouse,
termbox.InputEsc,
termbox.InputAlt,
}
inputmode++
if inputmode >= len(chmap) {
inputmode = 0
}
termbox.SetInputMode(chmap[inputmode])
}
if ev.Key == termbox.KeyCtrlX {
ctrlxpressed = true
} else {
ctrlxpressed = false
}
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
draw_keyboard()
dispatch_press(&ev)
pretty_print_press(&ev)
termbox.Flush()
case termbox.EventResize:
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
draw_keyboard()
pretty_print_resize(&ev)
termbox.Flush()
case termbox.EventMouse:
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
draw_keyboard()
pretty_print_mouse(&ev)
termbox.Flush()
case termbox.EventError:
panic(ev.Err)
}
}
}

228
vendor/github.com/nsf/termbox-go/_demos/output.go generated vendored Normal file
View File

@ -0,0 +1,228 @@
package main
import "github.com/mattn/go-runewidth"
import "github.com/nsf/termbox-go"
const chars = "nnnnnnnnnbbbbbbbbbuuuuuuuuuBBBBBBBBB"
var output_mode = termbox.OutputNormal
func next_char(current int) int {
current++
if current >= len(chars) {
return 0
}
return current
}
func print_combinations_table(sx, sy int, attrs []termbox.Attribute) {
var bg termbox.Attribute
current_char := 0
y := sy
all_attrs := []termbox.Attribute{
0,
termbox.AttrBold,
termbox.AttrUnderline,
termbox.AttrBold | termbox.AttrUnderline,
}
draw_line := func() {
x := sx
for _, a := range all_attrs {
for c := termbox.ColorDefault; c <= termbox.ColorWhite; c++ {
fg := a | c
termbox.SetCell(x, y, rune(chars[current_char]), fg, bg)
current_char = next_char(current_char)
x++
}
}
}
for _, a := range attrs {
for c := termbox.ColorDefault; c <= termbox.ColorWhite; c++ {
bg = a | c
draw_line()
y++
}
}
}
func print_wide(x, y int, s string) {
red := false
for _, r := range s {
c := termbox.ColorDefault
if red {
c = termbox.ColorRed
}
termbox.SetCell(x, y, r, termbox.ColorDefault, c)
w := runewidth.RuneWidth(r)
if w == 0 || (w == 2 && runewidth.IsAmbiguousWidth(r)) {
w = 1
}
x += w
red = !red
}
}
const hello_world = "こんにちは世界"
func draw_all() {
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
switch output_mode {
case termbox.OutputNormal:
print_combinations_table(1, 1, []termbox.Attribute{
0,
termbox.AttrBold,
})
print_combinations_table(2+len(chars), 1, []termbox.Attribute{
termbox.AttrReverse,
})
print_wide(2+len(chars), 11, hello_world)
case termbox.OutputGrayscale:
for y := 0; y < 26; y++ {
for x := 0; x < 26; x++ {
termbox.SetCell(x, y, 'n',
termbox.Attribute(x+1),
termbox.Attribute(y+1))
termbox.SetCell(x+27, y, 'b',
termbox.Attribute(x+1)|termbox.AttrBold,
termbox.Attribute(26-y))
termbox.SetCell(x+54, y, 'u',
termbox.Attribute(x+1)|termbox.AttrUnderline,
termbox.Attribute(y+1))
}
termbox.SetCell(82, y, 'd',
termbox.Attribute(y+1),
termbox.ColorDefault)
termbox.SetCell(83, y, 'd',
termbox.ColorDefault,
termbox.Attribute(26-y))
}
case termbox.Output216:
for r := 0; r < 6; r++ {
for g := 0; g < 6; g++ {
for b := 0; b < 6; b++ {
y := r
x := g + 6*b
c1 := termbox.Attribute(1 + r*36 + g*6 + b)
bg := termbox.Attribute(1 + g*36 + b*6 + r)
c2 := termbox.Attribute(1 + b*36 + r*6 + g)
bc1 := c1 | termbox.AttrBold
uc1 := c1 | termbox.AttrUnderline
bc2 := c2 | termbox.AttrBold
uc2 := c2 | termbox.AttrUnderline
termbox.SetCell(x, y, 'n', c1, bg)
termbox.SetCell(x, y+6, 'b', bc1, bg)
termbox.SetCell(x, y+12, 'u', uc1, bg)
termbox.SetCell(x, y+18, 'B', bc1|uc1, bg)
termbox.SetCell(x+37, y, 'n', c2, bg)
termbox.SetCell(x+37, y+6, 'b', bc2, bg)
termbox.SetCell(x+37, y+12, 'u', uc2, bg)
termbox.SetCell(x+37, y+18, 'B', bc2|uc2, bg)
}
c1 := termbox.Attribute(1 + g*6 + r*36)
c2 := termbox.Attribute(6 + g*6 + r*36)
termbox.SetCell(74+g, r, 'd', c1, termbox.ColorDefault)
termbox.SetCell(74+g, r+6, 'd', c2, termbox.ColorDefault)
termbox.SetCell(74+g, r+12, 'd', termbox.ColorDefault, c1)
termbox.SetCell(74+g, r+18, 'd', termbox.ColorDefault, c2)
}
}
case termbox.Output256:
for y := 0; y < 4; y++ {
for x := 0; x < 8; x++ {
for z := 0; z < 8; z++ {
bg := termbox.Attribute(1 + y*64 + x*8 + z)
c1 := termbox.Attribute(256 - y*64 - x*8 - z)
c2 := termbox.Attribute(1 + y*64 + z*8 + x)
c3 := termbox.Attribute(256 - y*64 - z*8 - x)
c4 := termbox.Attribute(1 + y*64 + x*4 + z*4)
bold := c2 | termbox.AttrBold
under := c3 | termbox.AttrUnderline
both := c1 | termbox.AttrBold | termbox.AttrUnderline
termbox.SetCell(z+8*x, y, ' ', 0, bg)
termbox.SetCell(z+8*x, y+5, 'n', c4, bg)
termbox.SetCell(z+8*x, y+10, 'b', bold, bg)
termbox.SetCell(z+8*x, y+15, 'u', under, bg)
termbox.SetCell(z+8*x, y+20, 'B', both, bg)
}
}
}
for x := 0; x < 12; x++ {
for y := 0; y < 2; y++ {
c1 := termbox.Attribute(233 + y*12 + x)
termbox.SetCell(66+x, y, 'd', c1, termbox.ColorDefault)
termbox.SetCell(66+x, 2+y, 'd', termbox.ColorDefault, c1)
}
}
for x := 0; x < 6; x++ {
for y := 0; y < 6; y++ {
c1 := termbox.Attribute(17 + x*6 + y*36)
c2 := termbox.Attribute(17 + 5 + x*6 + y*36)
termbox.SetCell(66+x, 6+y, 'd', c1, termbox.ColorDefault)
termbox.SetCell(66+x, 12+y, 'd', c2, termbox.ColorDefault)
termbox.SetCell(72+x, 6+y, 'd', termbox.ColorDefault, c1)
termbox.SetCell(72+x, 12+y, 'd', termbox.ColorDefault, c2)
}
}
}
termbox.Flush()
}
var available_modes = []termbox.OutputMode{
termbox.OutputNormal,
termbox.OutputGrayscale,
termbox.Output216,
termbox.Output256,
}
var output_mode_index = 0
func switch_output_mode(direction int) {
output_mode_index += direction
if output_mode_index < 0 {
output_mode_index = len(available_modes) - 1
} else if output_mode_index >= len(available_modes) {
output_mode_index = 0
}
output_mode = termbox.SetOutputMode(available_modes[output_mode_index])
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
termbox.Sync()
}
func main() {
err := termbox.Init()
if err != nil {
panic(err)
}
defer termbox.Close()
draw_all()
loop:
for {
switch ev := termbox.PollEvent(); ev.Type {
case termbox.EventKey:
switch ev.Key {
case termbox.KeyEsc:
break loop
case termbox.KeyArrowUp, termbox.KeyArrowRight:
switch_output_mode(1)
draw_all()
case termbox.KeyArrowDown, termbox.KeyArrowLeft:
switch_output_mode(-1)
draw_all()
}
case termbox.EventResize:
draw_all()
}
}
}

105
vendor/github.com/nsf/termbox-go/_demos/paint.go generated vendored Normal file
View File

@ -0,0 +1,105 @@
package main
import (
"github.com/nsf/termbox-go"
)
var curCol = 0
var curRune = 0
var backbuf []termbox.Cell
var bbw, bbh int
var runes = []rune{' ', '░', '▒', '▓', '█'}
var colors = []termbox.Attribute{
termbox.ColorBlack,
termbox.ColorRed,
termbox.ColorGreen,
termbox.ColorYellow,
termbox.ColorBlue,
termbox.ColorMagenta,
termbox.ColorCyan,
termbox.ColorWhite,
}
type attrFunc func(int) (rune, termbox.Attribute, termbox.Attribute)
func updateAndDrawButtons(current *int, x, y int, mx, my int, n int, attrf attrFunc) {
lx, ly := x, y
for i := 0; i < n; i++ {
if lx <= mx && mx <= lx+3 && ly <= my && my <= ly+1 {
*current = i
}
r, fg, bg := attrf(i)
termbox.SetCell(lx+0, ly+0, r, fg, bg)
termbox.SetCell(lx+1, ly+0, r, fg, bg)
termbox.SetCell(lx+2, ly+0, r, fg, bg)
termbox.SetCell(lx+3, ly+0, r, fg, bg)
termbox.SetCell(lx+0, ly+1, r, fg, bg)
termbox.SetCell(lx+1, ly+1, r, fg, bg)
termbox.SetCell(lx+2, ly+1, r, fg, bg)
termbox.SetCell(lx+3, ly+1, r, fg, bg)
lx += 4
}
lx, ly = x, y
for i := 0; i < n; i++ {
if *current == i {
fg := termbox.ColorRed | termbox.AttrBold
bg := termbox.ColorDefault
termbox.SetCell(lx+0, ly+2, '^', fg, bg)
termbox.SetCell(lx+1, ly+2, '^', fg, bg)
termbox.SetCell(lx+2, ly+2, '^', fg, bg)
termbox.SetCell(lx+3, ly+2, '^', fg, bg)
}
lx += 4
}
}
func update_and_redraw_all(mx, my int) {
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
if mx != -1 && my != -1 {
backbuf[bbw*my+mx] = termbox.Cell{Ch: runes[curRune], Fg: colors[curCol]}
}
copy(termbox.CellBuffer(), backbuf)
_, h := termbox.Size()
updateAndDrawButtons(&curRune, 0, 0, mx, my, len(runes), func(i int) (rune, termbox.Attribute, termbox.Attribute) {
return runes[i], termbox.ColorDefault, termbox.ColorDefault
})
updateAndDrawButtons(&curCol, 0, h-3, mx, my, len(colors), func(i int) (rune, termbox.Attribute, termbox.Attribute) {
return ' ', termbox.ColorDefault, colors[i]
})
termbox.Flush()
}
func reallocBackBuffer(w, h int) {
bbw, bbh = w, h
backbuf = make([]termbox.Cell, w*h)
}
func main() {
err := termbox.Init()
if err != nil {
panic(err)
}
defer termbox.Close()
termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse)
reallocBackBuffer(termbox.Size())
update_and_redraw_all(-1, -1)
mainloop:
for {
mx, my := -1, -1
switch ev := termbox.PollEvent(); ev.Type {
case termbox.EventKey:
if ev.Key == termbox.KeyEsc {
break mainloop
}
case termbox.EventMouse:
if ev.Key == termbox.MouseLeft {
mx, my = ev.MouseX, ev.MouseY
}
case termbox.EventResize:
reallocBackBuffer(ev.Width, ev.Height)
}
update_and_redraw_all(mx, my)
}
}

View File

@ -0,0 +1,46 @@
package main
import "github.com/nsf/termbox-go"
import "math/rand"
import "time"
func draw() {
w, h := termbox.Size()
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
termbox.SetCell(x, y, ' ', termbox.ColorDefault,
termbox.Attribute(rand.Int()%8)+1)
}
}
termbox.Flush()
}
func main() {
err := termbox.Init()
if err != nil {
panic(err)
}
defer termbox.Close()
event_queue := make(chan termbox.Event)
go func() {
for {
event_queue <- termbox.PollEvent()
}
}()
draw()
loop:
for {
select {
case ev := <-event_queue:
if ev.Type == termbox.EventKey && ev.Key == termbox.KeyEsc {
break loop
}
default:
draw()
time.Sleep(10 * time.Millisecond)
}
}
}

109
vendor/github.com/nsf/termbox-go/_demos/raw_input.go generated vendored Normal file
View File

@ -0,0 +1,109 @@
package main
import (
"fmt"
"github.com/nsf/termbox-go"
"strings"
)
func tbprint(x, y int, fg, bg termbox.Attribute, msg string) {
for _, c := range msg {
termbox.SetCell(x, y, c, fg, bg)
x++
}
}
var current string
var curev termbox.Event
func mouse_button_str(k termbox.Key) string {
switch k {
case termbox.MouseLeft:
return "MouseLeft"
case termbox.MouseMiddle:
return "MouseMiddle"
case termbox.MouseRight:
return "MouseRight"
case termbox.MouseRelease:
return "MouseRelease"
case termbox.MouseWheelUp:
return "MouseWheelUp"
case termbox.MouseWheelDown:
return "MouseWheelDown"
}
return "Key"
}
func mod_str(m termbox.Modifier) string {
var out []string
if m&termbox.ModAlt != 0 {
out = append(out, "ModAlt")
}
if m&termbox.ModMotion != 0 {
out = append(out, "ModMotion")
}
return strings.Join(out, " | ")
}
func redraw_all() {
const coldef = termbox.ColorDefault
termbox.Clear(coldef, coldef)
tbprint(0, 0, termbox.ColorMagenta, coldef, "Press 'q' to quit")
tbprint(0, 1, coldef, coldef, current)
switch curev.Type {
case termbox.EventKey:
tbprint(0, 2, coldef, coldef,
fmt.Sprintf("EventKey: k: %d, c: %c, mod: %s", curev.Key, curev.Ch, mod_str(curev.Mod)))
case termbox.EventMouse:
tbprint(0, 2, coldef, coldef,
fmt.Sprintf("EventMouse: x: %d, y: %d, b: %s, mod: %s",
curev.MouseX, curev.MouseY, mouse_button_str(curev.Key), mod_str(curev.Mod)))
case termbox.EventNone:
tbprint(0, 2, coldef, coldef, "EventNone")
}
tbprint(0, 3, coldef, coldef, fmt.Sprintf("%d", curev.N))
termbox.Flush()
}
func main() {
err := termbox.Init()
if err != nil {
panic(err)
}
defer termbox.Close()
termbox.SetInputMode(termbox.InputAlt | termbox.InputMouse)
redraw_all()
data := make([]byte, 0, 64)
mainloop:
for {
if cap(data)-len(data) < 32 {
newdata := make([]byte, len(data), len(data)+32)
copy(newdata, data)
data = newdata
}
beg := len(data)
d := data[beg : beg+32]
switch ev := termbox.PollRawEvent(d); ev.Type {
case termbox.EventRaw:
data = data[:beg+ev.N]
current = fmt.Sprintf("%q", data)
if current == `"q"` {
break mainloop
}
for {
ev := termbox.ParseEvent(data)
if ev.N == 0 {
break
}
curev = ev
copy(data, data[curev.N:])
data = data[:len(data)-curev.N]
}
case termbox.EventError:
panic(ev.Err)
}
redraw_all()
}
}

457
vendor/github.com/nsf/termbox-go/api.go generated vendored Normal file
View File

@ -0,0 +1,457 @@
// +build !windows
package termbox
import "github.com/mattn/go-runewidth"
import "fmt"
import "os"
import "os/signal"
import "syscall"
import "runtime"
// public API
// Initializes termbox library. This function should be called before any other functions.
// After successful initialization, the library must be finalized using 'Close' function.
//
// Example usage:
// err := termbox.Init()
// if err != nil {
// panic(err)
// }
// defer termbox.Close()
func Init() error {
var err error
out, err = os.OpenFile("/dev/tty", syscall.O_WRONLY, 0)
if err != nil {
return err
}
in, err = syscall.Open("/dev/tty", syscall.O_RDONLY, 0)
if err != nil {
return err
}
err = setup_term()
if err != nil {
return fmt.Errorf("termbox: error while reading terminfo data: %v", err)
}
signal.Notify(sigwinch, syscall.SIGWINCH)
signal.Notify(sigio, syscall.SIGIO)
_, err = fcntl(in, syscall.F_SETFL, syscall.O_ASYNC|syscall.O_NONBLOCK)
if err != nil {
return err
}
_, err = fcntl(in, syscall.F_SETOWN, syscall.Getpid())
if runtime.GOOS != "darwin" && err != nil {
return err
}
err = tcgetattr(out.Fd(), &orig_tios)
if err != nil {
return err
}
tios := orig_tios
tios.Iflag &^= syscall_IGNBRK | syscall_BRKINT | syscall_PARMRK |
syscall_ISTRIP | syscall_INLCR | syscall_IGNCR |
syscall_ICRNL | syscall_IXON
tios.Lflag &^= syscall_ECHO | syscall_ECHONL | syscall_ICANON |
syscall_ISIG | syscall_IEXTEN
tios.Cflag &^= syscall_CSIZE | syscall_PARENB
tios.Cflag |= syscall_CS8
tios.Cc[syscall_VMIN] = 1
tios.Cc[syscall_VTIME] = 0
err = tcsetattr(out.Fd(), &tios)
if err != nil {
return err
}
out.WriteString(funcs[t_enter_ca])
out.WriteString(funcs[t_enter_keypad])
out.WriteString(funcs[t_hide_cursor])
out.WriteString(funcs[t_clear_screen])
termw, termh = get_term_size(out.Fd())
back_buffer.init(termw, termh)
front_buffer.init(termw, termh)
back_buffer.clear()
front_buffer.clear()
go func() {
buf := make([]byte, 128)
for {
select {
case <-sigio:
for {
n, err := syscall.Read(in, buf)
if err == syscall.EAGAIN || err == syscall.EWOULDBLOCK {
break
}
select {
case input_comm <- input_event{buf[:n], err}:
ie := <-input_comm
buf = ie.data[:128]
case <-quit:
return
}
}
case <-quit:
return
}
}
}()
IsInit = true
return nil
}
// Interrupt an in-progress call to PollEvent by causing it to return
// EventInterrupt. Note that this function will block until the PollEvent
// function has successfully been interrupted.
func Interrupt() {
interrupt_comm <- struct{}{}
}
// Finalizes termbox library, should be called after successful initialization
// when termbox's functionality isn't required anymore.
func Close() {
quit <- 1
out.WriteString(funcs[t_show_cursor])
out.WriteString(funcs[t_sgr0])
out.WriteString(funcs[t_clear_screen])
out.WriteString(funcs[t_exit_ca])
out.WriteString(funcs[t_exit_keypad])
out.WriteString(funcs[t_exit_mouse])
tcsetattr(out.Fd(), &orig_tios)
out.Close()
syscall.Close(in)
// reset the state, so that on next Init() it will work again
termw = 0
termh = 0
input_mode = InputEsc
out = nil
in = 0
lastfg = attr_invalid
lastbg = attr_invalid
lastx = coord_invalid
lasty = coord_invalid
cursor_x = cursor_hidden
cursor_y = cursor_hidden
foreground = ColorDefault
background = ColorDefault
IsInit = false
}
// Synchronizes the internal back buffer with the terminal.
func Flush() error {
// invalidate cursor position
lastx = coord_invalid
lasty = coord_invalid
update_size_maybe()
for y := 0; y < front_buffer.height; y++ {
line_offset := y * front_buffer.width
for x := 0; x < front_buffer.width; {
cell_offset := line_offset + x
back := &back_buffer.cells[cell_offset]
front := &front_buffer.cells[cell_offset]
if back.Ch < ' ' {
back.Ch = ' '
}
w := runewidth.RuneWidth(back.Ch)
if w == 0 || w == 2 && runewidth.IsAmbiguousWidth(back.Ch) {
w = 1
}
if *back == *front {
x += w
continue
}
*front = *back
send_attr(back.Fg, back.Bg)
if w == 2 && x == front_buffer.width-1 {
// there's not enough space for 2-cells rune,
// let's just put a space in there
send_char(x, y, ' ')
} else {
send_char(x, y, back.Ch)
if w == 2 {
next := cell_offset + 1
front_buffer.cells[next] = Cell{
Ch: 0,
Fg: back.Fg,
Bg: back.Bg,
}
}
}
x += w
}
}
if !is_cursor_hidden(cursor_x, cursor_y) {
write_cursor(cursor_x, cursor_y)
}
return flush()
}
// Sets the position of the cursor. See also HideCursor().
func SetCursor(x, y int) {
if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) {
outbuf.WriteString(funcs[t_show_cursor])
}
if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) {
outbuf.WriteString(funcs[t_hide_cursor])
}
cursor_x, cursor_y = x, y
if !is_cursor_hidden(cursor_x, cursor_y) {
write_cursor(cursor_x, cursor_y)
}
}
// The shortcut for SetCursor(-1, -1).
func HideCursor() {
SetCursor(cursor_hidden, cursor_hidden)
}
// Changes cell's parameters in the internal back buffer at the specified
// position.
func SetCell(x, y int, ch rune, fg, bg Attribute) {
if x < 0 || x >= back_buffer.width {
return
}
if y < 0 || y >= back_buffer.height {
return
}
back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg}
}
// Returns a slice into the termbox's back buffer. You can get its dimensions
// using 'Size' function. The slice remains valid as long as no 'Clear' or
// 'Flush' function calls were made after call to this function.
func CellBuffer() []Cell {
return back_buffer.cells
}
// After getting a raw event from PollRawEvent function call, you can parse it
// again into an ordinary one using termbox logic. That is parse an event as
// termbox would do it. Returned event in addition to usual Event struct fields
// sets N field to the amount of bytes used within 'data' slice. If the length
// of 'data' slice is zero or event cannot be parsed for some other reason, the
// function will return a special event type: EventNone.
//
// IMPORTANT: EventNone may contain a non-zero N, which means you should skip
// these bytes, because termbox cannot recognize them.
//
// NOTE: This API is experimental and may change in future.
func ParseEvent(data []byte) Event {
event := Event{Type: EventKey}
ok := extract_event(data, &event)
if !ok {
return Event{Type: EventNone, N: event.N}
}
return event
}
// Wait for an event and return it. This is a blocking function call. Instead
// of EventKey and EventMouse it returns EventRaw events. Raw event is written
// into `data` slice and Event's N field is set to the amount of bytes written.
// The minimum required length of the 'data' slice is 1. This requirement may
// vary on different platforms.
//
// NOTE: This API is experimental and may change in future.
func PollRawEvent(data []byte) Event {
if len(data) == 0 {
panic("len(data) >= 1 is a requirement")
}
var event Event
if extract_raw_event(data, &event) {
return event
}
for {
select {
case ev := <-input_comm:
if ev.err != nil {
return Event{Type: EventError, Err: ev.err}
}
inbuf = append(inbuf, ev.data...)
input_comm <- ev
if extract_raw_event(data, &event) {
return event
}
case <-interrupt_comm:
event.Type = EventInterrupt
return event
case <-sigwinch:
event.Type = EventResize
event.Width, event.Height = get_term_size(out.Fd())
return event
}
}
}
// Wait for an event and return it. This is a blocking function call.
func PollEvent() Event {
var event Event
// try to extract event from input buffer, return on success
event.Type = EventKey
ok := extract_event(inbuf, &event)
if event.N != 0 {
copy(inbuf, inbuf[event.N:])
inbuf = inbuf[:len(inbuf)-event.N]
}
if ok {
return event
}
for {
select {
case ev := <-input_comm:
if ev.err != nil {
return Event{Type: EventError, Err: ev.err}
}
inbuf = append(inbuf, ev.data...)
input_comm <- ev
ok := extract_event(inbuf, &event)
if event.N != 0 {
copy(inbuf, inbuf[event.N:])
inbuf = inbuf[:len(inbuf)-event.N]
}
if ok {
return event
}
case <-interrupt_comm:
event.Type = EventInterrupt
return event
case <-sigwinch:
event.Type = EventResize
event.Width, event.Height = get_term_size(out.Fd())
return event
}
}
}
// Returns the size of the internal back buffer (which is mostly the same as
// terminal's window size in characters). But it doesn't always match the size
// of the terminal window, after the terminal size has changed, the internal
// back buffer will get in sync only after Clear or Flush function calls.
func Size() (width int, height int) {
return termw, termh
}
// Clears the internal back buffer.
func Clear(fg, bg Attribute) error {
foreground, background = fg, bg
err := update_size_maybe()
back_buffer.clear()
return err
}
// Sets termbox input mode. Termbox has two input modes:
//
// 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC means KeyEsc. This is the default input mode.
//
// 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC enables ModAlt modifier for the next keyboard event.
//
// Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will
// enable mouse button press/release and drag events.
//
// If 'mode' is InputCurrent, returns the current input mode. See also Input*
// constants.
func SetInputMode(mode InputMode) InputMode {
if mode == InputCurrent {
return input_mode
}
if mode&(InputEsc|InputAlt) == 0 {
mode |= InputEsc
}
if mode&(InputEsc|InputAlt) == InputEsc|InputAlt {
mode &^= InputAlt
}
if mode&InputMouse != 0 {
out.WriteString(funcs[t_enter_mouse])
} else {
out.WriteString(funcs[t_exit_mouse])
}
input_mode = mode
return input_mode
}
// Sets the termbox output mode. Termbox has four output options:
//
// 1. OutputNormal => [1..8]
// This mode provides 8 different colors:
// black, red, green, yellow, blue, magenta, cyan, white
// Shortcut: ColorBlack, ColorRed, ...
// Attributes: AttrBold, AttrUnderline, AttrReverse
//
// Example usage:
// SetCell(x, y, '@', ColorBlack | AttrBold, ColorRed);
//
// 2. Output256 => [1..256]
// In this mode you can leverage the 256 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
//
// Example usage:
// SetCell(x, y, '@', 184, 240);
// SetCell(x, y, '@', 0xb8, 0xf0);
//
// 3. Output216 => [1..216]
// This mode supports the 3rd range of the 256 mode only.
// But you dont need to provide an offset.
//
// 4. OutputGrayscale => [1..26]
// This mode supports the 4th range of the 256 mode
// and black and white colors from 3th range of the 256 mode
// But you dont need to provide an offset.
//
// In all modes, 0x00 represents the default color.
//
// `go run _demos/output.go` to see its impact on your terminal.
//
// If 'mode' is OutputCurrent, it returns the current output mode.
//
// Note that this may return a different OutputMode than the one requested,
// as the requested mode may not be available on the target platform.
func SetOutputMode(mode OutputMode) OutputMode {
if mode == OutputCurrent {
return output_mode
}
output_mode = mode
return output_mode
}
// Sync comes handy when something causes desync between termbox's understanding
// of a terminal buffer and the reality. Such as a third party process. Sync
// forces a complete resync between the termbox and a terminal, it may not be
// visually pretty though.
func Sync() error {
front_buffer.clear()
err := send_clear()
if err != nil {
return err
}
return Flush()
}

187
vendor/github.com/nsf/termbox-go/api_common.go generated vendored Normal file
View File

@ -0,0 +1,187 @@
// termbox is a library for creating cross-platform text-based interfaces
package termbox
// public API, common OS agnostic part
type (
InputMode int
OutputMode int
EventType uint8
Modifier uint8
Key uint16
Attribute uint16
)
// This type represents a termbox event. The 'Mod', 'Key' and 'Ch' fields are
// valid if 'Type' is EventKey. The 'Width' and 'Height' fields are valid if
// 'Type' is EventResize. The 'Err' field is valid if 'Type' is EventError.
type Event struct {
Type EventType // one of Event* constants
Mod Modifier // one of Mod* constants or 0
Key Key // one of Key* constants, invalid if 'Ch' is not 0
Ch rune // a unicode character
Width int // width of the screen
Height int // height of the screen
Err error // error in case if input failed
MouseX int // x coord of mouse
MouseY int // y coord of mouse
N int // number of bytes written when getting a raw event
}
// A cell, single conceptual entity on the screen. The screen is basically a 2d
// array of cells. 'Ch' is a unicode character, 'Fg' and 'Bg' are foreground
// and background attributes respectively.
type Cell struct {
Ch rune
Fg Attribute
Bg Attribute
}
// To know if termbox has been initialized or not
var (
IsInit bool = false
)
// Key constants, see Event.Key field.
const (
KeyF1 Key = 0xFFFF - iota
KeyF2
KeyF3
KeyF4
KeyF5
KeyF6
KeyF7
KeyF8
KeyF9
KeyF10
KeyF11
KeyF12
KeyInsert
KeyDelete
KeyHome
KeyEnd
KeyPgup
KeyPgdn
KeyArrowUp
KeyArrowDown
KeyArrowLeft
KeyArrowRight
key_min // see terminfo
MouseLeft
MouseMiddle
MouseRight
MouseRelease
MouseWheelUp
MouseWheelDown
)
const (
KeyCtrlTilde Key = 0x00
KeyCtrl2 Key = 0x00
KeyCtrlSpace Key = 0x00
KeyCtrlA Key = 0x01
KeyCtrlB Key = 0x02
KeyCtrlC Key = 0x03
KeyCtrlD Key = 0x04
KeyCtrlE Key = 0x05
KeyCtrlF Key = 0x06
KeyCtrlG Key = 0x07
KeyBackspace Key = 0x08
KeyCtrlH Key = 0x08
KeyTab Key = 0x09
KeyCtrlI Key = 0x09
KeyCtrlJ Key = 0x0A
KeyCtrlK Key = 0x0B
KeyCtrlL Key = 0x0C
KeyEnter Key = 0x0D
KeyCtrlM Key = 0x0D
KeyCtrlN Key = 0x0E
KeyCtrlO Key = 0x0F
KeyCtrlP Key = 0x10
KeyCtrlQ Key = 0x11
KeyCtrlR Key = 0x12
KeyCtrlS Key = 0x13
KeyCtrlT Key = 0x14
KeyCtrlU Key = 0x15
KeyCtrlV Key = 0x16
KeyCtrlW Key = 0x17
KeyCtrlX Key = 0x18
KeyCtrlY Key = 0x19
KeyCtrlZ Key = 0x1A
KeyEsc Key = 0x1B
KeyCtrlLsqBracket Key = 0x1B
KeyCtrl3 Key = 0x1B
KeyCtrl4 Key = 0x1C
KeyCtrlBackslash Key = 0x1C
KeyCtrl5 Key = 0x1D
KeyCtrlRsqBracket Key = 0x1D
KeyCtrl6 Key = 0x1E
KeyCtrl7 Key = 0x1F
KeyCtrlSlash Key = 0x1F
KeyCtrlUnderscore Key = 0x1F
KeySpace Key = 0x20
KeyBackspace2 Key = 0x7F
KeyCtrl8 Key = 0x7F
)
// Alt modifier constant, see Event.Mod field and SetInputMode function.
const (
ModAlt Modifier = 1 << iota
ModMotion
)
// Cell colors, you can combine a color with multiple attributes using bitwise
// OR ('|').
const (
ColorDefault Attribute = iota
ColorBlack
ColorRed
ColorGreen
ColorYellow
ColorBlue
ColorMagenta
ColorCyan
ColorWhite
)
// Cell attributes, it is possible to use multiple attributes by combining them
// using bitwise OR ('|'). Although, colors cannot be combined. But you can
// combine attributes and a single color.
//
// It's worth mentioning that some platforms don't support certain attibutes.
// For example windows console doesn't support AttrUnderline. And on some
// terminals applying AttrBold to background may result in blinking text. Use
// them with caution and test your code on various terminals.
const (
AttrBold Attribute = 1 << (iota + 9)
AttrUnderline
AttrReverse
)
// Input mode. See SetInputMode function.
const (
InputEsc InputMode = 1 << iota
InputAlt
InputMouse
InputCurrent InputMode = 0
)
// Output mode. See SetOutputMode function.
const (
OutputCurrent OutputMode = iota
OutputNormal
Output256
Output216
OutputGrayscale
)
// Event type. See Event.Type field.
const (
EventKey EventType = iota
EventResize
EventMouse
EventError
EventInterrupt
EventRaw
EventNone
)

239
vendor/github.com/nsf/termbox-go/api_windows.go generated vendored Normal file
View File

@ -0,0 +1,239 @@
package termbox
import (
"syscall"
)
// public API
// Initializes termbox library. This function should be called before any other functions.
// After successful initialization, the library must be finalized using 'Close' function.
//
// Example usage:
// err := termbox.Init()
// if err != nil {
// panic(err)
// }
// defer termbox.Close()
func Init() error {
var err error
interrupt, err = create_event()
if err != nil {
return err
}
in, err = syscall.Open("CONIN$", syscall.O_RDWR, 0)
if err != nil {
return err
}
out, err = syscall.Open("CONOUT$", syscall.O_RDWR, 0)
if err != nil {
return err
}
err = get_console_mode(in, &orig_mode)
if err != nil {
return err
}
err = set_console_mode(in, enable_window_input)
if err != nil {
return err
}
orig_size = get_term_size(out)
win_size := get_win_size(out)
err = set_console_screen_buffer_size(out, win_size)
if err != nil {
return err
}
err = get_console_cursor_info(out, &orig_cursor_info)
if err != nil {
return err
}
show_cursor(false)
term_size = get_term_size(out)
back_buffer.init(int(term_size.x), int(term_size.y))
front_buffer.init(int(term_size.x), int(term_size.y))
back_buffer.clear()
front_buffer.clear()
clear()
diffbuf = make([]diff_msg, 0, 32)
go input_event_producer()
IsInit = true
return nil
}
// Finalizes termbox library, should be called after successful initialization
// when termbox's functionality isn't required anymore.
func Close() {
// we ignore errors here, because we can't really do anything about them
Clear(0, 0)
Flush()
// stop event producer
cancel_comm <- true
set_event(interrupt)
select {
case <-input_comm:
default:
}
<-cancel_done_comm
set_console_cursor_info(out, &orig_cursor_info)
set_console_cursor_position(out, coord{})
set_console_screen_buffer_size(out, orig_size)
set_console_mode(in, orig_mode)
syscall.Close(in)
syscall.Close(out)
syscall.Close(interrupt)
IsInit = false
}
// Interrupt an in-progress call to PollEvent by causing it to return
// EventInterrupt. Note that this function will block until the PollEvent
// function has successfully been interrupted.
func Interrupt() {
interrupt_comm <- struct{}{}
}
// Synchronizes the internal back buffer with the terminal.
func Flush() error {
update_size_maybe()
prepare_diff_messages()
for _, diff := range diffbuf {
r := small_rect{
left: 0,
top: diff.pos,
right: term_size.x - 1,
bottom: diff.pos + diff.lines - 1,
}
write_console_output(out, diff.chars, r)
}
if !is_cursor_hidden(cursor_x, cursor_y) {
move_cursor(cursor_x, cursor_y)
}
return nil
}
// Sets the position of the cursor. See also HideCursor().
func SetCursor(x, y int) {
if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) {
show_cursor(true)
}
if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) {
show_cursor(false)
}
cursor_x, cursor_y = x, y
if !is_cursor_hidden(cursor_x, cursor_y) {
move_cursor(cursor_x, cursor_y)
}
}
// The shortcut for SetCursor(-1, -1).
func HideCursor() {
SetCursor(cursor_hidden, cursor_hidden)
}
// Changes cell's parameters in the internal back buffer at the specified
// position.
func SetCell(x, y int, ch rune, fg, bg Attribute) {
if x < 0 || x >= back_buffer.width {
return
}
if y < 0 || y >= back_buffer.height {
return
}
back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg}
}
// Returns a slice into the termbox's back buffer. You can get its dimensions
// using 'Size' function. The slice remains valid as long as no 'Clear' or
// 'Flush' function calls were made after call to this function.
func CellBuffer() []Cell {
return back_buffer.cells
}
// Wait for an event and return it. This is a blocking function call.
func PollEvent() Event {
select {
case ev := <-input_comm:
return ev
case <-interrupt_comm:
return Event{Type: EventInterrupt}
}
}
// Returns the size of the internal back buffer (which is mostly the same as
// console's window size in characters). But it doesn't always match the size
// of the console window, after the console size has changed, the internal back
// buffer will get in sync only after Clear or Flush function calls.
func Size() (int, int) {
return int(term_size.x), int(term_size.y)
}
// Clears the internal back buffer.
func Clear(fg, bg Attribute) error {
foreground, background = fg, bg
update_size_maybe()
back_buffer.clear()
return nil
}
// Sets termbox input mode. Termbox has two input modes:
//
// 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC means KeyEsc. This is the default input mode.
//
// 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC enables ModAlt modifier for the next keyboard event.
//
// Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will
// enable mouse button press/release and drag events.
//
// If 'mode' is InputCurrent, returns the current input mode. See also Input*
// constants.
func SetInputMode(mode InputMode) InputMode {
if mode == InputCurrent {
return input_mode
}
if mode&InputMouse != 0 {
err := set_console_mode(in, enable_window_input|enable_mouse_input|enable_extended_flags)
if err != nil {
panic(err)
}
} else {
err := set_console_mode(in, enable_window_input)
if err != nil {
panic(err)
}
}
input_mode = mode
return input_mode
}
// Sets the termbox output mode.
//
// Windows console does not support extra colour modes,
// so this will always set and return OutputNormal.
func SetOutputMode(mode OutputMode) OutputMode {
return OutputNormal
}
// Sync comes handy when something causes desync between termbox's understanding
// of a terminal buffer and the reality. Such as a third party process. Sync
// forces a complete resync between the termbox and a terminal, it may not be
// visually pretty though. At the moment on Windows it does nothing.
func Sync() error {
return nil
}

110
vendor/github.com/nsf/termbox-go/collect_terminfo.py generated vendored Executable file
View File

@ -0,0 +1,110 @@
#!/usr/bin/env python
import sys, os, subprocess
def escaped(s):
return repr(s)[1:-1]
def tput(term, name):
try:
return subprocess.check_output(['tput', '-T%s' % term, name]).decode()
except subprocess.CalledProcessError as e:
return e.output.decode()
def w(s):
if s == None:
return
sys.stdout.write(s)
terminals = {
'xterm' : 'xterm',
'rxvt-256color' : 'rxvt_256color',
'rxvt-unicode' : 'rxvt_unicode',
'linux' : 'linux',
'Eterm' : 'eterm',
'screen' : 'screen'
}
keys = [
"F1", "kf1",
"F2", "kf2",
"F3", "kf3",
"F4", "kf4",
"F5", "kf5",
"F6", "kf6",
"F7", "kf7",
"F8", "kf8",
"F9", "kf9",
"F10", "kf10",
"F11", "kf11",
"F12", "kf12",
"INSERT", "kich1",
"DELETE", "kdch1",
"HOME", "khome",
"END", "kend",
"PGUP", "kpp",
"PGDN", "knp",
"KEY_UP", "kcuu1",
"KEY_DOWN", "kcud1",
"KEY_LEFT", "kcub1",
"KEY_RIGHT", "kcuf1"
]
funcs = [
"T_ENTER_CA", "smcup",
"T_EXIT_CA", "rmcup",
"T_SHOW_CURSOR", "cnorm",
"T_HIDE_CURSOR", "civis",
"T_CLEAR_SCREEN", "clear",
"T_SGR0", "sgr0",
"T_UNDERLINE", "smul",
"T_BOLD", "bold",
"T_BLINK", "blink",
"T_REVERSE", "rev",
"T_ENTER_KEYPAD", "smkx",
"T_EXIT_KEYPAD", "rmkx"
]
def iter_pairs(iterable):
iterable = iter(iterable)
while True:
yield (next(iterable), next(iterable))
def do_term(term, nick):
w("// %s\n" % term)
w("var %s_keys = []string{\n\t" % nick)
for k, v in iter_pairs(keys):
w('"')
w(escaped(tput(term, v)))
w('",')
w("\n}\n")
w("var %s_funcs = []string{\n\t" % nick)
for k,v in iter_pairs(funcs):
w('"')
if v == "sgr":
w("\\033[3%d;4%dm")
elif v == "cup":
w("\\033[%d;%dH")
else:
w(escaped(tput(term, v)))
w('", ')
w("\n}\n\n")
def do_terms(d):
w("var terms = []struct {\n")
w("\tname string\n")
w("\tkeys []string\n")
w("\tfuncs []string\n")
w("}{\n")
for k, v in d.items():
w('\t{"%s", %s_keys, %s_funcs},\n' % (k, v, v))
w("}\n\n")
w("// +build !windows\n\npackage termbox\n\n")
for k,v in terminals.items():
do_term(k, v)
do_terms(terminals)

39
vendor/github.com/nsf/termbox-go/syscalls.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// +build ignore
package termbox
/*
#include <termios.h>
#include <sys/ioctl.h>
*/
import "C"
type syscall_Termios C.struct_termios
const (
syscall_IGNBRK = C.IGNBRK
syscall_BRKINT = C.BRKINT
syscall_PARMRK = C.PARMRK
syscall_ISTRIP = C.ISTRIP
syscall_INLCR = C.INLCR
syscall_IGNCR = C.IGNCR
syscall_ICRNL = C.ICRNL
syscall_IXON = C.IXON
syscall_OPOST = C.OPOST
syscall_ECHO = C.ECHO
syscall_ECHONL = C.ECHONL
syscall_ICANON = C.ICANON
syscall_ISIG = C.ISIG
syscall_IEXTEN = C.IEXTEN
syscall_CSIZE = C.CSIZE
syscall_PARENB = C.PARENB
syscall_CS8 = C.CS8
syscall_VMIN = C.VMIN
syscall_VTIME = C.VTIME
// on darwin change these to (on *bsd too?):
// C.TIOCGETA
// C.TIOCSETA
syscall_TCGETS = C.TCGETS
syscall_TCSETS = C.TCSETS
)

41
vendor/github.com/nsf/termbox-go/syscalls_darwin.go generated vendored Normal file
View File

@ -0,0 +1,41 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs syscalls.go
// +build !amd64
package termbox
type syscall_Termios struct {
Iflag uint32
Oflag uint32
Cflag uint32
Lflag uint32
Cc [20]uint8
Ispeed uint32
Ospeed uint32
}
const (
syscall_IGNBRK = 0x1
syscall_BRKINT = 0x2
syscall_PARMRK = 0x8
syscall_ISTRIP = 0x20
syscall_INLCR = 0x40
syscall_IGNCR = 0x80
syscall_ICRNL = 0x100
syscall_IXON = 0x200
syscall_OPOST = 0x1
syscall_ECHO = 0x8
syscall_ECHONL = 0x10
syscall_ICANON = 0x100
syscall_ISIG = 0x80
syscall_IEXTEN = 0x400
syscall_CSIZE = 0x300
syscall_PARENB = 0x1000
syscall_CS8 = 0x300
syscall_VMIN = 0x10
syscall_VTIME = 0x11
syscall_TCGETS = 0x402c7413
syscall_TCSETS = 0x802c7414
)

View File

@ -0,0 +1,40 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs syscalls.go
package termbox
type syscall_Termios struct {
Iflag uint64
Oflag uint64
Cflag uint64
Lflag uint64
Cc [20]uint8
Pad_cgo_0 [4]byte
Ispeed uint64
Ospeed uint64
}
const (
syscall_IGNBRK = 0x1
syscall_BRKINT = 0x2
syscall_PARMRK = 0x8
syscall_ISTRIP = 0x20
syscall_INLCR = 0x40
syscall_IGNCR = 0x80
syscall_ICRNL = 0x100
syscall_IXON = 0x200
syscall_OPOST = 0x1
syscall_ECHO = 0x8
syscall_ECHONL = 0x10
syscall_ICANON = 0x100
syscall_ISIG = 0x80
syscall_IEXTEN = 0x400
syscall_CSIZE = 0x300
syscall_PARENB = 0x1000
syscall_CS8 = 0x300
syscall_VMIN = 0x10
syscall_VTIME = 0x11
syscall_TCGETS = 0x40487413
syscall_TCSETS = 0x80487414
)

39
vendor/github.com/nsf/termbox-go/syscalls_dragonfly.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs syscalls.go
package termbox
type syscall_Termios struct {
Iflag uint32
Oflag uint32
Cflag uint32
Lflag uint32
Cc [20]uint8
Ispeed uint32
Ospeed uint32
}
const (
syscall_IGNBRK = 0x1
syscall_BRKINT = 0x2
syscall_PARMRK = 0x8
syscall_ISTRIP = 0x20
syscall_INLCR = 0x40
syscall_IGNCR = 0x80
syscall_ICRNL = 0x100
syscall_IXON = 0x200
syscall_OPOST = 0x1
syscall_ECHO = 0x8
syscall_ECHONL = 0x10
syscall_ICANON = 0x100
syscall_ISIG = 0x80
syscall_IEXTEN = 0x400
syscall_CSIZE = 0x300
syscall_PARENB = 0x1000
syscall_CS8 = 0x300
syscall_VMIN = 0x10
syscall_VTIME = 0x11
syscall_TCGETS = 0x402c7413
syscall_TCSETS = 0x802c7414
)

39
vendor/github.com/nsf/termbox-go/syscalls_freebsd.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs syscalls.go
package termbox
type syscall_Termios struct {
Iflag uint32
Oflag uint32
Cflag uint32
Lflag uint32
Cc [20]uint8
Ispeed uint32
Ospeed uint32
}
const (
syscall_IGNBRK = 0x1
syscall_BRKINT = 0x2
syscall_PARMRK = 0x8
syscall_ISTRIP = 0x20
syscall_INLCR = 0x40
syscall_IGNCR = 0x80
syscall_ICRNL = 0x100
syscall_IXON = 0x200
syscall_OPOST = 0x1
syscall_ECHO = 0x8
syscall_ECHONL = 0x10
syscall_ICANON = 0x100
syscall_ISIG = 0x80
syscall_IEXTEN = 0x400
syscall_CSIZE = 0x300
syscall_PARENB = 0x1000
syscall_CS8 = 0x300
syscall_VMIN = 0x10
syscall_VTIME = 0x11
syscall_TCGETS = 0x402c7413
syscall_TCSETS = 0x802c7414
)

33
vendor/github.com/nsf/termbox-go/syscalls_linux.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs syscalls.go
package termbox
import "syscall"
type syscall_Termios syscall.Termios
const (
syscall_IGNBRK = syscall.IGNBRK
syscall_BRKINT = syscall.BRKINT
syscall_PARMRK = syscall.PARMRK
syscall_ISTRIP = syscall.ISTRIP
syscall_INLCR = syscall.INLCR
syscall_IGNCR = syscall.IGNCR
syscall_ICRNL = syscall.ICRNL
syscall_IXON = syscall.IXON
syscall_OPOST = syscall.OPOST
syscall_ECHO = syscall.ECHO
syscall_ECHONL = syscall.ECHONL
syscall_ICANON = syscall.ICANON
syscall_ISIG = syscall.ISIG
syscall_IEXTEN = syscall.IEXTEN
syscall_CSIZE = syscall.CSIZE
syscall_PARENB = syscall.PARENB
syscall_CS8 = syscall.CS8
syscall_VMIN = syscall.VMIN
syscall_VTIME = syscall.VTIME
syscall_TCGETS = syscall.TCGETS
syscall_TCSETS = syscall.TCSETS
)

39
vendor/github.com/nsf/termbox-go/syscalls_netbsd.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs syscalls.go
package termbox
type syscall_Termios struct {
Iflag uint32
Oflag uint32
Cflag uint32
Lflag uint32
Cc [20]uint8
Ispeed int32
Ospeed int32
}
const (
syscall_IGNBRK = 0x1
syscall_BRKINT = 0x2
syscall_PARMRK = 0x8
syscall_ISTRIP = 0x20
syscall_INLCR = 0x40
syscall_IGNCR = 0x80
syscall_ICRNL = 0x100
syscall_IXON = 0x200
syscall_OPOST = 0x1
syscall_ECHO = 0x8
syscall_ECHONL = 0x10
syscall_ICANON = 0x100
syscall_ISIG = 0x80
syscall_IEXTEN = 0x400
syscall_CSIZE = 0x300
syscall_PARENB = 0x1000
syscall_CS8 = 0x300
syscall_VMIN = 0x10
syscall_VTIME = 0x11
syscall_TCGETS = 0x402c7413
syscall_TCSETS = 0x802c7414
)

39
vendor/github.com/nsf/termbox-go/syscalls_openbsd.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs syscalls.go
package termbox
type syscall_Termios struct {
Iflag uint32
Oflag uint32
Cflag uint32
Lflag uint32
Cc [20]uint8
Ispeed int32
Ospeed int32
}
const (
syscall_IGNBRK = 0x1
syscall_BRKINT = 0x2
syscall_PARMRK = 0x8
syscall_ISTRIP = 0x20
syscall_INLCR = 0x40
syscall_IGNCR = 0x80
syscall_ICRNL = 0x100
syscall_IXON = 0x200
syscall_OPOST = 0x1
syscall_ECHO = 0x8
syscall_ECHONL = 0x10
syscall_ICANON = 0x100
syscall_ISIG = 0x80
syscall_IEXTEN = 0x400
syscall_CSIZE = 0x300
syscall_PARENB = 0x1000
syscall_CS8 = 0x300
syscall_VMIN = 0x10
syscall_VTIME = 0x11
syscall_TCGETS = 0x402c7413
syscall_TCSETS = 0x802c7414
)

61
vendor/github.com/nsf/termbox-go/syscalls_windows.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs -- -DUNICODE syscalls.go
package termbox
const (
foreground_blue = 0x1
foreground_green = 0x2
foreground_red = 0x4
foreground_intensity = 0x8
background_blue = 0x10
background_green = 0x20
background_red = 0x40
background_intensity = 0x80
std_input_handle = -0xa
std_output_handle = -0xb
key_event = 0x1
mouse_event = 0x2
window_buffer_size_event = 0x4
enable_window_input = 0x8
enable_mouse_input = 0x10
enable_extended_flags = 0x80
vk_f1 = 0x70
vk_f2 = 0x71
vk_f3 = 0x72
vk_f4 = 0x73
vk_f5 = 0x74
vk_f6 = 0x75
vk_f7 = 0x76
vk_f8 = 0x77
vk_f9 = 0x78
vk_f10 = 0x79
vk_f11 = 0x7a
vk_f12 = 0x7b
vk_insert = 0x2d
vk_delete = 0x2e
vk_home = 0x24
vk_end = 0x23
vk_pgup = 0x21
vk_pgdn = 0x22
vk_arrow_up = 0x26
vk_arrow_down = 0x28
vk_arrow_left = 0x25
vk_arrow_right = 0x27
vk_backspace = 0x8
vk_tab = 0x9
vk_enter = 0xd
vk_esc = 0x1b
vk_space = 0x20
left_alt_pressed = 0x2
left_ctrl_pressed = 0x8
right_alt_pressed = 0x1
right_ctrl_pressed = 0x4
shift_pressed = 0x10
generic_read = 0x80000000
generic_write = 0x40000000
console_textmode_buffer = 0x1
)

511
vendor/github.com/nsf/termbox-go/termbox.go generated vendored Normal file
View File

@ -0,0 +1,511 @@
// +build !windows
package termbox
import "unicode/utf8"
import "bytes"
import "syscall"
import "unsafe"
import "strings"
import "strconv"
import "os"
import "io"
// private API
const (
t_enter_ca = iota
t_exit_ca
t_show_cursor
t_hide_cursor
t_clear_screen
t_sgr0
t_underline
t_bold
t_blink
t_reverse
t_enter_keypad
t_exit_keypad
t_enter_mouse
t_exit_mouse
t_max_funcs
)
const (
coord_invalid = -2
attr_invalid = Attribute(0xFFFF)
)
type input_event struct {
data []byte
err error
}
var (
// term specific sequences
keys []string
funcs []string
// termbox inner state
orig_tios syscall_Termios
back_buffer cellbuf
front_buffer cellbuf
termw int
termh int
input_mode = InputEsc
output_mode = OutputNormal
out *os.File
in int
lastfg = attr_invalid
lastbg = attr_invalid
lastx = coord_invalid
lasty = coord_invalid
cursor_x = cursor_hidden
cursor_y = cursor_hidden
foreground = ColorDefault
background = ColorDefault
inbuf = make([]byte, 0, 64)
outbuf bytes.Buffer
sigwinch = make(chan os.Signal, 1)
sigio = make(chan os.Signal, 1)
quit = make(chan int)
input_comm = make(chan input_event)
interrupt_comm = make(chan struct{})
intbuf = make([]byte, 0, 16)
// grayscale indexes
grayscale = []Attribute{
0, 17, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 232,
}
)
func write_cursor(x, y int) {
outbuf.WriteString("\033[")
outbuf.Write(strconv.AppendUint(intbuf, uint64(y+1), 10))
outbuf.WriteString(";")
outbuf.Write(strconv.AppendUint(intbuf, uint64(x+1), 10))
outbuf.WriteString("H")
}
func write_sgr_fg(a Attribute) {
switch output_mode {
case Output256, Output216, OutputGrayscale:
outbuf.WriteString("\033[38;5;")
outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10))
outbuf.WriteString("m")
default:
outbuf.WriteString("\033[3")
outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10))
outbuf.WriteString("m")
}
}
func write_sgr_bg(a Attribute) {
switch output_mode {
case Output256, Output216, OutputGrayscale:
outbuf.WriteString("\033[48;5;")
outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10))
outbuf.WriteString("m")
default:
outbuf.WriteString("\033[4")
outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10))
outbuf.WriteString("m")
}
}
func write_sgr(fg, bg Attribute) {
switch output_mode {
case Output256, Output216, OutputGrayscale:
outbuf.WriteString("\033[38;5;")
outbuf.Write(strconv.AppendUint(intbuf, uint64(fg-1), 10))
outbuf.WriteString("m")
outbuf.WriteString("\033[48;5;")
outbuf.Write(strconv.AppendUint(intbuf, uint64(bg-1), 10))
outbuf.WriteString("m")
default:
outbuf.WriteString("\033[3")
outbuf.Write(strconv.AppendUint(intbuf, uint64(fg-1), 10))
outbuf.WriteString(";4")
outbuf.Write(strconv.AppendUint(intbuf, uint64(bg-1), 10))
outbuf.WriteString("m")
}
}
type winsize struct {
rows uint16
cols uint16
xpixels uint16
ypixels uint16
}
func get_term_size(fd uintptr) (int, int) {
var sz winsize
_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
return int(sz.cols), int(sz.rows)
}
func send_attr(fg, bg Attribute) {
if fg == lastfg && bg == lastbg {
return
}
outbuf.WriteString(funcs[t_sgr0])
var fgcol, bgcol Attribute
switch output_mode {
case Output256:
fgcol = fg & 0x1FF
bgcol = bg & 0x1FF
case Output216:
fgcol = fg & 0xFF
bgcol = bg & 0xFF
if fgcol > 216 {
fgcol = ColorDefault
}
if bgcol > 216 {
bgcol = ColorDefault
}
if fgcol != ColorDefault {
fgcol += 0x10
}
if bgcol != ColorDefault {
bgcol += 0x10
}
case OutputGrayscale:
fgcol = fg & 0x1F
bgcol = bg & 0x1F
if fgcol > 26 {
fgcol = ColorDefault
}
if bgcol > 26 {
bgcol = ColorDefault
}
if fgcol != ColorDefault {
fgcol = grayscale[fgcol]
}
if bgcol != ColorDefault {
bgcol = grayscale[bgcol]
}
default:
fgcol = fg & 0x0F
bgcol = bg & 0x0F
}
if fgcol != ColorDefault {
if bgcol != ColorDefault {
write_sgr(fgcol, bgcol)
} else {
write_sgr_fg(fgcol)
}
} else if bgcol != ColorDefault {
write_sgr_bg(bgcol)
}
if fg&AttrBold != 0 {
outbuf.WriteString(funcs[t_bold])
}
if bg&AttrBold != 0 {
outbuf.WriteString(funcs[t_blink])
}
if fg&AttrUnderline != 0 {
outbuf.WriteString(funcs[t_underline])
}
if fg&AttrReverse|bg&AttrReverse != 0 {
outbuf.WriteString(funcs[t_reverse])
}
lastfg, lastbg = fg, bg
}
func send_char(x, y int, ch rune) {
var buf [8]byte
n := utf8.EncodeRune(buf[:], ch)
if x-1 != lastx || y != lasty {
write_cursor(x, y)
}
lastx, lasty = x, y
outbuf.Write(buf[:n])
}
func flush() error {
_, err := io.Copy(out, &outbuf)
outbuf.Reset()
return err
}
func send_clear() error {
send_attr(foreground, background)
outbuf.WriteString(funcs[t_clear_screen])
if !is_cursor_hidden(cursor_x, cursor_y) {
write_cursor(cursor_x, cursor_y)
}
// we need to invalidate cursor position too and these two vars are
// used only for simple cursor positioning optimization, cursor
// actually may be in the correct place, but we simply discard
// optimization once and it gives us simple solution for the case when
// cursor moved
lastx = coord_invalid
lasty = coord_invalid
return flush()
}
func update_size_maybe() error {
w, h := get_term_size(out.Fd())
if w != termw || h != termh {
termw, termh = w, h
back_buffer.resize(termw, termh)
front_buffer.resize(termw, termh)
front_buffer.clear()
return send_clear()
}
return nil
}
func tcsetattr(fd uintptr, termios *syscall_Termios) error {
r, _, e := syscall.Syscall(syscall.SYS_IOCTL,
fd, uintptr(syscall_TCSETS), uintptr(unsafe.Pointer(termios)))
if r != 0 {
return os.NewSyscallError("SYS_IOCTL", e)
}
return nil
}
func tcgetattr(fd uintptr, termios *syscall_Termios) error {
r, _, e := syscall.Syscall(syscall.SYS_IOCTL,
fd, uintptr(syscall_TCGETS), uintptr(unsafe.Pointer(termios)))
if r != 0 {
return os.NewSyscallError("SYS_IOCTL", e)
}
return nil
}
func parse_mouse_event(event *Event, buf string) (int, bool) {
if strings.HasPrefix(buf, "\033[M") && len(buf) >= 6 {
// X10 mouse encoding, the simplest one
// \033 [ M Cb Cx Cy
b := buf[3] - 32
switch b & 3 {
case 0:
if b&64 != 0 {
event.Key = MouseWheelUp
} else {
event.Key = MouseLeft
}
case 1:
if b&64 != 0 {
event.Key = MouseWheelDown
} else {
event.Key = MouseMiddle
}
case 2:
event.Key = MouseRight
case 3:
event.Key = MouseRelease
default:
return 6, false
}
event.Type = EventMouse // KeyEvent by default
if b&32 != 0 {
event.Mod |= ModMotion
}
// the coord is 1,1 for upper left
event.MouseX = int(buf[4]) - 1 - 32
event.MouseY = int(buf[5]) - 1 - 32
return 6, true
} else if strings.HasPrefix(buf, "\033[<") || strings.HasPrefix(buf, "\033[") {
// xterm 1006 extended mode or urxvt 1015 extended mode
// xterm: \033 [ < Cb ; Cx ; Cy (M or m)
// urxvt: \033 [ Cb ; Cx ; Cy M
// find the first M or m, that's where we stop
mi := strings.IndexAny(buf, "Mm")
if mi == -1 {
return 0, false
}
// whether it's a capital M or not
isM := buf[mi] == 'M'
// whether it's urxvt or not
isU := false
// buf[2] is safe here, because having M or m found means we have at
// least 3 bytes in a string
if buf[2] == '<' {
buf = buf[3:mi]
} else {
isU = true
buf = buf[2:mi]
}
s1 := strings.Index(buf, ";")
s2 := strings.LastIndex(buf, ";")
// not found or only one ';'
if s1 == -1 || s2 == -1 || s1 == s2 {
return 0, false
}
n1, err := strconv.ParseInt(buf[0:s1], 10, 64)
if err != nil {
return 0, false
}
n2, err := strconv.ParseInt(buf[s1+1:s2], 10, 64)
if err != nil {
return 0, false
}
n3, err := strconv.ParseInt(buf[s2+1:], 10, 64)
if err != nil {
return 0, false
}
// on urxvt, first number is encoded exactly as in X10, but we need to
// make it zero-based, on xterm it is zero-based already
if isU {
n1 -= 32
}
switch n1 & 3 {
case 0:
if n1&64 != 0 {
event.Key = MouseWheelUp
} else {
event.Key = MouseLeft
}
case 1:
if n1&64 != 0 {
event.Key = MouseWheelDown
} else {
event.Key = MouseMiddle
}
case 2:
event.Key = MouseRight
case 3:
event.Key = MouseRelease
default:
return mi + 1, false
}
if !isM {
// on xterm mouse release is signaled by lowercase m
event.Key = MouseRelease
}
event.Type = EventMouse // KeyEvent by default
if n1&32 != 0 {
event.Mod |= ModMotion
}
event.MouseX = int(n2) - 1
event.MouseY = int(n3) - 1
return mi + 1, true
}
return 0, false
}
func parse_escape_sequence(event *Event, buf []byte) (int, bool) {
bufstr := string(buf)
for i, key := range keys {
if strings.HasPrefix(bufstr, key) {
event.Ch = 0
event.Key = Key(0xFFFF - i)
return len(key), true
}
}
// if none of the keys match, let's try mouse seqences
return parse_mouse_event(event, bufstr)
}
func extract_raw_event(data []byte, event *Event) bool {
if len(inbuf) == 0 {
return false
}
n := len(data)
if n == 0 {
return false
}
n = copy(data, inbuf)
copy(inbuf, inbuf[n:])
inbuf = inbuf[:len(inbuf)-n]
event.N = n
event.Type = EventRaw
return true
}
func extract_event(inbuf []byte, event *Event) bool {
if len(inbuf) == 0 {
event.N = 0
return false
}
if inbuf[0] == '\033' {
// possible escape sequence
if n, ok := parse_escape_sequence(event, inbuf); n != 0 {
event.N = n
return ok
}
// it's not escape sequence, then it's Alt or Esc, check input_mode
switch {
case input_mode&InputEsc != 0:
// if we're in escape mode, fill Esc event, pop buffer, return success
event.Ch = 0
event.Key = KeyEsc
event.Mod = 0
event.N = 1
return true
case input_mode&InputAlt != 0:
// if we're in alt mode, set Alt modifier to event and redo parsing
event.Mod = ModAlt
ok := extract_event(inbuf[1:], event)
if ok {
event.N++
} else {
event.N = 0
}
return ok
default:
panic("unreachable")
}
}
// if we're here, this is not an escape sequence and not an alt sequence
// so, it's a FUNCTIONAL KEY or a UNICODE character
// first of all check if it's a functional key
if Key(inbuf[0]) <= KeySpace || Key(inbuf[0]) == KeyBackspace2 {
// fill event, pop buffer, return success
event.Ch = 0
event.Key = Key(inbuf[0])
event.N = 1
return true
}
// the only possible option is utf8 rune
if r, n := utf8.DecodeRune(inbuf); r != utf8.RuneError {
event.Ch = r
event.Key = 0
event.N = n
return true
}
return false
}
func fcntl(fd int, cmd int, arg int) (val int, err error) {
r, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), uintptr(cmd),
uintptr(arg))
val = int(r)
if e != 0 {
err = e
}
return
}

59
vendor/github.com/nsf/termbox-go/termbox_common.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
package termbox
// private API, common OS agnostic part
type cellbuf struct {
width int
height int
cells []Cell
}
func (this *cellbuf) init(width, height int) {
this.width = width
this.height = height
this.cells = make([]Cell, width*height)
}
func (this *cellbuf) resize(width, height int) {
if this.width == width && this.height == height {
return
}
oldw := this.width
oldh := this.height
oldcells := this.cells
this.init(width, height)
this.clear()
minw, minh := oldw, oldh
if width < minw {
minw = width
}
if height < minh {
minh = height
}
for i := 0; i < minh; i++ {
srco, dsto := i*oldw, i*width
src := oldcells[srco : srco+minw]
dst := this.cells[dsto : dsto+minw]
copy(dst, src)
}
}
func (this *cellbuf) clear() {
for i := range this.cells {
c := &this.cells[i]
c.Ch = ' '
c.Fg = foreground
c.Bg = background
}
}
const cursor_hidden = -1
func is_cursor_hidden(x, y int) bool {
return x == cursor_hidden || y == cursor_hidden
}

889
vendor/github.com/nsf/termbox-go/termbox_windows.go generated vendored Normal file
View File

@ -0,0 +1,889 @@
package termbox
import "syscall"
import "unsafe"
import "unicode/utf16"
import "github.com/mattn/go-runewidth"
type (
wchar uint16
short int16
dword uint32
word uint16
char_info struct {
char wchar
attr word
}
coord struct {
x short
y short
}
small_rect struct {
left short
top short
right short
bottom short
}
console_screen_buffer_info struct {
size coord
cursor_position coord
attributes word
window small_rect
maximum_window_size coord
}
console_cursor_info struct {
size dword
visible int32
}
input_record struct {
event_type word
_ [2]byte
event [16]byte
}
key_event_record struct {
key_down int32
repeat_count word
virtual_key_code word
virtual_scan_code word
unicode_char wchar
control_key_state dword
}
window_buffer_size_record struct {
size coord
}
mouse_event_record struct {
mouse_pos coord
button_state dword
control_key_state dword
event_flags dword
}
)
const (
mouse_lmb = 0x1
mouse_rmb = 0x2
mouse_mmb = 0x4 | 0x8 | 0x10
SM_CXMIN = 28
SM_CYMIN = 29
)
func (this coord) uintptr() uintptr {
return uintptr(*(*int32)(unsafe.Pointer(&this)))
}
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
var moduser32 = syscall.NewLazyDLL("user32.dll")
var is_cjk = runewidth.IsEastAsian()
var (
proc_set_console_active_screen_buffer = kernel32.NewProc("SetConsoleActiveScreenBuffer")
proc_set_console_screen_buffer_size = kernel32.NewProc("SetConsoleScreenBufferSize")
proc_create_console_screen_buffer = kernel32.NewProc("CreateConsoleScreenBuffer")
proc_get_console_screen_buffer_info = kernel32.NewProc("GetConsoleScreenBufferInfo")
proc_write_console_output = kernel32.NewProc("WriteConsoleOutputW")
proc_write_console_output_character = kernel32.NewProc("WriteConsoleOutputCharacterW")
proc_write_console_output_attribute = kernel32.NewProc("WriteConsoleOutputAttribute")
proc_set_console_cursor_info = kernel32.NewProc("SetConsoleCursorInfo")
proc_set_console_cursor_position = kernel32.NewProc("SetConsoleCursorPosition")
proc_get_console_cursor_info = kernel32.NewProc("GetConsoleCursorInfo")
proc_read_console_input = kernel32.NewProc("ReadConsoleInputW")
proc_get_console_mode = kernel32.NewProc("GetConsoleMode")
proc_set_console_mode = kernel32.NewProc("SetConsoleMode")
proc_fill_console_output_character = kernel32.NewProc("FillConsoleOutputCharacterW")
proc_fill_console_output_attribute = kernel32.NewProc("FillConsoleOutputAttribute")
proc_create_event = kernel32.NewProc("CreateEventW")
proc_wait_for_multiple_objects = kernel32.NewProc("WaitForMultipleObjects")
proc_set_event = kernel32.NewProc("SetEvent")
get_system_metrics = moduser32.NewProc("GetSystemMetrics")
)
func set_console_active_screen_buffer(h syscall.Handle) (err error) {
r0, _, e1 := syscall.Syscall(proc_set_console_active_screen_buffer.Addr(),
1, uintptr(h), 0, 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func set_console_screen_buffer_size(h syscall.Handle, size coord) (err error) {
r0, _, e1 := syscall.Syscall(proc_set_console_screen_buffer_size.Addr(),
2, uintptr(h), size.uintptr(), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func create_console_screen_buffer() (h syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall6(proc_create_console_screen_buffer.Addr(),
5, uintptr(generic_read|generic_write), 0, 0, console_textmode_buffer, 0, 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return syscall.Handle(r0), err
}
func get_console_screen_buffer_info(h syscall.Handle, info *console_screen_buffer_info) (err error) {
r0, _, e1 := syscall.Syscall(proc_get_console_screen_buffer_info.Addr(),
2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func write_console_output(h syscall.Handle, chars []char_info, dst small_rect) (err error) {
tmp_coord = coord{dst.right - dst.left + 1, dst.bottom - dst.top + 1}
tmp_rect = dst
r0, _, e1 := syscall.Syscall6(proc_write_console_output.Addr(),
5, uintptr(h), uintptr(unsafe.Pointer(&chars[0])), tmp_coord.uintptr(),
tmp_coord0.uintptr(), uintptr(unsafe.Pointer(&tmp_rect)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func write_console_output_character(h syscall.Handle, chars []wchar, pos coord) (err error) {
r0, _, e1 := syscall.Syscall6(proc_write_console_output_character.Addr(),
5, uintptr(h), uintptr(unsafe.Pointer(&chars[0])), uintptr(len(chars)),
pos.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func write_console_output_attribute(h syscall.Handle, attrs []word, pos coord) (err error) {
r0, _, e1 := syscall.Syscall6(proc_write_console_output_attribute.Addr(),
5, uintptr(h), uintptr(unsafe.Pointer(&attrs[0])), uintptr(len(attrs)),
pos.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func set_console_cursor_info(h syscall.Handle, info *console_cursor_info) (err error) {
r0, _, e1 := syscall.Syscall(proc_set_console_cursor_info.Addr(),
2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func get_console_cursor_info(h syscall.Handle, info *console_cursor_info) (err error) {
r0, _, e1 := syscall.Syscall(proc_get_console_cursor_info.Addr(),
2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func set_console_cursor_position(h syscall.Handle, pos coord) (err error) {
r0, _, e1 := syscall.Syscall(proc_set_console_cursor_position.Addr(),
2, uintptr(h), pos.uintptr(), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func read_console_input(h syscall.Handle, record *input_record) (err error) {
r0, _, e1 := syscall.Syscall6(proc_read_console_input.Addr(),
4, uintptr(h), uintptr(unsafe.Pointer(record)), 1, uintptr(unsafe.Pointer(&tmp_arg)), 0, 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func get_console_mode(h syscall.Handle, mode *dword) (err error) {
r0, _, e1 := syscall.Syscall(proc_get_console_mode.Addr(),
2, uintptr(h), uintptr(unsafe.Pointer(mode)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func set_console_mode(h syscall.Handle, mode dword) (err error) {
r0, _, e1 := syscall.Syscall(proc_set_console_mode.Addr(),
2, uintptr(h), uintptr(mode), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func fill_console_output_character(h syscall.Handle, char wchar, n int) (err error) {
r0, _, e1 := syscall.Syscall6(proc_fill_console_output_character.Addr(),
5, uintptr(h), uintptr(char), uintptr(n), tmp_coord.uintptr(),
uintptr(unsafe.Pointer(&tmp_arg)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func fill_console_output_attribute(h syscall.Handle, attr word, n int) (err error) {
r0, _, e1 := syscall.Syscall6(proc_fill_console_output_attribute.Addr(),
5, uintptr(h), uintptr(attr), uintptr(n), tmp_coord.uintptr(),
uintptr(unsafe.Pointer(&tmp_arg)), 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func create_event() (out syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall6(proc_create_event.Addr(),
4, 0, 0, 0, 0, 0, 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return syscall.Handle(r0), err
}
func wait_for_multiple_objects(objects []syscall.Handle) (err error) {
r0, _, e1 := syscall.Syscall6(proc_wait_for_multiple_objects.Addr(),
4, uintptr(len(objects)), uintptr(unsafe.Pointer(&objects[0])),
0, 0xFFFFFFFF, 0, 0)
if uint32(r0) == 0xFFFFFFFF {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func set_event(ev syscall.Handle) (err error) {
r0, _, e1 := syscall.Syscall(proc_set_event.Addr(),
1, uintptr(ev), 0, 0)
if int(r0) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
type diff_msg struct {
pos short
lines short
chars []char_info
}
type input_event struct {
event Event
err error
}
var (
orig_cursor_info console_cursor_info
orig_size coord
orig_mode dword
orig_screen syscall.Handle
back_buffer cellbuf
front_buffer cellbuf
term_size coord
input_mode = InputEsc
cursor_x = cursor_hidden
cursor_y = cursor_hidden
foreground = ColorDefault
background = ColorDefault
in syscall.Handle
out syscall.Handle
interrupt syscall.Handle
charbuf []char_info
diffbuf []diff_msg
beg_x = -1
beg_y = -1
beg_i = -1
input_comm = make(chan Event)
interrupt_comm = make(chan struct{})
cancel_comm = make(chan bool, 1)
cancel_done_comm = make(chan bool)
alt_mode_esc = false
// these ones just to prevent heap allocs at all costs
tmp_info console_screen_buffer_info
tmp_arg dword
tmp_coord0 = coord{0, 0}
tmp_coord = coord{0, 0}
tmp_rect = small_rect{0, 0, 0, 0}
)
func get_cursor_position(out syscall.Handle) coord {
err := get_console_screen_buffer_info(out, &tmp_info)
if err != nil {
panic(err)
}
return tmp_info.cursor_position
}
func get_term_size(out syscall.Handle) coord {
err := get_console_screen_buffer_info(out, &tmp_info)
if err != nil {
panic(err)
}
return tmp_info.size
}
func get_win_min_size(out syscall.Handle) coord {
x, _, err := get_system_metrics.Call(SM_CXMIN)
y, _, err := get_system_metrics.Call(SM_CYMIN)
if x == 0 || y == 0 {
if err != nil {
panic(err)
}
}
return coord{
x: short(x),
y: short(y),
}
}
func get_win_size(out syscall.Handle) coord {
err := get_console_screen_buffer_info(out, &tmp_info)
if err != nil {
panic(err)
}
min_size := get_win_min_size(out)
size := coord{
x: tmp_info.window.right - tmp_info.window.left + 1,
y: tmp_info.window.bottom - tmp_info.window.top + 1,
}
if size.x < min_size.x {
size.x = min_size.x
}
if size.y < min_size.y {
size.y = min_size.y
}
return size
}
func update_size_maybe() {
size := get_term_size(out)
if size.x != term_size.x || size.y != term_size.y {
term_size = size
back_buffer.resize(int(size.x), int(size.y))
front_buffer.resize(int(size.x), int(size.y))
front_buffer.clear()
clear()
area := int(size.x) * int(size.y)
if cap(charbuf) < area {
charbuf = make([]char_info, 0, area)
}
}
}
var color_table_bg = []word{
0, // default (black)
0, // black
background_red,
background_green,
background_red | background_green, // yellow
background_blue,
background_red | background_blue, // magenta
background_green | background_blue, // cyan
background_red | background_blue | background_green, // white
}
var color_table_fg = []word{
foreground_red | foreground_blue | foreground_green, // default (white)
0,
foreground_red,
foreground_green,
foreground_red | foreground_green, // yellow
foreground_blue,
foreground_red | foreground_blue, // magenta
foreground_green | foreground_blue, // cyan
foreground_red | foreground_blue | foreground_green, // white
}
const (
replacement_char = '\uFFFD'
max_rune = '\U0010FFFF'
surr1 = 0xd800
surr2 = 0xdc00
surr3 = 0xe000
surr_self = 0x10000
)
func append_diff_line(y int) int {
n := 0
for x := 0; x < front_buffer.width; {
cell_offset := y*front_buffer.width + x
back := &back_buffer.cells[cell_offset]
front := &front_buffer.cells[cell_offset]
attr, char := cell_to_char_info(*back)
charbuf = append(charbuf, char_info{attr: attr, char: char[0]})
*front = *back
n++
w := runewidth.RuneWidth(back.Ch)
if w == 0 || w == 2 && runewidth.IsAmbiguousWidth(back.Ch) {
w = 1
}
x += w
// If not CJK, fill trailing space with whitespace
if !is_cjk && w == 2 {
charbuf = append(charbuf, char_info{attr: attr, char: ' '})
}
}
return n
}
// compares 'back_buffer' with 'front_buffer' and prepares all changes in the form of
// 'diff_msg's in the 'diff_buf'
func prepare_diff_messages() {
// clear buffers
diffbuf = diffbuf[:0]
charbuf = charbuf[:0]
var diff diff_msg
gbeg := 0
for y := 0; y < front_buffer.height; y++ {
same := true
line_offset := y * front_buffer.width
for x := 0; x < front_buffer.width; x++ {
cell_offset := line_offset + x
back := &back_buffer.cells[cell_offset]
front := &front_buffer.cells[cell_offset]
if *back != *front {
same = false
break
}
}
if same && diff.lines > 0 {
diffbuf = append(diffbuf, diff)
diff = diff_msg{}
}
if !same {
beg := len(charbuf)
end := beg + append_diff_line(y)
if diff.lines == 0 {
diff.pos = short(y)
gbeg = beg
}
diff.lines++
diff.chars = charbuf[gbeg:end]
}
}
if diff.lines > 0 {
diffbuf = append(diffbuf, diff)
diff = diff_msg{}
}
}
func get_ct(table []word, idx int) word {
idx = idx & 0x0F
if idx >= len(table) {
idx = len(table) - 1
}
return table[idx]
}
func cell_to_char_info(c Cell) (attr word, wc [2]wchar) {
attr = get_ct(color_table_fg, int(c.Fg)) | get_ct(color_table_bg, int(c.Bg))
if c.Fg&AttrReverse|c.Bg&AttrReverse != 0 {
attr = (attr&0xF0)>>4 | (attr&0x0F)<<4
}
if c.Fg&AttrBold != 0 {
attr |= foreground_intensity
}
if c.Bg&AttrBold != 0 {
attr |= background_intensity
}
r0, r1 := utf16.EncodeRune(c.Ch)
if r0 == 0xFFFD {
wc[0] = wchar(c.Ch)
wc[1] = ' '
} else {
wc[0] = wchar(r0)
wc[1] = wchar(r1)
}
return
}
func move_cursor(x, y int) {
err := set_console_cursor_position(out, coord{short(x), short(y)})
if err != nil {
panic(err)
}
}
func show_cursor(visible bool) {
var v int32
if visible {
v = 1
}
var info console_cursor_info
info.size = 100
info.visible = v
err := set_console_cursor_info(out, &info)
if err != nil {
panic(err)
}
}
func clear() {
var err error
attr, char := cell_to_char_info(Cell{
' ',
foreground,
background,
})
area := int(term_size.x) * int(term_size.y)
err = fill_console_output_attribute(out, attr, area)
if err != nil {
panic(err)
}
err = fill_console_output_character(out, char[0], area)
if err != nil {
panic(err)
}
if !is_cursor_hidden(cursor_x, cursor_y) {
move_cursor(cursor_x, cursor_y)
}
}
func key_event_record_to_event(r *key_event_record) (Event, bool) {
if r.key_down == 0 {
return Event{}, false
}
e := Event{Type: EventKey}
if input_mode&InputAlt != 0 {
if alt_mode_esc {
e.Mod = ModAlt
alt_mode_esc = false
}
if r.control_key_state&(left_alt_pressed|right_alt_pressed) != 0 {
e.Mod = ModAlt
}
}
ctrlpressed := r.control_key_state&(left_ctrl_pressed|right_ctrl_pressed) != 0
if r.virtual_key_code >= vk_f1 && r.virtual_key_code <= vk_f12 {
switch r.virtual_key_code {
case vk_f1:
e.Key = KeyF1
case vk_f2:
e.Key = KeyF2
case vk_f3:
e.Key = KeyF3
case vk_f4:
e.Key = KeyF4
case vk_f5:
e.Key = KeyF5
case vk_f6:
e.Key = KeyF6
case vk_f7:
e.Key = KeyF7
case vk_f8:
e.Key = KeyF8
case vk_f9:
e.Key = KeyF9
case vk_f10:
e.Key = KeyF10
case vk_f11:
e.Key = KeyF11
case vk_f12:
e.Key = KeyF12
default:
panic("unreachable")
}
return e, true
}
if r.virtual_key_code <= vk_delete {
switch r.virtual_key_code {
case vk_insert:
e.Key = KeyInsert
case vk_delete:
e.Key = KeyDelete
case vk_home:
e.Key = KeyHome
case vk_end:
e.Key = KeyEnd
case vk_pgup:
e.Key = KeyPgup
case vk_pgdn:
e.Key = KeyPgdn
case vk_arrow_up:
e.Key = KeyArrowUp
case vk_arrow_down:
e.Key = KeyArrowDown
case vk_arrow_left:
e.Key = KeyArrowLeft
case vk_arrow_right:
e.Key = KeyArrowRight
case vk_backspace:
if ctrlpressed {
e.Key = KeyBackspace2
} else {
e.Key = KeyBackspace
}
case vk_tab:
e.Key = KeyTab
case vk_enter:
e.Key = KeyEnter
case vk_esc:
switch {
case input_mode&InputEsc != 0:
e.Key = KeyEsc
case input_mode&InputAlt != 0:
alt_mode_esc = true
return Event{}, false
}
case vk_space:
if ctrlpressed {
// manual return here, because KeyCtrlSpace is zero
e.Key = KeyCtrlSpace
return e, true
} else {
e.Key = KeySpace
}
}
if e.Key != 0 {
return e, true
}
}
if ctrlpressed {
if Key(r.unicode_char) >= KeyCtrlA && Key(r.unicode_char) <= KeyCtrlRsqBracket {
e.Key = Key(r.unicode_char)
if input_mode&InputAlt != 0 && e.Key == KeyEsc {
alt_mode_esc = true
return Event{}, false
}
return e, true
}
switch r.virtual_key_code {
case 192, 50:
// manual return here, because KeyCtrl2 is zero
e.Key = KeyCtrl2
return e, true
case 51:
if input_mode&InputAlt != 0 {
alt_mode_esc = true
return Event{}, false
}
e.Key = KeyCtrl3
case 52:
e.Key = KeyCtrl4
case 53:
e.Key = KeyCtrl5
case 54:
e.Key = KeyCtrl6
case 189, 191, 55:
e.Key = KeyCtrl7
case 8, 56:
e.Key = KeyCtrl8
}
if e.Key != 0 {
return e, true
}
}
if r.unicode_char != 0 {
e.Ch = rune(r.unicode_char)
return e, true
}
return Event{}, false
}
func input_event_producer() {
var r input_record
var err error
var last_button Key
var last_button_pressed Key
var last_state = dword(0)
var last_x, last_y = -1, -1
handles := []syscall.Handle{in, interrupt}
for {
err = wait_for_multiple_objects(handles)
if err != nil {
input_comm <- Event{Type: EventError, Err: err}
}
select {
case <-cancel_comm:
cancel_done_comm <- true
return
default:
}
err = read_console_input(in, &r)
if err != nil {
input_comm <- Event{Type: EventError, Err: err}
}
switch r.event_type {
case key_event:
kr := (*key_event_record)(unsafe.Pointer(&r.event))
ev, ok := key_event_record_to_event(kr)
if ok {
for i := 0; i < int(kr.repeat_count); i++ {
input_comm <- ev
}
}
case window_buffer_size_event:
sr := *(*window_buffer_size_record)(unsafe.Pointer(&r.event))
input_comm <- Event{
Type: EventResize,
Width: int(sr.size.x),
Height: int(sr.size.y),
}
case mouse_event:
mr := *(*mouse_event_record)(unsafe.Pointer(&r.event))
ev := Event{Type: EventMouse}
switch mr.event_flags {
case 0, 2:
// single or double click
cur_state := mr.button_state
switch {
case last_state&mouse_lmb == 0 && cur_state&mouse_lmb != 0:
last_button = MouseLeft
last_button_pressed = last_button
case last_state&mouse_rmb == 0 && cur_state&mouse_rmb != 0:
last_button = MouseRight
last_button_pressed = last_button
case last_state&mouse_mmb == 0 && cur_state&mouse_mmb != 0:
last_button = MouseMiddle
last_button_pressed = last_button
case last_state&mouse_lmb != 0 && cur_state&mouse_lmb == 0:
last_button = MouseRelease
case last_state&mouse_rmb != 0 && cur_state&mouse_rmb == 0:
last_button = MouseRelease
case last_state&mouse_mmb != 0 && cur_state&mouse_mmb == 0:
last_button = MouseRelease
default:
last_state = cur_state
continue
}
last_state = cur_state
ev.Key = last_button
last_x, last_y = int(mr.mouse_pos.x), int(mr.mouse_pos.y)
ev.MouseX = last_x
ev.MouseY = last_y
case 1:
// mouse motion
x, y := int(mr.mouse_pos.x), int(mr.mouse_pos.y)
if last_state != 0 && (last_x != x || last_y != y) {
ev.Key = last_button_pressed
ev.Mod = ModMotion
ev.MouseX = x
ev.MouseY = y
last_x, last_y = x, y
} else {
ev.Type = EventNone
}
case 4:
// mouse wheel
n := int16(mr.button_state >> 16)
if n > 0 {
ev.Key = MouseWheelUp
} else {
ev.Key = MouseWheelDown
}
last_x, last_y = int(mr.mouse_pos.x), int(mr.mouse_pos.y)
ev.MouseX = last_x
ev.MouseY = last_y
default:
ev.Type = EventNone
}
if ev.Type != EventNone {
input_comm <- ev
}
}
}
}

221
vendor/github.com/nsf/termbox-go/terminfo.go generated vendored Normal file
View File

@ -0,0 +1,221 @@
// +build !windows
// This file contains a simple and incomplete implementation of the terminfo
// database. Information was taken from the ncurses manpages term(5) and
// terminfo(5). Currently, only the string capabilities for special keys and for
// functions without parameters are actually used. Colors are still done with
// ANSI escape sequences. Other special features that are not (yet?) supported
// are reading from ~/.terminfo, the TERMINFO_DIRS variable, Berkeley database
// format and extended capabilities.
package termbox
import (
"bytes"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
)
const (
ti_magic = 0432
ti_header_length = 12
ti_mouse_enter = "\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h"
ti_mouse_leave = "\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l"
)
func load_terminfo() ([]byte, error) {
var data []byte
var err error
term := os.Getenv("TERM")
if term == "" {
return nil, fmt.Errorf("termbox: TERM not set")
}
// The following behaviour follows the one described in terminfo(5) as
// distributed by ncurses.
terminfo := os.Getenv("TERMINFO")
if terminfo != "" {
// if TERMINFO is set, no other directory should be searched
return ti_try_path(terminfo)
}
// next, consider ~/.terminfo
home := os.Getenv("HOME")
if home != "" {
data, err = ti_try_path(home + "/.terminfo")
if err == nil {
return data, nil
}
}
// next, TERMINFO_DIRS
dirs := os.Getenv("TERMINFO_DIRS")
if dirs != "" {
for _, dir := range strings.Split(dirs, ":") {
if dir == "" {
// "" -> "/usr/share/terminfo"
dir = "/usr/share/terminfo"
}
data, err = ti_try_path(dir)
if err == nil {
return data, nil
}
}
}
// fall back to /usr/share/terminfo
return ti_try_path("/usr/share/terminfo")
}
func ti_try_path(path string) (data []byte, err error) {
// load_terminfo already made sure it is set
term := os.Getenv("TERM")
// first try, the typical *nix path
terminfo := path + "/" + term[0:1] + "/" + term
data, err = ioutil.ReadFile(terminfo)
if err == nil {
return
}
// fallback to darwin specific dirs structure
terminfo = path + "/" + hex.EncodeToString([]byte(term[:1])) + "/" + term
data, err = ioutil.ReadFile(terminfo)
return
}
func setup_term_builtin() error {
name := os.Getenv("TERM")
if name == "" {
return errors.New("termbox: TERM environment variable not set")
}
for _, t := range terms {
if t.name == name {
keys = t.keys
funcs = t.funcs
return nil
}
}
compat_table := []struct {
partial string
keys []string
funcs []string
}{
{"xterm", xterm_keys, xterm_funcs},
{"rxvt", rxvt_unicode_keys, rxvt_unicode_funcs},
{"linux", linux_keys, linux_funcs},
{"Eterm", eterm_keys, eterm_funcs},
{"screen", screen_keys, screen_funcs},
// let's assume that 'cygwin' is xterm compatible
{"cygwin", xterm_keys, xterm_funcs},
{"st", xterm_keys, xterm_funcs},
}
// try compatibility variants
for _, it := range compat_table {
if strings.Contains(name, it.partial) {
keys = it.keys
funcs = it.funcs
return nil
}
}
return errors.New("termbox: unsupported terminal")
}
func setup_term() (err error) {
var data []byte
var header [6]int16
var str_offset, table_offset int16
data, err = load_terminfo()
if err != nil {
return setup_term_builtin()
}
rd := bytes.NewReader(data)
// 0: magic number, 1: size of names section, 2: size of boolean section, 3:
// size of numbers section (in integers), 4: size of the strings section (in
// integers), 5: size of the string table
err = binary.Read(rd, binary.LittleEndian, header[:])
if err != nil {
return
}
if (header[1]+header[2])%2 != 0 {
// old quirk to align everything on word boundaries
header[2] += 1
}
str_offset = ti_header_length + header[1] + header[2] + 2*header[3]
table_offset = str_offset + 2*header[4]
keys = make([]string, 0xFFFF-key_min)
for i, _ := range keys {
keys[i], err = ti_read_string(rd, str_offset+2*ti_keys[i], table_offset)
if err != nil {
return
}
}
funcs = make([]string, t_max_funcs)
// the last two entries are reserved for mouse. because the table offset is
// not there, the two entries have to fill in manually
for i, _ := range funcs[:len(funcs)-2] {
funcs[i], err = ti_read_string(rd, str_offset+2*ti_funcs[i], table_offset)
if err != nil {
return
}
}
funcs[t_max_funcs-2] = ti_mouse_enter
funcs[t_max_funcs-1] = ti_mouse_leave
return nil
}
func ti_read_string(rd *bytes.Reader, str_off, table int16) (string, error) {
var off int16
_, err := rd.Seek(int64(str_off), 0)
if err != nil {
return "", err
}
err = binary.Read(rd, binary.LittleEndian, &off)
if err != nil {
return "", err
}
_, err = rd.Seek(int64(table+off), 0)
if err != nil {
return "", err
}
var bs []byte
for {
b, err := rd.ReadByte()
if err != nil {
return "", err
}
if b == byte(0x00) {
break
}
bs = append(bs, b)
}
return string(bs), nil
}
// "Maps" the function constants from termbox.go to the number of the respective
// string capability in the terminfo file. Taken from (ncurses) term.h.
var ti_funcs = []int16{
28, 40, 16, 13, 5, 39, 36, 27, 26, 34, 89, 88,
}
// Same as above for the special keys.
var ti_keys = []int16{
66, 68 /* apparently not a typo; 67 is F10 for whatever reason */, 69, 70,
71, 72, 73, 74, 75, 67, 216, 217, 77, 59, 76, 164, 82, 81, 87, 61, 79, 83,
}

64
vendor/github.com/nsf/termbox-go/terminfo_builtin.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
// +build !windows
package termbox
// Eterm
var eterm_keys = []string{
"\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C",
}
var eterm_funcs = []string{
"\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "",
}
// screen
var screen_keys = []string{
"\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC",
}
var screen_funcs = []string{
"\x1b[?1049h", "\x1b[?1049l", "\x1b[34h\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave,
}
// xterm
var xterm_keys = []string{
"\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1bOH", "\x1bOF", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC",
}
var xterm_funcs = []string{
"\x1b[?1049h", "\x1b[?1049l", "\x1b[?12l\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b(B\x1b[m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave,
}
// rxvt-unicode
var rxvt_unicode_keys = []string{
"\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C",
}
var rxvt_unicode_funcs = []string{
"\x1b[?1049h", "\x1b[r\x1b[?1049l", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x1b(B", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave,
}
// linux
var linux_keys = []string{
"\x1b[[A", "\x1b[[B", "\x1b[[C", "\x1b[[D", "\x1b[[E", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C",
}
var linux_funcs = []string{
"", "", "\x1b[?25h\x1b[?0c", "\x1b[?25l\x1b[?1c", "\x1b[H\x1b[J", "\x1b[0;10m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "",
}
// rxvt-256color
var rxvt_256color_keys = []string{
"\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C",
}
var rxvt_256color_funcs = []string{
"\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave,
}
var terms = []struct {
name string
keys []string
funcs []string
}{
{"Eterm", eterm_keys, eterm_funcs},
{"screen", screen_keys, screen_funcs},
{"xterm", xterm_keys, xterm_funcs},
{"rxvt-unicode", rxvt_unicode_keys, rxvt_unicode_funcs},
{"linux", linux_keys, linux_funcs},
{"rxvt-256color", rxvt_256color_keys, rxvt_256color_funcs},
}