Esempio n. 1
0
// Move cursor forward to beginning of the previous word.
// Skips the rest of the current word, if any, unless is located at its
// first character. Returns true if the move was successful, false if EOF reached.
func (c *Cursor) PrevWord() bool {
	isNotSpace := func(r rune) bool {
		return !unicode.IsSpace(r)
	}
	for {
		// Skip space until we find a word character.
		// Re-try if we reached beginning-of-line.
		if !c.PrevRuneFunc(isNotSpace) {
			return false
		}
		if !c.BOL() {
			break
		}
	}
	r, _ := c.RuneBefore()
	if isNotSpace(r) {
		// Lowercase word motion differentiates words consisting of
		// (A-Z0-9_) and any other non-whitespace character. Skip until
		// we find either the other word type or whitespace.
		if utils.IsWord(r) {
			c.PrevRuneFunc(func(r rune) bool {
				return !utils.IsWord(r) || unicode.IsSpace(r)
			})
		} else {
			c.PrevRuneFunc(func(r rune) bool {
				return utils.IsWord(r) || unicode.IsSpace(r)
			})
		}
	}
	return !c.BOL()
}
Esempio n. 2
0
func (c *Cursor) WordUnderCursor() []byte {
	end, beg := *c, *c
	var (
		r    rune
		rlen int
	)

	r, _ = beg.RuneUnder()
	if unicode.IsSpace(r) {
		return nil
	}

	if !beg.BOL() {
		r, rlen = beg.RuneBefore()
		if r == utf8.RuneError {
			return nil
		}

		// move the `beg` cursor back to the start of the word
		for utils.IsWord(r) && !beg.BOL() {
			beg.Boffset -= rlen
			r, rlen = beg.RuneBefore()
		}
	}

	// set the end cursor to the same position as the start cursor
	end.Boffset = beg.Boffset

	// check if the word is just a single character
	r, rlen = end.RuneAfter()
	if !utils.IsWord(r) {
		return c.Line.Data[end.Boffset : end.Boffset+1]
	}

	// move to the the rune after the end of the word
	for utils.IsWord(r) && !end.EOL() {
		end.Boffset += rlen
		r, rlen = end.RuneAfter()
	}
	end.NextRune(false)

	if beg.Boffset == end.Boffset {
		return nil
	}
	return c.Line.Data[beg.Boffset:end.Boffset]
}
Esempio n. 3
0
// Move cursor forward to beginning of next word.
// Skips the rest of the current word, if any. Returns true if
// the move was successful, false if EOF reached.
func (c *Cursor) NextWord() bool {
	isNotSpace := func(r rune) bool {
		return !unicode.IsSpace(r)
	}
	r, _ := c.RuneUnder()
	if isNotSpace(r) {
		// Lowercase word motion differentiates words consisting of
		// (A-Z0-9_) and any other non-whitespace character. Skip until
		// we find either the other word type or whitespace.
		if utils.IsWord(r) {
			c.NextRuneFunc(func(r rune) bool {
				return !utils.IsWord(r) || unicode.IsSpace(r)
			})
		} else {
			c.NextRuneFunc(func(r rune) bool {
				return utils.IsWord(r) || unicode.IsSpace(r)
			})
		}
	}
	// Skip remaining whitespace until next word of any type.
	return c.NextRuneFunc(isNotSpace)
}
Esempio n. 4
0
// EndWord moves cursor to the end of current word or seeks to the
// beginning of next word, if character under cursor is a whitespace.
func (c *Cursor) EndWord() bool {
	if !c.NextRune(true) {
		return false
	}

	// Skip spaces until beginning of next word
	r, _ := c.RuneUnder()
	if c.EOL() || unicode.IsSpace(r) {
		c.NextWord()
	}

	// Skip to after the word.
	r, _ = c.RuneUnder()
	var f func(r rune) bool
	if utils.IsWord(r) {
		f = func(r rune) bool {
			return !utils.IsWord(r) || unicode.IsSpace(r)
		}
	} else {
		f = func(r rune) bool {
			return utils.IsWord(r) || unicode.IsSpace(r)
		}
	}

	// This can go back to end of buffer but can be ignored,
	// since we're going to backtrack one character.
	c.NextRuneFunc(f)
	c.PrevRune(true)
	// Keep going back until BOF if we end up at EOL. This
	// can happen on empty lines.
	for c.EOL() && !(c.BOL() && c.FirstLine()) {
		c.PrevRune(true)
	}

	return true
}
Esempio n. 5
0
func (c *Cursor) WordUnderCursor() []byte {
	end, beg := *c, *c
	r, rlen := beg.RuneBefore()
	if r == utf8.RuneError {
		return nil
	}

	for utils.IsWord(r) && !beg.BOL() {
		beg.Boffset -= rlen
		r, rlen = beg.RuneBefore()
	}

	if beg.Boffset == end.Boffset {
		return nil
	}
	return c.Line.Data[beg.Boffset:end.Boffset]
}