mirror of
https://github.com/zyedidia/micro.git
synced 2026-02-09 16:40:22 +09:00
Add word selection with double click
This commit is contained in:
@@ -42,7 +42,11 @@ type Cursor struct {
|
||||
x int
|
||||
y int
|
||||
|
||||
curSelection [2]int
|
||||
// The current selection as a range of character numbers (inclusive)
|
||||
curSelection [2]int
|
||||
// The original selection as a range of character numbers
|
||||
// This is used for line and word selection where it is necessary
|
||||
// to know what the original selection was
|
||||
origSelection [2]int
|
||||
}
|
||||
|
||||
@@ -97,43 +101,93 @@ func (c *Cursor) SelectLine() {
|
||||
c.End()
|
||||
c.curSelection[1] = c.Loc()
|
||||
|
||||
c.origSelection[0] = c.curSelection[0]
|
||||
c.origSelection[1] = c.curSelection[1]
|
||||
c.origSelection = c.curSelection
|
||||
}
|
||||
|
||||
// AddLineToSelection adds the current line to the selection
|
||||
func (c *Cursor) AddLineToSelection() {
|
||||
loc := c.Loc()
|
||||
|
||||
if loc < c.origSelection[0] {
|
||||
c.Start()
|
||||
c.curSelection[0] = c.Loc()
|
||||
c.curSelection[1] = c.origSelection[1]
|
||||
}
|
||||
if loc > c.origSelection[1] {
|
||||
c.End()
|
||||
c.curSelection[1] = c.Loc()
|
||||
c.curSelection[0] = c.origSelection[0]
|
||||
}
|
||||
|
||||
if loc < c.origSelection[1] && loc > c.origSelection[0] {
|
||||
c.curSelection = c.origSelection
|
||||
}
|
||||
}
|
||||
|
||||
// SelectWord selects the word the cursor is currently on
|
||||
func (c *Cursor) SelectWord() {
|
||||
if !IsWordChar(string(c.RuneUnder(c.x))) {
|
||||
return
|
||||
}
|
||||
|
||||
forward, backward := c.x, c.x
|
||||
|
||||
for backward > 0 && IsWordChar(string(c.RuneUnder(backward-1))) {
|
||||
backward--
|
||||
}
|
||||
|
||||
c.curSelection[0] = ToCharPos(backward, c.y, c.v.buf)
|
||||
c.origSelection[0] = c.curSelection[0]
|
||||
|
||||
for forward < Count(c.v.buf.lines[c.y])-1 && IsWordChar(string(c.RuneUnder(forward+1))) {
|
||||
forward++
|
||||
}
|
||||
|
||||
c.curSelection[1] = ToCharPos(forward, c.y, c.v.buf)
|
||||
c.origSelection[1] = c.curSelection[1]
|
||||
}
|
||||
|
||||
// AddWordToSelection adds the word the cursor is currently on to the selection
|
||||
func (c *Cursor) AddWordToSelection() {
|
||||
loc := c.Loc()
|
||||
|
||||
if loc > c.origSelection[0] && loc < c.origSelection[1] {
|
||||
c.curSelection = c.origSelection
|
||||
return
|
||||
}
|
||||
|
||||
if loc < c.origSelection[0] {
|
||||
c.Start()
|
||||
c.curSelection[0] = c.Loc()
|
||||
} else if loc > c.origSelection[1] {
|
||||
c.End()
|
||||
c.curSelection[1] = c.Loc()
|
||||
backward := c.x
|
||||
|
||||
for backward > 0 && IsWordChar(string(c.RuneUnder(backward-1))) {
|
||||
backward--
|
||||
}
|
||||
|
||||
c.curSelection[0] = ToCharPos(backward, c.y, c.v.buf)
|
||||
c.curSelection[1] = c.origSelection[1]
|
||||
}
|
||||
|
||||
if loc < c.curSelection[0] {
|
||||
c.Start()
|
||||
c.curSelection[0] = c.Loc()
|
||||
} else if loc > c.curSelection[1] {
|
||||
c.End()
|
||||
c.curSelection[1] = c.Loc()
|
||||
if loc > c.origSelection[1] {
|
||||
forward := c.x
|
||||
|
||||
for forward < Count(c.v.buf.lines[c.y])-1 && IsWordChar(string(c.RuneUnder(forward+1))) {
|
||||
forward++
|
||||
}
|
||||
|
||||
c.curSelection[1] = ToCharPos(forward, c.y, c.v.buf)
|
||||
c.curSelection[0] = c.origSelection[0]
|
||||
}
|
||||
}
|
||||
|
||||
// RuneUnder returns the rune under the cursor
|
||||
func (c *Cursor) RuneUnder() rune {
|
||||
line := c.v.buf.lines[c.y]
|
||||
if c.x >= Count(line) {
|
||||
return ' '
|
||||
// RuneUnder returns the rune under the given x position
|
||||
func (c *Cursor) RuneUnder(x int) rune {
|
||||
line := []rune(c.v.buf.lines[c.y])
|
||||
if x >= len(line) {
|
||||
x = len(line) - 1
|
||||
} else if x < 0 {
|
||||
x = 0
|
||||
}
|
||||
return []rune(line)[c.x]
|
||||
return line[x]
|
||||
}
|
||||
|
||||
// Up moves the cursor up one line (if possible)
|
||||
|
||||
12
src/util.go
12
src/util.go
@@ -48,3 +48,15 @@ func Max(a, b int) int {
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// IsWordChar returns whether or not the string is a 'word character'
|
||||
// If it is a unicode character, then it does not match
|
||||
// Word characters are defined as [A-Za-z0-9_]
|
||||
func IsWordChar(str string) bool {
|
||||
if len(str) > 1 {
|
||||
// Unicode
|
||||
return false
|
||||
}
|
||||
c := str[0]
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_')
|
||||
}
|
||||
|
||||
@@ -33,3 +33,33 @@ func TestSpaces(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsWordChar(t *testing.T) {
|
||||
if IsWordChar("t") == false {
|
||||
t.Errorf("IsWordChar(t) = false")
|
||||
}
|
||||
if IsWordChar("T") == false {
|
||||
t.Errorf("IsWordChar(T) = false")
|
||||
}
|
||||
if IsWordChar("5") == false {
|
||||
t.Errorf("IsWordChar(5) = false")
|
||||
}
|
||||
if IsWordChar("_") == false {
|
||||
t.Errorf("IsWordChar(_) = false")
|
||||
}
|
||||
if IsWordChar("~") == true {
|
||||
t.Errorf("IsWordChar(~) = true")
|
||||
}
|
||||
if IsWordChar(" ") == true {
|
||||
t.Errorf("IsWordChar( ) = true")
|
||||
}
|
||||
if IsWordChar("ß") == true {
|
||||
t.Errorf("IsWordChar(ß) = true")
|
||||
}
|
||||
if IsWordChar(")") == true {
|
||||
t.Errorf("IsWordChar()) = true")
|
||||
}
|
||||
if IsWordChar("\n") == true {
|
||||
t.Errorf("IsWordChar(\n)) = true")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,14 +456,19 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
if v.doubleClick {
|
||||
// Triple click
|
||||
v.lastClickTime = time.Now()
|
||||
|
||||
v.tripleClick = true
|
||||
v.doubleClick = false
|
||||
|
||||
v.cursor.SelectLine()
|
||||
} else {
|
||||
// Double click
|
||||
v.lastClickTime = time.Now()
|
||||
|
||||
v.doubleClick = true
|
||||
v.tripleClick = false
|
||||
v.lastClickTime = time.Now()
|
||||
|
||||
v.cursor.SelectWord()
|
||||
}
|
||||
} else {
|
||||
v.doubleClick = false
|
||||
@@ -478,7 +483,7 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
if v.tripleClick {
|
||||
v.cursor.AddLineToSelection()
|
||||
} else if v.doubleClick {
|
||||
|
||||
v.cursor.AddWordToSelection()
|
||||
} else {
|
||||
v.cursor.curSelection[1] = v.cursor.Loc()
|
||||
}
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
- [ ] Search and replace
|
||||
|
||||
- [ ] Better selection
|
||||
- [ ] Double click selects current word
|
||||
- [x] Triple click enables line selection
|
||||
|
||||
- [ ] More keybindings
|
||||
- [x] Page up and page down
|
||||
- [x] CtrlA for select all
|
||||
@@ -40,6 +36,10 @@
|
||||
- [x] Help screen which lists keybindings and commands
|
||||
- [x] Opened with Ctrl-h
|
||||
|
||||
- [x] Better selection
|
||||
- [x] Double click selects current word
|
||||
- [x] Triple click enables line selection
|
||||
|
||||
- [x] Options
|
||||
- [x] Colorscheme
|
||||
- [x] tab size
|
||||
|
||||
Reference in New Issue
Block a user