mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Merge pull request #10 from achilleasa/improve-tty-and-fix-fmt-bugs
Improve tty and fix fmt bugs
This commit is contained in:
commit
be529349bb
@ -5,6 +5,7 @@ import "io"
|
|||||||
// Tty is implemented by objects that can register themselves as ttys.
|
// Tty is implemented by objects that can register themselves as ttys.
|
||||||
type Tty interface {
|
type Tty interface {
|
||||||
io.Writer
|
io.Writer
|
||||||
|
io.ByteWriter
|
||||||
|
|
||||||
// Position returns the current cursor position (x, y).
|
// Position returns the current cursor position (x, y).
|
||||||
Position() (uint16, uint16)
|
Position() (uint16, uint16)
|
||||||
|
@ -5,6 +5,7 @@ import "github.com/achilleasa/gopher-os/kernel/driver/video/console"
|
|||||||
const (
|
const (
|
||||||
defaultFg = console.LightGrey
|
defaultFg = console.LightGrey
|
||||||
defaultBg = console.Black
|
defaultBg = console.Black
|
||||||
|
tabWidth = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// Vt implements a simple terminal that can process LF and CR characters. The
|
// Vt implements a simple terminal that can process LF and CR characters. The
|
||||||
@ -59,26 +60,47 @@ func (t *Vt) SetPosition(x, y uint16) {
|
|||||||
|
|
||||||
// Write implements io.Writer.
|
// Write implements io.Writer.
|
||||||
func (t *Vt) Write(data []byte) (int, error) {
|
func (t *Vt) Write(data []byte) (int, error) {
|
||||||
attr := t.curAttr
|
|
||||||
for _, b := range data {
|
for _, b := range data {
|
||||||
switch b {
|
t.WriteByte(b)
|
||||||
case '\r':
|
|
||||||
t.cr()
|
|
||||||
case '\n':
|
|
||||||
t.cr()
|
|
||||||
t.lf()
|
|
||||||
default:
|
|
||||||
t.cons.Write(b, attr, t.curX, t.curY)
|
|
||||||
t.curX++
|
|
||||||
if t.curX == t.width {
|
|
||||||
t.lf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(data), nil
|
return len(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write implements io.ByteWriter.
|
||||||
|
func (t *Vt) WriteByte(b byte) error {
|
||||||
|
switch b {
|
||||||
|
case '\r':
|
||||||
|
t.cr()
|
||||||
|
case '\n':
|
||||||
|
t.cr()
|
||||||
|
t.lf()
|
||||||
|
case '\b':
|
||||||
|
if t.curX > 0 {
|
||||||
|
t.cons.Write(' ', t.curAttr, t.curX, t.curY)
|
||||||
|
t.curX--
|
||||||
|
}
|
||||||
|
case '\t':
|
||||||
|
for i := 0; i < tabWidth; i++ {
|
||||||
|
t.cons.Write(' ', t.curAttr, t.curX, t.curY)
|
||||||
|
t.curX++
|
||||||
|
if t.curX == t.width {
|
||||||
|
t.cr()
|
||||||
|
t.lf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.cons.Write(b, t.curAttr, t.curX, t.curY)
|
||||||
|
t.curX++
|
||||||
|
if t.curX == t.width {
|
||||||
|
t.cr()
|
||||||
|
t.lf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// cls clears the terminal.
|
// cls clears the terminal.
|
||||||
func (t *Vt) clear() {
|
func (t *Vt) clear() {
|
||||||
t.cons.Clear(0, 0, t.width, t.height)
|
t.cons.Clear(0, 0, t.width, t.height)
|
||||||
|
@ -44,7 +44,12 @@ func TestWrite(t *testing.T) {
|
|||||||
|
|
||||||
vt.Clear()
|
vt.Clear()
|
||||||
vt.SetPosition(0, 1)
|
vt.SetPosition(0, 1)
|
||||||
vt.Write([]byte("12\n3\n4\r56"))
|
vt.Write([]byte("12\n\t3\n4\r567\b8"))
|
||||||
|
|
||||||
|
// Tab spanning rows
|
||||||
|
vt.SetPosition(78, 4)
|
||||||
|
vt.WriteByte('\t')
|
||||||
|
vt.WriteByte('9')
|
||||||
|
|
||||||
// Trigger scroll
|
// Trigger scroll
|
||||||
vt.SetPosition(79, 24)
|
vt.SetPosition(79, 24)
|
||||||
@ -56,9 +61,22 @@ func TestWrite(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{0, 0, '1'},
|
{0, 0, '1'},
|
||||||
{1, 0, '2'},
|
{1, 0, '2'},
|
||||||
{0, 1, '3'},
|
// tabs
|
||||||
|
{0, 1, ' '},
|
||||||
|
{1, 1, ' '},
|
||||||
|
{2, 1, ' '},
|
||||||
|
{3, 1, ' '},
|
||||||
|
{4, 1, '3'},
|
||||||
|
// tab spanning 2 rows
|
||||||
|
{78, 3, ' '},
|
||||||
|
{79, 3, ' '},
|
||||||
|
{0, 4, ' '},
|
||||||
|
{1, 4, ' '},
|
||||||
|
{2, 4, '9'},
|
||||||
|
//
|
||||||
{0, 2, '5'},
|
{0, 2, '5'},
|
||||||
{1, 2, '6'},
|
{1, 2, '6'},
|
||||||
|
{2, 2, '8'}, // overwritten by BS
|
||||||
{79, 23, '!'},
|
{79, 23, '!'},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ var (
|
|||||||
errWrongArgType = []byte("%!(WRONGTYPE)")
|
errWrongArgType = []byte("%!(WRONGTYPE)")
|
||||||
errNoVerb = []byte("%!(NOVERB)")
|
errNoVerb = []byte("%!(NOVERB)")
|
||||||
errExtraArg = []byte("%!(EXTRA)")
|
errExtraArg = []byte("%!(EXTRA)")
|
||||||
padding = []byte{' '}
|
padding = byte(' ')
|
||||||
trueValue = []byte("true")
|
trueValue = []byte("true")
|
||||||
falseValue = []byte("false")
|
falseValue = []byte("false")
|
||||||
)
|
)
|
||||||
@ -62,7 +62,9 @@ func Printf(format string, args ...interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if blockStart < blockEnd {
|
if blockStart < blockEnd {
|
||||||
hal.ActiveTerminal.Write([]byte(format[blockStart:blockEnd]))
|
for i := blockStart; i < blockEnd; i++ {
|
||||||
|
hal.ActiveTerminal.WriteByte(format[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan til we hit the format character
|
// Scan til we hit the format character
|
||||||
@ -109,7 +111,9 @@ func Printf(format string, args ...interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if blockStart != blockEnd {
|
if blockStart != blockEnd {
|
||||||
hal.ActiveTerminal.Write([]byte(format[blockStart:blockEnd]))
|
for i := blockStart; i < blockEnd; i++ {
|
||||||
|
hal.ActiveTerminal.WriteByte(format[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for unused args
|
// Check for unused args
|
||||||
@ -139,23 +143,25 @@ func fmtBool(v interface{}) {
|
|||||||
// padding specified by padLen. This function uses hal.ActiveTerminal for its
|
// padding specified by padLen. This function uses hal.ActiveTerminal for its
|
||||||
// output.
|
// output.
|
||||||
func fmtString(v interface{}, padLen int) {
|
func fmtString(v interface{}, padLen int) {
|
||||||
var sval []byte
|
|
||||||
|
|
||||||
switch castedVal := v.(type) {
|
switch castedVal := v.(type) {
|
||||||
case string:
|
case string:
|
||||||
sval = []byte(castedVal)
|
fmtRepeat(padding, padLen-len(castedVal))
|
||||||
|
for i := 0; i < len(castedVal); i++ {
|
||||||
|
hal.ActiveTerminal.WriteByte(castedVal[i])
|
||||||
|
}
|
||||||
case []byte:
|
case []byte:
|
||||||
sval = castedVal
|
fmtRepeat(padding, padLen-len(castedVal))
|
||||||
|
hal.ActiveTerminal.Write(castedVal)
|
||||||
default:
|
default:
|
||||||
hal.ActiveTerminal.Write(errWrongArgType)
|
hal.ActiveTerminal.Write(errWrongArgType)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for pad := padLen - len(sval); pad > 0; pad-- {
|
// fmtRepeat writes count bytes with value ch to the hal.ActiveTerminal.
|
||||||
hal.ActiveTerminal.Write(padding)
|
func fmtRepeat(ch byte, count int) {
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
hal.ActiveTerminal.WriteByte(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
hal.ActiveTerminal.Write(sval)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmtInt prints out a formatted version of v in the requested base, applying the
|
// fmtInt prints out a formatted version of v in the requested base, applying the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user