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())
}
// if len(state.rows) == 0 || (len(state.rows) == 1 && state.rows[0] == "") {
// state.rows = []string{" "}
// }
if len(state.rows) == 0 || (len(state.rows) == 1 && state.rows[0] == "") {
state.rows = []string{""}
}
}
f.Close()
@ -47,14 +47,24 @@ func fileSave() {
defer f.Close()
bytesWritten := 0
charsWritten := 0
linesWritten := 0
for _, row := range state.rows {
bw, err := fmt.Fprintf(f, "%s\n", row)
if err != nil {
log.Fatalf("COULD NOT SAVE FILE: %v", err)
}
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 {
char := editorReadKey()
state.StatusLine = ""
editorMoveCaret(char)
state.StatusLines[1] = ""
if char == ctrl_key('r') {
uiRefresh()
@ -55,71 +53,133 @@ func editorKeyPresses() bool {
editorRemoveChar(char)
} else if char >= 32 && char <= 126 || char == KEY_ENTER || char == KEY_TAB {
editorInsertChar(char)
} else {
editorMoveCaret(char)
}
return true
}
func editorRemoveChar(char rune) {
lineText := state.rows[state.Cy]
rl := state.getCurrentRowLen()
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 cx == 0 && state.Cy > 0 {
plt := state.rows[state.Cy-1]
state.rows[state.Cy-1] = fmt.Sprintf("%s%s", plt, lineText)
if state.Cy < len(state.rows)-1 {
state.rows = append(state.rows[:state.Cy-1], state.rows[state.Cy:]...)
editorMoveCaret(KEY_UP_ARROW)
if cx == 0 && cy == 0 {
return
}
// backspace in the middle of a line
if cx > 0 && cx < rl {
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 {
state.rows = state.rows[:state.Cy-1]
state.Cy--
state.rows = append(state.rows[:cy], state.rows[cy+1:]...)
}
state.Cx = 0
} else if cx == 0 {
// do nothing because there are no characters
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)
return
}
} else if char == KEY_DELETE {
// in middle of line
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) {
lt := ""
cx := state.Cx
if len(state.rows) > 0 {
lt = state.rows[state.Cy]
} else {
state.rows = []string{fmt.Sprintf("%c", char)}
return
cy := state.Cy
rc := len(state.rows)
lt := ""
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 {
oldL := lt[:cx]
newL := lt[cx:]
state.rows[state.Cy] = oldL
if state.Cy == len(state.rows)-1 {
state.rows[state.Cy] = oldL
state.rows = append(state.rows, newL)
} else {
state.rows = append(append(state.rows[:state.Cy], newL), state.rows[state.Cy:]...)
// beginning of line
if cx == 0 {
if cy == rc {
state.rows = append(state.rows, lt)
} else if cy < rc {
state.rows = append(append(state.rows[:cy], lt), state.rows[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
editorMoveCaret(KEY_DOWN_ARROW)
} 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)
}
}
@ -165,6 +225,8 @@ func editorMoveCaret(char rune) {
case KEY_END:
x = state.Cols - 1
break
default:
return
}
if char == ctrl_key(KEY_DOWN_ARROW) {

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

41
ui.go

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

Loading…
Cancel
Save