|
|
|
@ -12,12 +12,14 @@ import (
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
stdin = bufio.NewReader(os.Stdin)
|
|
|
|
|
stdout = bufio.NewWriter(os.Stdout)
|
|
|
|
|
stdin = bufio.NewReader(os.Stdin)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
KEY_ESC = rune('\x1b')
|
|
|
|
|
KEY_BACKSPACE = rune('\x08')
|
|
|
|
|
KEY_ENTER = rune('\x0d')
|
|
|
|
|
KEY_TAB = rune('\x09')
|
|
|
|
|
KEY_UP_ARROW = (iota + 1000)
|
|
|
|
|
KEY_DOWN_ARROW = (iota + 1000)
|
|
|
|
|
KEY_LEFT_ARROW = (iota + 1000)
|
|
|
|
@ -31,33 +33,102 @@ const (
|
|
|
|
|
|
|
|
|
|
func editorKeyPresses() bool {
|
|
|
|
|
char := editorReadKey()
|
|
|
|
|
state.StatusLine = ""
|
|
|
|
|
|
|
|
|
|
editorMoveCaret(char)
|
|
|
|
|
|
|
|
|
|
if char == ctrl_key('r') {
|
|
|
|
|
uiRefresh()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if char == ctrl_key('w') {
|
|
|
|
|
} else if char == ctrl_key('s') {
|
|
|
|
|
fileSave()
|
|
|
|
|
} else if char == ctrl_key('j') {
|
|
|
|
|
for i := state.rowOffset + state.Cy; i > 0; i-- {
|
|
|
|
|
editorMoveCaret(KEY_UP_ARROW)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if char == ctrl_key('s') {
|
|
|
|
|
} else if char == ctrl_key('k') {
|
|
|
|
|
for i := state.rowOffset + state.Cy; i < state.getCurrentRowLen()-1; i++ {
|
|
|
|
|
editorMoveCaret(KEY_DOWN_ARROW)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if char == ctrl_key('q') || char == 'q' {
|
|
|
|
|
} else if char == ctrl_key('q') {
|
|
|
|
|
return false
|
|
|
|
|
} else if char == KEY_BACKSPACE || char == KEY_DELETE {
|
|
|
|
|
editorRemoveChar(char)
|
|
|
|
|
} else if char >= 32 && char <= 126 || char == KEY_ENTER || char == KEY_TAB {
|
|
|
|
|
editorInsertChar(char)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func editorRemoveChar(char rune) {
|
|
|
|
|
lineText := state.rows[state.Cy]
|
|
|
|
|
rl := state.getCurrentRowLen()
|
|
|
|
|
|
|
|
|
|
cx := state.Cx
|
|
|
|
|
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)
|
|
|
|
|
} else {
|
|
|
|
|
state.rows = state.rows[:state.Cy-1]
|
|
|
|
|
state.Cy--
|
|
|
|
|
}
|
|
|
|
|
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:])
|
|
|
|
|
editorMoveCaret(KEY_LEFT_ARROW)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if char == KEY_DELETE {
|
|
|
|
|
if cx < rl-1 {
|
|
|
|
|
state.rows[state.Cy] = fmt.Sprintf("%s%s", lineText[:cx], lineText[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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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:]...)
|
|
|
|
|
}
|
|
|
|
|
state.Cx = 0
|
|
|
|
|
editorMoveCaret(KEY_DOWN_ARROW)
|
|
|
|
|
} else {
|
|
|
|
|
state.rows[state.Cy] = fmt.Sprintf("%s%c%s", lt[:cx], char, lt[cx:])
|
|
|
|
|
editorMoveCaret(KEY_RIGHT_ARROW)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func editorMoveCaret(char rune) {
|
|
|
|
|
x, y := state.Cx, state.Cy
|
|
|
|
|
if len(state.rows) == 0 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rx := editorCxoRx(state.rows[y], x)
|
|
|
|
|
|
|
|
|
@ -96,7 +167,6 @@ func editorMoveCaret(char rune) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if char == ctrl_key(KEY_DOWN_ARROW) {
|
|
|
|
|
y = len(state.rows) - 1
|
|
|
|
|
}
|
|
|
|
@ -129,13 +199,13 @@ func editorScroll() {
|
|
|
|
|
state.colOffset = rx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if state.Cx >= state.colOffset+displayWidth {
|
|
|
|
|
// state.colOffset = state.Cx - displayWidth
|
|
|
|
|
// }
|
|
|
|
|
if state.Cx >= state.colOffset+displayWidth {
|
|
|
|
|
state.colOffset = state.Cx - displayWidth
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if state.Cx < state.colOffset {
|
|
|
|
|
// state.colOffset = state.Cx
|
|
|
|
|
// }
|
|
|
|
|
if state.Cx < state.colOffset {
|
|
|
|
|
state.colOffset = state.Cx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if state.Cy >= state.rowOffset+(state.Rows-2) {
|
|
|
|
|
state.rowOffset = state.Cy - (state.Rows - 2)
|
|
|
|
@ -154,30 +224,27 @@ func editorReadKey() rune {
|
|
|
|
|
for read != 1 {
|
|
|
|
|
in, read, err = stdin.ReadRune()
|
|
|
|
|
if err != nil && err != io.EOF {
|
|
|
|
|
log.Fatal("FAILED TO READ:", err)
|
|
|
|
|
return KEY_ESC
|
|
|
|
|
//log.Fatal("FAILED TO READ:", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fmt.Printf("%v == %v ? %v", rune(in[0]), KEY_ESC, rune(in[0]) == KEY_ESC)
|
|
|
|
|
if in == KEY_ESC {
|
|
|
|
|
seq := make([]rune, 3)
|
|
|
|
|
if seq[0], read, err = stdin.ReadRune(); err != nil || read != 1 {
|
|
|
|
|
return KEY_ESC
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if seq[1], read, err = stdin.ReadRune(); err != nil || read != 1 {
|
|
|
|
|
return KEY_ESC
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if seq[0] == '[' {
|
|
|
|
|
|
|
|
|
|
// fmt.Printf("%c %c %c", seq[0], seq[1], seq[2])
|
|
|
|
|
if seq[1] >= '0' && seq[1] <= '9' {
|
|
|
|
|
if seq[2], read, err = stdin.ReadRune(); err != nil || read != 1 {
|
|
|
|
|
return KEY_ESC
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
state.StatusLine = fmt.Sprintf("Last Read = '%c''%c''%c' ", seq[0], seq[1], seq[2])
|
|
|
|
|
|
|
|
|
|
// handle page up/down and home keys
|
|
|
|
|
if seq[2] == '~' {
|
|
|
|
|
switch seq[1] {
|
|
|
|
@ -224,6 +291,13 @@ func editorReadKey() rune {
|
|
|
|
|
return KEY_ESC
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch in {
|
|
|
|
|
case '\x7f': // backspace
|
|
|
|
|
return KEY_BACKSPACE
|
|
|
|
|
case '\x0d':
|
|
|
|
|
return KEY_ENTER
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return in
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|