got backspace and enter working

master
Adam Veldhousen 4 years ago
parent cab3304e5b
commit def28180f2
Signed by: adam
GPG Key ID: 6DB29003C6DD1E4B

@ -29,9 +29,9 @@ func fileOpen(fname string) {
state.rows = append(state.rows, fread.Text()) state.rows = append(state.rows, fread.Text())
} }
// if len(state.rows) == 0 || (len(state.rows) == 1 && state.rows[0] == "") { if len(state.rows) == 0 || (len(state.rows) == 1 && state.rows[0] == "") {
// state.rows = []string{" "} state.rows = []string{""}
// } }
} }
f.Close() f.Close()
@ -47,14 +47,24 @@ func fileSave() {
defer f.Close() defer f.Close()
bytesWritten := 0 bytesWritten := 0
charsWritten := 0
linesWritten := 0
for _, row := range state.rows { for _, row := range state.rows {
bw, err := fmt.Fprintf(f, "%s\n", row) bw, err := fmt.Fprintf(f, "%s\n", row)
if err != nil { if err != nil {
log.Fatalf("COULD NOT SAVE FILE: %v", err) log.Fatalf("COULD NOT SAVE FILE: %v", err)
} }
bytesWritten += bw bytesWritten += bw
charsWritten += len([]rune(row)) + 1
linesWritten++
} }
state.StatusLine = fmt.Sprintf("'%s' wrote %d bytes.", state.file, bytesWritten) state.StatusLines[1] = fmt.Sprintf(
"'%s' saved. %dL, %dC, %d bytes",
state.file,
linesWritten,
charsWritten,
bytesWritten,
)
} }

