// Editor methods involved in drawing to the console package editor import ( "fmt" "strings" "time" "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) e.drawStatusBar(ab) e.drawMessageBar(ab) ab.append(terminal.MoveCursor(e.renderX-e.offset.x, e.cursor.y-e.offset.y)) ab.append(terminal.ShowCursor) terminal.Write(ab.toString()) } func (e *editor) scroll() { e.renderX = 0 if e.cursor.y < e.document.rowCount() { e.renderX = e.document.rows[e.cursor.y].cursorXToRenderX(e.cursor.x) } 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.renderX < e.offset.x { e.offset.x = e.renderX } if e.renderX >= e.offset.x+e.screen.Cols { e.offset.x = e.renderX - e.screen.Cols } } func (e *editor) drawRows(ab *buffer) { for y := 0; y < e.screen.Rows; y++ { fileRow := y + e.offset.y if fileRow >= e.document.rowCount() { e.drawPlaceholderRow(y, ab) } else { rawRow := e.document.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.document.rows[fileRow].rSize() - e.offset.x outputRow := truncate(string(e.document.rows[fileRow].render[e.offset.x:]), rowLen) ab.append(outputRow) } ab.appendLn(terminal.ClearLine) } } func (e *editor) drawPlaceholderRow(y int, ab *buffer) { if e.document.rowCount() == 0 && y == e.screen.Rows/3 { welcome := fmt.Sprintf("Gilo editor -- version %s", KiloVersion) if len(welcome) > e.screen.Cols { welcome = truncate(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('~') } } func (e *editor) drawStatusBar(ab *buffer) { cols := e.screen.Cols ab.append(terminal.InvertColor) fileName := "[No Name]" if e.document.filename != "" { fileName = e.document.filename } leftStatus := fmt.Sprintf("%.20s - %d lines", fileName, e.document.rowCount()) length := len(leftStatus) if length > cols { leftStatus = truncate(leftStatus, cols) ab.append(leftStatus) ab.append(terminal.ResetColor) return } rightStatus := fmt.Sprintf("%d/%d", e.cursor.y, e.document.rowCount()) rlength := len(rightStatus) statusLength := length + rlength if statusLength <= cols { paddingLength := cols - statusLength padding := strings.Repeat(" ", paddingLength) ab.append(leftStatus) ab.append(padding) ab.append(rightStatus) ab.append(terminal.ResetColor) return } ab.append(leftStatus) // Pad the rest of the status line padding := strings.Repeat(" ", cols-length) ab.append(padding) ab.append(terminal.ResetColor) } func (e *editor) drawMessageBar(ab *buffer) { ab.append("\r\n") ab.append(terminal.ClearLine) msg := truncate(e.status.message, e.screen.Cols) if len(msg) > 0 && time.Since(e.status.created).Seconds() < 5.0 { ab.append(msg) } }