Add gocui dependency to vendor
Along with its dependencies.4f518eddb0
97311d9f77
10cefba34b
This commit is contained in:
parent
a1e0fb3b7e
commit
086b8e5f4e
1
vendor/github.com/jroimartin/gocui/.gitignore
generated
vendored
Normal file
1
vendor/github.com/jroimartin/gocui/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.swp
|
30
vendor/github.com/jroimartin/gocui/AUTHORS
generated
vendored
Normal file
30
vendor/github.com/jroimartin/gocui/AUTHORS
generated
vendored
Normal 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
23
vendor/github.com/jroimartin/gocui/LICENSE
generated
vendored
Normal 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
105
vendor/github.com/jroimartin/gocui/README.md
generated
vendored
Normal 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! :)
|
420
vendor/github.com/jroimartin/gocui/_examples/Mark.Twain-Tom.Sawyer.txt
generated
vendored
Normal file
420
vendor/github.com/jroimartin/gocui/_examples/Mark.Twain-Tom.Sawyer.txt
generated
vendored
Normal 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
119
vendor/github.com/jroimartin/gocui/_examples/active.go
generated
vendored
Normal 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
70
vendor/github.com/jroimartin/gocui/_examples/bufs.go
generated
vendored
Normal 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
49
vendor/github.com/jroimartin/gocui/_examples/colors.go
generated
vendored
Normal 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
|
||||
}
|
74
vendor/github.com/jroimartin/gocui/_examples/colors256.go
generated
vendored
Normal file
74
vendor/github.com/jroimartin/gocui/_examples/colors256.go
generated
vendored
Normal 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
211
vendor/github.com/jroimartin/gocui/_examples/demo.go
generated
vendored
Normal 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
190
vendor/github.com/jroimartin/gocui/_examples/dynamic.go
generated
vendored
Normal 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
|
||||
}
|
87
vendor/github.com/jroimartin/gocui/_examples/flow_layout.go
generated
vendored
Normal file
87
vendor/github.com/jroimartin/gocui/_examples/flow_layout.go
generated
vendored
Normal 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
|
||||
}
|
97
vendor/github.com/jroimartin/gocui/_examples/goroutine.go
generated
vendored
Normal file
97
vendor/github.com/jroimartin/gocui/_examples/goroutine.go
generated
vendored
Normal 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
45
vendor/github.com/jroimartin/gocui/_examples/hello.go
generated
vendored
Normal 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
50
vendor/github.com/jroimartin/gocui/_examples/layout.go
generated
vendored
Normal 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
75
vendor/github.com/jroimartin/gocui/_examples/mask.go
generated
vendored
Normal 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
107
vendor/github.com/jroimartin/gocui/_examples/mouse.go
generated
vendored
Normal 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
88
vendor/github.com/jroimartin/gocui/_examples/ontop.go
generated
vendored
Normal 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
|
||||
}
|
74
vendor/github.com/jroimartin/gocui/_examples/overlap.go
generated
vendored
Normal file
74
vendor/github.com/jroimartin/gocui/_examples/overlap.go
generated
vendored
Normal 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
45
vendor/github.com/jroimartin/gocui/_examples/size.go
generated
vendored
Normal 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
109
vendor/github.com/jroimartin/gocui/_examples/stdin.go
generated
vendored
Normal 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
162
vendor/github.com/jroimartin/gocui/_examples/title.go
generated
vendored
Normal 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
179
vendor/github.com/jroimartin/gocui/_examples/widgets.go
generated
vendored
Normal 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
50
vendor/github.com/jroimartin/gocui/_examples/wrap.go
generated
vendored
Normal 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
32
vendor/github.com/jroimartin/gocui/attribute.go
generated
vendored
Normal 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
118
vendor/github.com/jroimartin/gocui/doc.go
generated
vendored
Normal 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
344
vendor/github.com/jroimartin/gocui/edit.go
generated
vendored
Normal 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
229
vendor/github.com/jroimartin/gocui/escape.go
generated
vendored
Normal 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
636
vendor/github.com/jroimartin/gocui/gui.go
generated
vendored
Normal 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
137
vendor/github.com/jroimartin/gocui/keybinding.go
generated
vendored
Normal 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
479
vendor/github.com/jroimartin/gocui/view.go
generated
vendored
Normal 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
8
vendor/github.com/mattn/go-runewidth/.travis.yml
generated
vendored
Normal 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
21
vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
Normal 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
27
vendor/github.com/mattn/go-runewidth/README.mkd
generated
vendored
Normal 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
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
8
vendor/github.com/mattn/go-runewidth/runewidth_js.go
generated
vendored
Normal 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
|
||||
}
|
77
vendor/github.com/mattn/go-runewidth/runewidth_posix.go
generated
vendored
Normal file
77
vendor/github.com/mattn/go-runewidth/runewidth_posix.go
generated
vendored
Normal 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
279
vendor/github.com/mattn/go-runewidth/runewidth_test.go
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
25
vendor/github.com/mattn/go-runewidth/runewidth_windows.go
generated
vendored
Normal file
25
vendor/github.com/mattn/go-runewidth/runewidth_windows.go
generated
vendored
Normal 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
4
vendor/github.com/nsf/termbox-go/AUTHORS
generated
vendored
Normal 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
19
vendor/github.com/nsf/termbox-go/LICENSE
generated
vendored
Normal 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
38
vendor/github.com/nsf/termbox-go/README.md
generated
vendored
Normal 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
300
vendor/github.com/nsf/termbox-go/_demos/editbox.go
generated
vendored
Normal 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
69
vendor/github.com/nsf/termbox-go/_demos/interrupt.go
generated
vendored
Normal 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
722
vendor/github.com/nsf/termbox-go/_demos/keyboard.go
generated
vendored
Normal 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
228
vendor/github.com/nsf/termbox-go/_demos/output.go
generated
vendored
Normal 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
105
vendor/github.com/nsf/termbox-go/_demos/paint.go
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
46
vendor/github.com/nsf/termbox-go/_demos/random_output.go
generated
vendored
Normal file
46
vendor/github.com/nsf/termbox-go/_demos/random_output.go
generated
vendored
Normal 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
109
vendor/github.com/nsf/termbox-go/_demos/raw_input.go
generated
vendored
Normal 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
457
vendor/github.com/nsf/termbox-go/api.go
generated
vendored
Normal 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
187
vendor/github.com/nsf/termbox-go/api_common.go
generated
vendored
Normal 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
239
vendor/github.com/nsf/termbox-go/api_windows.go
generated
vendored
Normal 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
110
vendor/github.com/nsf/termbox-go/collect_terminfo.py
generated
vendored
Executable 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
39
vendor/github.com/nsf/termbox-go/syscalls.go
generated
vendored
Normal 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
41
vendor/github.com/nsf/termbox-go/syscalls_darwin.go
generated
vendored
Normal 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
|
||||
)
|
40
vendor/github.com/nsf/termbox-go/syscalls_darwin_amd64.go
generated
vendored
Normal file
40
vendor/github.com/nsf/termbox-go/syscalls_darwin_amd64.go
generated
vendored
Normal 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
39
vendor/github.com/nsf/termbox-go/syscalls_dragonfly.go
generated
vendored
Normal 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
39
vendor/github.com/nsf/termbox-go/syscalls_freebsd.go
generated
vendored
Normal 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
33
vendor/github.com/nsf/termbox-go/syscalls_linux.go
generated
vendored
Normal 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
39
vendor/github.com/nsf/termbox-go/syscalls_netbsd.go
generated
vendored
Normal 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
39
vendor/github.com/nsf/termbox-go/syscalls_openbsd.go
generated
vendored
Normal 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
61
vendor/github.com/nsf/termbox-go/syscalls_windows.go
generated
vendored
Normal 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
511
vendor/github.com/nsf/termbox-go/termbox.go
generated
vendored
Normal 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
59
vendor/github.com/nsf/termbox-go/termbox_common.go
generated
vendored
Normal 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
889
vendor/github.com/nsf/termbox-go/termbox_windows.go
generated
vendored
Normal 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
221
vendor/github.com/nsf/termbox-go/terminfo.go
generated
vendored
Normal 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
64
vendor/github.com/nsf/termbox-go/terminfo_builtin.go
generated
vendored
Normal 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},
|
||||
}
|
Reference in New Issue
Block a user