// startReadLine prepares the terminal for the editor. func (ed *Editor) startReadLine() error { ed.activeMutex.Lock() defer ed.activeMutex.Unlock() ed.active = true savedTermios, err := setupTerminal(ed.file) if err != nil { return err } ed.savedTermios = savedTermios _, width := sys.GetWinsize(int(ed.file.Fd())) // Turn on autowrap, write lackEOL along with enough padding to fill the // whole screen. If the cursor was in the first column, we end up in the // same line (just off the line boundary); otherwise we are now in the next // line. We now rewind to the first column and erase anything there. The // final effect is that a lackEOL gets written if and only if the cursor // was not in the first column. fmt.Fprintf(ed.file, "\033[?7h%s%*s\r \r", lackEOL, width-util.Wcwidth(lackEOLRune), "") // Turn off autowrap. The edito has its own wrapping mechanism. Doing // wrapping manually means that when the actual width of some characters // are greater than what our wcwidth implementation tells us, characters at // the end of that line gets hidden -- compared to pushed to the next line, // which is more disastrous. ed.file.WriteString("\033[?7l") // Turn on SGR-style mouse tracking. //ed.file.WriteString("\033[?1000;1006h") // Enable bracketed paste. ed.file.WriteString("\033[?2004h") return nil }
// write appends a single rune to a buffer. func (b *buffer) write(r rune, style string) { if r == '\n' { b.newline() return } else if r < 0x20 || r == 0x7f { // BUG(xiaq): buffer.write drops ASCII control characters silently return } wd := util.Wcwidth(r) c := cell{r, byte(wd), style} if b.col+wd > b.width { b.newline() b.appendCell(c) } else { b.appendCell(c) if b.col == b.width && b.newlineWhenFull { b.newline() } } }