Implemented SubWordRight, SubWordLeft, SelectSubWordRight, SelectSubWordLeft and DeleteSubWordRight, DeleteSubWordLeft
This commit is contained in:
parent
889a841575
commit
5dbdf8c0e8
5 changed files with 253 additions and 3 deletions
|
@ -283,6 +283,22 @@ func (h *BufPane) WordLeft() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// SubWordRight moves the cursor one sub-word to the right
|
||||
func (h *BufPane) SubWordRight() bool {
|
||||
h.Cursor.Deselect(false)
|
||||
h.Cursor.SubWordRight()
|
||||
h.Relocate()
|
||||
return true
|
||||
}
|
||||
|
||||
// SubWordLeft moves the cursor one sub-word to the left
|
||||
func (h *BufPane) SubWordLeft() bool {
|
||||
h.Cursor.Deselect(true)
|
||||
h.Cursor.SubWordLeft()
|
||||
h.Relocate()
|
||||
return true
|
||||
}
|
||||
|
||||
// SelectUp selects up one line
|
||||
func (h *BufPane) SelectUp() bool {
|
||||
if !h.Cursor.HasSelection() {
|
||||
|
@ -359,6 +375,28 @@ func (h *BufPane) SelectWordLeft() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// SelectSubWordRight selects the sub-word to the right of the cursor
|
||||
func (h *BufPane) SelectSubWordRight() bool {
|
||||
if !h.Cursor.HasSelection() {
|
||||
h.Cursor.OrigSelection[0] = h.Cursor.Loc
|
||||
}
|
||||
h.Cursor.SubWordRight()
|
||||
h.Cursor.SelectTo(h.Cursor.Loc)
|
||||
h.Relocate()
|
||||
return true
|
||||
}
|
||||
|
||||
// SelectSubWordLeft selects the sub-word to the left of the cursor
|
||||
func (h *BufPane) SelectSubWordLeft() bool {
|
||||
if !h.Cursor.HasSelection() {
|
||||
h.Cursor.OrigSelection[0] = h.Cursor.Loc
|
||||
}
|
||||
h.Cursor.SubWordLeft()
|
||||
h.Cursor.SelectTo(h.Cursor.Loc)
|
||||
h.Relocate()
|
||||
return true
|
||||
}
|
||||
|
||||
// StartOfText moves the cursor to the start of the text of the line
|
||||
func (h *BufPane) StartOfText() bool {
|
||||
h.Cursor.Deselect(true)
|
||||
|
@ -622,6 +660,28 @@ func (h *BufPane) DeleteWordLeft() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// DeleteSubWordRight deletes the sub-word to the right of the cursor
|
||||
func (h *BufPane) DeleteSubWordRight() bool {
|
||||
h.SelectSubWordRight()
|
||||
if h.Cursor.HasSelection() {
|
||||
h.Cursor.DeleteSelection()
|
||||
h.Cursor.ResetSelection()
|
||||
}
|
||||
h.Relocate()
|
||||
return true
|
||||
}
|
||||
|
||||
// DeleteSubWordLeft deletes the sub-word to the left of the cursor
|
||||
func (h *BufPane) DeleteSubWordLeft() bool {
|
||||
h.SelectSubWordLeft()
|
||||
if h.Cursor.HasSelection() {
|
||||
h.Cursor.DeleteSelection()
|
||||
h.Cursor.ResetSelection()
|
||||
}
|
||||
h.Relocate()
|
||||
return true
|
||||
}
|
||||
|
||||
// Delete deletes the next character
|
||||
func (h *BufPane) Delete() bool {
|
||||
if h.Cursor.HasSelection() {
|
||||
|
|
|
@ -746,10 +746,16 @@ var BufKeyActions = map[string]BufKeyAction{
|
|||
"SelectRight": (*BufPane).SelectRight,
|
||||
"WordRight": (*BufPane).WordRight,
|
||||
"WordLeft": (*BufPane).WordLeft,
|
||||
"SubWordRight": (*BufPane).SubWordRight,
|
||||
"SubWordLeft": (*BufPane).SubWordLeft,
|
||||
"SelectWordRight": (*BufPane).SelectWordRight,
|
||||
"SelectWordLeft": (*BufPane).SelectWordLeft,
|
||||
"SelectSubWordRight": (*BufPane).SelectSubWordRight,
|
||||
"SelectSubWordLeft": (*BufPane).SelectSubWordLeft,
|
||||
"DeleteWordRight": (*BufPane).DeleteWordRight,
|
||||
"DeleteWordLeft": (*BufPane).DeleteWordLeft,
|
||||
"DeleteSubWordRight": (*BufPane).DeleteSubWordRight,
|
||||
"DeleteSubWordLeft": (*BufPane).DeleteSubWordLeft,
|
||||
"SelectLine": (*BufPane).SelectLine,
|
||||
"SelectToStartOfLine": (*BufPane).SelectToStartOfLine,
|
||||
"SelectToStartOfText": (*BufPane).SelectToStartOfText,
|
||||
|
@ -876,10 +882,16 @@ var MultiActions = map[string]bool{
|
|||
"SelectRight": true,
|
||||
"WordRight": true,
|
||||
"WordLeft": true,
|
||||
"SubWordRight": true,
|
||||
"SubWordLeft": true,
|
||||
"SelectWordRight": true,
|
||||
"SelectWordLeft": true,
|
||||
"SelectSubWordRight": true,
|
||||
"SelectSubWordLeft": true,
|
||||
"DeleteWordRight": true,
|
||||
"DeleteWordLeft": true,
|
||||
"DeleteSubWordRight": true,
|
||||
"DeleteSubWordLeft": true,
|
||||
"SelectLine": true,
|
||||
"SelectToStartOfLine": true,
|
||||
"SelectToStartOfText": true,
|
||||
|
|
|
@ -438,6 +438,127 @@ func (c *Cursor) WordLeft() {
|
|||
c.Right()
|
||||
}
|
||||
|
||||
// SubWordRight moves the cursor one sub-word to the right
|
||||
func (c *Cursor) SubWordRight() {
|
||||
if util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
for util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
if c.X == util.CharacterCount(c.buf.LineBytes(c.Y)) {
|
||||
c.Right()
|
||||
return
|
||||
}
|
||||
c.Right()
|
||||
}
|
||||
return
|
||||
}
|
||||
if util.IsNonWordChar(c.RuneUnder(c.X)) && !util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
for util.IsNonWordChar(c.RuneUnder(c.X)) && !util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
if c.X == util.CharacterCount(c.buf.LineBytes(c.Y)) {
|
||||
c.Right()
|
||||
return
|
||||
}
|
||||
c.Right()
|
||||
}
|
||||
return
|
||||
}
|
||||
if util.IsSubwordDelimiter(c.RuneUnder(c.X)) {
|
||||
for util.IsSubwordDelimiter(c.RuneUnder(c.X)) {
|
||||
if c.X == util.CharacterCount(c.buf.LineBytes(c.Y)) {
|
||||
c.Right()
|
||||
return
|
||||
}
|
||||
c.Right()
|
||||
}
|
||||
if util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if c.X == util.CharacterCount(c.buf.LineBytes(c.Y)) {
|
||||
return
|
||||
}
|
||||
if util.IsUpperLetter(c.RuneUnder(c.X)) &&
|
||||
util.IsUpperLetter(c.RuneUnder(c.X+1)) {
|
||||
for util.IsUpperAlphanumeric(c.RuneUnder(c.X)) {
|
||||
if c.X == util.CharacterCount(c.buf.LineBytes(c.Y)) {
|
||||
return
|
||||
}
|
||||
c.Right()
|
||||
}
|
||||
if util.IsLowerAlphanumeric(c.RuneUnder(c.X)) {
|
||||
c.Left()
|
||||
}
|
||||
} else {
|
||||
c.Right()
|
||||
for util.IsLowerAlphanumeric(c.RuneUnder(c.X)) {
|
||||
if c.X == util.CharacterCount(c.buf.LineBytes(c.Y)) {
|
||||
return
|
||||
}
|
||||
c.Right()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SubWordLeft moves the cursor one sub-word to the left
|
||||
func (c *Cursor) SubWordLeft() {
|
||||
c.Left()
|
||||
if util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
for util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
if c.X == 0 {
|
||||
return
|
||||
}
|
||||
c.Left()
|
||||
}
|
||||
c.Right()
|
||||
return
|
||||
}
|
||||
if util.IsNonWordChar(c.RuneUnder(c.X)) && !util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
for util.IsNonWordChar(c.RuneUnder(c.X)) && !util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
if c.X == 0 {
|
||||
return
|
||||
}
|
||||
c.Left()
|
||||
}
|
||||
c.Right()
|
||||
return
|
||||
}
|
||||
if util.IsSubwordDelimiter(c.RuneUnder(c.X)) {
|
||||
for util.IsSubwordDelimiter(c.RuneUnder(c.X)) {
|
||||
if c.X == 0 {
|
||||
return
|
||||
}
|
||||
c.Left()
|
||||
}
|
||||
if util.IsWhitespace(c.RuneUnder(c.X)) {
|
||||
c.Right()
|
||||
return
|
||||
}
|
||||
}
|
||||
if c.X == 0 {
|
||||
return
|
||||
}
|
||||
if util.IsUpperLetter(c.RuneUnder(c.X)) &&
|
||||
util.IsUpperLetter(c.RuneUnder(c.X-1)) {
|
||||
for util.IsUpperAlphanumeric(c.RuneUnder(c.X)) {
|
||||
if c.X == 0 {
|
||||
return
|
||||
}
|
||||
c.Left()
|
||||
}
|
||||
if !util.IsUpperAlphanumeric(c.RuneUnder(c.X)) {
|
||||
c.Right()
|
||||
}
|
||||
} else {
|
||||
for util.IsLowerAlphanumeric(c.RuneUnder(c.X)) {
|
||||
if c.X == 0 {
|
||||
return
|
||||
}
|
||||
c.Left()
|
||||
}
|
||||
if !util.IsAlphanumeric(c.RuneUnder(c.X)) {
|
||||
c.Right()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RuneUnder returns the rune under the given x position
|
||||
func (c *Cursor) RuneUnder(x int) rune {
|
||||
line := c.buf.LineBytes(c.Y)
|
||||
|
|
|
@ -219,18 +219,69 @@ func FSize(f *os.File) int64 {
|
|||
}
|
||||
|
||||
// IsWordChar returns whether or not a rune is a 'word character'
|
||||
// Word characters are defined as numbers, letters or '_'
|
||||
// Word characters are defined as numbers, letters or sub-word delimiters
|
||||
func IsWordChar(r rune) bool {
|
||||
return unicode.IsLetter(r) || unicode.IsNumber(r) || r == '_'
|
||||
return IsAlphanumeric(r) || IsSubwordDelimiter(r)
|
||||
}
|
||||
|
||||
// IsNonWordChar returns whether or not a rune is not a 'word character'
|
||||
// Non word characters are defined as all characters not being numbers, letters or '_'
|
||||
// Non word characters are defined as all characters not being numbers, letters or sub-word delimiters
|
||||
// See IsWordChar()
|
||||
func IsNonWordChar(r rune) bool {
|
||||
return !IsWordChar(r)
|
||||
}
|
||||
|
||||
// IsUpperWordChar returns whether or not a rune is an 'upper word character'
|
||||
// Upper word characters are defined as numbers, upper-case letters or sub-word delimiters
|
||||
func IsUpperWordChar(r rune) bool {
|
||||
return IsUpperAlphanumeric(r) || IsSubwordDelimiter(r)
|
||||
}
|
||||
|
||||
// IsLowerWordChar returns whether or not a rune is a 'lower word character'
|
||||
// Lower word characters are defined as numbers, lower-case letters or sub-word delimiters
|
||||
func IsLowerWordChar(r rune) bool {
|
||||
return IsLowerAlphanumeric(r) || IsSubwordDelimiter(r)
|
||||
}
|
||||
|
||||
// IsSubwordDelimiter returns whether or not a rune is a 'sub-word delimiter character'
|
||||
// i.e. is considered a part of the word and is used as a delimiter between sub-words of the word.
|
||||
// For now the only sub-word delimiter character is '_'.
|
||||
func IsSubwordDelimiter(r rune) bool {
|
||||
return r == '_'
|
||||
}
|
||||
|
||||
// IsAlphanumeric returns whether or not a rune is an 'alphanumeric character'
|
||||
// Alphanumeric characters are defined as numbers or letters
|
||||
func IsAlphanumeric(r rune) bool {
|
||||
return unicode.IsLetter(r) || unicode.IsNumber(r)
|
||||
}
|
||||
|
||||
// IsUpperAlphanumeric returns whether or not a rune is an 'upper alphanumeric character'
|
||||
// Upper alphanumeric characters are defined as numbers or upper-case letters
|
||||
func IsUpperAlphanumeric(r rune) bool {
|
||||
return IsUpperLetter(r) || unicode.IsNumber(r)
|
||||
}
|
||||
|
||||
// IsLowerAlphanumeric returns whether or not a rune is a 'lower alphanumeric character'
|
||||
// Lower alphanumeric characters are defined as numbers or lower-case letters
|
||||
func IsLowerAlphanumeric(r rune) bool {
|
||||
return IsLowerLetter(r) || unicode.IsNumber(r)
|
||||
}
|
||||
|
||||
// IsUpperLetter returns whether or not a rune is an 'upper letter character'
|
||||
// Upper letter characters are defined as upper-case letters
|
||||
func IsUpperLetter(r rune) bool {
|
||||
// unicode.IsUpper() returns true for letters only
|
||||
return unicode.IsUpper(r)
|
||||
}
|
||||
|
||||
// IsLowerLetter returns whether or not a rune is a 'lower letter character'
|
||||
// Lower letter characters are defined as lower-case letters
|
||||
func IsLowerLetter(r rune) bool {
|
||||
// unicode.IsLower() returns true for letters only
|
||||
return unicode.IsLower(r)
|
||||
}
|
||||
|
||||
// Spaces returns a string with n spaces
|
||||
func Spaces(n int) string {
|
||||
return strings.Repeat(" ", n)
|
||||
|
|
|
@ -178,12 +178,18 @@ SelectToStartOfText
|
|||
SelectToStartOfTextToggle
|
||||
WordRight
|
||||
WordLeft
|
||||
SubWordRight
|
||||
SubWordLeft
|
||||
SelectWordRight
|
||||
SelectWordLeft
|
||||
SelectSubWordRight
|
||||
SelectSubWordLeft
|
||||
MoveLinesUp
|
||||
MoveLinesDown
|
||||
DeleteWordRight
|
||||
DeleteWordLeft
|
||||
DeleteSubWordRight
|
||||
DeleteSubWordLeft
|
||||
SelectLine
|
||||
SelectToStartOfLine
|
||||
SelectToEndOfLine
|
||||
|
|
Loading…
Reference in a new issue