Example #1
0
File: edit.go Project: chai2010/T
func (e move) do(ed *Editor, _ io.Writer) (addr, error) {
	s, err := e.src.where(ed)
	if err != nil {
		return addr{}, err
	}
	d, err := e.dst.where(ed)
	if err != nil {
		return addr{}, err
	}
	d.from = d.to

	if d.from > s.from && d.from < s.to {
		return addr{}, errors.New("addresses overlap")
	}

	if d.from >= s.to {
		// Moving to after the source. Delete the source first.
		if err := pend(ed, s, runes.EmptyReader()); err != nil {
			return addr{}, err
		}
	}
	r := runes.LimitReader(ed.buf.runes.Reader(s.from), s.size())
	if err := pend(ed, d, r); err != nil {
		return addr{}, err
	}
	if d.from <= s.from {
		// Moving to before the source. Delete the source second.
		if err := pend(ed, s, runes.EmptyReader()); err != nil {
			return addr{}, err
		}
	}
	return d, nil
}
Example #2
0
File: log.go Project: chai2010/T
// Data returns the entry's data.
func (e entry) data() runes.Reader {
	if e.err != nil {
		panic("data called on the end iterator")
	}
	from := e.offs + headerRunes
	return runes.LimitReader(e.l.buf.Reader(from), e.size)
}
Example #3
0
File: edit.go Project: chai2010/T
func (e print) do(ed *Editor, w io.Writer) (addr, error) {
	at, err := e.a.where(ed)
	if err != nil {
		return addr{}, err
	}
	r := runes.LimitReader(ed.buf.runes.Reader(at.from), at.size())
	if _, err := runes.Copy(runes.UTF8Writer(w), r); err != nil {
		return addr{}, err
	}
	return at, nil
}
Example #4
0
File: edit.go Project: chai2010/T
func (e cpy) do(ed *Editor, _ io.Writer) (addr, error) {
	s, err := e.src.where(ed)
	if err != nil {
		return addr{}, err
	}
	d, err := e.dst.where(ed)
	if err != nil {
		return addr{}, err
	}
	d.from = d.to
	r := runes.LimitReader(ed.buf.runes.Reader(s.from), s.size())
	return d, pend(ed, d, r)
}
Example #5
0
File: editor.go Project: chai2010/T
// Do applies changes to an Editor's Buffer.
//
// Changes are applied in two phases:
// Phase one logs the changes without modifying the Buffer.
// Phase two applies the changes to the Buffer.
// The two phases occur with the buffer Lock held.
//
// The f function performs phase one.
// It is called with the Editor's pending log cleared.
// It will typically append changes to the Editor's pending log
// and/or modify the Editor's marks.
// In the case of an error, the marks are restored
// to their values before any changes were made.
//
// The f function must return the address
// over which changes were computed.
// This address is used to compute and set dot
// after the changes are applied.
func (ed *Editor) do(f func() (addr, error)) error {
	ed.buf.Lock()
	defer ed.buf.Unlock()

	marks0 := make(map[rune]addr, len(ed.marks))
	for r, a := range ed.marks {
		marks0[r] = a
	}
	defer func() { ed.marks = marks0 }()

	if err := ed.pending.clear(); err != nil {
		return err
	}
	at, err := f()
	if err != nil {
		return err
	}

	if at, err = fixAddrs(at, ed.pending); err != nil {
		return err
	}

	if err := ed.buf.redo.clear(); err != nil {
		return err
	}

	for e := logFirst(ed.pending); !e.end(); e = e.next() {
		undoAt := addr{from: e.at.from, to: e.at.from + e.size}
		undoSrc := ed.buf.runes.Reader(e.at.from)
		undoSrc = runes.LimitReader(undoSrc, e.at.size())
		if err := ed.buf.undo.append(ed.buf.seq, undoAt, undoSrc); err != nil {
			return err
		}

		if err := ed.buf.change(e.at, e.data()); err != nil {
			// TODO(eaburns): Very bad; what should we do?
			return err
		}
	}

	ed.buf.seq++
	ed.marks['.'] = at
	marks0 = ed.marks
	return err
}
Example #6
0
File: editor.go Project: chai2010/T
// Undo1 undoes the most recent
// sequence of changes.
// A sequence of changes is one in which
// all changes have the same seq.
// It returns the address that covers
// all changes in the sequence.
// If nothing is undone, dot is returned.
func (ed *Editor) undo1() (addr, error) {
	e := logLast(ed.buf.undo)
	if e.end() {
		return ed.marks['.'], nil
	}
	for {
		prev := e.prev()
		if prev.end() || prev.seq != e.seq {
			break
		}
		e = prev
	}

	all := addr{from: ed.buf.size() + 1, to: -1}
	start := e
	for !e.end() {
		redoAt := addr{from: e.at.from, to: e.at.from + e.size}
		redoSrc := ed.buf.runes.Reader(e.at.from)
		redoSrc = runes.LimitReader(redoSrc, e.at.size())
		if err := ed.buf.redo.append(ed.buf.seq, redoAt, redoSrc); err != nil {
			return addr{}, err
		}

		// There is no need to call all.update,
		// because changes always apply
		// in sequence of increasing addresses.
		if e.at.from < all.from {
			all.from = e.at.from
		}
		if to := e.at.from + e.size; to > all.to {
			all.to = to
		}

		if err := ed.buf.change(e.at, e.data()); err != nil {
			return addr{}, err
		}
		e = e.next()
	}
	return all, start.pop()
}
Example #7
0
File: edit.go Project: chai2010/T
func (e pipe) do(ed *Editor, w io.Writer) (addr, error) {
	at, err := e.a.where(ed)
	if err != nil {
		return addr{}, err
	}

	cmd := exec.Command(shell(), "-c", e.cmd)
	cmd.Stderr = w

	if e.to {
		r := ed.buf.runes.Reader(at.from)
		r = runes.LimitReader(r, at.size())
		cmd.Stdin = runes.UTF8Reader(r)
	}

	if !e.from {
		cmd.Stdout = w
		if err := cmd.Run(); err != nil {
			return addr{}, err
		}
		return at, nil
	}

	r, err := cmd.StdoutPipe()
	if err != nil {
		return addr{}, err
	}
	if err := cmd.Start(); err != nil {
		return addr{}, err
	}
	pendErr := pend(ed, at, runes.RunesReader(bufio.NewReader(r)))
	if err = cmd.Wait(); err != nil {
		return addr{}, err
	}
	if pendErr != nil {
		return addr{}, pendErr
	}
	return at, nil
}