@ -33,9 +33,7 @@ const (
func editorKeyPresses() bool { func editorKeyPresses() bool {
char := editorReadKey() char := editorReadKey()
state.StatusLine = "" state.StatusLines[1] = ""
editorMoveCaret(char)
if char == ctrl_key('r') { if char == ctrl_key('r') {
uiRefresh() uiRefresh()
@ -55,71 +53,133 @@ func editorKeyPresses() bool {
editorRemoveChar(char) editorRemoveChar(char)
} else if char >= 32 && char <= 126 || char == KEY_ENTER || char == KEY_TAB { } else if char >= 32 && char <= 126 || char == KEY_ENTER || char == KEY_TAB {
editorInsertChar(char) editorInsertChar(char)
} else {
editorMoveCaret(char)
} }
return true return true
} }
func editorRemoveChar(char rune) { func editorRemoveChar(char rune) {
lineText := state.rows[state.Cy]
rl := state.getCurrentRowLen()
cx := state.Cx cx := state.Cx
cy := state.Cy
rc := len(state.rows)
lt := ""
rl := 0
if rc > 0 {
lt = state.rows[cy]
rl = state.getCurrentRowLen()
}
// file is empty
if rc == 0 && lt == "" {
return
}
/*
1. Backspace at beginning of a line
2. Backspace in middle of a line
3. Backspace at end of a line
4. Backspace when there are 0 characters in the file
*/
if char == KEY_BACKSPACE { if char == KEY_BACKSPACE {
if cx == 0 && state.Cy > 0 { if cx == 0 && cy == 0 {
plt := state.rows[state.Cy-1] return
state.rows[state.Cy-1] = fmt.Sprintf("%s%s", plt, lineText) }
if state.Cy < len(state.rows)-1 { // backspace in the middle of a line
state.rows = append(state.rows[:state.Cy-1], state.rows[state.Cy:]...) if cx > 0 && cx < rl {
editorMoveCaret(KEY_UP_ARROW) state.rows[cy] = fmt.Sprintf("%s%s", lt[:cx-1], lt[cx:])
editorMoveCaret(KEY_LEFT_ARROW)
return
}
// backspace at start of line
// join lines together and remove
if cx == 0 && cy > 0 {
plt := state.rows[cy-1]
_, highlightedRowLen := renderLine(plt)
state.rows[cy-1] = fmt.Sprintf("%s%s", plt, lt)
editorMoveCaret(KEY_UP_ARROW)
for x := 0; x < highlightedRowLen; x++ {
editorMoveCaret(KEY_RIGHT_ARROW)
}
// if we're at the last row, make sure to only remove the last line
if cy == rc-1 {
state.rows = state.rows[:cy]
} else { } else {
state.rows = state.rows[:state.Cy-1] state.rows = append(state.rows[:cy], state.rows[cy+1:]...)
state.Cy--
} }
state.Cx = 0
} else if cx == 0 {
// do nothing because there are no characters
return return
} else { }
state.StatusLine = fmt.Sprintf("D: %d - %s%s", cx, lineText[:cx-1], lineText[cx:])
state.rows[state.Cy] = fmt.Sprintf("%s%s", lineText[:cx-1], lineText[cx:]) // backspace at end of line
if cx == rl {
state.rows[cy] = lt[:cx-1]
editorMoveCaret(KEY_LEFT_ARROW) editorMoveCaret(KEY_LEFT_ARROW)
return
} }
} else if char == KEY_DELETE { } else if char == KEY_DELETE {
// in middle of line
if cx < rl-1 { if cx < rl-1 {
state.rows[state.Cy] = fmt.Sprintf("%s%s", lineText[:cx], lineText[cx+1:]) state.rows[state.Cy] = fmt.Sprintf("%s%s", lt[:cx], lt[cx+1:])
} }
} else {
return
} }
} }
func editorInsertChar(char rune) { func editorInsertChar(char rune) {
lt := ""
cx := state.Cx cx := state.Cx
if len(state.rows) > 0 { cy := state.Cy
lt = state.rows[state.Cy] rc := len(state.rows)
} else {
state.rows = []string{fmt.Sprintf("%c", char)} lt := ""
return rl := 0
if rc > 0 {
lt = state.rows[cy]
rl = state.getCurrentRowLen()
} }
/*
1. Enter at beginning line
2. Enter at middle of line
3. Enter at end of line
*/
if char == KEY_ENTER { if char == KEY_ENTER {
oldL := lt[:cx] // beginning of line
newL := lt[cx:] if cx == 0 {
state.rows[state.Cy] = oldL if cy == rc {
if state.Cy == len(state.rows)-1 { state.rows = append(state.rows, lt)
state.rows[state.Cy] = oldL } else if cy < rc {
state.rows = append(state.rows, newL) state.rows = append(append(state.rows[:cy], lt), state.rows[cy:]...)
} else { }
state.rows = append(append(state.rows[:state.Cy], newL), state.rows[state.Cy:]...) state.rows[cy] = ""
// end of a line
} else if cx >= rl {
if cy < rc {
state.rows = append(append(state.rows[:cy], ""), state.rows[cy:]...)
state.rows[cy] = lt
} else if cy == rc {
state.rows = append(state.rows[:cy], "")
}
// mid line
} else if cx > 0 {
state.rows = append(append(state.rows[:cy], lt[cx:]), state.rows[cy:]...)
state.rows[cy] = lt[:cx]
} }
state.Cx = 0 state.Cx = 0
editorMoveCaret(KEY_DOWN_ARROW) editorMoveCaret(KEY_DOWN_ARROW)
} else { } else {
state.rows[state.Cy] = fmt.Sprintf("%s%c%s", lt[:cx], char, lt[cx:]) state.StatusLines[1] = fmt.Sprintf("%c %d", char, char)
state.rows[cy] = fmt.Sprintf("%s%c%s", lt[:cx], char, lt[cx:])
editorMoveCaret(KEY_RIGHT_ARROW) editorMoveCaret(KEY_RIGHT_ARROW)
} }
} }
@ -165,6 +225,8 @@ func editorMoveCaret(char rune) {
case KEY_END: case KEY_END:
x = state.Cols - 1 x = state.Cols - 1
break break
default:
return
} }
if char == ctrl_key(KEY_DOWN_ARROW) { if char == ctrl_key(KEY_DOWN_ARROW) {

@ -19,7 +19,7 @@ type editorState struct {
Cy int Cy int
Rows int Rows int
Cols int Cols int
StatusLine string StatusLines [2]string
DebugLine string DebugLine string
rows []string rows []string
rowOffset int rowOffset int
@ -66,6 +66,7 @@ func initEditor() {
state.Buffer = &bytes.Buffer{} state.Buffer = &bytes.Buffer{}
state.rows = []string{fmt.Sprintf("Pound Ed %s", Version)} state.rows = []string{fmt.Sprintf("Pound Ed %s", Version)}
state.file = "" state.file = ""
state.StatusLines = [2]string{}
} }
func cleanup() { func cleanup() {

41
ui.go

@ -16,8 +16,11 @@ import (
const ( const (
CLEAR = "\x1b[K" CLEAR = "\x1b[K"
TAB_SIZE = 8 TAB_SIZE = 8
EMPTY_LINE_GUTTER = " x~ " EMPTY_LINE_GUTTER = " ~ "
LINE_GUTTER = " " LINE_GUTTER = " "
STATUSLINEHEIGHT = 2
WHITESPACE = "\xB8"
NEWLINE = '\xAC'
) )
func uiDrawRows() { func uiDrawRows() {
@ -36,26 +39,22 @@ func uiDrawRows() {
file = "NO FILE" file = "NO FILE"
} }
statusLine := fmt.Sprintf( state.StatusLines[0] = fmt.Sprintf(
"%s\x1b[1;7m '%s' \x1b[m L:%d/%d C:%d/%d | H:%d W: %d | %s", "%s\x1b[1;7m '%s' \x1b[m L:%d/%d C:%d/%d | H:%d W: %d",
CLEAR, CLEAR,
file, file,
state.Cy+1, state.Cy+1,
len(state.rows), len(state.rows),
rx+1, rx+1,
highlightedRowLen, highlightedRowLen+1,
state.Rows-1, state.Rows-1,
state.Cols-gutterWidth-1, state.Cols-gutterWidth-1)
state.StatusLine)
for y := 0; y < state.Rows; y++ { for y := 0; y < state.Rows; y++ {
if y == state.Rows-1 { if y >= state.Rows-STATUSLINEHEIGHT {
statusLen := len(statusLine) buf.WriteString(drawStatusLine(y - (state.Rows - STATUSLINEHEIGHT)))
if statusLen > state.Cols { } else if state.Cy < len(state.rows) && y + state.rowOffset < len(state.rows) {
statusLen = state.Cols
}
buf.WriteString(statusLine[:statusLen])
} else if y < state.Rows && state.Cy < len(state.rows) {
rowIdx := y + state.rowOffset rowIdx := y + state.rowOffset
if rowIdx < len(state.rows) { if rowIdx < len(state.rows) {
@ -75,8 +74,8 @@ func uiDrawRows() {
renderLen = rowEnd renderLen = rowEnd
} }
if state.colOffset < renderLen { if state.colOffset <= renderLen {
buf.WriteString(row[state.colOffset:renderLen]) buf.WriteString(fmt.Sprintf("%s%c", row[state.colOffset:renderLen], NEWLINE))
} }
if rowLen > rowEnd { if rowLen > rowEnd {
@ -95,6 +94,16 @@ func uiDrawRows() {
} }
} }
func drawStatusLine(row int) string {
statusLine := state.StatusLines[row]
statusLen := len(statusLine)
if statusLen > state.Cols {
statusLen = state.Cols
}
return statusLine[:statusLen]
}
func uiRefresh() { func uiRefresh() {
buf := state.Buffer buf := state.Buffer
fmt.Fprintf(buf, "\x1b[?251") fmt.Fprintf(buf, "\x1b[?251")
@ -222,7 +231,7 @@ func renderLine(line string) (string, int) {
if char == '\t' { if char == '\t' {
tabCount++ tabCount++
for i := 0; i < TAB_SIZE; i++ { for i := 0; i < TAB_SIZE; i++ {
rl += " " rl += WHITESPACE
} }
continue continue
} }

Loading…
Cancel
Save