// Editor methods involved in drawing to the console package editor import ( "fmt" "strings" "timshome.page/gilo/terminal" ) // ---------------------------------------------------------------------------- // !Editor Methods // ---------------------------------------------------------------------------- func (e *editor) RefreshScreen() { e.scroll() ab := newBuffer() ab.append(terminal.HideCursor) ab.append(terminal.ResetCursor) e.drawRows(ab) ab.append(terminal.MoveCursor(e.cursor.x - e.offset.x, e.cursor.y - e.offset.y)) ab.append(terminal.ShowCursor) terminal.Write(ab.toString()) } func (e *editor) scroll() { if e.cursor.y < e.offset.y { e.offset.y = e.cursor.y } if e.cursor.y >= e.offset.y + e.screen.Rows { e.offset.y = e.cursor.y - e.screen.Rows + 1 } if e.cursor.x < e.offset.x { e.offset.x = e.cursor.x } if e.cursor.x >= e.offset.x + e.screen.Cols { e.offset.x = e.cursor.x - e.screen.Cols } } func (e *editor) drawRows(ab *buffer) { for y :=0; y < e.screen.Rows; y++ { fileRow := y + e.offset.y if fileRow >= len(e.rows) { e.drawPlaceholderRow(y, ab) } else { rawRow := e.rows[fileRow] // If the column offset is greater than the length of the row, // just display an empty row if e.offset.x > rawRow.size() { ab.append("") continue } rowLen := e.rows[fileRow].rSize() - e.offset.x outputRow := truncateString(string(e.rows[fileRow].render[e.offset.x:]), rowLen) ab.append(outputRow) } ab.append(terminal.ClearLine) if y < (e.screen.Rows - 1) { ab.append("\r\n") } } } func (e *editor) drawPlaceholderRow(y int, ab *buffer) { if len(e.rows) == 0 && y == e.screen.Rows / 3 { welcome := fmt.Sprintf("Gilo editor -- version %s", KiloVersion) if len(welcome) > e.screen.Cols { welcome = truncateString(welcome, e.screen.Cols) } padding := (e.screen.Cols - len(welcome)) / 2 if padding > 0 { ab.appendRune('~') padding-- } for padding > 0 { padding-- ab.appendRune(' ') } ab.append(welcome) } else { ab.appendRune('~') } } // ---------------------------------------------------------------------------- // !Output Buffer // ---------------------------------------------------------------------------- type buffer struct { buf *strings.Builder } func newBuffer() *buffer { var buf strings.Builder b := new(buffer) b.buf = &buf return b } func (b *buffer) appendRune(r rune) int { size, _ := b.buf.WriteRune(r) return size } func (b *buffer) append(s string) int { size, _ := b.buf.WriteString(s) return size } func (b *buffer) appendLn(s string) int { str := fmt.Sprintf("%s\r\n", s) size, _ := b.buf.WriteString(str) return size } func (b *buffer) toString() string { return b.buf.String() }