You can access the code in this chapter in the Kilo-Go Github repository, in the statusbar branch.
Currently your file structure should look something like this:
Scrolling with Page Up and Page Down
Now that we have scrolling, let's make the Page Up and Page Down scroll an entire page
File: editor/input.go
func (e *EditorConfig) editorProcessKeypress() {
...
switch b {
...
case utils.PAGE_DOWN:
e.cy = min(e.rowoffset+e.screenrows+1, e.numrows)
times := e.screenrows
for range times {
e.editorMoveCursor(utils.ARROW_DOWN)
}
case utils.PAGE_UP:
e.cy = e.rowoffset
times := e.screenrows
for range times {
e.editorMoveCursor(utils.ARROW_UP)
}
...
}
Move to the end of the line with End
Now let's have the End key to move the cursor to the end of the current line, not the end of the screen.
File: editor/input.go
func (e *EditorConfig) editorProcessKeypress() {
...
switch b {
...
case utils.END_KEY:
if e.cy < e.numrows {
e.cx = len(e.rows[e.cy].chars)
}
}
}
Make space for the status bar
The last thing we will add before editing text, is a status bar. This will display useful information such as the file name, the cursor position, and other things that we will find useful as we continue working on the editor. However, first thing is we need to have some space in the screen to display the status bar.
File: editor/editor.go
func NewEditor(f func()) *EditorConfig {
rows, cols, err := utils.GetWindowSize()
...
return &EditorConfig{
...
screenrows: rows - 1,
...
}
}
File: editor/output.go
func (e *EditorConfig) editorDrawRows(abuf *ab.AppendBuffer) {
for y := range e.screenrows {
filerow := y + e.rowoffset
...
fmt.Fprintf(abuf, "%c[K", utils.ESC) // We moved this line from the top to the bottom of the for loop
fmt.Fprintf(abuf, "\r\n")
}
}
Display the status bar
To display the status bar, lets make it have inverted color as the rest of the screen. The m command causes the text printed after it to be printed with various possible attributes including bold 1, underscore 4, blink 5, and inverted colors 7. For example, you could specify all of these attributes using the command <Esc>[1;4;5;7m. An argument of 0 clears all attributes, and is the default argument, so we use <Esc>[m to go back to normal text formatting.
File: editor/output.go
func (e *EditorConfig) editorRefreshScreen() {
...
e.editorDrawRows(abuf)
e.editorDrawStatusBar(abuf)
...
}
func (e *EditorConfig) editorDrawStatusBar(abuf *ab.AppendBuffer) {
fmt.Fprintf(abuf, "%c[7m", utils.ESC)
for range e.screencols {
fmt.Fprintf(abuf, " ")
}
fmt.Fprintf(abuf, "%c[m", utils.ESC)
}
Display the file name
So lets begin displaying some useful information to the status line, the first thing we will show is the name of the file we are currently editing, and if we haven't opened any file we will display [No name]
File: editor/editor.go
type EditorConfig struct {
...
filename string
...
}
func NewEditor(f func()) *EditorConfig {
...
return &EditorConfig{
...
filename: "",
...
}
}
File: editor/file.go
func (e *EditorConfig) editorOpen(filename string) {
...
e.filename = filename
...
}
File: editor/output.go
func (e *EditorConfig) editorDrawStatusBar(abuf *ab.AppendBuffer) {
status := e.filename
if status == "" {
status = "[No Name]"
}
fmt.Fprintf(abuf, "%c[7m", utils.ESC)
fmt.Fprintf(abuf, " %s", status)
for range e.screencols - (len(status) + 1) {
fmt.Fprintf(abuf, " ")
}
fmt.Fprintf(abuf, "%c[m", utils.ESC)
}
Display the cursor position
Let's display at the right side of the status bar the cursor's position information
File: editor/output.go
func (e *EditorConfig) editorDrawStatusBar(abuf *ab.AppendBuffer) {
...
width := e.screencols - len(status) - 1
rstatus := fmt.Sprintf("column: %d row: %d/%d ", e.rx+1, e.cy+1, e.numrows)
...
for k := range width {
if k+len(rstatus) == width {
fmt.Fprintf(abuf, "%s", rstatus)
break
}
fmt.Fprintf(abuf, " ")
}
...
}
Status message
We will now add a place where we can give user some information below the status bar
File: editor/editor.go
type EditorConfig struct {
...
statusMessage string
...
}
func NewEditor(f func()) *EditorConfig {
rows, cols, err := utils.GetWindowSize()
if err != nil {
utils.SafeExit(f, err)
}
return &EditorConfig{
...
screenrows: rows - 2,
...
statusMessage: "",
...
}
}
func (e *EditorConfig) EditorLoop() {
...
e.editorSetStatusMessage("HELP: Ctrl-Q = quit")
for {
...
}
}
File: editor/output.go
func (e *EditorConfig) editorRefreshScreen() {
...
e.editorDrawRows(abuf)
e.editorDrawStatusBar(abuf)
e.editorDrawMessageBar(abuf)
...
}
func (e *EditorConfig) editorDrawStatusBar(abuf *ab.AppendBuffer) {
...
fmt.Fprintf(abuf, "%c[m", utils.ESC)
fmt.Fprintf(abuf, "\r\n")
}
func (e *EditorConfig) editorSetStatusMessage(message string) {
e.statusMessage = message
}
func (e *EditorConfig) editorDrawMessageBar(abuf *ab.AppendBuffer) {
fmt.Fprintf(abuf, "%c[K", utils.ESC)
fmt.Fprintf(abuf, " %s", e.statusMessage)
}
What we've achieved
After finishing all of the steps until now, the editor, should look something like this:


Top comments (0)