fixed not working in screen #3

This commit is contained in:
Cheney 2015-09-27 10:12:15 +08:00
parent 7e432495e0
commit a81fb5db7a
3 changed files with 122 additions and 80 deletions

View File

@ -194,12 +194,17 @@ Users can change that in terminal simulator(i.e. iTerm2) to `Alt`+`B`
# Tested with # Tested with
| Environment | $TERM | | Environment | $TERM |
|-------------------------------|-------| |-------------------------------|--------|
| Mac OS X iTerm2 | xterm | | Mac OS X iTerm2 | xterm |
| Mac OS X default Terminal.app | xterm | | Mac OS X default Terminal.app | xterm |
| Ubuntu Server 14.04 LTS | linux | | Mac OS X iTerm2 Screen | screen |
| Centos 7 | linux | | Mac OS X iTerm2 Tmux | screen |
| Ubuntu Server 14.04 LTS | linux |
| Centos 7 | linux |
### Notice:
* `Ctrl`+`A` is not working as a Control Command in screen
If you test it otherwhere, whether it works fine or not, please let me know! If you test it otherwhere, whether it works fine or not, please let me know!

View File

@ -24,7 +24,7 @@ func (w *wrapWriter) Write(b []byte) (int, error) {
buf.Clean() buf.Clean()
n, err := w.target.Write(b) n, err := w.target.Write(b)
if w.t.IsReading() { if w.t.IsReading() {
w.r.buf.Refresh() w.r.buf.Refresh(nil)
} }
if w.r.IsSearchMode() { if w.r.IsSearchMode() {
w.r.SearchRefresh(-1) w.r.SearchRefresh(-1)
@ -61,7 +61,7 @@ func (o *Operation) ioloop() {
continue continue
} }
o.buf.Refresh() o.buf.Refresh(nil)
switch r { switch r {
case CharEnter, CharCtrlJ: case CharEnter, CharCtrlJ:
o.UpdateHistory(o.buf.Runes(), false) o.UpdateHistory(o.buf.Runes(), false)
@ -75,14 +75,16 @@ func (o *Operation) ioloop() {
} }
switch r { switch r {
case 'i':
o.buf.Clean()
case CharCancel: case CharCancel:
if o.IsSearchMode() { if o.IsSearchMode() {
o.ExitSearchMode(true) o.ExitSearchMode(true)
o.buf.Refresh() o.buf.Refresh(nil)
} }
if o.IsInCompleteMode() { if o.IsInCompleteMode() {
o.ExitCompleteMode(true) o.ExitCompleteMode(true)
o.buf.Refresh() o.buf.Refresh(nil)
} }
case CharTab: case CharTab:
if o.opCompleter == nil { if o.opCompleter == nil {
@ -162,11 +164,11 @@ func (o *Operation) ioloop() {
if o.IsInCompleteMode() { if o.IsInCompleteMode() {
o.t.KickRead() o.t.KickRead()
o.ExitCompleteMode(true) o.ExitCompleteMode(true)
o.buf.Refresh() o.buf.Refresh(nil)
break break
} }
o.buf.MoveToLineEnd() o.buf.MoveToLineEnd()
o.buf.Refresh() o.buf.Refresh(nil)
o.buf.WriteString("^C\n") o.buf.WriteString("^C\n")
o.outchan <- nil o.outchan <- nil
default: default:
@ -183,13 +185,13 @@ func (o *Operation) ioloop() {
} }
if !keepInSearchMode && o.IsSearchMode() { if !keepInSearchMode && o.IsSearchMode() {
o.ExitSearchMode(false) o.ExitSearchMode(false)
o.buf.Refresh() o.buf.Refresh(nil)
} else if o.IsInCompleteMode() { } else if o.IsInCompleteMode() {
if !keepInCompleteMode { if !keepInCompleteMode {
o.ExitCompleteMode(false) o.ExitCompleteMode(false)
o.buf.Refresh() o.buf.Refresh(nil)
} else { } else {
o.buf.Refresh() o.buf.Refresh(nil)
o.CompleteRefresh() o.CompleteRefresh()
} }
} }
@ -216,7 +218,7 @@ func (o *Operation) String() (string, error) {
} }
func (o *Operation) Runes() ([]rune, error) { func (o *Operation) Runes() ([]rune, error) {
o.buf.Refresh() // print prompt o.buf.Refresh(nil) // print prompt
o.t.KickRead() o.t.KickRead()
r := <-o.outchan r := <-o.outchan
if r == nil { if r == nil {

View File

@ -10,6 +10,8 @@ type RuneBuffer struct {
idx int idx int
prompt []rune prompt []rune
w io.Writer w io.Writer
cleanInScreen bool
} }
func NewRuneBuffer(w io.Writer, prompt string) *RuneBuffer { func NewRuneBuffer(w io.Writer, prompt string) *RuneBuffer {
@ -57,16 +59,19 @@ func (r *RuneBuffer) MoveToLineStart() {
if r.idx == 0 { if r.idx == 0 {
return return
} }
r.idx = 0
r.Refresh() r.Refresh(func() {
r.idx = 0
})
} }
func (r *RuneBuffer) MoveBackward() { func (r *RuneBuffer) MoveBackward() {
if r.idx == 0 { if r.idx == 0 {
return return
} }
r.idx-- r.Refresh(func() {
r.Refresh() r.idx--
})
} }
func (r *RuneBuffer) WriteString(s string) { func (r *RuneBuffer) WriteString(s string) {
@ -78,26 +83,29 @@ func (r *RuneBuffer) WriteRune(s rune) {
} }
func (r *RuneBuffer) WriteRunes(s []rune) { func (r *RuneBuffer) WriteRunes(s []rune) {
tail := append(s, r.buf[r.idx:]...) r.Refresh(func() {
r.buf = append(r.buf[:r.idx], tail...) tail := append(s, r.buf[r.idx:]...)
r.idx += len(s) r.buf = append(r.buf[:r.idx], tail...)
r.Refresh() r.idx += len(s)
})
} }
func (r *RuneBuffer) MoveForward() { func (r *RuneBuffer) MoveForward() {
if r.idx == len(r.buf) { r.Refresh(func() {
return if r.idx == len(r.buf) {
} return
r.idx++ }
r.Refresh() r.idx++
})
} }
func (r *RuneBuffer) Delete() { func (r *RuneBuffer) Delete() {
if r.idx == len(r.buf) { r.Refresh(func() {
return if r.idx == len(r.buf) {
} return
r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...) }
r.Refresh() r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...)
})
} }
func (r *RuneBuffer) DeleteWord() { func (r *RuneBuffer) DeleteWord() {
@ -110,8 +118,9 @@ func (r *RuneBuffer) DeleteWord() {
} }
for i := init + 1; i < len(r.buf); i++ { for i := init + 1; i < len(r.buf); i++ {
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) { if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
r.buf = append(r.buf[:r.idx], r.buf[i-1:]...) r.Refresh(func() {
r.Refresh() r.buf = append(r.buf[:r.idx], r.buf[i-1:]...)
})
return return
} }
} }
@ -124,13 +133,15 @@ func (r *RuneBuffer) MoveToPrevWord() {
} }
for i := r.idx - 1; i > 0; i-- { for i := r.idx - 1; i > 0; i-- {
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) { if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
r.idx = i r.Refresh(func() {
r.Refresh() r.idx = i
})
return return
} }
} }
r.idx = 0 r.Refresh(func() {
r.Refresh() r.idx = 0
})
} }
func (r *RuneBuffer) SetIdx(idx int) (change int) { func (r *RuneBuffer) SetIdx(idx int) (change int) {
@ -140,38 +151,43 @@ func (r *RuneBuffer) SetIdx(idx int) (change int) {
} }
func (r *RuneBuffer) Kill() { func (r *RuneBuffer) Kill() {
r.buf = r.buf[:r.idx] r.Refresh(func() {
r.Refresh() r.buf = r.buf[:r.idx]
})
} }
func (r *RuneBuffer) Transpose() { func (r *RuneBuffer) Transpose() {
if len(r.buf) < 2 { if len(r.buf) < 2 {
if len(r.buf) == 1 { if len(r.buf) == 1 {
r.idx++ r.Refresh(func() {
r.Refresh() r.idx++
})
} }
return return
} }
if r.idx == 0 { r.Refresh(func() {
r.idx = 1 if r.idx == 0 {
} else if r.idx >= len(r.buf) { r.idx = 1
r.idx = len(r.buf) - 1 } else if r.idx >= len(r.buf) {
} r.idx = len(r.buf) - 1
r.buf[r.idx], r.buf[r.idx-1] = r.buf[r.idx-1], r.buf[r.idx] }
r.idx++ r.buf[r.idx], r.buf[r.idx-1] = r.buf[r.idx-1], r.buf[r.idx]
r.Refresh() r.idx++
})
} }
func (r *RuneBuffer) MoveToNextWord() { func (r *RuneBuffer) MoveToNextWord() {
for i := r.idx + 1; i < len(r.buf); i++ { for i := r.idx + 1; i < len(r.buf); i++ {
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) { if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
r.idx = i r.Refresh(func() {
r.Refresh() r.idx = i
})
return return
} }
} }
r.idx = len(r.buf) r.Refresh(func() {
r.Refresh() r.idx = len(r.buf)
})
} }
func (r *RuneBuffer) BackEscapeWord() { func (r *RuneBuffer) BackEscapeWord() {
@ -180,33 +196,38 @@ func (r *RuneBuffer) BackEscapeWord() {
} }
for i := r.idx - 1; i > 0; i-- { for i := r.idx - 1; i > 0; i-- {
if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) { if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
r.buf = append(r.buf[:i], r.buf[r.idx:]...) r.Refresh(func() {
r.idx = i r.buf = append(r.buf[:i], r.buf[r.idx:]...)
r.Refresh() r.idx = i
})
return return
} }
} }
r.buf = r.buf[:0] r.Refresh(func() {
r.idx = 0 r.buf = r.buf[:0]
r.Refresh() r.idx = 0
})
} }
func (r *RuneBuffer) Backspace() { func (r *RuneBuffer) Backspace() {
if r.idx == 0 { if r.idx == 0 {
return return
} }
r.idx-- r.Refresh(func() {
r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...) r.idx--
r.Refresh() r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...)
})
} }
func (r *RuneBuffer) MoveToLineEnd() { func (r *RuneBuffer) MoveToLineEnd() {
if r.idx == len(r.buf) { if r.idx == len(r.buf) {
return return
} }
r.idx = len(r.buf)
r.Refresh() r.Refresh(func() {
r.idx = len(r.buf)
})
} }
func (r *RuneBuffer) LineCount() int { func (r *RuneBuffer) LineCount() int {
@ -216,10 +237,9 @@ func (r *RuneBuffer) LineCount() int {
func (r *RuneBuffer) IdxLine() int { func (r *RuneBuffer) IdxLine() int {
totalWidth := RunesWidth(r.buf[:r.idx]) + r.PromptLen() totalWidth := RunesWidth(r.buf[:r.idx]) + r.PromptLen()
w := getWidth() w := getWidth()
line := 0 line := totalWidth / w
for totalWidth >= w { if totalWidth%w == 0 {
totalWidth -= w line--
line++
} }
return line return line
} }
@ -228,13 +248,17 @@ func (r *RuneBuffer) CursorLineCount() int {
return r.LineCount() - r.IdxLine() return r.LineCount() - r.IdxLine()
} }
func (r *RuneBuffer) Refresh() { func (r *RuneBuffer) Refresh(f func()) {
r.w.Write(r.Output()) r.Clean()
if f != nil {
f()
}
r.w.Write(r.output())
r.cleanInScreen = false
} }
func (r *RuneBuffer) Output() []byte { func (r *RuneBuffer) output() []byte {
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
buf.Write(r.CleanOutput())
buf.WriteString(string(r.prompt)) buf.WriteString(string(r.prompt))
buf.Write([]byte(string(r.buf))) buf.Write([]byte(string(r.buf)))
if len(r.buf) > r.idx { if len(r.buf) > r.idx {
@ -247,14 +271,24 @@ func (r *RuneBuffer) CleanOutput() []byte {
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
buf.Write([]byte("\033[J")) // just like ^k :) buf.Write([]byte("\033[J")) // just like ^k :)
// TODO: calculate how many line before cursor. idxLine := r.IdxLine()
for i := 0; i <= 100; i++ { if idxLine == 0 {
buf.WriteString("\033[2K\r")
return buf.Bytes()
}
for i := 0; i < idxLine; i++ {
buf.WriteString("\033[2K\r\b") buf.WriteString("\033[2K\r\b")
} }
buf.WriteString("\033[2K\r")
return buf.Bytes() return buf.Bytes()
} }
func (r *RuneBuffer) Clean() { func (r *RuneBuffer) Clean() {
if r.cleanInScreen {
return
}
r.cleanInScreen = true
r.w.Write(r.CleanOutput()) r.w.Write(r.CleanOutput())
} }
@ -291,9 +325,10 @@ func (r *RuneBuffer) SetStyle(start, end int, style string) {
} }
func (r *RuneBuffer) SetWithIdx(idx int, buf []rune) { func (r *RuneBuffer) SetWithIdx(idx int, buf []rune) {
r.buf = buf r.Refresh(func() {
r.idx = idx r.buf = buf
r.Refresh() r.idx = idx
})
} }
func (r *RuneBuffer) Set(buf []rune) { func (r *RuneBuffer) Set(buf []rune) {