mirror of https://github.com/chzyer/readline.git
add Ctrl+U
This commit is contained in:
parent
c814ccae9a
commit
03d201ab65
|
@ -162,7 +162,7 @@ Users can change that in terminal simulator(i.e. iTerm2) to `Alt`+`B`
|
|||
| `Ctrl`+`S` | Search forwards in history |
|
||||
| `Ctrl`+`T` | Transpose characters |
|
||||
| `Meta`+`T` | Transpose words (TODO) |
|
||||
| `Ctrl`+`U` | Cut text to the beginning of line (TODO) |
|
||||
| `Ctrl`+`U` | Cut text to the beginning of line |
|
||||
| `Ctrl`+`W` | Cut previous word |
|
||||
| `Backspace` | Delete previous character |
|
||||
| `Meta`+`Backspace` | Cut previous word |
|
||||
|
|
1
char.go
1
char.go
|
@ -18,6 +18,7 @@ const (
|
|||
CharBckSearch = 18
|
||||
CharFwdSearch = 19
|
||||
CharTranspose = 20
|
||||
CharCtrlU = 21
|
||||
CharCtrlW = 23
|
||||
CharEsc = 27
|
||||
CharEscapeEx = 91
|
||||
|
|
|
@ -97,6 +97,8 @@ func (o *Operation) ioloop() {
|
|||
case CharBckSearch:
|
||||
o.SearchMode(S_DIR_BCK)
|
||||
keepInSearchMode = true
|
||||
case CharCtrlU:
|
||||
o.buf.KillFront()
|
||||
case CharFwdSearch:
|
||||
o.SearchMode(S_DIR_FWD)
|
||||
keepInSearchMode = true
|
||||
|
@ -185,6 +187,7 @@ func (o *Operation) ioloop() {
|
|||
keepInCompleteMode = true
|
||||
}
|
||||
}
|
||||
|
||||
if !keepInSearchMode && o.IsSearchMode() {
|
||||
o.ExitSearchMode(false)
|
||||
o.buf.Refresh(nil)
|
||||
|
|
121
runebuf.go
121
runebuf.go
|
@ -60,20 +60,19 @@ func (r *RuneBuffer) Len() int {
|
|||
}
|
||||
|
||||
func (r *RuneBuffer) MoveToLineStart() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
r.Refresh(func() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
r.idx = 0
|
||||
})
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) MoveBackward() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
r.Refresh(func() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
r.idx--
|
||||
})
|
||||
}
|
||||
|
@ -132,26 +131,32 @@ func (r *RuneBuffer) DeleteWord() {
|
|||
}
|
||||
|
||||
func (r *RuneBuffer) MoveToPrevWord() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
for i := r.idx - 1; i > 0; i-- {
|
||||
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
|
||||
r.Refresh(func() {
|
||||
r.idx = i
|
||||
})
|
||||
r.Refresh(func() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
r.Refresh(func() {
|
||||
|
||||
for i := r.idx - 1; i > 0; i-- {
|
||||
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
|
||||
r.idx = i
|
||||
return
|
||||
}
|
||||
}
|
||||
r.idx = 0
|
||||
})
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) SetIdx(idx int) (change int) {
|
||||
i := r.idx
|
||||
r.idx = idx
|
||||
return r.idx - i
|
||||
func (r *RuneBuffer) KillFront() {
|
||||
r.Refresh(func() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
length := len(r.buf) - r.idx
|
||||
copy(r.buf[:length], r.buf[r.idx:])
|
||||
r.idx = 0
|
||||
r.buf = r.buf[:length]
|
||||
})
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) Kill() {
|
||||
|
@ -161,15 +166,15 @@ func (r *RuneBuffer) Kill() {
|
|||
}
|
||||
|
||||
func (r *RuneBuffer) Transpose() {
|
||||
if len(r.buf) < 2 {
|
||||
if len(r.buf) == 1 {
|
||||
r.Refresh(func() {
|
||||
r.idx++
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
r.Refresh(func() {
|
||||
if len(r.buf) == 1 {
|
||||
r.idx++
|
||||
}
|
||||
|
||||
if len(r.buf) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
if r.idx == 0 {
|
||||
r.idx = 1
|
||||
} else if r.idx >= len(r.buf) {
|
||||
|
@ -181,55 +186,53 @@ func (r *RuneBuffer) Transpose() {
|
|||
}
|
||||
|
||||
func (r *RuneBuffer) MoveToNextWord() {
|
||||
for i := r.idx + 1; i < len(r.buf); i++ {
|
||||
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
|
||||
r.Refresh(func() {
|
||||
r.idx = i
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
r.Refresh(func() {
|
||||
for i := r.idx + 1; i < len(r.buf); i++ {
|
||||
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
|
||||
r.idx = i
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
r.idx = len(r.buf)
|
||||
})
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) BackEscapeWord() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
for i := r.idx - 1; i > 0; i-- {
|
||||
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
|
||||
r.Refresh(func() {
|
||||
r.buf = append(r.buf[:i], r.buf[r.idx:]...)
|
||||
r.idx = i
|
||||
})
|
||||
r.Refresh(func() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
for i := r.idx - 1; i > 0; i-- {
|
||||
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
|
||||
r.buf = append(r.buf[:i], r.buf[r.idx:]...)
|
||||
r.idx = i
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
r.Refresh(func() {
|
||||
r.buf = r.buf[:0]
|
||||
r.idx = 0
|
||||
})
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) Backspace() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
r.Refresh(func() {
|
||||
if r.idx == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
r.idx--
|
||||
r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...)
|
||||
})
|
||||
}
|
||||
|
||||
func (r *RuneBuffer) MoveToLineEnd() {
|
||||
if r.idx == len(r.buf) {
|
||||
return
|
||||
}
|
||||
|
||||
r.Refresh(func() {
|
||||
if r.idx == len(r.buf) {
|
||||
return
|
||||
}
|
||||
|
||||
r.idx = len(r.buf)
|
||||
})
|
||||
}
|
||||
|
@ -242,9 +245,15 @@ func (r *RuneBuffer) IdxLine() int {
|
|||
totalWidth := RunesWidth(r.buf[:r.idx]) + r.PromptLen()
|
||||
w := getWidth()
|
||||
line := totalWidth / w
|
||||
if totalWidth%w == 0 {
|
||||
|
||||
// if cursor is in last colmun and not any character behind it
|
||||
// the cursor will in the first line, otherwise will in the second line
|
||||
// this situation only occurs in golang's Stdout
|
||||
// TODO: figure out why
|
||||
if totalWidth%w == 0 && len(r.buf) == r.idx {
|
||||
line--
|
||||
}
|
||||
|
||||
return line
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue